web/satellite/vuetify-poc: allow for sharing files and folders
This change allows linksharing URLs to be generated for files and folders within the Vuetify project's file browser. Resolves #6111 Change-Id: I8cbe81b33cb5e35de0c34bba8ccc9175c727bd94
This commit is contained in:
parent
8f1682941e
commit
ec8f3b4528
@ -59,7 +59,7 @@
|
|||||||
</v-list-item>
|
</v-list-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-list-item density="comfortable" link rounded="lg">
|
<v-list-item density="comfortable" link rounded="lg" @click="() => emit('shareClick')">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<icon-share bold />
|
<icon-share bold />
|
||||||
</template>
|
</template>
|
||||||
@ -134,6 +134,7 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
deleteFolderClick: [];
|
deleteFolderClick: [];
|
||||||
|
shareClick: [];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const isDownloading = ref<boolean>(false);
|
const isDownloading = ref<boolean>(false);
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
<browser-row-actions
|
<browser-row-actions
|
||||||
:file="item.raw.browserObject"
|
:file="item.raw.browserObject"
|
||||||
@delete-folder-click="() => onDeleteFolderClick(item.raw.browserObject)"
|
@delete-folder-click="() => onDeleteFolderClick(item.raw.browserObject)"
|
||||||
|
@share-click="() => onShareClick(item.raw.browserObject)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</v-data-table-row>
|
</v-data-table-row>
|
||||||
@ -76,7 +77,18 @@
|
|||||||
<file-preview-dialog v-model="previewDialog" />
|
<file-preview-dialog v-model="previewDialog" />
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<delete-folder-dialog v-if="folderToDelete" v-model="isDeleteFolderDialogShown" :folder="folderToDelete" />
|
<delete-folder-dialog
|
||||||
|
v-if="folderToDelete"
|
||||||
|
v-model="isDeleteFolderDialogShown"
|
||||||
|
:folder="folderToDelete"
|
||||||
|
@content-removed="folderToDelete = null"
|
||||||
|
/>
|
||||||
|
<share-dialog
|
||||||
|
v-model="isShareDialogShown"
|
||||||
|
:bucket-name="bucketName"
|
||||||
|
:file="fileToShare || undefined"
|
||||||
|
@content-removed="fileToShare = null"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -107,6 +119,7 @@ import { tableSizeOptions } from '@/types/common';
|
|||||||
import BrowserRowActions from '@poc/components/BrowserRowActions.vue';
|
import BrowserRowActions from '@poc/components/BrowserRowActions.vue';
|
||||||
import FilePreviewDialog from '@poc/components/dialogs/FilePreviewDialog.vue';
|
import FilePreviewDialog from '@poc/components/dialogs/FilePreviewDialog.vue';
|
||||||
import DeleteFolderDialog from '@poc/components/dialogs/DeleteFolderDialog.vue';
|
import DeleteFolderDialog from '@poc/components/dialogs/DeleteFolderDialog.vue';
|
||||||
|
import ShareDialog from '@poc/components/dialogs/ShareDialog.vue';
|
||||||
|
|
||||||
import folderIcon from '@poc/assets/icon-folder-tonal.svg';
|
import folderIcon from '@poc/assets/icon-folder-tonal.svg';
|
||||||
import pdfIcon from '@poc/assets/icon-pdf-tonal.svg';
|
import pdfIcon from '@poc/assets/icon-pdf-tonal.svg';
|
||||||
@ -164,8 +177,10 @@ const search = ref<string>('');
|
|||||||
const selected = ref([]);
|
const selected = ref([]);
|
||||||
const previewDialog = ref<boolean>(false);
|
const previewDialog = ref<boolean>(false);
|
||||||
const options = ref<TableOptions>();
|
const options = ref<TableOptions>();
|
||||||
const folderToDelete = ref<BrowserObject>();
|
const folderToDelete = ref<BrowserObject | null>(null);
|
||||||
const isDeleteFolderDialogShown = ref<boolean>(false);
|
const isDeleteFolderDialogShown = ref<boolean>(false);
|
||||||
|
const fileToShare = ref<BrowserObject | null>(null);
|
||||||
|
const isShareDialogShown = ref<boolean>(false);
|
||||||
|
|
||||||
const sortBy = [{ key: 'name', order: 'asc' }];
|
const sortBy = [{ key: 'name', order: 'asc' }];
|
||||||
const headers = [
|
const headers = [
|
||||||
@ -405,6 +420,14 @@ function onDeleteFolderClick(folder: BrowserObject): void {
|
|||||||
isDeleteFolderDialogShown.value = true;
|
isDeleteFolderDialogShown.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Share button click event.
|
||||||
|
*/
|
||||||
|
function onShareClick(file: BrowserObject): void {
|
||||||
|
fileToShare.value = file;
|
||||||
|
isShareDialogShown.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
watch(filePath, fetchFiles, { immediate: true });
|
watch(filePath, fetchFiles, { immediate: true });
|
||||||
watch(() => props.forceEmpty, v => !v && fetchFiles());
|
watch(() => props.forceEmpty, v => !v && fetchFiles());
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
transition="fade-transition"
|
transition="fade-transition"
|
||||||
:persistent="isLoading"
|
:persistent="isLoading"
|
||||||
>
|
>
|
||||||
<v-card rounded="xlg">
|
<v-card rounded="xlg" ref="innerContent">
|
||||||
<v-card-item class="pl-7 py-4">
|
<v-card-item class="pl-7 py-4">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-sheet
|
<v-sheet
|
||||||
@ -62,7 +62,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed, ref, Component, watch } from 'vue';
|
||||||
import {
|
import {
|
||||||
VDialog,
|
VDialog,
|
||||||
VCard,
|
VCard,
|
||||||
@ -91,6 +91,7 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'update:modelValue': [value: boolean],
|
'update:modelValue': [value: boolean],
|
||||||
|
'contentRemoved': [],
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const model = computed<boolean>({
|
const model = computed<boolean>({
|
||||||
@ -104,6 +105,8 @@ const bucketsStore = useBucketsStore();
|
|||||||
const { isLoading, withLoading } = useLoading();
|
const { isLoading, withLoading } = useLoading();
|
||||||
const notify = useNotify();
|
const notify = useNotify();
|
||||||
|
|
||||||
|
const innerContent = ref<Component | null>(null);
|
||||||
|
|
||||||
const filePath = computed<string>(() => bucketsStore.state.fileComponentPath);
|
const filePath = computed<string>(() => bucketsStore.state.fileComponentPath);
|
||||||
|
|
||||||
async function onDeleteClick(): Promise<void> {
|
async function onDeleteClick(): Promise<void> {
|
||||||
@ -120,4 +123,6 @@ async function onDeleteClick(): Promise<void> {
|
|||||||
model.value = false;
|
model.value = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(innerContent, comp => !comp && emit('contentRemoved'));
|
||||||
</script>
|
</script>
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
Download
|
Download
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn icon size="small" color="white">
|
<v-btn icon size="small" color="white" @click="isShareDialogShown = true">
|
||||||
<icon-share size="22" />
|
<icon-share size="22" />
|
||||||
<v-tooltip
|
<v-tooltip
|
||||||
activator="parent"
|
activator="parent"
|
||||||
@ -90,6 +90,8 @@
|
|||||||
</v-carousel>
|
</v-carousel>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
||||||
|
<share-dialog v-model="isShareDialogShown" :bucket-name="bucketName" :file="currentFile" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -105,9 +107,7 @@ import {
|
|||||||
VToolbarTitle,
|
VToolbarTitle,
|
||||||
VTooltip,
|
VTooltip,
|
||||||
} from 'vuetify/components';
|
} from 'vuetify/components';
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import { useAppStore } from '@/store/modules/appStore';
|
|
||||||
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
||||||
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||||
import { useNotify } from '@/utils/hooks';
|
import { useNotify } from '@/utils/hooks';
|
||||||
@ -115,15 +115,14 @@ import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames
|
|||||||
|
|
||||||
import IconShare from '@poc/components/icons/IconShare.vue';
|
import IconShare from '@poc/components/icons/IconShare.vue';
|
||||||
import FilePreviewItem from '@poc/components/dialogs/filePreviewComponents/FilePreviewItem.vue';
|
import FilePreviewItem from '@poc/components/dialogs/filePreviewComponents/FilePreviewItem.vue';
|
||||||
|
import ShareDialog from '@poc/components/dialogs/ShareDialog.vue';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const obStore = useObjectBrowserStore();
|
const obStore = useObjectBrowserStore();
|
||||||
const bucketsStore = useBucketsStore();
|
const bucketsStore = useBucketsStore();
|
||||||
const notify = useNotify();
|
const notify = useNotify();
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
const isDownloading = ref<boolean>(false);
|
const isDownloading = ref<boolean>(false);
|
||||||
|
const isShareDialogShown = ref<boolean>(false);
|
||||||
|
|
||||||
const folderType = 'folder';
|
const folderType = 'folder';
|
||||||
|
|
||||||
@ -182,6 +181,13 @@ const currentPath = computed((): string => {
|
|||||||
return obStore.state.path;
|
return obStore.state.path;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the current bucket from the store.
|
||||||
|
*/
|
||||||
|
const bucketName = computed((): string => {
|
||||||
|
return bucketsStore.state.fileComponentBucketName;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download the current opened file.
|
* Download the current opened file.
|
||||||
*/
|
*/
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
</v-sheet>
|
</v-sheet>
|
||||||
</template>
|
</template>
|
||||||
<v-card-title class="font-weight-bold">
|
<v-card-title class="font-weight-bold">
|
||||||
Share {{ !filePath ? 'Bucket' : isFolder ? 'Folder' : 'File' }}
|
Share {{ !file ? 'Bucket' : file.type == 'folder' ? 'Folder' : 'File' }}
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-btn
|
<v-btn
|
||||||
@ -118,18 +118,20 @@ import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
|||||||
import { useNotify } from '@/utils/hooks';
|
import { useNotify } from '@/utils/hooks';
|
||||||
import { useLinksharing } from '@/composables/useLinksharing';
|
import { useLinksharing } from '@/composables/useLinksharing';
|
||||||
import { SHARE_BUTTON_CONFIGS, ShareOptions } from '@/types/browser';
|
import { SHARE_BUTTON_CONFIGS, ShareOptions } from '@/types/browser';
|
||||||
|
import { BrowserObject } from '@/store/modules/objectBrowserStore';
|
||||||
|
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||||
|
|
||||||
import IconShare from '@poc/components/icons/IconShare.vue';
|
import IconShare from '@poc/components/icons/IconShare.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: boolean,
|
modelValue: boolean,
|
||||||
bucketName: string;
|
bucketName: string,
|
||||||
filePath?: string;
|
file?: BrowserObject,
|
||||||
isFolder?: boolean;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'update:modelValue': [value: boolean],
|
'update:modelValue': [value: boolean];
|
||||||
|
'contentRemoved': [];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const model = computed<boolean>({
|
const model = computed<boolean>({
|
||||||
@ -138,6 +140,7 @@ const model = computed<boolean>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const analyticsStore = useAnalyticsStore();
|
const analyticsStore = useAnalyticsStore();
|
||||||
|
const bucketsStore = useBucketsStore();
|
||||||
|
|
||||||
const notify = useNotify();
|
const notify = useNotify();
|
||||||
const { generateBucketShareURL, generateFileOrFolderShareURL } = useLinksharing();
|
const { generateBucketShareURL, generateFileOrFolderShareURL } = useLinksharing();
|
||||||
@ -149,6 +152,8 @@ const link = ref<string>('');
|
|||||||
const copiedTimeout = ref<ReturnType<typeof setTimeout> | null>(null);
|
const copiedTimeout = ref<ReturnType<typeof setTimeout> | null>(null);
|
||||||
const justCopied = computed<boolean>(() => copiedTimeout.value !== null);
|
const justCopied = computed<boolean>(() => copiedTimeout.value !== null);
|
||||||
|
|
||||||
|
const filePath = computed<string>(() => bucketsStore.state.fileComponentPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves link to clipboard.
|
* Saves link to clipboard.
|
||||||
*/
|
*/
|
||||||
@ -166,20 +171,23 @@ function onCopy(): void {
|
|||||||
* Generates linksharing URL when the dialog is opened.
|
* Generates linksharing URL when the dialog is opened.
|
||||||
*/
|
*/
|
||||||
watch(() => innerContent.value, async (comp: Component | null): Promise<void> => {
|
watch(() => innerContent.value, async (comp: Component | null): Promise<void> => {
|
||||||
if (!comp) return;
|
if (!comp) {
|
||||||
|
emit('contentRemoved');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
link.value = '';
|
link.value = '';
|
||||||
analyticsStore.eventTriggered(AnalyticsEvent.LINK_SHARED);
|
analyticsStore.eventTriggered(AnalyticsEvent.LINK_SHARED);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!props.filePath) {
|
if (!props.file) {
|
||||||
link.value = await generateBucketShareURL(props.bucketName);
|
link.value = await generateBucketShareURL(props.bucketName);
|
||||||
} else {
|
} else {
|
||||||
link.value = await generateFileOrFolderShareURL(
|
link.value = await generateFileOrFolderShareURL(
|
||||||
props.bucketName,
|
props.bucketName,
|
||||||
props.filePath,
|
`${filePath.value ? filePath.value + '/' : ''}${props.file.Key}`,
|
||||||
props.isFolder,
|
props.file.type === 'folder',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user