diff --git a/ui/apps/everest/src/hooks/api/db-engines/useDbEngines.ts b/ui/apps/everest/src/hooks/api/db-engines/useDbEngines.ts index 5d01bf43d..d1c19ee8d 100644 --- a/ui/apps/everest/src/hooks/api/db-engines/useDbEngines.ts +++ b/ui/apps/everest/src/hooks/api/db-engines/useDbEngines.ts @@ -135,6 +135,26 @@ export type UseOperatorsUpgradePlanType = OperatorsUpgradePlan & { }>; }; +export const operatorUpgradePlanQueryFn = async ( + namespace: string, + dbEngines: DbEngine[] +) => { + const operatorUpgradePlan = await getOperatorsUpgradePlan(namespace); + const operatorsWithUpgrades = operatorUpgradePlan.upgrades.map( + (plan) => plan.name + ); + + return { + ...operatorUpgradePlan, + upToDate: dbEngines + .filter((engine) => !operatorsWithUpgrades.includes(engine.name)) + .map((engine) => ({ + name: engine.name, + currentVersion: engine.operatorVersion || '', + })), + }; +}; + export const useOperatorsUpgradePlan = ( namespace: string, dbEngines: DbEngine[], @@ -142,21 +162,6 @@ export const useOperatorsUpgradePlan = ( ) => useQuery({ queryKey: ['operatorUpgradePlan', namespace], - queryFn: async () => { - const operatorUpgradePlan = await getOperatorsUpgradePlan(namespace); - const operatorsWithUpgrades = operatorUpgradePlan.upgrades.map( - (plan) => plan.name - ); - - return { - ...operatorUpgradePlan, - upToDate: dbEngines - .filter((engine) => !operatorsWithUpgrades.includes(engine.name)) - .map((engine) => ({ - name: engine.name, - currentVersion: engine.operatorVersion || '', - })), - }; - }, + queryFn: () => operatorUpgradePlanQueryFn(namespace, dbEngines), ...options, }); diff --git a/ui/apps/everest/src/pages/settings/namespaces/namespace-details/cluster-status-table.tsx b/ui/apps/everest/src/pages/settings/namespaces/namespace-details/cluster-status-table.tsx index d83e34c0f..11e25fa1c 100644 --- a/ui/apps/everest/src/pages/settings/namespaces/namespace-details/cluster-status-table.tsx +++ b/ui/apps/everest/src/pages/settings/namespaces/namespace-details/cluster-status-table.tsx @@ -2,20 +2,28 @@ import { useCallback, useMemo, useRef, useState } from 'react'; import { MRT_ColumnDef } from 'material-react-table'; import { Button } from '@mui/material'; import { Table } from '@percona/ui-lib'; +import { beautifyDbTypeName, dbEngineToDbType } from '@percona/utils'; import semverCoerce from 'semver/functions/coerce'; import { DbEngineToolStatus, OperatorUpgradePendingAction, } from 'shared-types/dbEngines.types'; -import { DbCluster } from 'shared-types/dbCluster.types'; +import { DbCluster, DbClusterStatus, Spec } from 'shared-types/dbCluster.types'; import { ClusterStatusTableProps } from './types'; import { useDbClusters } from 'hooks/api/db-clusters/useDbClusters'; +import { DB_CLUSTER_STATUS_TO_BASE_STATUS } from 'pages/databases/DbClusterView.constants'; +import { beautifyDbClusterStatus } from 'pages/databases/DbClusterView.utils'; import { useUpdateDbClusterCrd, useUpdateDbClusterEngine, } from 'hooks/api/db-cluster/useUpdateDbCluster'; import { ConfirmDialog } from 'components/confirm-dialog/confirm-dialog'; import { Messages } from './messages'; +import StatusField from 'components/status-field'; + +type EnhancedDbList = OperatorUpgradePendingAction & { + db?: DbCluster; +}; const ClusterStatusTable = ({ namespace, @@ -36,6 +44,20 @@ const ClusterStatusTable = ({ const [openUpdateEngineDialog, setOpenUpdateEngineDialog] = useState(false); const selectedDbCluster = useRef(); const selectedDbEngineVersion = useRef(); + const enhancedDbList: EnhancedDbList[] = useMemo( + () => + pendingActions.map((action) => { + const db = dbClusters.find( + (cluster) => cluster.metadata.name === action.name + ); + + return { + ...action, + db, + }; + }), + [dbClusters, pendingActions] + ); const onDbClick = useCallback( (db: OperatorUpgradePendingAction) => { @@ -135,24 +157,45 @@ const ClusterStatusTable = ({ setOpenUpdateEngineDialog(false); }; - const columns = useMemo[]>( + const columns = useMemo[]>( () => [ + { + id: 'status', + header: 'Status', + accessorFn: (row) => row.db?.status?.status, + Cell: ({ cell }) => ( + ()} + statusMap={DB_CLUSTER_STATUS_TO_BASE_STATUS} + > + {beautifyDbClusterStatus(cell.getValue())} + + ), + }, { accessorKey: 'name', header: 'Database name', }, { - id: 'crd', - accessorFn: (row) => row.name, - header: 'CRD Version', + id: 'technology', + header: 'Technology', + accessorFn: (row) => row.db?.spec.engine, Cell: ({ cell }) => { - if (!dbClusters.length) { - return null; + const engine = cell.getValue(); + + if (!engine) { + return 'N/A'; } - const db = dbClusters.find( - (cluster) => cluster.metadata.name === cell.getValue() - ); + return `${beautifyDbTypeName(dbEngineToDbType(engine.type))} ${engine.version}`; + }, + }, + { + id: 'crd', + accessorFn: (row) => row.db, + header: 'CRD Version', + Cell: ({ cell }) => { + const db = cell.getValue(); return db?.status?.crVersion || 'N/A'; }, @@ -188,7 +231,7 @@ const ClusterStatusTable = ({ tableName={`${namespace}-upgrade-pending-actions`} noDataMessage="No pending actions" columns={columns} - data={pendingActions} + data={enhancedDbList} /> { const navigate = useNavigate(); const dbEngines = useDBEnginesForNamespaces(); - const namespacesData = dbEngines.map((item) => ({ + const operatorsUpgradePlan = useQueries({ + queries: dbEngines.map((item) => ({ + queryKey: ['operatorUpgradePlan', item.namespace], + queryFn: () => + operatorUpgradePlanQueryFn(item.namespace, item.data || []), + enabled: dbEngines.every((result) => result.isSuccess), + })), + }); + + const namespacesData: NamespaceInstance[] = dbEngines.map((item, idx) => ({ name: item.namespace, + upgradeAvailable: operatorsUpgradePlan[idx].isSuccess + ? operatorsUpgradePlan[idx].data.upgrades.length > 0 + : false, operator: item.isSuccess ? item.data?.reduce((prevVal, currVal, idx) => { if (idx === 0 || prevVal === '') { @@ -26,20 +41,38 @@ export const Namespaces = () => { : '-', })); - const isFetching = dbEngines.some((result) => result.isLoading); + const isFetching = + dbEngines.some((result) => result.isLoading) || + operatorsUpgradePlan.some((result) => result.isLoading); const columns = useMemo[]>( () => [ { accessorKey: 'name', header: 'Namespace', + Cell: ({ cell }) => {cell.getValue()}, }, { accessorKey: 'operator', header: 'Operator', + Cell: ({ cell, row }) => ( + + {cell.getValue()} + {row.original.upgradeAvailable && ( + + )} + + ), }, ], - [] + [navigate] ); return ( @@ -53,14 +86,6 @@ export const Namespaces = () => { }} columns={columns} data={namespacesData} - muiTableBodyRowProps={({ row }) => ({ - onClick: () => { - navigate(`/settings/namespaces/${row.original.name}`); - }, - sx: { - cursor: 'pointer', - }, - })} // enableRowActions // renderRowActionMenuItems={({ row, closeMenu }) => [ //