diff --git a/.devcontainer/.vscode-server/.gitkeep b/.devcontainer/.vscode-server/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..3f97d1c9af3758783cd306e50398bc850ebb2661 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,2 @@ +FROM mcr.microsoft.com/devcontainers/javascript-node:20 as develop +EXPOSE 6000 diff --git a/.devcontainer/compose.yml b/.devcontainer/compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..ecbdd8d9fa99ab8c74ad4cdd8c9529e4f0dddb6e --- /dev/null +++ b/.devcontainer/compose.yml @@ -0,0 +1,30 @@ +version: "3.7" + +services: + app: + build: + target: develop + user: node + userns_mode: keep-id:uid=1000,gid=1000 + environment: + SSH_AUTH_SOCK: /.ssh/ssh-agent.sock + MOCKUP: "false" + command: /bin/sh -c "while sleep 2s; do :; done" + labels: + - "traefik.enable=true" + - "traefik.http.routers.web-ui.rule=HostRegexp(`^web-ui-.*$`)" + - "traefik.http.routers.web-ui.entrypoints=web" + volumes: + - ..:/workspace/app:cached + - ./.vscode-server:/home/node/.vscode-server/:cached + - ${SSH_AUTH_SOCK}:/.ssh/ssh-agent.sock + networks: + - proxy-net + - default + +networks: + default: + driver: bridge + proxy-net: + external: true + name: proxy-net diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000000000000000000000000000000000..8dc0a517e14a9ea53fdf52ce5ff4665328ad4637 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,9 @@ +{ + "name": "Web UI Devcontainer", + "dockerComposeFile": ["compose.yml"], + "service": "app", + "workspaceFolder": "/workspace/app", + "updateRemoteUserUID": false, + "remoteUser": "node", + "containerUser": "node" +} diff --git a/.gitignore b/.gitignore index f5d774609839a1db681aa0ec621c53301e9fe66b..eaf867358e183b10e010debe9acac4d2b378bb2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +/.devcontainer/.vscode-server/* +!/.devcontainer/.vscode-server/.gitkeep +/.devcontainer/.config/* +!/.devcontainer/.config/.gitkeep # Created by https://www.toptal.com/developers/gitignore/api/vue,node,macos,windows,linux,vscode,intellij+all # Edit at https://www.toptal.com/developers/gitignore?templates=vue,node,macos,windows,linux,vscode,intellij+all diff --git a/.vscode/extensions.json b/.vscode/extensions.json index daaa5ee2ec3f21f43965ff0d83625bcbe5fd47e8..9a346e45c1c6f5732b088ed847fa44b22e7fcef8 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,8 @@ "recommendations": [ "arcanis.vscode-zipfs", "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode" + "esbenp.prettier-vscode", + "vue.vscode-typescript-vue-plugin", + "mhutchie.git-graph" ] } diff --git a/src/i18n/de.ts b/src/i18n/de.ts index a7b232a63961204b8855114c7193dcd3c444794c..379526270737ae6efa31f39909f0dc42ec7da374 100644 --- a/src/i18n/de.ts +++ b/src/i18n/de.ts @@ -184,40 +184,30 @@ export default { fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) ist objektbasierter Speicher für Forschungsdaten. Sie können RDS-Ressourcen mit Speicherplatz für Ihre Forschungsdaten erstellen solange das Projekt ausreichend Speicherquota hat. Projektbesitzer können zusätzliche Speicherquota beantragen.", - disclaimer: - "Aufgrund von Browser-Einschränkungen und unserer aktuellen API beträgt die maximale Dateigröße für einzelne Uploads ca. 2 GB. Falls Sie größere Dateien hochladen müssen, prüfen Sie die Option, eine @:(resourceTypes.rdss3rwth.displayName) Ressource zu verwenden.", }, rdsude: { displayName: "UDE-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) Universität Duisburg-Essen ist objektbasierter Speicher für Forschungsdaten. Sie können RDS-Ressourcen mit Speicherplatz für Ihre Forschungsdaten erstellen solange das Projekt ausreichend Speicherquota hat. Projektbesitzer können zusätzliche Speicherquota beantragen.", - disclaimer: - "Aufgrund von Browser-Einschränkungen und unserer aktuellen API beträgt die maximale Dateigröße für einzelne Uploads ca. 2 GB. Falls Sie größere Dateien hochladen müssen, prüfen Sie die Option, eine @:(resourceTypes.rdss3ude.displayName) Ressource zu verwenden.", }, rdstudo: { displayName: "TUDO-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) Technische Universität Dortmund ist objektbasierter Speicher für Forschungsdaten. Sie können RDS-Ressourcen mit Speicherplatz für Ihre Forschungsdaten erstellen solange das Projekt ausreichend Speicherquota hat. Projektbesitzer können zusätzliche Speicherquota beantragen.", - disclaimer: - "Aufgrund von Browser-Einschränkungen und unserer aktuellen API beträgt die maximale Dateigröße für einzelne Uploads ca. 2 GB. Falls Sie größere Dateien hochladen müssen, prüfen Sie die Option, eine @:(resourceTypes.rdss3tudo.displayName) Ressource zu verwenden.", }, rdsrub: { displayName: "RUB-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) Ruhr-Universität Bochum ist objektbasierter Speicher für Forschungsdaten. Sie können RDS-Ressourcen mit Speicherplatz für Ihre Forschungsdaten erstellen solange das Projekt ausreichend Speicherquota hat. Projektbesitzer können zusätzliche Speicherquota beantragen.", - disclaimer: - "Aufgrund von Browser-Einschränkungen und unserer aktuellen API beträgt die maximale Dateigröße für einzelne Uploads ca. 2 GB. Falls Sie größere Dateien hochladen müssen, prüfen Sie die Option, eine @:(resourceTypes.rdss3rub.displayName) Ressource zu verwenden.", }, rdsnrw: { displayName: "NRW-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) Nordrhein-Westfalen ist objektbasierter Speicher für Forschungsdaten. Sie können RDS-Ressourcen mit Speicherplatz für Ihre Forschungsdaten erstellen solange das Projekt ausreichend Speicherquota hat. Projektbesitzer können zusätzliche Speicherquota beantragen.", - disclaimer: - "Aufgrund von Browser-Einschränkungen und unserer aktuellen API beträgt die maximale Dateigröße für einzelne Uploads ca. 2 GB. Falls Sie größere Dateien hochladen müssen, prüfen Sie die Option, eine @:(resourceTypes.rdss3nrw.displayName) Ressource zu verwenden.", }, s3: { displayName: "S3 Bucket", diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 062243b39bb38b4b5aa3bbb45d84f4b8838de701..45c764780140e908429ad166534396e84ac6d5db 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -182,40 +182,30 @@ export default { fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) is object-based storage for research data. You can create RDS resources with storage space for your research data as long as the project has sufficient storage quota. Project owners can request additional storage quota.", - disclaimer: - "Due to browser constraints and our current API's limitations, the maximum individual file size for uploads is approximately 2 GB. If you need to upload larger files, please explore the option to use an @:(resourceTypes.rdss3rwth.displayName) resource.", }, rdsude: { displayName: "UDE-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) University of Duisburg-Essen is object-based storage for research data. You can create RDS resources with storage space for your research data as long as the project has sufficient storage quota. Project owners can request additional storage quota.", - disclaimer: - "Due to browser constraints and our current API's limitations, the maximum individual file size for uploads is approximately 2 GB. If you need to upload larger files, please explore the option to use a @:(resourceTypes.rdss3ude.displayName) resource.", }, rdstudo: { displayName: "TUDO-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) TU Dortmund University is object-based storage for research data. You can create RDS resources with storage space for your research data as long as the project has sufficient storage quota. Project owners can request additional storage quota.", - disclaimer: - "Due to browser constraints and our current API's limitations, the maximum individual file size for uploads is approximately 2 GB. If you need to upload larger files, please explore the option to use a @:(resourceTypes.rdss3tudo.displayName) resource.", }, rdsrub: { displayName: "RUB-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) Ruhr-Universität Bochum is object-based storage for research data. You can create RDS resources with storage space for your research data as long as the project has sufficient storage quota. Project owners can request additional storage quota.", - disclaimer: - "Due to browser constraints and our current API's limitations, the maximum individual file size for uploads is approximately 2 GB. If you need to upload larger files, please explore the option to use an @:(resourceTypes.rdss3rub.displayName) resource.", }, rdsnrw: { displayName: "NRW-RDS-Web", fullName: "Research Data Storage (RDS)", description: "Research Data Storage (RDS) North Rhine-Westphalia is object-based storage for research data. You can create RDS resources with storage space for your research data as long as the project has sufficient storage quota. Project owners can request additional storage quota.", - disclaimer: - "Due to browser constraints and our current API's limitations, the maximum individual file size for uploads is approximately 2 GB. If you need to upload larger files, please explore the option to use an @:(resourceTypes.rdss3nrw.displayName) resource.", }, s3: { displayName: "S3 Bucket", diff --git a/src/modules/resource/components/create-resource/ConfigurationSizeSlider.vue b/src/modules/resource/components/create-resource/ConfigurationSizeSlider.vue index 3fd7f8219f394ae2831c1a94325e8ea44ab0261a..6b7442e98e1ecc142f4a5f44d81d14a9e8565957 100644 --- a/src/modules/resource/components/create-resource/ConfigurationSizeSlider.vue +++ b/src/modules/resource/components/create-resource/ConfigurationSizeSlider.vue @@ -24,22 +24,6 @@ </router-link> </div> </div> - - <template #hint> - <span - v-if=" - $te( - `resourceTypes.${selectedResourceTypeInformation.specificType}.disclaimer`, - ) - " - > - {{ - $t( - `resourceTypes.${selectedResourceTypeInformation.specificType}.disclaimer`, - ) - }} - </span> - </template> </CoscineFormGroup> </div> </template> diff --git a/src/modules/resource/components/resource-page/modals/OversizedFilesModal.vue b/src/modules/resource/components/resource-page/modals/OversizedFilesModal.vue deleted file mode 100644 index bc39026bebb029f56e7565cad3ce81acb13aebfb..0000000000000000000000000000000000000000 --- a/src/modules/resource/components/resource-page/modals/OversizedFilesModal.vue +++ /dev/null @@ -1,101 +0,0 @@ -<template> - <b-modal - id="oversizedFilesModal" - :title="$t(`page.resource.modals.oversizedFiles.${generalType}.header`)" - ok-only - @hidden="$emit('close', $event.target.value)" - > - <i18n :path="`page.resource.modals.oversizedFiles.${generalType}.body`"> - <template #maxFileSize> - {{ formatBytes(maxFileByteSize) }} - </template> - <template #documentation> - <a - :href=" - $t( - `page.resource.modals.oversizedFiles.${generalType}.documentation.url`, - ).toString() - " - target="_blank" - > - {{ - $t( - `page.resource.modals.oversizedFiles.${generalType}.documentation.text`, - ) - }} - </a> - </template> - </i18n> - - <b-table class="mt-3" :items="oversizedFiles" :fields="defaultHeaders"> - <template #default="{ row: file }"> - <b-table-column :key="file.name" field="name" /> - <b-table-column :key="file.size" field="size" /> - </template> - </b-table> - </b-modal> -</template> - -<script lang="ts"> -import { defineComponent, type PropType } from "vue"; - -import type { CustomTableField, FileInformation } from "../../../types"; -import { FileUtil } from "../../../utils/FileUtil"; -import type { ResourceTypeInformationDto } from "@coscine/api-client/dist/types/Coscine.Api"; - -export default defineComponent({ - name: "OversizedFilesModal", - props: { - resourceTypeInformation: { - type: Object as PropType<ResourceTypeInformationDto | undefined>, - required: true, - }, - maxFileByteSize: { - type: Number, - required: true, - }, - oversizedFiles: { - type: Array as PropType<Array<FileInformation>>, - required: true, - }, - }, - - computed: { - generalType(): string | null | undefined { - return this.resourceTypeInformation?.generalType; - }, - defaultHeaders(): Array<CustomTableField> { - // Define as computed property to have table - // header text react on language changes. - return [ - { - label: this.$t("page.resource.fileName").toString(), - key: "name", - sortable: true, - active: true, - }, - { - label: this.$t("page.resource.size").toString(), - key: "size", - sortable: true, - active: true, - formatter: (value, key, item: FileInformation) => { - return this.formatBytes(item.size); - }, - filterByFormatted: true, - }, - ]; - }, - }, - - methods: { - /** - * - * @param bytes - */ - formatBytes(bytes: number) { - return FileUtil.formatBytes(bytes); - }, - }, -}); -</script> diff --git a/src/modules/resource/i18n/de.ts b/src/modules/resource/i18n/de.ts index bba463fea36aecb2aad3ec4140cdfc01ef74c8b1..a71e6756e46de0400d46841c15e35a17465ec316 100644 --- a/src/modules/resource/i18n/de.ts +++ b/src/modules/resource/i18n/de.ts @@ -180,38 +180,9 @@ export default { modalSaveDuplicateFilesBtnSkip: "DIESE DATEIEN ÜBERSPRINGEN", modalSaveDuplicateFilesBtnOverwrite: "ÜBERSCHREIBEN", - modals: { - oversizedFiles: { - gitlab: { - header: "Einschränkung beim Upload großer Dateien", - body: "Sie haben Dateien ausgewählt, die unser Upload-Limit aufgrund von Browser-Einschränkungen und den Limitationen unserer API überschreiten, festgelegt auf {maxFileSize} pro Datei für direkte Uploads. Für GitLab-Ressourcen empfehlen wir die Dateien direkt in GitLab hochzuladen.", - }, - rds: { - header: "Einschränkung beim Upload großer Dateien", - body: "Sie haben Dateien ausgewählt, die unser Upload-Limit aufgrund von Browser-Einschränkungen und den Limitationen unserer API überschreiten, festgelegt auf {maxFileSize} pro Datei. Die unten aufgelisteten Dateien können derzeit nicht hochgeladen werden.", - }, - rdss3: { - header: "Einschränkung beim Upload großer Dateien", - body: "Sie haben Dateien ausgewählt, die unser Upload-Limit aufgrund von Browser-Einschränkungen und den Limitationen unserer API überschreiten, festgelegt auf {maxFileSize} pro Datei für direkte Uploads. Für S3-Ressourcen empfehlen wir die Verwendung eines Drittanbieter-S3-Clients, um große Dateien zu verwalten. Bitte konsultieren Sie unsere {documentation} für weitere Informationen.", - documentation: { - text: "Dokumentation", - url: "https://docs.coscine.de/de/resources/s3-clients/", - }, - }, - rdss3worm: { - header: "Einschränkung beim Upload großer Dateien", - body: "Sie haben Dateien ausgewählt, die unser Upload-Limit aufgrund von Browser-Einschränkungen und den Limitationen unserer API überschreiten, festgelegt auf {maxFileSize} pro Datei für direkte Uploads. Für S3-WORM-Ressourcen empfehlen wir die Verwendung eines Drittanbieter-S3-Clients, um große Dateien zu verwalten. Bitte konsultieren Sie unsere {documentation} für weitere Informationen.", - documentation: { - text: "Dokumentation", - url: "https://docs.coscine.de/de/resources/s3-clients/", - }, - }, - }, - }, - modalDeleteFolderContentsHeader: "Löschen von Dateien und Metadaten", modalDeleteFolderContentsBody: - "Sind Sie sicher, dass Sie die folgenen Dateien und Metadaten löschen wollen:", + "Sind Sie sicher, dass Sie die folgenden Dateien und Metadaten löschen wollen:", modalLeavingPageHeader: "Dateien werden hochgeladen", modalLeavingPageBodyTop: "Diese Dateien werden momentan hochgeladen:", diff --git a/src/modules/resource/i18n/en.ts b/src/modules/resource/i18n/en.ts index eb4499009c9d7bda757a802ceda68ca753ea4def..95b83b2796ac8aba259be96364c42782e5abb172 100644 --- a/src/modules/resource/i18n/en.ts +++ b/src/modules/resource/i18n/en.ts @@ -177,35 +177,6 @@ export default { modalSaveDuplicateFilesBtnSkip: "SKIP DUPLICATE FILES", modalSaveDuplicateFilesBtnOverwrite: "OVERWRITE", - modals: { - oversizedFiles: { - gitlab: { - header: "Large File Upload Restriction", - body: "You have selected files that exceed our upload size cap due to browser constraints and our API's current limitations, set at {maxFileSize} per file. For GitLab resources, we recommend uploading large files directly to GitLab.", - }, - rds: { - header: "Large File Upload Restriction", - body: "You have selected files that exceed our upload size cap due to browser constraints and our API's current limitations, set at {maxFileSize} per file. The files listed below cannot be uploaded at this time.", - }, - rdss3: { - header: "Large File Upload Restriction", - body: "You have selected files that exceed our upload size cap due to browser constraints and our API's current limitations, set at {maxFileSize} per file for direct uploads. For S3 resources, we recommend using a third-party S3 client to manage large file uploads. Please refer to our {documentation} for more information.", - documentation: { - text: "documentation", - url: "https://docs.coscine.de/en/resources/s3-clients/", - }, - }, - rdss3worm: { - header: "Large File Upload Restriction", - body: "You have selected files that exceed our upload size cap due to browser constraints and our API's current limitations, set at {maxFileSize} per file for direct uploads. For S3-WORM resources, we recommend using a third-party S3 client to manage large file uploads. Please refer to our {documentation} for more information.", - documentation: { - text: "documentation", - url: "https://docs.coscine.de/en/resources/s3-clients/", - }, - }, - }, - }, - modalDeleteFolderContentsHeader: "Delete files and metadata", modalDeleteFolderContentsBody: "Are you sure, you want to delete the following files and metadata:", diff --git a/src/modules/resource/pages/ResourcePage.spec.ts b/src/modules/resource/pages/ResourcePage.spec.ts index 0cb5816302ace1648ebbef848e16e7d0620f5198..2f42b5932c04d4879c135cc25f3fd4a67fe69aa3 100644 --- a/src/modules/resource/pages/ResourcePage.spec.ts +++ b/src/modules/resource/pages/ResourcePage.spec.ts @@ -174,7 +174,7 @@ describe("ResourcePage.vue", async () => { }, ); - test("Should properly handle files on upload, that exceed the upload limit cap", async () => { + test("Should properly handle files on upload", async () => { await wrapper.vm.$nextTick(); // Mock file selection @@ -185,9 +185,7 @@ describe("ResourcePage.vue", async () => { generateDummyFile(1024 * 1024 * 1024 * 3, "oversizedFile2.txt"), // A 3 GiB file ]; - // Starting with a clean state, no files should be present for upload or be marked as oversized - let oversizedFiles: FileInformation[] = wrapper.vm.$data.oversizedFiles; - expect(oversizedFiles.length).toBe(0); + // Starting with a clean state, no files should be present for upload let fileListUpload: FileInformation[] = wrapper.vm.$data.fileListUpload; expect(fileListUpload.length).toBe(0); @@ -195,26 +193,13 @@ describe("ResourcePage.vue", async () => { const fileTrigger = wrapper.findComponent({ ref: "fileTrigger" }); fileTrigger.vm.$emit("input", files); - // After selecting files, the oversized files should be marked and the correct files should be present for upload - oversizedFiles = wrapper.vm.$data.oversizedFiles as FileInformation[]; - expect(oversizedFiles.length).toBe(2); // The 2 GiB and 3 GiB files should be marked as oversized - expect( - oversizedFiles.some((f) => f.name === "oversizedFile1.txt"), - ).toBeTruthy(); - expect( - oversizedFiles.some((f) => f.name === "oversizedFile2.txt"), - ).toBeTruthy(); fileListUpload = wrapper.vm.$data.fileListUpload; - expect(fileListUpload.length).toBe(2); // The 500 MiB and 2 GiB - 1 byte files should be present for upload + expect(fileListUpload.length).toBe(4); // The 500 MiB and 2 GiB - 1 byte files should be present for upload expect( fileListUpload.some((f) => f.name === "normalSizeFile.txt"), ).toBeTruthy(); expect( fileListUpload.some((f) => f.name === "largeSizeFile.txt"), ).toBeTruthy(); - - /* TODO: Test the modal is shown and the user is informed about the oversized files. - I couldn't make it work as of now, as the 'visible' property is inconsistent... - */ }); }); diff --git a/src/modules/resource/pages/ResourcePage.vue b/src/modules/resource/pages/ResourcePage.vue index ed3fe7576f66d09567fe9d3b47c2388aba90e866..7eafa33b867f98515f60a251455ee114a1e606bc 100644 --- a/src/modules/resource/pages/ResourcePage.vue +++ b/src/modules/resource/pages/ResourcePage.vue @@ -122,14 +122,6 @@ <!-- Page Loading Spinner --> <LoadingSpinner :is-waiting-for-response="isWaitingForResponse" /> - <!-- Oversized Files Modal --> - <OversizedFilesModal - :resource-type-information="resourceTypeInformation" - :max-file-byte-size="maxFileByteSize" - :oversized-files="oversizedFiles" - @close="oversizedFiles = []" - /> - <!-- Delete File Modal --> <DeleteFolderContentsModal :visible="deleteModalVisible" @@ -150,7 +142,6 @@ import useMainStore from "@/store/index"; import useProjectStore from "@/modules/project/store"; import FilesView from "../components/resource-page/FilesView.vue"; import MetadataManager from "../components/resource-page/MetadataManager.vue"; -import OversizedFilesModal from "../components/resource-page/modals/OversizedFilesModal.vue"; import DeleteFolderContentsModal from "../components/resource-page/modals/DeleteFolderContentsModal.vue"; import { v4 as uuidv4 } from "uuid"; import { type ExtendedFile, FileUtil } from "@/modules/resource/utils/FileUtil"; @@ -168,7 +159,6 @@ export default defineComponent({ components: { FilesView, MetadataManager, - OversizedFilesModal, DeleteFolderContentsModal, }, @@ -189,13 +179,11 @@ export default defineComponent({ return { isWaitingForResponse: false, showDetail: false, - oversizedFiles: [] as FileInformation[], fileListEdit: [] as FolderContent[], fileListUpload: [] as FileInformation[], filesToBeDeleted: [] as FolderContent[], folderContents: [] as FolderContent[], dragCounter: 0, - maxFileByteSize: 2147483647, // 2 GiB in bytes isFullscreenActive: false, isMetadataManagerHidden: false, @@ -434,24 +422,25 @@ export default defineComponent({ metadata: { [version]: factory.dataset() as unknown as Dataset }, }; - if (file.size > this.maxFileByteSize) { - // File is too large, add its details to oversizedFiles and skip further processing - this.oversizedFiles.push(fileInformation); - continue; // Skip this iteration, do not add the file to fileListUpload + // Prevent duplicates + if ( + !this.fileListUpload.some( + (entry) => entry.path === fileInformation.path, + ) + ) { + this.fileListUpload.push(fileInformation); } - - this.fileListUpload.push(fileInformation); } - // After processing files, check if there are oversized files to notify the user - if (this.oversizedFiles.length > 0) { - // Here, trigger your modal or notification mechanism - this.$bvModal.show("oversizedFilesModal"); - } // Clear selection in files view table ( (this.$refs.filesView as Vue).$refs.adaptTable as BTable ).clearSelected(); + + // Clear form-file inputs + (this.$refs.fileTrigger as BFormFile).reset(); + (this.$refs.folderTrigger as BFormFile).reset(); + this.showDetail = false; },