From 6ef006a8faeaa392267546d2b2382355d50aac12 Mon Sep 17 00:00:00 2001 From: NicolasRichel Date: Wed, 2 Jun 2021 14:30:39 +0200 Subject: [PATCH] feat(files-manager): add file-upload feature + some fixes on file management --- .../generic/generic-table/GenericTable.scss | 8 + .../generic/generic-table/GenericTable.vue | 8 + .../generic/mapbox-wrapper/MapboxWrapper.vue | 2 +- .../file-upload-button/FileUploadButton.vue | 61 +----- .../files/files-manager/FilesManager.vue | 37 +++- .../files-action-bar/FilesActionBar.vue | 8 +- .../specific/files/files-table/FilesTable.vue | 67 ++++++- .../file-actions-cell/FileActionsCell.vue | 18 +- .../file-upload-cell/FileUploadCell.scss | 64 ++++++ .../file-upload-cell/FileUploadCell.vue | 182 ++++++++++++++++++ .../models/models-card/ModelsCard.vue | 11 +- .../ModelsCardModelPreview.vue | 8 +- .../models/models-overview/ModelsOverview.vue | 14 +- src/state/files.js | 12 +- src/utils/file-structure.js | 4 +- .../project-files/ProjectFiles.vue | 22 ++- .../project-overview/ProjectOverview.vue | 3 + 17 files changed, 425 insertions(+), 104 deletions(-) create mode 100644 src/components/specific/files/files-table/file-upload-cell/FileUploadCell.scss create mode 100644 src/components/specific/files/files-table/file-upload-cell/FileUploadCell.vue diff --git a/src/components/generic/generic-table/GenericTable.scss b/src/components/generic/generic-table/GenericTable.scss index 44a034af8..4535de91f 100644 --- a/src/components/generic/generic-table/GenericTable.scss +++ b/src/components/generic/generic-table/GenericTable.scss @@ -26,6 +26,14 @@ th { font-weight: bold; color: $color-primary; + + &.cell-sub-header { + min-height: 0; + padding: 0; + text-align: left; + font-weight: normal; + color: $color-tertiary-darkest; + } } td { diff --git a/src/components/generic/generic-table/GenericTable.vue b/src/components/generic/generic-table/GenericTable.vue index 141d35040..2b62c2e91 100644 --- a/src/components/generic/generic-table/GenericTable.vue +++ b/src/components/generic/generic-table/GenericTable.vue @@ -30,6 +30,14 @@ + + + + + diff --git a/src/components/specific/files/file-upload-button/FileUploadButton.vue b/src/components/specific/files/file-upload-button/FileUploadButton.vue index a3b48bdaf..ef5579dd7 100644 --- a/src/components/specific/files/file-upload-button/FileUploadButton.vue +++ b/src/components/specific/files/file-upload-button/FileUploadButton.vue @@ -15,10 +15,7 @@ diff --git a/src/components/specific/files/files-table/FilesTable.vue b/src/components/specific/files/files-table/FilesTable.vue index 5f194804b..563948b5e 100644 --- a/src/components/specific/files/files-table/FilesTable.vue +++ b/src/components/specific/files/files-table/FilesTable.vue @@ -9,6 +9,20 @@ @selection-changed="$emit('selection-changed', $event)" :placeholder="$t('FilesTable.emptyTablePlaceholder')" > + @@ -56,6 +70,7 @@ import FileLastUpdateCell from "./file-last-update-cell/FileLastUpdateCell"; import FileNameCell from "./file-name-cell/FileNameCell"; import FileTagsCell from "./file-tags-cell/FileTagsCell"; import FileTypeCell from "./file-type-cell/FileTypeCell"; +import FileUploadCell from "./file-upload-cell/FileUploadCell"; export default { components: { @@ -64,25 +79,35 @@ export default { FileLastUpdateCell, FileNameCell, FileTagsCell, - FileTypeCell + FileTypeCell, + FileUploadCell }, props: { project: { type: Object, required: true }, + folder: { + type: Object, + required: true + }, files: { type: Array, required: true + }, + filesToUpload: { + type: Array, + default: () => [] } }, emits: [ - "delete-clicked", - "download-clicked", + "delete", + "download", "file-clicked", + "file-uploaded", "selection-changed" ], - setup(props) { + setup(props, { emit }) { const { locale, t } = useI18n(); const columns = ref([]); @@ -109,10 +134,38 @@ export default { { immediate: true } ); + const fileUploads = ref([]); + watch( + () => props.filesToUpload, + () => { + fileUploads.value = fileUploads.value.concat( + props.filesToUpload.map((file, i) => + Object.assign(file, { key: `${i}-${file.name}` }) + ) + ); + }, + { immediate: true } + ); + + const onUploadCompleted = (key, file) => { + cleanUpload(key, 500); + emit("file-uploaded", file); + }; + + const cleanUpload = (key, delay = 100) => { + setTimeout(() => { + const index = fileUploads.value.findIndex(f => f.key === key); + fileUploads.value.splice(index, 1); + }, delay); + }; + return { // References + cleanUpload, columns, + fileUploads, nameEditMode, + onUploadCompleted, // Methods formatBytes }; diff --git a/src/components/specific/files/files-table/file-actions-cell/FileActionsCell.vue b/src/components/specific/files/files-table/file-actions-cell/FileActionsCell.vue index 00c5767c0..c9da260ec 100644 --- a/src/components/specific/files/files-table/file-actions-cell/FileActionsCell.vue +++ b/src/components/specific/files/files-table/file-actions-cell/FileActionsCell.vue @@ -72,13 +72,13 @@ export default { } }, emits: [ - "access-clicked", - "delete-clicked", - "download-clicked", - "tags-clicked", - "update-clicked", - "validation-clicked", - "version-clicked" + "add-tags", + "add-version", + "delete", + "download", + "manage-access", + "request-validation", + "update" ], setup(props, { emit }) { const showMenu = ref(false); @@ -89,9 +89,9 @@ export default { showMenu.value = !showMenu.value; }; - const onClick = eventType => { + const onClick = event => { closeMenu(); - emit(`${eventType}-clicked`, props.file); + emit(event, props.file); }; return { diff --git a/src/components/specific/files/files-table/file-upload-cell/FileUploadCell.scss b/src/components/specific/files/files-table/file-upload-cell/FileUploadCell.scss new file mode 100644 index 000000000..03e99874d --- /dev/null +++ b/src/components/specific/files/files-table/file-upload-cell/FileUploadCell.scss @@ -0,0 +1,64 @@ +.file-upload-cell { + display: flex; + align-items: center; + gap: $spacing-unit; + height: 44px; + padding: $spacing-unit; + font-size: 0.8rem; + background-color: $color-white; + + &.failed { + border: 2px solid $color-high; + background-color: #fff2f2; + } + + &--center { + flex-grow: 1; + } + + &__info { + color: $color-tertiary-dark; + + &__file-name { + margin-bottom: $spacing-unit/4; + } + + &__progress-bar { + width: 100%; + height: 4px; + border-radius: 2px; + background-color: $color-tertiary; + + .progress-level { + height: 100%; + border-radius: 2px; + background-color: $color-primary; + } + } + + &__upload-data { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: $spacing-unit/4; + font-style: italic; + + .message { + &::before { + content: "-"; + margin-right: $spacing-unit/3; + color: $color-tertiary-dark; + } + margin-left: $spacing-unit/3; + font-weight: bold; + color: $color-high; + } + } + } + + &__btn-cancel { + border: 1px solid $color-tertiary-dark; + color: $color-tertiary-dark; + transform: scale(0.8); + } +} diff --git a/src/components/specific/files/files-table/file-upload-cell/FileUploadCell.vue b/src/components/specific/files/files-table/file-upload-cell/FileUploadCell.vue new file mode 100644 index 000000000..b886b98e8 --- /dev/null +++ b/src/components/specific/files/files-table/file-upload-cell/FileUploadCell.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/src/components/specific/models/models-card/ModelsCard.vue b/src/components/specific/models/models-card/ModelsCard.vue index d525c363e..bb6a5a9d9 100644 --- a/src/components/specific/models/models-card/ModelsCard.vue +++ b/src/components/specific/models/models-card/ModelsCard.vue @@ -43,18 +43,20 @@ export default { setup(props, { emit }) { const router = useRouter(); - const currentModel = ref(); + const currentModel = ref(null); watch( () => props.models, () => { - currentModel.value = props.models[0]; + currentModel.value = props.models.length > 0 ? props.models[0] : null; }, { immediate: true } ); const onModelChange = model => { - currentModel.value = model; - emit("model-changed", model); + if (!currentModel.value || currentModel.value.id !== model.id) { + currentModel.value = model; + emit("model-changed", model); + } }; const goToModelViewer = () => { @@ -69,6 +71,7 @@ export default { }; return { + // Methods goToModelViewer, onModelChange }; diff --git a/src/components/specific/models/models-card/models-card-model-preview/ModelsCardModelPreview.vue b/src/components/specific/models/models-card/models-card-model-preview/ModelsCardModelPreview.vue index 56e0a305d..bb270980d 100644 --- a/src/components/specific/models/models-card/models-card-model-preview/ModelsCardModelPreview.vue +++ b/src/components/specific/models/models-card/models-card-model-preview/ModelsCardModelPreview.vue @@ -112,9 +112,11 @@ export default { }, { immediate: true } ); - watch(index, i => { - image.value = images.value[i] || null; - emit("model-changed", props.models[i]); + watch(index, (newIndex, oldIndex) => { + if (newIndex !== oldIndex) { + image.value = images.value[newIndex] || null; + emit("model-changed", props.models[newIndex]); + } }); return { diff --git a/src/components/specific/models/models-overview/ModelsOverview.vue b/src/components/specific/models/models-overview/ModelsOverview.vue index 8e4db7b98..5ed7db2e9 100644 --- a/src/components/specific/models/models-overview/ModelsOverview.vue +++ b/src/components/specific/models/models-overview/ModelsOverview.vue @@ -22,7 +22,7 @@