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:
parent
623b989973
commit
7311d08139
@ -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>
|
@ -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>
|
Loading…
Reference in New Issue
Block a user