web/satellite/vuetify-poc: upload via drag and drop

This change adds the drag-drop upload feature to the vuetify app.

Issue: https://github.com/storj/storj/issues/6104

Change-Id: I177e33a677d94db9ef95a31e32da853a46a7dc51
This commit is contained in:
Wilfred Asomani 2023-09-01 13:28:32 +00:00 committed by Storj Robot
parent 623b989973
commit 7311d08139
2 changed files with 99 additions and 2 deletions

View File

@ -0,0 +1,69 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<v-dialog
v-model="model"
fullscreen
persistent
transition="fade-transition"
@dragleave.self="model = false"
@mouseout="model = false"
@mouseleave="model = false"
>
<v-container
fluid
class="fill-height border-white border-sm border-dashed justify-center align-center"
@dragenter.prevent
@dragover.prevent
@drop.stop.prevent="(e) => emit('fileDrop', e)"
>
<v-alert
rounded="lg"
class="alert"
color="success"
>
Drop your files to put it into the {{ bucket }} bucket.
</v-alert>
<p class="info font-weight-bold text-h3 text-center">Drag and drop files here to upload</p>
</v-container>
</v-dialog>
</template>
<script setup lang="ts">
import { VAlert, VContainer, VDialog } from 'vuetify/components';
import { computed } from 'vue';
const props = defineProps<{
modelValue: boolean,
bucket: string,
}>();
const emit = defineEmits<{
(event: 'update:modelValue', value: boolean): void,
(event: 'fileDrop', value: Event): void,
}>();
const model = computed<boolean>({
get: () => props.modelValue,
set: value => emit('update:modelValue', value),
});
</script>
<style scoped lang="scss">
.alert {
position: absolute;
top: 24px;
pointer-events: none;
}
.info {
max-width: 380px;
color: rgb(var(--v-theme-on-primary));
}
.border-white {
border-color: rgb(var(--v-theme-on-primary))!important;
}
</style>

View File

@ -2,7 +2,11 @@
// See LICENSE for copying information.
<template>
<v-container>
<v-container
class="bucket-view"
@dragover.prevent="isDragging = true"
>
<dropzone-dialog v-model="isDragging" :bucket="bucketName" @file-drop="upload" />
<page-title-component title="Browse Files" />
<browser-breadcrumbs-component />
@ -53,7 +57,8 @@ import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { EdgeCredentials } from '@/types/accessGrants';
import { useNotify } from '@/utils/hooks';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
import PageTitleComponent from '@poc/components/PageTitleComponent.vue';
import BrowserBreadcrumbsComponent from '@poc/components/BrowserBreadcrumbsComponent.vue';
@ -63,16 +68,19 @@ import BrowserNewFolderDialog from '@poc/components/dialogs/BrowserNewFolderDial
import IconUpload from '@poc/components/icons/IconUpload.vue';
import IconFolder from '@poc/components/icons/IconFolder.vue';
import EnterBucketPassphraseDialog from '@poc/components/dialogs/EnterBucketPassphraseDialog.vue';
import DropzoneDialog from '@poc/components/dialogs/DropzoneDialog.vue';
const bucketsStore = useBucketsStore();
const obStore = useObjectBrowserStore();
const projectsStore = useProjectsStore();
const analyticsStore = useAnalyticsStore();
const router = useRouter();
const route = useRoute();
const notify = useNotify();
const isLoading = ref<boolean>(true);
const isDragging = ref<boolean>(false);
const isContentDisabled = ref<boolean>(true);
const snackbar = ref<boolean>(false);
const isBucketPassphraseDialogOpen = ref<boolean>(bucketsStore.state.promptForPassphrase);
@ -111,6 +119,20 @@ function initObjectStore(): void {
isContentDisabled.value = false;
}
/**
* Upload the current selected or dragged-and-dropped file.
*/
async function upload(e: Event): Promise<void> {
if (isDragging.value) {
isDragging.value = false;
}
await obStore.upload({ e });
analyticsStore.eventTriggered(AnalyticsEvent.OBJECT_UPLOADED);
const target = e.target as HTMLInputElement;
target.value = '';
}
watch(isBucketPassphraseDialogOpen, isOpen => {
if (isOpen || !isPromptForPassphrase.value) return;
router.push(`/projects/${projectId.value}/dashboard`);
@ -155,3 +177,9 @@ onMounted(async () => {
isLoading.value = false;
});
</script>
<style scoped lang="scss">
.bucket-view {
height: 100%;
}
</style>