From 6b21a3a32daa344f317f39237746d84c4515d3b7 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Tue, 26 Mar 2024 16:02:50 -0400 Subject: [PATCH 1/3] implement landing page changes --- .../PlacementGroupsAssignLinodesDrawer.tsx | 4 +- .../PlacementGroupsEditDrawer.tsx | 4 +- .../PlacementGroupsLanding.tsx | 67 +++++++++++++------ .../PlacementGroupsRow.test.tsx | 2 +- .../PlacementGroupsRow.tsx | 41 ++++++++---- .../features/PlacementGroups/utils.test.ts | 6 +- .../src/features/PlacementGroups/utils.ts | 2 +- 7 files changed, 85 insertions(+), 41 deletions(-) diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx index b53cf3edc2b..821645bd3af 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx @@ -20,7 +20,7 @@ import { import { LinodeSelect } from '../Linodes/LinodeSelect/LinodeSelect'; import { - getAffinityEnforcement, + getAffinityTypeEnforcement, getLinodesFromAllPlacementGroups, } from './utils'; @@ -139,7 +139,7 @@ export const PlacementGroupsAssignLinodesDrawer = ( {generalError ? : null} Affinity Enforcement: - {getAffinityEnforcement(selectedPlacementGroup.is_strict)} + {getAffinityTypeEnforcement(selectedPlacementGroup.is_strict)}
diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsEditDrawer.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsEditDrawer.tsx index 121571edcc9..b2424096141 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsEditDrawer.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsEditDrawer.tsx @@ -23,7 +23,7 @@ import { import { getFormikErrorsFromAPIErrors } from 'src/utilities/formikErrorUtils'; import { scrollErrorIntoView } from 'src/utilities/scrollErrorIntoView'; -import { getAffinityEnforcement } from './utils'; +import { getAffinityTypeEnforcement } from './utils'; import type { PlacementGroupsEditDrawerProps } from './types'; import type { UpdatePlacementGroupPayload } from '@linode/api-v4'; @@ -137,7 +137,7 @@ export const PlacementGroupsEditDrawer = ( Affinity Enforcement: - {getAffinityEnforcement(placementGroup.is_strict)} + {getAffinityTypeEnforcement(placementGroup.is_strict)} diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx index 815e3e62c11..26b20294410 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { useHistory } from 'react-router-dom'; import { CircleProgress } from 'src/components/CircleProgress'; +import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField'; import { ErrorState } from 'src/components/ErrorState/ErrorState'; import { Hidden } from 'src/components/Hidden'; import { IconButton } from 'src/components/IconButton'; @@ -14,8 +15,8 @@ import { TableBody } from 'src/components/TableBody'; import { TableCell } from 'src/components/TableCell'; import { TableHead } from 'src/components/TableHead'; import { TableRow } from 'src/components/TableRow'; +import { TableRowEmpty } from 'src/components/TableRowEmpty/TableRowEmpty'; import { TableSortCell } from 'src/components/TableSortCell/TableSortCell'; -import { TextField } from 'src/components/TextField'; import { getRestrictedResourceText } from 'src/features/Account/utils'; import { useOrder } from 'src/hooks/useOrder'; import { usePagination } from 'src/hooks/usePagination'; @@ -57,13 +58,16 @@ export const PlacementGroupsLanding = React.memo(() => { filter['label'] = { '+contains': query }; } - const params = { - page: pagination.page, - page_size: pagination.pageSize, - }; - - const { data: placementGroups, error, isLoading } = usePlacementGroupsQuery( - params, + const { + data: placementGroups, + error, + isFetching, + isLoading, + } = usePlacementGroupsQuery( + { + page: pagination.page, + page_size: pagination.pageSize, + }, filter ); @@ -101,7 +105,7 @@ export const PlacementGroupsLanding = React.memo(() => { return ; } - if (placementGroups?.results === 0) { + if (placementGroups?.results === 0 && query === '') { return ( <> { onButtonClick={handleCreatePlacementGroup} title="Placement Groups" /> - - setQuery('')} - size="small" - sx={{ padding: 'unset' }} - > - - + {isFetching ? ( + + ) : ( + setQuery('')} + size="small" + sx={{ padding: 'unset' }} + > + + + )} ), }} + debounceTime={250} hideLabel label="Filter" onChange={(e) => setQuery(e.target.value)} @@ -176,10 +185,29 @@ export const PlacementGroupsLanding = React.memo(() => { direction={order} handleClick={handleOrderChange} label="label" - sx={{ width: '40%' }} + sx={{ width: '20%' }} > Label + + Affinity Type + + + + Affinity Type Enforcement + + Linodes { + {placementGroups?.data.length === 0 && } {placementGroups?.data.map((placementGroup) => ( diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.test.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.test.tsx index 4b2ed2bc05f..149635793be 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.test.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.test.tsx @@ -88,7 +88,7 @@ describe('PlacementGroupsLanding', () => { ); expect(getByTestId('link-to-placement-group-1')).toHaveTextContent( - 'group 1 (Anti-affinity)' + 'group 1' ); expect(getByText('Non-compliant')).toBeInTheDocument(); expect(getByTestId('placement-group-1-assigned-linodes')).toHaveTextContent( diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx index 7a7135024fb..2a573f3335a 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx @@ -12,6 +12,7 @@ import { TextTooltip } from 'src/components/TextTooltip'; import { Typography } from 'src/components/Typography'; import { usePlacementGroupData } from 'src/hooks/usePlacementGroupsData'; +import { getAffinityTypeEnforcement } from '../utils'; import { StyledWarningIcon } from './PlacementGroupsRow.styles'; import type { PlacementGroup } from '@linode/api-v4'; @@ -31,7 +32,13 @@ export const PlacementGroupsRow = React.memo( handleEditPlacementGroup, placementGroup, }: PlacementGroupsRowProps) => { - const { affinity_type, id, is_compliant, label } = placementGroup; + const { + affinity_type, + id, + is_compliant, + is_strict, + label, + } = placementGroup; const { assignedLinodes, linodesCount, region } = usePlacementGroupData({ placementGroup, }); @@ -57,7 +64,7 @@ export const PlacementGroupsRow = React.memo( style={{ marginRight: 8 }} to={`/placement-groups/${id}`} > - {label} ({AFFINITY_TYPES[affinity_type]}) + {label} {!is_compliant && ( @@ -66,18 +73,26 @@ export const PlacementGroupsRow = React.memo( )} + {AFFINITY_TYPES[affinity_type]} + + {getAffinityTypeEnforcement(is_strict)} + - - {assignedLinodes?.map((linode, idx) => ( - {linode.label} - ))} - - } - displayText={`${linodesCount}`} - minWidth={200} - /> + {assignedLinodes?.length === 0 ? ( + '0' + ) : ( + + {assignedLinodes?.map((linode, idx) => ( + {linode.label} + ))} + + } + displayText={`${linodesCount}`} + minWidth={200} + /> + )}   of {region?.maximum_vms_per_pg} diff --git a/packages/manager/src/features/PlacementGroups/utils.test.ts b/packages/manager/src/features/PlacementGroups/utils.test.ts index dca7ea1a3ef..cfdaeb70ef3 100644 --- a/packages/manager/src/features/PlacementGroups/utils.test.ts +++ b/packages/manager/src/features/PlacementGroups/utils.test.ts @@ -2,7 +2,7 @@ import { placementGroupFactory, regionFactory } from 'src/factories'; import { affinityTypeOptions, - getAffinityEnforcement, + getAffinityTypeEnforcement, getLinodesFromAllPlacementGroups, getPlacementGroupLinodeCount, hasPlacementGroupReachedCapacity, @@ -109,11 +109,11 @@ describe('getLinodesFromAllPlacementGroups', () => { describe('getAffinityEnforcement', () => { it('returns "Strict" if `is_strict` is true', () => { - expect(getAffinityEnforcement(true)).toBe('Strict'); + expect(getAffinityTypeEnforcement(true)).toBe('Strict'); }); it('returns "Flexible" if `is_strict` is false', () => { - expect(getAffinityEnforcement(false)).toBe('Flexible'); + expect(getAffinityTypeEnforcement(false)).toBe('Flexible'); }); }); diff --git a/packages/manager/src/features/PlacementGroups/utils.ts b/packages/manager/src/features/PlacementGroups/utils.ts index d95101aa4ed..f0b323831bc 100644 --- a/packages/manager/src/features/PlacementGroups/utils.ts +++ b/packages/manager/src/features/PlacementGroups/utils.ts @@ -10,7 +10,7 @@ import type { /** * Helper to get the affinity enforcement readable string. */ -export const getAffinityEnforcement = ( +export const getAffinityTypeEnforcement = ( is_strict: boolean ): AffinityEnforcement => { return is_strict ? 'Strict' : 'Flexible'; From 31b93e6cfa0cb61436e5347a817322bd89a6ec7f Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Tue, 26 Mar 2024 17:37:43 -0400 Subject: [PATCH 2/3] changeset --- .../.changeset/pr-10318-upcoming-features-1711489006250.md | 5 +++++ .../PlacementGroupsLanding/PlacementGroupsRow.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 packages/manager/.changeset/pr-10318-upcoming-features-1711489006250.md diff --git a/packages/manager/.changeset/pr-10318-upcoming-features-1711489006250.md b/packages/manager/.changeset/pr-10318-upcoming-features-1711489006250.md new file mode 100644 index 00000000000..6e9cb8591cf --- /dev/null +++ b/packages/manager/.changeset/pr-10318-upcoming-features-1711489006250.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Update Placement Groups landing page table ([#10318](https://github.com/linode/manager/pull/10318)) diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx index 2a573f3335a..efda7adc492 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx @@ -93,7 +93,7 @@ export const PlacementGroupsRow = React.memo( minWidth={200} /> )} -   of {region?.maximum_vms_per_pg} +   of {region?.maximum_vms_per_pg ?? 'unknown'} {region?.label} From 9424a3430975a885f8dca61839b0ccc26bee3058 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 28 Mar 2024 10:34:19 -0400 Subject: [PATCH 3/3] Address all feedback --- .../PlacementGroupsLanding.tsx | 47 ++++++++++--------- .../PlacementGroupsRow.tsx | 4 +- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx index 26b20294410..93a6f7fef2f 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsLanding.tsx @@ -1,4 +1,5 @@ import CloseIcon from '@mui/icons-material/Close'; +import { useMediaQuery, useTheme } from '@mui/material'; import * as React from 'react'; import { useHistory } from 'react-router-dom'; @@ -37,10 +38,12 @@ const preferenceKey = 'placement-groups'; export const PlacementGroupsLanding = React.memo(() => { const history = useHistory(); const pagination = usePagination(1, preferenceKey); + const theme = useTheme(); const [query, setQuery] = React.useState(''); const [selectedPlacementGroup, setSelectedPlacementGroup] = React.useState< PlacementGroup | undefined >(undefined); + const matchesSmDown = useMediaQuery(theme.breakpoints.down('md')); const { handleOrderChange, order, orderBy } = useOrder( { order: 'asc', @@ -154,18 +157,16 @@ export const PlacementGroupsLanding = React.memo(() => { InputProps={{ endAdornment: query && ( - {isFetching ? ( - - ) : ( - setQuery('')} - size="small" - sx={{ padding: 'unset' }} - > - - - )} + {isFetching && } + + setQuery('')} + size="small" + sx={{ padding: 'unset' }} + > + + ), }} @@ -185,18 +186,20 @@ export const PlacementGroupsLanding = React.memo(() => { direction={order} handleClick={handleOrderChange} label="label" - sx={{ width: '20%' }} + sx={{ width: matchesSmDown ? '40%' : '20%' }} > Label - - Affinity Type - + + + Affinity Type + + { - {placementGroups?.data.length === 0 && } + {placementGroups?.data.length === 0 && } {placementGroups?.data.map((placementGroup) => ( diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx index efda7adc492..7ab28641b81 100644 --- a/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx +++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsLanding/PlacementGroupsRow.tsx @@ -73,7 +73,9 @@ export const PlacementGroupsRow = React.memo( )} - {AFFINITY_TYPES[affinity_type]} + + {AFFINITY_TYPES[affinity_type]} + {getAffinityTypeEnforcement(is_strict)}