From c5ca91be09594eba313bb26976979dae814721dd Mon Sep 17 00:00:00 2001 From: stefanonardo Date: Tue, 7 Apr 2026 10:36:35 +0200 Subject: [PATCH] Fix VolumeSnapshot and VolumeSnapshotContent table sorting The Status, Size, and Source columns in the VolumeSnapshot table and Status and Size columns in VolumeSnapshotContent table were not sorting correctly because they referenced non-existent sort field names instead of using the sorts registry. --- .../volume-snapshot-content-details.tsx | 8 ++++---- .../volume-snapshot-content.tsx | 15 +++++++++------ .../volume-snapshot-details.tsx | 6 +++--- .../volume-snapshot/volume-snapshot.tsx | 17 +++++++++++------ .../console-app/src/status/snapshot.ts | 14 ++++---------- .../dashboard/inventory-card/utils.ts | 6 +++--- .../console-shared/src/sorts/snapshot.ts | 18 ++++++++++++++++-- .../public/components/factory/table-filters.ts | 4 ++-- frontend/public/components/factory/table.tsx | 14 ++++++++++++-- frontend/public/module/k8s/types.ts | 3 ++- 10 files changed, 66 insertions(+), 39 deletions(-) diff --git a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content-details.tsx b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content-details.tsx index 93eb74b1e50..b920525cbf4 100644 --- a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content-details.tsx +++ b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content-details.tsx @@ -20,9 +20,9 @@ import { } from '@console/internal/components/utils'; import { VolumeSnapshotClassModel, VolumeSnapshotModel } from '@console/internal/models'; import { referenceForModel, VolumeSnapshotContentKind } from '@console/internal/module/k8s'; -import { Status } from '@console/shared'; import PaneBody from '@console/shared/src/components/layout/PaneBody'; -import { volumeSnapshotStatus } from '../../status'; +import { Status } from '@console/shared/src/components/status/Status'; +import { snapshotStatus } from '@console/shared/src/sorts/snapshot'; const { editYaml, events } = navFactory; @@ -43,7 +43,7 @@ const Details: React.FC = ({ obj }) => { {t('console-app~Status')} - + @@ -116,7 +116,7 @@ const VolumeSnapshotContentDetailsPage: React.FC = (props) => return ( diff --git a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content.tsx b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content.tsx index f69aaa75fa3..db9162fcfc8 100644 --- a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content.tsx +++ b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-content.tsx @@ -12,8 +12,9 @@ import { TableColumn, RowProps, } from '@console/dynamic-plugin-sdk/src/lib-core'; -import { TableData } from '@console/internal/components/factory'; +import { sorts, TableData } from '@console/internal/components/factory'; import { useActiveColumns } from '@console/internal/components/factory/Table/active-columns-hook'; +import { sortResourceByValue } from '@console/internal/components/factory/Table/sort'; import { ResourceLink, ResourceKebab, @@ -28,9 +29,9 @@ import { VolumeSnapshotContentModel, } from '@console/internal/models'; import { referenceForModel, VolumeSnapshotContentKind } from '@console/internal/module/k8s'; -import { Status } from '@console/shared'; +import { snapshotStatus, Status } from '@console/shared'; import { Timestamp } from '@console/shared/src/components/datetime/Timestamp'; -import { snapshotStatusFilters, volumeSnapshotStatus } from '../../status'; +import { snapshotStatusFilters } from '../../status'; export const tableColumnInfo = [ { id: 'name' }, @@ -54,7 +55,7 @@ const Row: React.FC> = ({ obj }) => { - + {sizeMetrics} @@ -95,14 +96,16 @@ const VolumeSnapshotContentTable: React.FC = (p }, { title: t('console-app~Status'), - sort: 'snapshotStatus', + sort: (data, direction) => + data.sort(sortResourceByValue(direction, sorts.volumeSnapshotStatus)), transforms: [sortable], props: { className: tableColumnInfo[1].className }, id: tableColumnInfo[1].id, }, { title: t('console-app~Size'), - sort: 'volumeSnapshotSize', + sort: (data, direction) => + data.sort(sortResourceByValue(direction, sorts.volumeSnapshotContentSize)), transforms: [sortable], props: { className: tableColumnInfo[2].className }, id: tableColumnInfo[2].id, diff --git a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-details.tsx b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-details.tsx index 41c82d2987f..e0bb441dbf5 100644 --- a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-details.tsx +++ b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot-details.tsx @@ -31,10 +31,10 @@ import { Status, snapshotSource, FLAGS, + snapshotStatus, } from '@console/shared'; import PaneBody from '@console/shared/src/components/layout/PaneBody'; import { useFlag } from '@console/shared/src/hooks/flag'; -import { volumeSnapshotStatus } from '../../status'; const { editYaml, events } = navFactory; @@ -62,7 +62,7 @@ const Details: React.FC = ({ obj }) => { {t('console-app~Status')} - + @@ -146,7 +146,7 @@ const VolumeSnapshotDetailsPage: React.FC = (props) => { ); diff --git a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot.tsx b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot.tsx index df8b0d93475..e44be87623e 100644 --- a/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot.tsx +++ b/frontend/packages/console-app/src/components/volume-snapshot/volume-snapshot.tsx @@ -14,8 +14,9 @@ import { TableColumn, RowProps, } from '@console/dynamic-plugin-sdk/src/lib-core'; -import { TableData } from '@console/internal/components/factory'; +import { sorts, TableData } from '@console/internal/components/factory'; import { useActiveColumns } from '@console/internal/components/factory/Table/active-columns-hook'; +import { sortResourceByValue } from '@console/internal/components/factory/Table/sort'; import { ResourceLink, Kebab, @@ -45,10 +46,11 @@ import { getNamespace, snapshotSource, FLAGS, + snapshotStatus, } from '@console/shared'; import { Timestamp } from '@console/shared/src/components/datetime/Timestamp'; import { useFlag } from '@console/shared/src/hooks/flag'; -import { snapshotStatusFilters, volumeSnapshotStatus } from '../../status'; +import { snapshotStatusFilters } from '../../status'; const tableColumnInfo = [ { id: 'name' }, @@ -78,21 +80,24 @@ const getTableColumns = (t: TFunction, disableItems = {}): TableColumn + data.sort(sortResourceByValue(direction, sorts.volumeSnapshotStatus)), transforms: [sortable], props: { className: tableColumnInfo[2].className }, id: tableColumnInfo[2].id, }, { title: t('console-app~Size'), - sort: 'volumeSnapshotSize', + sort: (data, direction) => + data.sort(sortResourceByValue(direction, sorts.volumeSnapshotSize)), transforms: [sortable], props: { className: tableColumnInfo[3].className }, id: tableColumnInfo[3].id, }, { title: t('console-app~Source'), - sort: 'volumeSnapshotSource', + sort: (data, direction) => + data.sort(sortResourceByValue(direction, sorts.volumeSnapshotSource)), transforms: [sortable], props: { className: tableColumnInfo[4].className }, id: tableColumnInfo[4].id, @@ -154,7 +159,7 @@ const Row: React.FC - + {sizeMetrics} {!customData?.disableItems?.Source && ( diff --git a/frontend/packages/console-app/src/status/snapshot.ts b/frontend/packages/console-app/src/status/snapshot.ts index e430d11dbda..e20b4f7f179 100644 --- a/frontend/packages/console-app/src/status/snapshot.ts +++ b/frontend/packages/console-app/src/status/snapshot.ts @@ -1,19 +1,13 @@ -import { TFunction } from 'i18next'; -import { RowFilter } from '@console/dynamic-plugin-sdk/src/extensions/console-types'; -import { VolumeSnapshotStatus } from '@console/internal/module/k8s'; - -export const volumeSnapshotStatus = ({ status }: { status?: VolumeSnapshotStatus }) => { - const readyToUse = status?.readyToUse; - const isError = !!status?.error?.message; - return readyToUse ? 'Ready' : isError ? 'Error' : 'Pending'; -}; +import type { TFunction } from 'i18next'; +import type { RowFilter } from '@console/dynamic-plugin-sdk/src/extensions/console-types'; +import { snapshotStatus } from '@console/shared/src/sorts/snapshot'; export const snapshotStatusFilters = (t: TFunction): RowFilter[] => { return [ { filterGroupName: t('console-app~Status'), type: 'snapshot-status', - reducer: volumeSnapshotStatus, + reducer: snapshotStatus, filter: () => null, items: [ { id: 'Ready', title: 'Ready' }, diff --git a/frontend/packages/console-shared/src/components/dashboard/inventory-card/utils.ts b/frontend/packages/console-shared/src/components/dashboard/inventory-card/utils.ts index 17319e5dbfa..f65a05c18e9 100644 --- a/frontend/packages/console-shared/src/components/dashboard/inventory-card/utils.ts +++ b/frontend/packages/console-shared/src/components/dashboard/inventory-card/utils.ts @@ -1,7 +1,7 @@ import { nodeStatus } from '@console/app/src/status/node'; -import { volumeSnapshotStatus } from '@console/app/src/status/snapshot'; import { podPhaseFilterReducer } from '@console/internal/module/k8s'; -import { StatusGroupMapper } from './InventoryItem'; +import { snapshotStatus } from '@console/shared/src/sorts/snapshot'; +import type { StatusGroupMapper } from './InventoryItem'; import { InventoryStatusGroup } from './status-group'; const POD_PHASE_GROUP_MAPPING = { @@ -69,4 +69,4 @@ export const getPVCStatusGroups: StatusGroupMapper = (resources) => export const getPVStatusGroups: StatusGroupMapper = (resources) => getStatusGroups(resources, PV_STATUS_GROUP_MAPPING, (pv) => pv.status.phase, 'pv-status'); export const getVSStatusGroups: StatusGroupMapper = (resources) => - getStatusGroups(resources, VS_STATUS_GROUP_MAPPING, volumeSnapshotStatus, 'snapshot-status'); + getStatusGroups(resources, VS_STATUS_GROUP_MAPPING, snapshotStatus, 'status'); diff --git a/frontend/packages/console-shared/src/sorts/snapshot.ts b/frontend/packages/console-shared/src/sorts/snapshot.ts index 46768464810..de9ba58aee4 100644 --- a/frontend/packages/console-shared/src/sorts/snapshot.ts +++ b/frontend/packages/console-shared/src/sorts/snapshot.ts @@ -1,5 +1,15 @@ -import { convertToBaseValue } from '@console/internal/components/utils'; -import { VolumeSnapshotKind } from '@console/internal/module/k8s'; +import { convertToBaseValue } from '@console/internal/components/utils/units'; +import type { + VolumeSnapshotContentKind, + VolumeSnapshotKind, + VolumeSnapshotStatus, +} from '@console/internal/module/k8s'; + +export const snapshotStatus = ({ status }: { status?: VolumeSnapshotStatus }): string => { + const readyToUse = status?.readyToUse; + const isError = !!status?.error?.message; + return readyToUse ? 'Ready' : isError ? 'Error' : 'Pending'; +}; export const snapshotSize = (snapshot: VolumeSnapshotKind): number => { const size = snapshot?.status?.restoreSize; @@ -9,3 +19,7 @@ export const snapshotSize = (snapshot: VolumeSnapshotKind): number => { export const snapshotSource = (snapshot: VolumeSnapshotKind): string => snapshot.spec?.source?.persistentVolumeClaimName ?? snapshot.spec?.source?.volumeSnapshotContentName; + +export const snapshotContentSize = (snapshot: VolumeSnapshotContentKind): number => { + return snapshot?.status?.restoreSize ?? 0; +}; diff --git a/frontend/public/components/factory/table-filters.ts b/frontend/public/components/factory/table-filters.ts index 5001d34488c..a8c83ef948b 100644 --- a/frontend/public/components/factory/table-filters.ts +++ b/frontend/public/components/factory/table-filters.ts @@ -1,7 +1,7 @@ import * as _ from 'lodash-es'; import * as fuzzy from 'fuzzysearch'; import { nodeStatus } from '@console/app/src/status/node'; -import { volumeSnapshotStatus } from '@console/app/src/status/snapshot'; +import { snapshotStatus } from '@console/shared/src/sorts/snapshot'; import { getNodeRoles } from '@console/shared/src/selectors/node'; import { getLabelsAsString } from '@console/shared/src/utils/label-filter'; import { Alert, Rule } from '@console/dynamic-plugin-sdk/src/api/common-types'; @@ -220,7 +220,7 @@ export const tableFilters = (isExactSearch: boolean): FilterMap => { return true; } - const status = volumeSnapshotStatus(snapshot); + const status = snapshotStatus(snapshot); return statuses.selected.includes(status) || !_.includes(statuses.all, status); }, 'node-disk-name': (name, disks) => matchFn(name.selected?.[0], disks?.path), diff --git a/frontend/public/components/factory/table.tsx b/frontend/public/components/factory/table.tsx index 99a5c68bf5b..69f11c4ac77 100644 --- a/frontend/public/components/factory/table.tsx +++ b/frontend/public/components/factory/table.tsx @@ -25,7 +25,12 @@ import { useNavigate } from 'react-router-dom-v5-compat'; import { getMachinePhase } from '@console/shared/src/selectors/machine'; import { getMachineSetInstanceType } from '@console/shared/src/selectors/machineSet'; import { pvcUsed } from '@console/shared/src/sorts/pvc'; -import { snapshotSize, snapshotSource } from '@console/shared/src/sorts/snapshot'; +import { + snapshotContentSize, + snapshotSize, + snapshotSource, + snapshotStatus, +} from '@console/shared/src/sorts/snapshot'; import { ALL_NAMESPACES_KEY } from '@console/shared/src/constants/common'; import { getName } from '@console/shared/src/selectors/common'; import { useDeepCompareMemoize } from '@console/shared/src/hooks/deep-compare-memoize'; @@ -46,6 +51,7 @@ import { MachineKind, VolumeSnapshotKind, ClusterOperator, + VolumeSnapshotContentKind, } from '../../module/k8s/types'; import { getClusterOperatorStatus } from '../../module/k8s/cluster-operator'; import { getClusterOperatorVersion, getJobTypeAndCompletions } from '../../module/k8s'; @@ -55,7 +61,7 @@ import { podPhase, podReadiness, podRestarts } from '../../module/k8s/pods'; import { useTableData } from './table-data-hook'; import TableHeader from './Table/TableHeader'; -const sorts = { +export const sorts = { alertingRuleStateOrder, alertSeverityOrder, crdLatestVersion: (crd: CustomResourceDefinitionKind): string => getLatestVersionForCRD(crd), @@ -82,7 +88,11 @@ const sorts = { getTemplateInstanceStatus, machinePhase: (machine: MachineKind): string => getMachinePhase(machine), pvcUsed: (pvc: K8sResourceKind): number => pvcUsed(pvc), + volumeSnapshotStatus: (snapshot: VolumeSnapshotKind | VolumeSnapshotContentKind): string => + snapshotStatus(snapshot), volumeSnapshotSize: (snapshot: VolumeSnapshotKind): number => snapshotSize(snapshot), + volumeSnapshotContentSize: (snapshot: VolumeSnapshotContentKind): number => + snapshotContentSize(snapshot), volumeSnapshotSource: (snapshot: VolumeSnapshotKind): string => snapshotSource(snapshot), snapshotLastRestore: (snapshot: K8sResourceKind, { restores }) => restores[getName(snapshot)]?.status?.restoreTime, diff --git a/frontend/public/module/k8s/types.ts b/frontend/public/module/k8s/types.ts index 6fc1d390883..6fd720803e2 100644 --- a/frontend/public/module/k8s/types.ts +++ b/frontend/public/module/k8s/types.ts @@ -1078,6 +1078,7 @@ export type MachineHealthCheckKind = K8sResourceCommon & { export type VolumeSnapshotKind = K8sResourceCommon & { status?: VolumeSnapshotStatus & { boundVolumeSnapshotContentName?: string; + restoreSize?: string; }; spec: { source: { @@ -1091,6 +1092,7 @@ export type VolumeSnapshotKind = K8sResourceCommon & { export type VolumeSnapshotContentKind = K8sResourceCommon & { status: VolumeSnapshotStatus & { snapshotHandle?: string; + restoreSize?: number; }; spec: { volumeSnapshotRef: { @@ -1109,7 +1111,6 @@ export type VolumeSnapshotContentKind = K8sResourceCommon & { export type VolumeSnapshotStatus = { readyToUse: boolean; - restoreSize?: number; error?: { message: string; time: string;