From f598accd458a9dc53a2646ba944a9b9f9d206852 Mon Sep 17 00:00:00 2001 From: Mason Hu Date: Fri, 22 Mar 2024 10:44:57 +0200 Subject: [PATCH] feat: limit functionalities for storage pool with driver that's not fully supported in the UI - remove volumes tab in storage detail page - remove main configuration form menu tab and default to show yaml configs editor - filter out storage pool options with unsupported drivers (applies to creating custom volumes, selecting root storage pool for instance and profile, creating custom volume while creating instance, uploading custom iso) Signed-off-by: Mason Hu --- src/pages/storage/EditStoragePool.tsx | 15 +++++- src/pages/storage/StoragePoolSelector.tsx | 25 ++++++++-- src/pages/storage/UploadCustomIso.tsx | 49 +++++-------------- src/pages/storage/forms/StoragePoolForm.tsx | 11 ++++- .../storage/forms/StoragePoolFormMenu.tsx | 13 ++++- .../storage/forms/StorageVolumeFormMain.tsx | 1 + src/util/storageOptions.tsx | 8 +++ 7 files changed, 75 insertions(+), 47 deletions(-) diff --git a/src/pages/storage/EditStoragePool.tsx b/src/pages/storage/EditStoragePool.tsx index 1bcdfdb10..bd2111cbe 100644 --- a/src/pages/storage/EditStoragePool.tsx +++ b/src/pages/storage/EditStoragePool.tsx @@ -19,10 +19,15 @@ import { checkDuplicateName } from "util/helpers"; import { useClusterMembers } from "context/useClusterMembers"; import FormFooterLayout from "components/forms/FormFooterLayout"; import { toStoragePoolFormValues } from "util/storagePoolForm"; -import { MAIN_CONFIGURATION } from "./forms/StoragePoolFormMenu"; +import { + MAIN_CONFIGURATION, + YAML_CONFIGURATION, +} from "./forms/StoragePoolFormMenu"; import { slugify } from "util/slugify"; import { useToastNotification } from "context/toastNotificationProvider"; import { yamlToObject } from "util/yaml"; +import { useSettings } from "context/useSettings"; +import { getSupportedStorageDrivers } from "util/storageOptions"; interface Props { pool: LxdStoragePool; @@ -31,6 +36,7 @@ interface Props { const EditStoragePool: FC = ({ pool }) => { const navigate = useNavigate(); const notify = useNotify(); + const { data: settings } = useSettings(); const toastNotify = useToastNotification(); const queryClient = useQueryClient(); const { project, section } = useParams<{ @@ -99,11 +105,16 @@ const EditStoragePool: FC = ({ pool }) => { : navigate(`${baseUrl}/${slugify(newSection)}`); }; + const supportedStorageDrivers = getSupportedStorageDrivers(settings); + const defaultFormSection = supportedStorageDrivers.has(formik.values.driver) + ? slugify(MAIN_CONFIGURATION) + : slugify(YAML_CONFIGURATION); + return (
diff --git a/src/pages/storage/StoragePoolSelector.tsx b/src/pages/storage/StoragePoolSelector.tsx index 04f83339c..1b9fd982b 100644 --- a/src/pages/storage/StoragePoolSelector.tsx +++ b/src/pages/storage/StoragePoolSelector.tsx @@ -5,12 +5,15 @@ import { queryKeys } from "util/queryKeys"; import { fetchStoragePools } from "api/storage-pools"; import Loader from "components/Loader"; import { Props as SelectProps } from "@canonical/react-components/dist/components/Select/Select"; +import { useSettings } from "context/useSettings"; +import { getSupportedStorageDrivers } from "util/storageOptions"; interface Props { project: string; value: string; setValue: (value: string) => void; selectProps?: SelectProps; + hidePoolsWithUnsupportedDrivers?: boolean; } const StoragePoolSelector: FC = ({ @@ -18,8 +21,10 @@ const StoragePoolSelector: FC = ({ value, setValue, selectProps, + hidePoolsWithUnsupportedDrivers = false, }) => { const notify = useNotify(); + const { data: settings } = useSettings(); const { data: pools = [], error, @@ -29,11 +34,20 @@ const StoragePoolSelector: FC = ({ queryFn: () => fetchStoragePools(project), }); + const supportedStorageDrivers = getSupportedStorageDrivers(settings); + const poolsWithSupportedDriver = pools.filter((pool) => + supportedStorageDrivers.has(pool.driver), + ); + + const poolsToUse = hidePoolsWithUnsupportedDrivers + ? poolsWithSupportedDriver + : pools; + useEffect(() => { - if (!value && pools.length > 0) { - setValue(pools[0].name); + if (!value && poolsToUse.length > 0) { + setValue(poolsToUse[0].name); } - }, [value, pools]); + }, [value, poolsToUse]); if (isLoading) { return ; @@ -44,7 +58,7 @@ const StoragePoolSelector: FC = ({ } const getStoragePoolOptions = () => { - const options = pools.map((pool) => { + const options = poolsToUse.map((pool) => { return { label: pool.name, value: pool.name, @@ -52,7 +66,8 @@ const StoragePoolSelector: FC = ({ }; }); options.unshift({ - label: pools.length === 0 ? "No storage pool available" : "Select option", + label: + poolsToUse.length === 0 ? "No storage pool available" : "Select option", value: "", disabled: true, }); diff --git a/src/pages/storage/UploadCustomIso.tsx b/src/pages/storage/UploadCustomIso.tsx index de6b5df27..67ab7b7b9 100644 --- a/src/pages/storage/UploadCustomIso.tsx +++ b/src/pages/storage/UploadCustomIso.tsx @@ -1,14 +1,13 @@ import { ChangeEvent, FC, useEffect, useState } from "react"; -import { useQuery, useQueryClient } from "@tanstack/react-query"; +import { useQueryClient } from "@tanstack/react-query"; import { queryKeys } from "util/queryKeys"; import { ActionButton, Button, Input, - Select, useNotify, } from "@canonical/react-components"; -import { createIsoStorageVolume, fetchStoragePools } from "api/storage-pools"; +import { createIsoStorageVolume } from "api/storage-pools"; import { useProject } from "context/project"; import Loader from "components/Loader"; import NotificationRow from "components/NotificationRow"; @@ -18,6 +17,7 @@ import { humanFileSize } from "util/helpers"; import UploadCustomImageHint from "pages/storage/UploadCustomImageHint"; import { useEventQueue } from "context/eventQueue"; import { useToastNotification } from "context/toastNotificationProvider"; +import StoragePoolSelector from "./StoragePoolSelector"; interface Props { onFinish: (name: string, pool: string) => void; @@ -43,28 +43,6 @@ const UploadCustomIso: FC = ({ onCancel, onFinish }) => { const projectName = project?.name ?? ""; - const { - data: pools = [], - isLoading: arePoolsLoading, - error: poolError, - } = useQuery({ - queryKey: [queryKeys.storage], - queryFn: () => fetchStoragePools(projectName), - }); - - if (poolError) { - notify.failure("Loading storage pools failed", poolError); - onCancel(); - } - - if (arePoolsLoading) { - return ; - } - - if (pools.length > 0 && !pool) { - setPool(pools[0].name); - } - const handleCancel = () => { uploadAbort?.abort(); onCancel(); @@ -142,19 +120,16 @@ const UploadCustomIso: FC = ({ onCancel, onFinish }) => { disabled={file === null} stacked /> -