From e2f5237a7f92723b84855c5fd2c32913797669ca Mon Sep 17 00:00:00 2001 From: Jacob Nesbitt Date: Wed, 20 Nov 2024 11:58:15 -0500 Subject: [PATCH] Add dialog to manage uploads for embargoed dandisets --- web/src/rest.ts | 8 ++ web/src/types/index.ts | 8 ++ .../DandisetLandingView/DandisetUnembargo.vue | 119 +++++++++++++++--- 3 files changed, 121 insertions(+), 14 deletions(-) diff --git a/web/src/rest.ts b/web/src/rest.ts index 69922b1e3..9cde8b971 100644 --- a/web/src/rest.ts +++ b/web/src/rest.ts @@ -12,6 +12,7 @@ import type { AssetPath, Zarr, DandisetSearchResult, + IncompleteUpload, } from '@/types'; import type { Dandiset as DandisetMetadata, @@ -106,6 +107,13 @@ const dandiRest = { throw e; } }, + async uploads(identifier: string): Promise { + const res = await client.get(`dandisets/${identifier}/uploads/`); + return res.data; + }, + async clearUploads(identifier: string) { + await client.delete(`dandisets/${identifier}/uploads/`); + }, async assets( identifier: string, version: string, diff --git a/web/src/types/index.ts b/web/src/types/index.ts index 7e6caaf69..8f040553a 100644 --- a/web/src/types/index.ts +++ b/web/src/types/index.ts @@ -102,3 +102,11 @@ export interface AssetPath { aggregate_size: number; asset: AssetFile | null; } + +export interface IncompleteUpload { + created: string; + blob: string; + upload_id: string; + etag: string; + size: number; +} \ No newline at end of file diff --git a/web/src/views/DandisetLandingView/DandisetUnembargo.vue b/web/src/views/DandisetLandingView/DandisetUnembargo.vue index d7d7cfe42..d862d6333 100644 --- a/web/src/views/DandisetLandingView/DandisetUnembargo.vue +++ b/web/src/views/DandisetLandingView/DandisetUnembargo.vue @@ -4,6 +4,65 @@ outlined class="mt-4 px-3" > + + + + This dandiset has active uploads + + + + This dandiset has {{ incompleteUploads.length }} active uploads. Unembargo may not proceed until these are addressed. You may delete these uploads using the "Clear Uploads" button below. + + + + + + + + + + + Close + + + + + + + + Delete all uploads? Once deleted, any partially uploaded data will be lost. + + + Delete + + + + + + - + - This dandiset is being unembargoed, please wait. - This dandiset has active uploads. Please complete or clear these uploads before proceeding. + This dandiset is being unembargoed, please wait. @@ -119,19 +175,54 @@ import { computed, ref } from 'vue'; import moment from 'moment'; import { dandiRest } from '@/rest'; import { useDandisetStore } from '@/stores/dandiset'; +import type { IncompleteUpload } from '@/types'; +import filesize from 'filesize'; -function formatDate(date: string): string { - return moment(date).format('ll'); +function formatDate(date: string, format: string = 'll'): string { + return moment(date).format(format); } -const store = useDandisetStore(); +const uploadHeaders = [ + { + text: 'Started at', + value: 'created', + }, + { + text: 'Size', + value: 'size', + }, + { + text: 'E-Tag', + value: 'etag', + }, +]; +const store = useDandisetStore(); const currentDandiset = computed(() => store.dandiset); const unembargo_in_progress = computed(() => currentDandiset.value?.dandiset.embargo_status === 'UNEMBARGOING'); -const unembargoDisabled = computed(() => !!(unembargo_in_progress.value || currentDandiset.value === null || currentDandiset.value.active_uploads)); const showWarningDialog = ref(false); const confirmationPhrase = ref(''); +// Upload management +const showUploadManagementDialog = ref(false); +const incompleteUploads = ref([]); +const unembargoDisabled = computed(() => !!(unembargo_in_progress.value || currentDandiset.value === null || currentDandiset.value.active_uploads)); +if (unembargoDisabled.value) { + fetchIncompleteUploads(); +} + +async function fetchIncompleteUploads() { + incompleteUploads.value = await dandiRest.uploads(currentDandiset.value!.dandiset.identifier); +} + +async function clearUploads() { + const identifier = currentDandiset.value!.dandiset.identifier; + await dandiRest.clearUploads(identifier); + showUploadManagementDialog.value = false; + + store.fetchDandiset({ identifier, version: 'draft' }); +} + async function unembargo() { if (currentDandiset.value) { // Display the warning dialog before releasing