Skip to content

Commit 765a0ba

Browse files
Upcoming: [UIE-9540] - Implement filter for GPU plans in plans panel (#13115)
* Upcoming: [UIE-9540] - Implement filter for GPU plans in plans panel * Added changeset: Implement filter for GPU plans in plans panel
1 parent 3c9e18f commit 765a0ba

File tree

11 files changed

+335
-180
lines changed

11 files changed

+335
-180
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+
Implement filter for GPU plans in plans panel ([#13115](https://github.com/linode/manager/pull/13115))

packages/manager/src/features/Kubernetes/KubernetesPlansPanel/KubernetesPlanContainer.tsx

Lines changed: 9 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -348,26 +348,6 @@ export const KubernetesPlanContainer = (
348348

349349
const shouldDisplayPagination = !shouldDisplayNoRegionSelectedMessage;
350350

351-
const dividerTables = planSelectionDividers
352-
.map((divider) => ({
353-
planType: divider.planType,
354-
tables: divider.tables
355-
.map((table) => ({
356-
filterOptions: table,
357-
plans: table.planFilter
358-
? paginatedPlans.filter(table.planFilter)
359-
: paginatedPlans,
360-
}))
361-
.filter((table) => table.plans.length > 0),
362-
}))
363-
.filter((divider) => divider.tables.length > 0);
364-
365-
const activeDivider = dividerTables.find(
366-
(divider) => divider.planType === planType
367-
);
368-
369-
const hasActiveGpuDivider = planType === 'gpu' && activeDivider;
370-
371351
return (
372352
<>
373353
<Grid container spacing={2}>
@@ -399,21 +379,6 @@ export const KubernetesPlanContainer = (
399379
text={tableEmptyState.message}
400380
variant="info"
401381
/>
402-
) : hasActiveGpuDivider ? (
403-
activeDivider.tables.map(({ filterOptions, plans }, idx) => (
404-
<React.Fragment
405-
key={`k8-mobile-${filterOptions.header ?? idx}`}
406-
>
407-
{filterOptions.header ? (
408-
<Grid size={12}>
409-
<Typography variant="h3">
410-
{filterOptions.header}
411-
</Typography>
412-
</Grid>
413-
) : null}
414-
{renderPlanSelection(plans)}
415-
</React.Fragment>
416-
))
417382
) : (
418383
renderPlanSelection(paginatedPlans)
419384
)}
@@ -425,31 +390,15 @@ export const KubernetesPlanContainer = (
425390
xs: 12,
426391
}}
427392
>
428-
{hasActiveGpuDivider ? (
429-
activeDivider.tables.map(
430-
({ filterOptions, plans }, idx) => (
431-
<KubernetesPlanSelectionTable
432-
filterOptions={filterOptions}
433-
key={`k8-plan-filter-${idx}`}
434-
plans={plans}
435-
renderPlanSelection={renderPlanSelection}
436-
shouldDisplayNoRegionSelectedMessage={
437-
shouldDisplayNoRegionSelectedMessage
438-
}
439-
/>
440-
)
441-
)
442-
) : (
443-
<KubernetesPlanSelectionTable
444-
filterEmptyStateMessage={tableEmptyState?.message}
445-
key={planType ?? 'all'}
446-
plans={paginatedPlans}
447-
renderPlanSelection={renderPlanSelection}
448-
shouldDisplayNoRegionSelectedMessage={
449-
shouldDisplayNoRegionSelectedMessage
450-
}
451-
/>
452-
)}
393+
<KubernetesPlanSelectionTable
394+
filterEmptyStateMessage={tableEmptyState?.message}
395+
key={planType ?? 'all'}
396+
plans={paginatedPlans}
397+
renderPlanSelection={renderPlanSelection}
398+
shouldDisplayNoRegionSelectedMessage={
399+
shouldDisplayNoRegionSelectedMessage
400+
}
401+
/>
453402
</Grid>
454403
</Hidden>
455404
</Grid>

packages/manager/src/features/Kubernetes/KubernetesPlansPanel/KubernetesPlansPanel.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { JSX } from 'react';
44

55
import { TabbedPanel } from 'src/components/TabbedPanel/TabbedPanel';
66
import { createDedicatedPlanFiltersRenderProp } from 'src/features/components/PlansPanel/DedicatedPlanFilters';
7+
import { createGPUPlanFilterRenderProp } from 'src/features/components/PlansPanel/GpuFilters';
78
import { PlanInformation } from 'src/features/components/PlansPanel/PlanInformation';
89
import {
910
determineInitialPlanCategoryTab,
@@ -153,11 +154,16 @@ export const KubernetesPlansPanel = (props: Props) => {
153154
hasMajorityOfPlansDisabled={hasMajorityOfPlansDisabled}
154155
onAdd={onAdd}
155156
onSelect={onSelect}
156-
planFilters={
157-
plan === 'dedicated'
158-
? createDedicatedPlanFiltersRenderProp()
159-
: undefined
160-
}
157+
planFilters={(() => {
158+
switch (plan) {
159+
case 'dedicated':
160+
return createDedicatedPlanFiltersRenderProp();
161+
case 'gpu':
162+
return createGPUPlanFilterRenderProp();
163+
default:
164+
return undefined;
165+
}
166+
})()}
161167
plans={plansForThisLinodeTypeClass}
162168
planType={plan}
163169
selectedId={selectedId}

packages/manager/src/features/components/PlansPanel/DedicatedPlanFilters.tsx

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@ import { Select } from '@linode/ui';
1212
import * as React from 'react';
1313

1414
import {
15-
PLAN_FILTER_GENERATION_ALL,
15+
PLAN_FILTER_ALL,
1616
PLAN_FILTER_GENERATION_G6,
1717
PLAN_FILTER_GENERATION_G7,
1818
PLAN_FILTER_GENERATION_G8,
19-
PLAN_FILTER_TYPE_ALL,
2019
PLAN_FILTER_TYPE_COMPUTE_OPTIMIZED,
2120
PLAN_FILTER_TYPE_GENERAL_PURPOSE,
2221
} from './constants';
23-
import { applyPlanFilters, supportsTypeFiltering } from './utils/planFilters';
22+
import {
23+
applyDedicatedPlanFilters,
24+
supportsTypeFiltering,
25+
} from './utils/planFilters';
2426

2527
import type {
2628
PlanFilterRenderArgs,
@@ -31,20 +33,20 @@ import type { PlanFilterGeneration, PlanFilterType } from './types/planFilters';
3133
import type { SelectOption } from '@linode/ui';
3234

3335
const GENERATION_OPTIONS: SelectOption<PlanFilterGeneration>[] = [
34-
{ label: 'All', value: PLAN_FILTER_GENERATION_ALL },
36+
{ label: 'All', value: PLAN_FILTER_ALL },
3537
{ label: 'G8 Dedicated', value: PLAN_FILTER_GENERATION_G8 },
3638
{ label: 'G7 Dedicated', value: PLAN_FILTER_GENERATION_G7 },
3739
{ label: 'G6 Dedicated', value: PLAN_FILTER_GENERATION_G6 },
3840
];
3941

4042
const TYPE_OPTIONS_WITH_SUBTYPES: SelectOption<PlanFilterType>[] = [
41-
{ label: 'All', value: PLAN_FILTER_TYPE_ALL },
43+
{ label: 'All', value: PLAN_FILTER_ALL },
4244
{ label: 'Compute Optimized', value: PLAN_FILTER_TYPE_COMPUTE_OPTIMIZED },
4345
{ label: 'General Purpose', value: PLAN_FILTER_TYPE_GENERAL_PURPOSE },
4446
];
4547

4648
const TYPE_OPTIONS_ALL_ONLY: SelectOption<PlanFilterType>[] = [
47-
{ label: 'All', value: PLAN_FILTER_TYPE_ALL },
49+
{ label: 'All', value: PLAN_FILTER_ALL },
4850
];
4951

5052
interface DedicatedPlanFiltersComponentProps {
@@ -59,12 +61,10 @@ const DedicatedPlanFiltersComponent = React.memo(
5961
const { disabled = false, onResult, plans, resetPagination } = props;
6062

6163
// Local state - persists automatically because component stays mounted
62-
const [generation, setGeneration] = React.useState<PlanFilterGeneration>(
63-
PLAN_FILTER_GENERATION_ALL
64-
);
64+
const [generation, setGeneration] =
65+
React.useState<PlanFilterGeneration>(PLAN_FILTER_ALL);
6566

66-
const [type, setType] =
67-
React.useState<PlanFilterType>(PLAN_FILTER_TYPE_ALL);
67+
const [type, setType] = React.useState<PlanFilterType>(PLAN_FILTER_ALL);
6868

6969
const typeFilteringSupported = supportsTypeFiltering(generation);
7070

@@ -109,11 +109,11 @@ const DedicatedPlanFiltersComponent = React.memo(
109109
// When clearing, default to "All" instead of undefined
110110
const newGeneration =
111111
(option?.value as PlanFilterGeneration | undefined) ??
112-
PLAN_FILTER_GENERATION_ALL;
112+
PLAN_FILTER_ALL;
113113
setGeneration(newGeneration);
114114

115115
// Reset type filter when generation changes
116-
setType(PLAN_FILTER_TYPE_ALL);
116+
setType(PLAN_FILTER_ALL);
117117
},
118118
[]
119119
);
@@ -124,25 +124,23 @@ const DedicatedPlanFiltersComponent = React.memo(
124124
option: null | SelectOption<number | string>
125125
) => {
126126
setType(
127-
(option?.value as PlanFilterType | undefined) ?? PLAN_FILTER_TYPE_ALL
127+
(option?.value as PlanFilterType | undefined) ?? PLAN_FILTER_ALL
128128
);
129129
},
130130
[]
131131
);
132132

133133
const filteredPlans = React.useMemo(() => {
134-
const normalizedType = typeFilteringSupported
135-
? type
136-
: PLAN_FILTER_TYPE_ALL;
137-
return applyPlanFilters(plans, generation, normalizedType);
134+
const normalizedType = typeFilteringSupported ? type : PLAN_FILTER_ALL;
135+
return applyDedicatedPlanFilters(plans, generation, normalizedType);
138136
}, [generation, plans, type, typeFilteringSupported]);
139137

140138
const selectedGenerationOption = React.useMemo(() => {
141139
return GENERATION_OPTIONS.find((opt) => opt.value === generation) ?? null;
142140
}, [generation]);
143141

144142
const selectedTypeOption = React.useMemo(() => {
145-
const displayType = typeFilteringSupported ? type : PLAN_FILTER_TYPE_ALL;
143+
const displayType = typeFilteringSupported ? type : PLAN_FILTER_ALL;
146144
return typeOptions.find((opt) => opt.value === displayType) ?? null;
147145
}, [type, typeFilteringSupported, typeOptions]);
148146

@@ -155,6 +153,7 @@ const DedicatedPlanFiltersComponent = React.memo(
155153
flexWrap: 'wrap',
156154
gap: '19px',
157155
marginBottom: 16,
156+
marginTop: -16,
158157
}}
159158
>
160159
<Select
@@ -189,7 +188,7 @@ const DedicatedPlanFiltersComponent = React.memo(
189188
return {
190189
filteredPlans,
191190
filterUI,
192-
hasActiveFilters: generation !== PLAN_FILTER_GENERATION_ALL,
191+
hasActiveFilters: generation !== PLAN_FILTER_ALL,
193192
};
194193
}, [
195194
disabled,

0 commit comments

Comments
 (0)