Skip to content

Commit c14b95b

Browse files
upcoming: [DI-22941] - Update dependency and order for tags (linode#11615)
* upcoming: [DI-22941] - Update dependency and order for tags * upcoming: [DI-22941] - Type fix * upcoming: [DI-22941] - Xfilter update * upcoming: [DI-22941] - Small revert * upcoming: [DI-22941] - Preferences fix * upcoming: [DI-22941] - PR comment * upcoming: [DI-22941] - Mock enhancement * upcoming: [DI-22941]: Preferences fix for resources * upcoming: [DI-22941] - UT fix * upcoming: [DI-22941] - Linting fix * upcoming: [DI-22941] - Comments * upcoming: [DI-22941] - Comments * upcoming: [DI-22941] - Comments * upcoming: [DI-22941] - Comments * upcoming: [DI-22941] - UT fix * upcoming: [DI-22941] - Add changeset * upcoming: [DI-22941] - PR comment - improve quality of unit test * upcoming: [DI-22941] - PR comment - improve comment --------- Co-authored-by: vmangalr <[email protected]>
1 parent 8914a3b commit c14b95b

9 files changed

+238
-67
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
Update Tags dependency and filtering based on Region in CloudPulse ([#11615](https://github.com/linode/manager/pull/11615))

packages/manager/src/features/CloudPulse/Utils/FilterBuilder.test.ts

+90
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
getMetricsCallCustomFilters,
1414
getRegionProperties,
1515
getResourcesProperties,
16+
getTagsProperties,
1617
getTimeDurationProperties,
1718
} from './FilterBuilder';
1819
import { deepEqual, getFilters } from './FilterBuilder';
@@ -52,6 +53,38 @@ it('test getRegionProperties method', () => {
5253
}
5354
});
5455

56+
it('test getTagsProperties', () => {
57+
const tagsConfig = linodeConfig?.filters.find(
58+
(filterObj) => filterObj.name === 'Tags'
59+
);
60+
61+
expect(tagsConfig).toBeDefined();
62+
63+
if (tagsConfig) {
64+
const {
65+
disabled,
66+
handleTagsChange,
67+
label,
68+
region,
69+
resourceType,
70+
} = getTagsProperties(
71+
{
72+
config: tagsConfig,
73+
dashboard: mockDashboard,
74+
dependentFilters: { region: 'us-east' },
75+
isServiceAnalyticsIntegration: true,
76+
},
77+
vi.fn()
78+
);
79+
const { name } = tagsConfig.configuration;
80+
expect(handleTagsChange).toBeDefined();
81+
expect(disabled).toEqual(false);
82+
expect(label).toEqual(name);
83+
expect(region).toEqual('us-east');
84+
expect(resourceType).toEqual('linode');
85+
}
86+
});
87+
5588
it('test getTimeDuratonProperties method', () => {
5689
const timeDurationConfig = linodeConfig?.filters.find(
5790
({ name }) => name === 'Time Range'
@@ -145,6 +178,46 @@ it('test getResourceSelectionProperties method with disabled true', () => {
145178
}
146179
});
147180

181+
describe('checkIfWeNeedToDisableFilterByFilterKey', () => {
182+
// resources filter has region as mandatory and tags as an optional filter, this should reflect in the dependent filters
183+
it('should enable filter when dependent filter region is provided', () => {
184+
const result = checkIfWeNeedToDisableFilterByFilterKey(
185+
'resource_id',
186+
{ region: 'us-east' },
187+
mockDashboard
188+
);
189+
expect(result).toEqual(false);
190+
});
191+
192+
it('should disable filter when dependent filter region is undefined', () => {
193+
const result = checkIfWeNeedToDisableFilterByFilterKey(
194+
'resource_id',
195+
{ region: undefined },
196+
mockDashboard
197+
);
198+
expect(result).toEqual(true);
199+
});
200+
201+
it('should disable filter when no dependent filters are provided', () => {
202+
const result = checkIfWeNeedToDisableFilterByFilterKey(
203+
'resource_id',
204+
{},
205+
mockDashboard
206+
);
207+
expect(result).toEqual(true);
208+
});
209+
210+
it('should disable filter when required dependent filter is undefined in dependent filters but defined in preferences', () => {
211+
const result = checkIfWeNeedToDisableFilterByFilterKey(
212+
'resource_id',
213+
{ region: 'us-east', tags: undefined },
214+
mockDashboard,
215+
{ region: 'us-east', tags: ['tag-1'] } // tags are defined in preferences which confirms that this optional filter was selected
216+
);
217+
expect(result).toEqual(true);
218+
});
219+
});
220+
148221
it('test checkIfWeNeedToDisableFilterByFilterKey method all cases', () => {
149222
let result = checkIfWeNeedToDisableFilterByFilterKey(
150223
'resource_id',
@@ -169,6 +242,23 @@ it('test checkIfWeNeedToDisableFilterByFilterKey method all cases', () => {
169242
);
170243

171244
expect(result).toEqual(true);
245+
246+
result = checkIfWeNeedToDisableFilterByFilterKey(
247+
'resource_id',
248+
{ region: 'us-east', tags: undefined },
249+
mockDashboard,
250+
{ ['region']: 'us-east', ['tags']: ['tag-1'] }
251+
);
252+
253+
expect(result).toEqual(true); // disabled is true as tags are not updated in dependent filters
254+
255+
result = checkIfWeNeedToDisableFilterByFilterKey(
256+
'tags',
257+
{ region: undefined },
258+
mockDashboard
259+
);
260+
261+
expect(result).toEqual(true);
172262
});
173263

174264
it('test buildXfilter method', () => {

packages/manager/src/features/CloudPulse/Utils/FilterBuilder.ts

+28-4
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,34 @@ interface CloudPulseMandatoryFilterCheckProps {
5454
* @param config - accepts a CloudPulseServiceTypeFilters of tag key
5555
* @param handleTagsChange - the callback when we select new tag
5656
* @param dashboard - the selected dashboard's service type
57+
* @param dependentFilters - tags are dependent on region filter, we need this for disabling the tags selection component
5758
* @param isServiceAnalyticsIntegration - only if this is false, we need to save preferences , else no need
5859
* @returns CloudPulseTagSelectProps
5960
*/
6061
export const getTagsProperties = (
6162
props: CloudPulseFilterProperties,
6263
handleTagsChange: (tags: CloudPulseTags[], savePref?: boolean) => void
6364
): CloudPulseTagsSelectProps => {
64-
const { name: label, placeholder } = props.config.configuration;
65-
const { dashboard, isServiceAnalyticsIntegration, preferences } = props;
65+
const { filterKey, name: label, placeholder } = props.config.configuration;
66+
const {
67+
dashboard,
68+
dependentFilters,
69+
isServiceAnalyticsIntegration,
70+
preferences,
71+
} = props;
6672
return {
6773
defaultValue: preferences?.[TAGS],
74+
disabled: checkIfWeNeedToDisableFilterByFilterKey(
75+
filterKey,
76+
dependentFilters ?? {},
77+
dashboard,
78+
preferences
79+
),
6880
handleTagsChange,
6981
label,
7082
optional: props.config.configuration.isOptional,
7183
placeholder,
84+
region: dependentFilters?.[REGION],
7285
resourceType: dashboard.service_type,
7386
savePreferences: !isServiceAnalyticsIntegration,
7487
};
@@ -133,7 +146,8 @@ export const getResourcesProperties = (
133146
disabled: checkIfWeNeedToDisableFilterByFilterKey(
134147
filterKey,
135148
dependentFilters ?? {},
136-
dashboard
149+
dashboard,
150+
preferences
137151
),
138152
handleResourcesSelection: handleResourceChange,
139153
label,
@@ -282,7 +296,8 @@ export const checkIfWeNeedToDisableFilterByFilterKey = (
282296
dependentFilters: {
283297
[key: string]: FilterValueType | TimeDuration;
284298
},
285-
dashboard: Dashboard
299+
dashboard: Dashboard,
300+
preferences?: AclpConfig
286301
): boolean | undefined => {
287302
if (dashboard?.service_type) {
288303
const serviceTypeConfig = FILTER_CONFIG.get(dashboard.service_type);
@@ -304,6 +319,15 @@ export const checkIfWeNeedToDisableFilterByFilterKey = (
304319
return filter.configuration.dependency?.some((dependent) => {
305320
const dependentFilter = dependentFilters[dependent];
306321

322+
if (
323+
preferences &&
324+
preferences[dependent] &&
325+
(!dependentFilter ||
326+
(Array.isArray(dependentFilter) && dependentFilter.length === 0))
327+
) {
328+
return true; // Since filters are set one by one, disabled will be true until the values that are defined inside the preferences are populated in the dependent filters as well
329+
}
330+
307331
return (
308332
!optionalFilters.has(dependent) &&
309333
(!dependentFilter ||

packages/manager/src/features/CloudPulse/Utils/FilterConfig.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,31 @@ export const LINODE_CONFIG: Readonly<CloudPulseServiceTypeFilterMap> = {
1111
filters: [
1212
{
1313
configuration: {
14-
filterKey: 'tags',
14+
filterKey: 'region',
1515
filterType: 'string',
1616
isFilterable: false,
1717
isMetricsFilter: false,
18-
isMultiSelect: true,
19-
isOptional: true,
20-
name: 'Tags',
18+
name: 'Region',
2119
neededInServicePage: false,
22-
placeholder: 'Select Tags',
23-
priority: 4,
20+
priority: 1,
2421
},
25-
name: 'Tags',
22+
name: 'Region',
2623
},
2724
{
2825
configuration: {
29-
filterKey: 'region',
26+
dependency: ['region'],
27+
filterKey: 'tags',
3028
filterType: 'string',
3129
isFilterable: false,
3230
isMetricsFilter: false,
33-
name: 'Region',
31+
isMultiSelect: true,
32+
isOptional: true,
33+
name: 'Tags',
3434
neededInServicePage: false,
35-
priority: 1,
35+
placeholder: 'Select Tags',
36+
priority: 4,
3637
},
37-
name: 'Region',
38+
name: 'Tags',
3839
},
3940
{
4041
configuration: {

packages/manager/src/features/CloudPulse/shared/CloudPulseDashboardFilterBuilder.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export const CloudPulseDashboardFilterBuilder = React.memo(
138138
selectedTags,
139139
savePref,
140140
{
141+
[RESOURCE_ID]: undefined,
141142
[TAGS]: selectedTags,
142143
}
143144
);
@@ -171,6 +172,7 @@ export const CloudPulseDashboardFilterBuilder = React.memo(
171172
const updatedPreferenceData = {
172173
[REGION]: region,
173174
[RESOURCES]: undefined,
175+
[TAGS]: undefined,
174176
};
175177
emitFilterChangeByFilterKey(
176178
REGION,
@@ -209,6 +211,7 @@ export const CloudPulseDashboardFilterBuilder = React.memo(
209211
{
210212
config,
211213
dashboard,
214+
dependentFilters: dependentFilterReference.current,
212215
isServiceAnalyticsIntegration,
213216
preferences,
214217
},

packages/manager/src/features/CloudPulse/shared/CloudPulseResourcesSelect.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ export const CloudPulseResourcesSelect = React.memo(
102102

103103
// Once the data is loaded, set the state variable with value stored in preferences
104104
React.useEffect(() => {
105+
if (disabled && !selectedResources) {
106+
return;
107+
}
108+
// To save default values, go through side effects if disabled is false
105109
if (resources && savePreferences && !selectedResources) {
106110
const defaultResources =
107111
defaultValue && Array.isArray(defaultValue)

0 commit comments

Comments
 (0)