Skip to content

Commit 4d59953

Browse files
upcoming: [DI-21119] - Handle jwe token limit in ACLP UI and Bug fix for resources component (#11309)
* upcoming: [DI-21119] - Handle jwe token limit in ACLP UI * upcoming: [DI-21119] - small fix * upcoming: [DI-21119] - Wait issue & preferences fix, UTs updated * upcoming: [DI-21119] - Comments updated * upcoming: [DI-21119] - Small fix * upcoming: [DI-21119] - Small fix * upcoming: [DI-21119] - PR comments * upcoming: [DI-21119] - Resources call restored and minor updates * upcoming: [DI-21119] - Sanity fixes * upcoming: [DI-21119] - Fallback fix for undefined token * upcoming: [DI-21119] - sorting for payload * upcoming: [DI-21999] - Bug fix for resource limit selection * upcoming: [DI-21999] - Test case update for resource component bug fix * upcoming: [DI-21119] - linting fix * upcoming: [DI-21119] - Added changeset * upcoming: [DI-21119] - Updated changeset description Co-authored-by: Harsh Shankar Rao <[email protected]> --------- Co-authored-by: Harsh Shankar Rao <[email protected]>
1 parent df45bb2 commit 4d59953

File tree

9 files changed

+81
-21
lines changed

9 files changed

+81
-21
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
Handle JWE token limit of 250 in ACLP UI ([#11309](https://github.com/linode/manager/pull/11309))

packages/manager/src/features/CloudPulse/Dashboard/CloudPulseDashboard.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const CloudPulseDashboard = (props: DashboardProperties) => {
6767

6868
const getJweTokenPayload = (): JWETokenPayLoad => {
6969
return {
70-
resource_ids: resourceList?.map((resource) => Number(resource.id)) ?? [],
70+
resource_ids: resources?.map((resource) => Number(resource)) ?? [],
7171
};
7272
};
7373

@@ -100,11 +100,11 @@ export const CloudPulseDashboard = (props: DashboardProperties) => {
100100
const {
101101
data: jweToken,
102102
isError: isJweTokenError,
103-
isLoading: isJweTokenLoading,
103+
isFetching: isJweTokenFetching,
104104
} = useCloudPulseJWEtokenQuery(
105105
dashboard?.service_type,
106106
getJweTokenPayload(),
107-
Boolean(resourceList)
107+
Boolean(resources) && !isDashboardLoading && !isDashboardApiError
108108
);
109109

110110
if (isDashboardApiError) {
@@ -123,12 +123,7 @@ export const CloudPulseDashboard = (props: DashboardProperties) => {
123123
return renderErrorState('Error loading the definitions of metrics.');
124124
}
125125

126-
if (
127-
isMetricDefinitionLoading ||
128-
isDashboardLoading ||
129-
isResourcesLoading ||
130-
isJweTokenLoading
131-
) {
126+
if (isMetricDefinitionLoading || isDashboardLoading || isResourcesLoading) {
132127
return <CircleProgress />;
133128
}
134129

@@ -137,6 +132,7 @@ export const CloudPulseDashboard = (props: DashboardProperties) => {
137132
additionalFilters={additionalFilters}
138133
dashboard={dashboard}
139134
duration={duration}
135+
isJweTokenFetching={isJweTokenFetching}
140136
jweToken={jweToken}
141137
manualRefreshTimeStamp={manualRefreshTimeStamp}
142138
metricDefinitions={metricDefinitions}

packages/manager/src/features/CloudPulse/Widget/CloudPulseWidget.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export interface CloudPulseWidgetProperties {
5151
/**
5252
* token to fetch metrics data
5353
*/
54-
authToken: string;
54+
authToken?: string;
5555

5656
/**
5757
* metrics defined of this widget
@@ -68,6 +68,11 @@ export interface CloudPulseWidgetProperties {
6868
*/
6969
errorLabel?: string;
7070

71+
/**
72+
* Jwe token fetching status check
73+
*/
74+
isJweTokenFetching: boolean;
75+
7176
/**
7277
* resources ids selected by user to show metrics for
7378
*/
@@ -136,6 +141,7 @@ export const CloudPulseWidget = (props: CloudPulseWidgetProperties) => {
136141
authToken,
137142
availableMetrics,
138143
duration,
144+
isJweTokenFetching,
139145
resourceIds,
140146
resources,
141147
savePref,
@@ -232,7 +238,7 @@ export const CloudPulseWidget = (props: CloudPulseWidgetProperties) => {
232238
},
233239
{
234240
authToken,
235-
isFlags: Boolean(flags),
241+
isFlags: Boolean(flags && !isJweTokenFetching),
236242
label: widget.label,
237243
timeStamp,
238244
url: flags.aclpReadEndpoint!,
@@ -326,13 +332,17 @@ export const CloudPulseWidget = (props: CloudPulseWidgetProperties) => {
326332
? metricsApiCallError ?? 'Error while rendering graph'
327333
: undefined
328334
}
335+
loading={
336+
isLoading ||
337+
metricsApiCallError === jweTokenExpiryError ||
338+
isJweTokenFetching
339+
} // keep loading until we are trying to fetch the refresh token
329340
areas={areas}
330341
ariaLabel={ariaLabel ? ariaLabel : ''}
331342
data={data}
332343
dotRadius={1.5}
333344
height={424}
334345
legendRows={legendRows}
335-
loading={isLoading || metricsApiCallError === jweTokenExpiryError} // keep loading until we fetch the refresh token
336346
showDot
337347
showLegend={data.length !== 0}
338348
timezone={timezone}

packages/manager/src/features/CloudPulse/Widget/CloudPulseWidgetRenderer.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ interface WidgetProps {
3030
additionalFilters?: CloudPulseMetricsAdditionalFilters[];
3131
dashboard?: Dashboard | undefined;
3232
duration: TimeDuration;
33+
isJweTokenFetching: boolean;
3334
jweToken?: JWEToken | undefined;
3435
manualRefreshTimeStamp?: number;
3536
metricDefinitions: MetricDefinitions | undefined;
@@ -55,6 +56,7 @@ export const RenderWidgets = React.memo(
5556
additionalFilters,
5657
dashboard,
5758
duration,
59+
isJweTokenFetching,
5860
jweToken,
5961
manualRefreshTimeStamp,
6062
metricDefinitions,
@@ -74,6 +76,7 @@ export const RenderWidgets = React.memo(
7476
availableMetrics: undefined,
7577
duration,
7678
errorLabel: 'Error occurred while loading data.',
79+
isJweTokenFetching: false,
7780
resourceIds: resources,
7881
resources: [],
7982
serviceType: dashboard?.service_type ?? '',
@@ -123,7 +126,7 @@ export const RenderWidgets = React.memo(
123126
if (
124127
!dashboard.service_type ||
125128
!Boolean(resources.length > 0) ||
126-
!jweToken?.token ||
129+
(!isJweTokenFetching && !jweToken?.token) ||
127130
!Boolean(resourceList?.length)
128131
) {
129132
return renderPlaceHolder(
@@ -162,6 +165,7 @@ export const RenderWidgets = React.memo(
162165
{...cloudPulseWidgetProperties}
163166
authToken={jweToken?.token}
164167
availableMetrics={availMetrics}
168+
isJweTokenFetching={isJweTokenFetching}
165169
resources={resourceList!}
166170
savePref={savePref}
167171
/>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ export const CloudPulseDashboardFilterBuilder = React.memo(
311311
container
312312
display={showFilter ? 'flex' : 'none'}
313313
item
314-
maxHeight={theme.spacing(22)}
314+
maxHeight={theme.spacing(23)}
315315
overflow={'auto'}
316316
rowGap={theme.spacing(2)}
317317
xs={12}

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ describe('CloudPulseResourcesSelect component tests', () => {
254254
expect(screen.getByText('Failed to fetch Resources.')).toBeInTheDocument();
255255
});
256256

257-
it('should be able to select limited resources', async () => {
257+
it('should be able to select limited resources and select/deselect all will not be available if resource are more than max resource selection limit', async () => {
258258
const user = userEvent.setup();
259259

260260
queryMocks.useResourcesQuery.mockReturnValue({
@@ -298,4 +298,36 @@ describe('CloudPulseResourcesSelect component tests', () => {
298298

299299
expect(queryByRole('option', { name: SELECT_ALL })).not.toBeInTheDocument();
300300
});
301+
302+
it('should be able to select all and deselect all the resources when number of resources are equal to resource limit', async () => {
303+
const user = userEvent.setup();
304+
305+
queryMocks.useResourcesQuery.mockReturnValue({
306+
data: linodeFactory.buildList(10),
307+
isError: false,
308+
isLoading: false,
309+
status: 'success',
310+
});
311+
312+
renderWithTheme(
313+
<CloudPulseResourcesSelect
314+
handleResourcesSelection={mockResourceHandler}
315+
label="Resources"
316+
region={'us-east'}
317+
resourceType={'linode'}
318+
/>
319+
);
320+
321+
await user.click(screen.getByRole('button', { name: 'Open' }));
322+
await user.click(screen.getByRole('option', { name: SELECT_ALL }));
323+
await user.click(screen.getByRole('option', { name: 'Deselect All' }));
324+
325+
expect(screen.getByLabelText('Resources')).toBeInTheDocument();
326+
327+
for (let i = 26; i <= 35; i++) {
328+
expect(
329+
screen.getByRole('option', { name: `linode-${i}` })
330+
).toHaveAttribute(ARIA_SELECTED, 'false');
331+
}
332+
});
301333
});

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import { Box, ListItem } from '@mui/material';
1+
import { Box } from '@mui/material';
22
import React from 'react';
33

44
import { Autocomplete } from 'src/components/Autocomplete/Autocomplete';
5-
import { SelectedIcon } from 'src/components/Autocomplete/Autocomplete.styles';
5+
import {
6+
SelectedIcon,
7+
StyledListItem,
8+
} from 'src/components/Autocomplete/Autocomplete.styles';
69
import { useFlags } from 'src/hooks/useFlags';
710
import { useResourcesQuery } from 'src/queries/cloudpulse/resources';
811
import { themes } from 'src/utilities/theme';
@@ -149,10 +152,20 @@ export const CloudPulseResourcesSelect = React.memo(
149152
const isResourceSelected = selectedResources?.some(
150153
(item) => item.label === option.label
151154
);
155+
156+
const isSelectAllORDeslectAllOption =
157+
option.label === 'Select All ' || option.label === 'Deselect All ';
158+
152159
const isMaxSelectionsReached =
153160
selectedResources &&
154161
selectedResources.length >= maxResourceSelectionLimit &&
155-
!isResourceSelected;
162+
!isResourceSelected &&
163+
!isSelectAllORDeslectAllOption;
164+
165+
const ListItem = isSelectAllORDeslectAllOption
166+
? StyledListItem
167+
: 'li';
168+
156169
return (
157170
<ListItem
158171
{...rest}

packages/manager/src/queries/cloudpulse/metrics.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const useCloudPulseMetricsQuery = (
1818
serviceType: string,
1919
request: CloudPulseMetricsRequest,
2020
obj: {
21-
authToken: string;
21+
authToken?: string;
2222
isFlags: boolean;
2323
label: string;
2424
timeStamp: number | undefined;
@@ -29,7 +29,7 @@ export const useCloudPulseMetricsQuery = (
2929

3030
const query = useQuery<CloudPulseMetricsResponse, APIError[]>({
3131
...queryFactory.metrics(
32-
obj.authToken,
32+
obj.authToken ?? '',
3333
obj.url,
3434
serviceType,
3535
request,

packages/manager/src/queries/cloudpulse/queries.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,6 @@ export const queryFactory = createQueryKeys(key, {
8484

8585
token: (serviceType: string | undefined, request: JWETokenPayLoad) => ({
8686
queryFn: () => getJWEToken(request, serviceType!),
87-
queryKey: [serviceType],
87+
queryKey: [serviceType, { resource_ids: request.resource_ids.sort() }],
8888
}),
8989
});

0 commit comments

Comments
 (0)