From f2612de1a20d714643e447c3d435497e7c69aced Mon Sep 17 00:00:00 2001 From: John Chilton Date: Wed, 7 Feb 2024 14:32:09 -0500 Subject: [PATCH] UI for "relocating" a dataset's object store. --- client/src/api/objectStores.ts | 7 ++ client/src/api/schema/schema.ts | 5 + .../Dataset/DatasetStorage/DatasetStorage.vue | 36 +++--- .../Dataset/DatasetStorage/RelocateDialog.vue | 67 +++++++++++ .../Dataset/DatasetStorage/RelocateLink.vue | 107 ++++++++++++++++++ .../Dataset/DatasetStorage/RelocateModal.vue | 51 +++++++++ .../ObjectStore/DescribeObjectStore.vue | 14 ++- .../webapps/galaxy/services/datasets.py | 5 + 8 files changed, 276 insertions(+), 16 deletions(-) create mode 100644 client/src/components/Dataset/DatasetStorage/RelocateDialog.vue create mode 100644 client/src/components/Dataset/DatasetStorage/RelocateLink.vue create mode 100644 client/src/components/Dataset/DatasetStorage/RelocateModal.vue diff --git a/client/src/api/objectStores.ts b/client/src/api/objectStores.ts index c24f6a096795..6b1ace439818 100644 --- a/client/src/api/objectStores.ts +++ b/client/src/api/objectStores.ts @@ -13,3 +13,10 @@ export async function getObjectStoreDetails(id: string) { const { data } = await getObjectStore({ object_store_id: id }); return data; } + +const updateObjectStoreFetcher = fetcher.path("/api/datasets/{dataset_id}/object_store_id").method("put").create(); + +export async function updateObjectStore(datasetId: string, objectStoreId: string) { + const { data } = await updateObjectStoreFetcher({ dataset_id: datasetId, object_store_id: objectStoreId }); + return data; +} diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index b037de899d31..af3f0d3c7626 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -3822,6 +3822,11 @@ export interface components { percent_used: number | null; /** @description Information about quota sources around dataset storage. */ quota: components["schemas"]["ConcreteObjectStoreQuotaSourceDetails"]; + /** + * Relocatable + * @description Indicator of whether the objectstore for this dataset can be switched by this user. + */ + relocatable: boolean; /** * Shareable * @description Is this dataset shareable. diff --git a/client/src/components/Dataset/DatasetStorage/DatasetStorage.vue b/client/src/components/Dataset/DatasetStorage/DatasetStorage.vue index 90706afe28ea..ec020cf1e174 100644 --- a/client/src/components/Dataset/DatasetStorage/DatasetStorage.vue +++ b/client/src/components/Dataset/DatasetStorage/DatasetStorage.vue @@ -5,6 +5,7 @@ import { DatasetStorageDetails } from "@/api"; import { fetchDatasetStorage } from "@/api/datasets"; import { errorMessageAsString } from "@/utils/simple-error"; +import RelocateLink from "./RelocateLink.vue"; import LoadingSpan from "@/components/LoadingSpan.vue"; import DescribeObjectStore from "@/components/ObjectStore/DescribeObjectStore.vue"; @@ -42,25 +43,30 @@ const sourceUri = computed(() => { return rootSources[0]?.source_uri; }); -watch( - props, - async () => { - const datasetId = props.datasetId; - const datasetType = props.datasetType; - try { - const response = await fetchDatasetStorage({ dataset_id: datasetId, hda_ldda: datasetType }); - storageInfo.value = response.data; - } catch (error) { - errorMessage.value = errorMessageAsString(error); - } - }, - { immediate: true } -); +async function fetch() { + const datasetId = props.datasetId; + const datasetType = props.datasetType; + try { + const response = await fetchDatasetStorage({ dataset_id: datasetId, hda_ldda: datasetType }); + storageInfo.value = response.data; + } catch (error) { + errorMessage.value = errorMessageAsString(error); + } +} + +watch(props, fetch, { immediate: true });