From 24d3e5b4642dbd66c21208506e98ea20c5595e62 Mon Sep 17 00:00:00 2001 From: Ugo Palatucci Date: Wed, 9 Oct 2024 10:50:59 +0200 Subject: [PATCH] CNV-41403: localize loading --- .../EnvironmentEditor/EnvironmentForm.tsx | 20 +-- .../components/EnvironmentEditor.tsx | 133 ++------------- .../components/EnvironmentSelectResource.tsx | 157 ++++++++++++++++++ .../vm/hooks/disk/useDisksSources.ts | 16 +- .../components/tables/disk/DiskList.tsx | 8 +- .../components/tables/disk/DiskRow.tsx | 22 ++- 6 files changed, 212 insertions(+), 144 deletions(-) create mode 100644 src/utils/components/EnvironmentEditor/components/EnvironmentSelectResource.tsx diff --git a/src/utils/components/EnvironmentEditor/EnvironmentForm.tsx b/src/utils/components/EnvironmentEditor/EnvironmentForm.tsx index 5d87df100..7a7727da3 100644 --- a/src/utils/components/EnvironmentEditor/EnvironmentForm.tsx +++ b/src/utils/components/EnvironmentEditor/EnvironmentForm.tsx @@ -3,6 +3,8 @@ import { useImmer } from 'use-immer'; import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt'; import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; +import { getNamespace } from '@kubevirt-utils/resources/shared'; +import { isEmpty } from '@kubevirt-utils/utils/utils'; import { Button, Form } from '@patternfly/react-core'; import { PlusCircleIcon } from '@patternfly/react-icons'; @@ -11,7 +13,6 @@ import EnvironmentFormActions from './components/EnvironmentFormActions'; import EnvironmentFormSkeleton from './components/EnvironmentFormSkeleton'; import EnvironmentFormTitle from './components/EnvironmentFormTitle'; import useEnvironments from './hooks/useEnvironments'; -import useEnvironmentsResources from './hooks/useEnvironmentsResources'; import './EnvironmentForm.scss'; @@ -25,15 +26,6 @@ const EnvironmentForm: FC = ({ onEditChange, updateVM, vm const [temporaryVM, setTemporaryVM] = useImmer(vm); const { t } = useKubevirtTranslation(); - const ns = vm?.metadata?.namespace; - - const { - configMaps, - error: loadError, - loaded, - secrets, - serviceAccounts, - } = useEnvironmentsResources(ns); const { edited, @@ -55,7 +47,7 @@ const EnvironmentForm: FC = ({ onEditChange, updateVM, vm [environments], ); - if (!loaded) return ; + if (isEmpty(vm)) return ; return ( <> @@ -75,18 +67,16 @@ const EnvironmentForm: FC = ({ onEditChange, updateVM, vm {environments.map((environment, index) => ( ))} @@ -110,7 +100,7 @@ const EnvironmentForm: FC = ({ onEditChange, updateVM, vm }) } closeError={() => setFormError(null)} - error={loadError || formError} + error={formError} isSaveDisabled={!edited || !environments.every((env) => env.name)} onSave={() => updateVM(temporaryVM)} /> diff --git a/src/utils/components/EnvironmentEditor/components/EnvironmentEditor.tsx b/src/utils/components/EnvironmentEditor/components/EnvironmentEditor.tsx index 5288466ae..ad932a976 100644 --- a/src/utils/components/EnvironmentEditor/components/EnvironmentEditor.tsx +++ b/src/utils/components/EnvironmentEditor/components/EnvironmentEditor.tsx @@ -1,151 +1,54 @@ -import * as React from 'react'; +import React, { FC } from 'react'; -import { - IoK8sApiCoreV1ConfigMap, - IoK8sApiCoreV1Secret, - IoK8sApiCoreV1ServiceAccount, -} from '@kubevirt-ui/kubevirt-api/kubernetes/models'; import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; -import { Button, Divider, TextInput, Tooltip } from '@patternfly/react-core'; -import { Select, SelectGroup, SelectVariant } from '@patternfly/react-core/deprecated'; +import { Button, TextInput, Tooltip } from '@patternfly/react-core'; import { MinusCircleIcon } from '@patternfly/react-icons'; -import { EnvironmentKind, MapKindToAbbr } from '../constants'; -import { EnvironmentOption } from '../utils'; +import { EnvironmentKind } from '../constants'; -import EnvironmentSelectOption from './EnvironmentSelectOption'; +import EnvironmentSelectResource from './EnvironmentSelectResource'; import './EnvironmentEditor.scss'; + type EnvironmentEditorProps = { - configMaps: IoK8sApiCoreV1ConfigMap[]; diskName: string; environmentName?: string; environmentNamesSelected: string[]; id: number; kind?: EnvironmentKind; + namespace: string; onChange: (diskName: string, name: string, serial: string, kind: EnvironmentKind) => void; onRemove?: (diskName: string) => void; - secrets: IoK8sApiCoreV1Secret[]; serial?: string; - serviceAccounts: IoK8sApiCoreV1ServiceAccount[]; }; -const EnvironmentEditor: React.FC = ({ - configMaps, +const EnvironmentEditor: FC = ({ diskName, environmentName, environmentNamesSelected, id, kind, + namespace, onChange, onRemove, - secrets, serial, - serviceAccounts, }) => { const { t } = useKubevirtTranslation(); - const [isOpen, setOpen] = React.useState(false); - - const onFilter = React.useCallback( - (event: React.ChangeEvent, value: string): React.ReactElement[] => { - const filteredSecrets = secrets - ?.filter((secret) => secret.metadata.name.includes(value)) - ?.map((secret) => ( - - )); - - const filteredConfigMaps = configMaps - ?.filter((configMap) => configMap.metadata.name.includes(value)) - ?.map((configMap) => ( - - )); - - const filteredServiceAccounts = serviceAccounts - ?.filter((serviceAccount) => serviceAccount.metadata.name.includes(value)) - ?.map((serviceAccount) => ( - - )); - - return [...filteredSecrets, ...filteredConfigMaps, ...filteredServiceAccounts]; - }, - [configMaps, environmentNamesSelected, secrets, serviceAccounts], - ); return (
- +
+
void; + serial: string; +}; + +const EnvironmentSelectResource: FC = ({ + diskName, + environmentName, + environmentNamesSelected, + kind, + namespace, + onChange, + serial, +}) => { + const { t } = useKubevirtTranslation(); + + const [isOpen, setOpen] = useState(false); + + const { + configMaps, + error: loadError, + loaded, + secrets, + serviceAccounts, + } = useEnvironmentsResources(namespace); + + const onFilter = useCallback( + (event: ChangeEvent, value: string): ReactElement[] => { + const filteredSecrets = secrets + ?.filter((secret) => secret.metadata.name.includes(value)) + ?.map((secret) => ( + + )); + + const filteredConfigMaps = configMaps + ?.filter((configMap) => configMap.metadata.name.includes(value)) + ?.map((configMap) => ( + + )); + + const filteredServiceAccounts = serviceAccounts + ?.filter((serviceAccount) => serviceAccount.metadata.name.includes(value)) + ?.map((serviceAccount) => ( + + )); + + return [...filteredSecrets, ...filteredConfigMaps, ...filteredServiceAccounts]; + }, + [configMaps, environmentNamesSelected, secrets, serviceAccounts], + ); + + if (!loaded) return ; + + if (loadError) + return ( + +
{loadError?.message}
+
+ ); + + return ( + + ); +}; + +export default EnvironmentSelectResource; diff --git a/src/utils/resources/vm/hooks/disk/useDisksSources.ts b/src/utils/resources/vm/hooks/disk/useDisksSources.ts index b3e01142d..4dedb8b9d 100644 --- a/src/utils/resources/vm/hooks/disk/useDisksSources.ts +++ b/src/utils/resources/vm/hooks/disk/useDisksSources.ts @@ -22,13 +22,19 @@ const useDisksSources = (vm: V1VirtualMachine) => { [pvcWatchesResult], ); - const loaded = Object.values(pvcWatchesResult).every( - (watch) => watch.loaded || !isEmpty(watch.loadError), + const loaded = useMemo( + () => + Object.values(pvcWatchesResult).every((watch) => watch.loaded || !isEmpty(watch.loadError)), + [pvcWatchesResult], ); - const loadingError = Object.values(pvcWatchesResult).find((watch) => { - return !isEmpty(watch.loadError) && watch.loadError?.code !== 404; - }); + const loadingError = useMemo( + () => + Object.values(pvcWatchesResult).find((watch) => { + return !isEmpty(watch.loadError) && watch.loadError?.code !== 404; + }), + [pvcWatchesResult], + ); return { loaded, loadingError, pvcs }; }; diff --git a/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskList.tsx b/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskList.tsx index 679e13ad8..b73f1d207 100644 --- a/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskList.tsx +++ b/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskList.tsx @@ -34,7 +34,7 @@ type DiskListProps = { const DiskList: FC = ({ customize = false, onDiskUpdate, vm, vmi }) => { const { createModal } = useModal(); const columns = useDiskColumns(); - const [disks, loaded, loadError] = useDisksTableData(vm, vmi); + const [disks, sourcesLoaded, loadError] = useDisksTableData(vm, vmi); const filters = useDisksFilters(); const [data, filteredData, onFilterChange] = useListPageFilter(disks, filters); @@ -63,7 +63,7 @@ const DiskList: FC = ({ customize = false, onDiskUpdate, vm, vmi @@ -76,10 +76,10 @@ const DiskList: FC = ({ customize = false, onDiskUpdate, vm, vmi
diff --git a/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskRow.tsx b/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskRow.tsx index a12a26398..1a70d5efc 100644 --- a/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskRow.tsx +++ b/src/views/virtualmachines/details/tabs/configuration/storage/components/tables/disk/DiskRow.tsx @@ -7,7 +7,14 @@ import { NameWithPercentages } from '@kubevirt-utils/resources/vm/hooks/types'; import { DiskRowDataLayout } from '@kubevirt-utils/resources/vm/utils/disk/constants'; import { readableSizeUnit } from '@kubevirt-utils/utils/units'; import { ResourceLink, RowProps, TableData } from '@openshift-console/dynamic-plugin-sdk'; -import { Label, Popover, PopoverPosition, Stack, StackItem } from '@patternfly/react-core'; +import { + Label, + Popover, + PopoverPosition, + Skeleton, + Stack, + StackItem, +} from '@patternfly/react-core'; import { isPVCSource } from './utils/helpers'; import DiskRowActions from './DiskRowActions'; @@ -20,6 +27,7 @@ const DiskRow: FC< customize?: boolean; onSubmit?: (updatedVM: V1VirtualMachine) => Promise; provisioningPercentages: NameWithPercentages; + sourcesLoaded?: boolean; vm: V1VirtualMachine; vmi?: V1VirtualMachineInstance; } @@ -27,12 +35,14 @@ const DiskRow: FC< > = ({ activeColumnIDs, obj, - rowData: { customize = false, onSubmit, provisioningPercentages, vm, vmi }, + rowData: { customize = false, onSubmit, provisioningPercentages, sourcesLoaded, vm, vmi }, }) => { const { t } = useKubevirtTranslation(); const provisioningPercentage = provisioningPercentages?.[obj?.source]; + const hasPVC = isPVCSource(obj); + return ( <> @@ -72,15 +82,17 @@ const DiskRow: FC< - {isPVCSource(obj) ? ( + {sourcesLoaded && hasPVC && ( - ) : ( - obj?.source )} + + {!sourcesLoaded && hasPVC && } + + {!hasPVC && obj?.source} {readableSizeUnit(obj?.size)}