From 560fdffc35d746da8fd875e741c4362d97d1bf4c Mon Sep 17 00:00:00 2001 From: Aviv Turgeman Date: Mon, 16 Dec 2024 13:03:30 +0200 Subject: [PATCH] CNV-53212: Tree-view alignments Signed-off-by: Aviv Turgeman --- locales/en/plugin__kubevirt-plugin.json | 6 ++-- .../hooks/usePreviewFeaturesData.ts | 6 ++-- .../useVirtualMachineActionsProvider.test.tsx | 2 -- .../details/VirtualMachineNavPageTitle.tsx | 2 +- .../details/virtual-machine-page.scss | 1 + .../VMNotMigratableLabel.scss | 1 + .../VMNotMigratableLabel.tsx | 34 +++++++++---------- .../VMStatusConditionLabel.tsx | 1 + .../VirtualMachineStatus.tsx | 18 +++++----- .../tree/components/CreateProject.tsx | 9 ----- .../tree/components/TreeViewToolbar.tsx | 6 ++-- .../tree/hooks/useSyncClicksEffects.ts | 10 +++--- .../tree/icons/CollapseAllIcon.tsx | 14 ++++---- .../tree/icons/ExpandAllIcon.tsx | 8 ++--- .../tree/icons/TreeViewVirtualMachineIcon.tsx | 26 ++++++++++++++ src/views/virtualmachines/tree/icons/utils.ts | 4 +-- .../virtualmachines/tree/utils/utils.tsx | 1 - 17 files changed, 82 insertions(+), 67 deletions(-) create mode 100644 src/views/virtualmachines/tree/icons/TreeViewVirtualMachineIcon.tsx diff --git a/locales/en/plugin__kubevirt-plugin.json b/locales/en/plugin__kubevirt-plugin.json index 6762f4a08..099327298 100644 --- a/locales/en/plugin__kubevirt-plugin.json +++ b/locales/en/plugin__kubevirt-plugin.json @@ -489,7 +489,7 @@ "Enable automatic images download and update": "Enable automatic images download and update", "Enable automatic subscription for Red Hat Enterprise Linux VirtualMachines.\n": "Enable automatic subscription for Red Hat Enterprise Linux VirtualMachines.\n", "Enable Descheduler": "Enable Descheduler", - "Enable folders to VirtualMachine tree-view": "Enable folders to VirtualMachine tree-view", + "Enable folders in Virtual Machines tree view": "Enable folders in Virtual Machines tree view", "Enable guest system log access": "Enable guest system log access", "Enable headless mode": "Enable headless mode", "Enable memory density": "Enable memory density", @@ -497,7 +497,7 @@ "Enable preallocation": "Enable preallocation", "Enable predictive analytics": "Enable predictive analytics", "Enable the creation of LoadBalancer services for SSH connections to VirtualMachines. A load balancer must be configured": "Enable the creation of LoadBalancer services for SSH connections to VirtualMachines. A load balancer must be configured", - "Enable VirtualMachine tree-view": "Enable VirtualMachine tree-view", + "Enable Virtual Machines tree view": "Enable Virtual Machines tree view", "Enabled": "Enabled", "Enables access to the VirtualMachine guest system log. Wait a few seconds for logging to start before viewing the log.": "Enables access to the VirtualMachine guest system log. Wait a few seconds for logging to start before viewing the log.", "Enables access to the VirtualMachine's guest system log. Wait a few seconds for logging to start before viewing the log.": "Enables access to the VirtualMachine's guest system log. Wait a few seconds for logging to start before viewing the log.", @@ -1135,7 +1135,7 @@ "Show all": "Show all", "Show all alerts": "Show all alerts", "Show less": "Show less", - "Show projects with VirtualMachines": "Show projects with VirtualMachines", + "Show only projects with VirtualMachines": "Show only projects with VirtualMachines", "Show top 10": "Show top 10", "Show top 5": "Show top 5", "Show uncategorized VirtualMachines": "Show uncategorized VirtualMachines", diff --git a/src/views/clusteroverview/SettingsTab/PreviewFeaturesTab/hooks/usePreviewFeaturesData.ts b/src/views/clusteroverview/SettingsTab/PreviewFeaturesTab/hooks/usePreviewFeaturesData.ts index 561710e38..4a0590009 100644 --- a/src/views/clusteroverview/SettingsTab/PreviewFeaturesTab/hooks/usePreviewFeaturesData.ts +++ b/src/views/clusteroverview/SettingsTab/PreviewFeaturesTab/hooks/usePreviewFeaturesData.ts @@ -31,14 +31,14 @@ const usePreviewFeaturesData: UsePreviewFeaturesData = () => { const features = [ { externalLink: null, - id: TREE_VIEW_FOLDERS, - label: t('Enable VirtualMachine tree-view'), + id: TREE_VIEW, + label: t('Enable Virtual Machines tree view'), ...treeViewFeature, }, { externalLink: null, id: TREE_VIEW_FOLDERS, - label: t('Enable folders to VirtualMachine tree-view'), + label: t('Enable folders in Virtual Machines tree view'), ...treeViewFoldersFeature, }, ]; diff --git a/src/views/virtualmachines/actions/tests/useVirtualMachineActionsProvider.test.tsx b/src/views/virtualmachines/actions/tests/useVirtualMachineActionsProvider.test.tsx index d487372dd..379fbd54b 100644 --- a/src/views/virtualmachines/actions/tests/useVirtualMachineActionsProvider.test.tsx +++ b/src/views/virtualmachines/actions/tests/useVirtualMachineActionsProvider.test.tsx @@ -9,8 +9,6 @@ import { exampleRunningVirtualMachine } from './mocks'; jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ getGroupVersionKindForModel: jest.fn(() => ({})), k8sPatch: jest.fn(() => ({})), - // useFeatures: jest.fn(() => ({ featureEnabled: true })), - // useFeaturesConfigMap: jest.fn(() => ({ featuresConfigMapData: [[], true, null], isAdmin: true })), useFlag: jest.fn(() => true), useK8sModel: jest.fn(() => [[], true]), useK8sWatchResource: jest.fn(() => [[], true]), diff --git a/src/views/virtualmachines/details/VirtualMachineNavPageTitle.tsx b/src/views/virtualmachines/details/VirtualMachineNavPageTitle.tsx index c4e212212..9e7b43915 100644 --- a/src/views/virtualmachines/details/VirtualMachineNavPageTitle.tsx +++ b/src/views/virtualmachines/details/VirtualMachineNavPageTitle.tsx @@ -60,8 +60,8 @@ const VirtualMachineNavPageTitle: FC = ({ name, {vm?.status?.printableStatus} )} + - diff --git a/src/views/virtualmachines/details/virtual-machine-page.scss b/src/views/virtualmachines/details/virtual-machine-page.scss index 8cf06b739..ec23a9a3d 100644 --- a/src/views/virtualmachines/details/virtual-machine-page.scss +++ b/src/views/virtualmachines/details/virtual-machine-page.scss @@ -1,5 +1,6 @@ .vm-resource-label { vertical-align: middle; + margin-right: var(--pf-global--spacer--xs); } .VirtualMachineNavPage--tabs__main { diff --git a/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.scss b/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.scss index f5e64d8a2..c0adb453e 100644 --- a/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.scss +++ b/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.scss @@ -1,5 +1,6 @@ .migratable-label { vertical-align: middle; + width: fit-content; .pf-c-label__content { color: var(--pf-global--palette--blue-400); } diff --git a/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.tsx b/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.tsx index 9190d1e7b..c487c1063 100644 --- a/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.tsx +++ b/src/views/virtualmachines/list/components/VMNotMigratableLabel/VMNotMigratableLabel.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; +import React, { FC } from 'react'; import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt'; import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; import useSingleNodeCluster from '@kubevirt-utils/hooks/useSingleNodeCluster'; -import { Label, SplitItem } from '@patternfly/react-core'; +import { Label } from '@patternfly/react-core'; import { isLiveMigratable, printableVMStatus } from '@virtualmachines/utils'; import './VMNotMigratableLabel.scss'; @@ -12,25 +12,25 @@ type VMNotMigratableLabelProps = { vm: V1VirtualMachine; }; -const VMNotMigratableLabel: React.FC = ({ vm }) => { +const VMNotMigratableLabel: FC = ({ vm }) => { const { t } = useKubevirtTranslation(); const [isSingleNodeCluster] = useSingleNodeCluster(); const isMigratable = isLiveMigratable(vm, isSingleNodeCluster); - const isVMrunning = vm?.status?.printableStatus === printableVMStatus.Running; + const isRunning = vm?.status?.printableStatus === printableVMStatus.Running; - return isVMrunning && !isMigratable ? ( - - - - ) : null; + if (!isRunning || isMigratable) return null; + + return ( + + ); }; export default VMNotMigratableLabel; diff --git a/src/views/virtualmachines/list/components/VMStatusConditionLabel/VMStatusConditionLabel.tsx b/src/views/virtualmachines/list/components/VMStatusConditionLabel/VMStatusConditionLabel.tsx index 01694cdce..6f300377c 100644 --- a/src/views/virtualmachines/list/components/VMStatusConditionLabel/VMStatusConditionLabel.tsx +++ b/src/views/virtualmachines/list/components/VMStatusConditionLabel/VMStatusConditionLabel.tsx @@ -15,6 +15,7 @@ export const VMStatusConditionLabel: FC = memo((condi e.preventDefault(); }} color="grey" + textMaxWidth="6ch" > {condition?.type}={condition?.status} diff --git a/src/views/virtualmachines/list/components/VirtualMachineStatus/VirtualMachineStatus.tsx b/src/views/virtualmachines/list/components/VirtualMachineStatus/VirtualMachineStatus.tsx index d9e6450d5..63af98252 100644 --- a/src/views/virtualmachines/list/components/VirtualMachineStatus/VirtualMachineStatus.tsx +++ b/src/views/virtualmachines/list/components/VirtualMachineStatus/VirtualMachineStatus.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; +import React, { FC } from 'react'; import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt'; -import { HelperText, HelperTextItem, Split, SplitItem, Truncate } from '@patternfly/react-core'; +import { HelperText, HelperTextItem, Stack, StackItem } from '@patternfly/react-core'; import { getVMStatusIcon } from '../../../utils'; import VMNotMigratableLabel from '../VMNotMigratableLabel/VMNotMigratableLabel'; @@ -10,21 +10,19 @@ type VirtualMachinesPageStatusProps = { vm: V1VirtualMachine; }; -const VirtualMachineStatus: React.FC = ({ vm }) => { +const VirtualMachineStatus: FC = ({ vm }) => { const printableStatus = vm?.status?.printableStatus; const Icon = getVMStatusIcon(printableStatus); return ( - - + + - }> - - + }>{printableStatus} - + - + ); }; diff --git a/src/views/virtualmachines/tree/components/CreateProject.tsx b/src/views/virtualmachines/tree/components/CreateProject.tsx index 72585edf3..184e9eded 100644 --- a/src/views/virtualmachines/tree/components/CreateProject.tsx +++ b/src/views/virtualmachines/tree/components/CreateProject.tsx @@ -8,9 +8,6 @@ import { useActiveNamespace } from '@openshift-console/dynamic-plugin-sdk'; import { Button, ButtonVariant } from '@patternfly/react-core'; import { PlusCircleIcon } from '@patternfly/react-icons'; -import { PROJECT_SELECTOR_PREFIX } from '../utils/constants'; -import { setSelectedTreeItem } from '../utils/utils'; - const CreateProject: FC = () => { const { t } = useKubevirtTranslation(); const [_, setActiveNamespace] = useActiveNamespace(); @@ -23,12 +20,6 @@ const CreateProject: FC = () => { {...props} createdProject={(namespace) => { const nsName = getName(namespace); - setSelectedTreeItem({ - customBadgeContent: 0, - defaultExpanded: true, - id: `${PROJECT_SELECTOR_PREFIX}/${nsName}`, - name: nsName, - }); setActiveNamespace(nsName); }} /> diff --git a/src/views/virtualmachines/tree/components/TreeViewToolbar.tsx b/src/views/virtualmachines/tree/components/TreeViewToolbar.tsx index fde3a91c7..09b32d226 100644 --- a/src/views/virtualmachines/tree/components/TreeViewToolbar.tsx +++ b/src/views/virtualmachines/tree/components/TreeViewToolbar.tsx @@ -47,14 +47,14 @@ const TreeViewToolbar: FC = ({ closeComponent, onSearch }) - {t('Show projects with VirtualMachines')} + {t('Show only projects with VirtualMachines')} setShowEmptyProjects(checked ? SHOW : HIDE)} + onChange={(_, checked) => setShowEmptyProjects(checked ? HIDE : SHOW)} /> diff --git a/src/views/virtualmachines/tree/hooks/useSyncClicksEffects.ts b/src/views/virtualmachines/tree/hooks/useSyncClicksEffects.ts index 71ced4819..07af9a3fa 100644 --- a/src/views/virtualmachines/tree/hooks/useSyncClicksEffects.ts +++ b/src/views/virtualmachines/tree/hooks/useSyncClicksEffects.ts @@ -12,15 +12,15 @@ export const useSyncClicksEffects = (activeNamespace: string, loaded: boolean) = useEffect(() => { const pathname = location.pathname; if (loaded) { - const dataMap = treeDataMap.value; + const treeData = treeDataMap.value; if (pathname.startsWith(`/k8s/${ALL_NAMESPACES}`)) { - setSelectedTreeItem(dataMap[ALL_NAMESPACES_SESSION_KEY]); + setSelectedTreeItem(treeData[ALL_NAMESPACES_SESSION_KEY]); return; } const vmName = pathname.split('/')[5]; if (vmName) { - setSelectedTreeItem(dataMap[`${activeNamespace}/${vmName}`]); + setSelectedTreeItem(treeData[`${activeNamespace}/${vmName}`]); return; } @@ -28,12 +28,12 @@ export const useSyncClicksEffects = (activeNamespace: string, loaded: boolean) = const folderFilterName = queryParams.get('labels')?.split('=')?.[1]; if (folderFilterName) { setSelectedTreeItem( - dataMap[`${FOLDER_SELECTOR_PREFIX}/${activeNamespace}/${folderFilterName}`], + treeData[`${FOLDER_SELECTOR_PREFIX}/${activeNamespace}/${folderFilterName}`], ); return; } - setSelectedTreeItem(dataMap[`${PROJECT_SELECTOR_PREFIX}/${activeNamespace}`]); + setSelectedTreeItem(treeData[`${PROJECT_SELECTOR_PREFIX}/${activeNamespace}`]); } }, [activeNamespace, loaded, location.search, location.pathname]); }; diff --git a/src/views/virtualmachines/tree/icons/CollapseAllIcon.tsx b/src/views/virtualmachines/tree/icons/CollapseAllIcon.tsx index ca5cc94af..11957e03e 100644 --- a/src/views/virtualmachines/tree/icons/CollapseAllIcon.tsx +++ b/src/views/virtualmachines/tree/icons/CollapseAllIcon.tsx @@ -4,28 +4,28 @@ const CollapseAllIcon: FC = () => ( - + - - + + diff --git a/src/views/virtualmachines/tree/icons/ExpandAllIcon.tsx b/src/views/virtualmachines/tree/icons/ExpandAllIcon.tsx index 10f2ea21d..feb71fbd9 100644 --- a/src/views/virtualmachines/tree/icons/ExpandAllIcon.tsx +++ b/src/views/virtualmachines/tree/icons/ExpandAllIcon.tsx @@ -4,15 +4,15 @@ const ExpandAllIcon: FC = () => ( @@ -25,7 +25,7 @@ const ExpandAllIcon: FC = () => ( - + diff --git a/src/views/virtualmachines/tree/icons/TreeViewVirtualMachineIcon.tsx b/src/views/virtualmachines/tree/icons/TreeViewVirtualMachineIcon.tsx new file mode 100644 index 000000000..0bd402e86 --- /dev/null +++ b/src/views/virtualmachines/tree/icons/TreeViewVirtualMachineIcon.tsx @@ -0,0 +1,26 @@ +import React, { FC } from 'react'; + +const TreeViewVirtualMachineIcon: FC = () => ( + + + + + + + + + +); + +export default TreeViewVirtualMachineIcon; diff --git a/src/views/virtualmachines/tree/icons/utils.ts b/src/views/virtualmachines/tree/icons/utils.ts index c5cc696b8..ee95b2f2e 100644 --- a/src/views/virtualmachines/tree/icons/utils.ts +++ b/src/views/virtualmachines/tree/icons/utils.ts @@ -1,9 +1,9 @@ -import { VirtualMachineIcon } from '@patternfly/react-icons'; import { printableVMStatus } from '@virtualmachines/utils'; import PausedVirtualMachineIcon from './PausedVirtualMachineIcon'; import RunningVirtualMachineIcon from './RunningVirtualMachineIcon'; import StoppedVirtualMachineIcon from './StoppedVirtualMachineIcon'; +import TreeViewVirtualMachineIcon from './TreeViewVirtualMachineIcon'; const statusIconMapper = { [printableVMStatus.Paused]: PausedVirtualMachineIcon, @@ -13,6 +13,6 @@ const statusIconMapper = { export const statusIcon = new Proxy(statusIconMapper, { get(target, prop: string) { - return target[prop] ?? VirtualMachineIcon; + return target[prop] ?? TreeViewVirtualMachineIcon; }, }); diff --git a/src/views/virtualmachines/tree/utils/utils.tsx b/src/views/virtualmachines/tree/utils/utils.tsx index 56a76f42c..3fcf34cf7 100644 --- a/src/views/virtualmachines/tree/utils/utils.tsx +++ b/src/views/virtualmachines/tree/utils/utils.tsx @@ -17,7 +17,6 @@ import { VM_FOLDER_LABEL, } from './constants'; -export const vmsPerNamespaceMap = signal<{ [ns: string]: number }>(null); export const treeDataMap = signal>(null); export const selectedTreeItem = signal(null); export const setSelectedTreeItem = (selected: TreeViewDataItem) =>