From 085bc0c4cb0842553c28145b379d2de898f463cf Mon Sep 17 00:00:00 2001 From: Wilfred Asomani Date: Tue, 4 Apr 2023 15:57:38 +0000 Subject: [PATCH] web/satellite: fix browser hover and click behaviour This change adds checkboxes to file items in the browser so they can be selected that way instead of the previous click behaviour, which now opens the object modal for files and open folder for folders. This change also features some styling fixes for the browser. Issue: https://github.com/storj/storj/issues/5726 Change-Id: I5b38208a8e8673d8212c749586bdb7e169c086f8 --- .../src/components/browser/FileBrowser.vue | 82 +++++++++++++++---- .../components/browser/FileBrowserHeader.vue | 7 +- .../src/components/browser/FileEntry.vue | 54 +++++++++--- .../components/browser/LockedFilesEntry.vue | 2 + .../src/components/browser/UpEntry.vue | 3 +- .../src/components/common/TableItem.vue | 22 ++--- .../src/components/common/VTable.vue | 20 ++++- .../src/components/common/VTableCheckbox.vue | 22 +++-- .../components/team/ProjectMemberListItem.vue | 2 +- .../components/team/ProjectMembersArea.vue | 2 +- 10 files changed, 159 insertions(+), 57 deletions(-) diff --git a/web/satellite/src/components/browser/FileBrowser.vue b/web/satellite/src/components/browser/FileBrowser.vue index 9c20161a8..7b675738c 100644 --- a/web/satellite/src/components/browser/FileBrowser.vue +++ b/web/satellite/src/components/browser/FileBrowser.vue @@ -95,7 +95,7 @@ :on-close="closeBanner" /> - + @@ -105,8 +105,9 @@ :key="index" > +

@@ -114,7 +115,7 @@ {{ filename(file) }}

- +
- + - + - + + {{ formattedFilesWaitingToBeUploaded }} waiting to be uploaded... - - + + @@ -318,21 +320,42 @@ const bucketName = computed((): string => { return store.state.files.bucket; }); -const files = computed((): BrowserFile[] => { +/** + * Whether all files are selected. + * */ +const allFilesSelected = computed((): boolean => { + if (files.value.length === 0) { + return false; + } + const shiftSelectedFiles = store.state.files.shiftSelectedFiles; + const selectedFiles = store.state.files.selectedFiles; + const selectedAnchorFile = store.state.files.selectedAnchorFile; + const allSelectedFiles = [ + ...selectedFiles, + ...shiftSelectedFiles, + ]; + + if (selectedAnchorFile && !allSelectedFiles.includes(selectedAnchorFile)) { + allSelectedFiles.push(selectedAnchorFile); + } + return allSelectedFiles.length === files.value.length; +}); + +const files = computed((): BrowserObject[] => { return store.getters['files/sortedFiles']; }); /** * Return an array of BrowserFile type that are files and not folders. */ -const singleFiles = computed((): BrowserFile[] => { +const singleFiles = computed((): BrowserObject[] => { return files.value.filter((f) => f.type === 'file'); }); /** * Return an array of BrowserFile type that are folders and not files. */ -const folders = computed((): BrowserFile[] => { +const folders = computed((): BrowserObject[] => { return files.value.filter((f) => f.type === 'folder'); }); @@ -382,9 +405,7 @@ function closeModalDropdown(): void { store.dispatch('files/closeDropdown'); } - if (store.state.files.selectedFile) { - store.dispatch('files/clearAllSelectedFiles'); - } + store.dispatch('files/clearAllSelectedFiles'); } /** @@ -477,6 +498,22 @@ async function goToBuckets(): Promise { await onRouteChange(); } +/** + * Toggles the selection of all files. + * */ +async function toggleSelectAllFiles(): Promise { + if (files.value.length === 0) { + return; + } + if (allFilesSelected.value) { + await store.dispatch('files/clearAllSelectedFiles'); + } else { + await store.dispatch('files/clearAllSelectedFiles'); + store.commit('files/setSelectedAnchorFile', files.value[0]); + await store.dispatch('files/updateSelectedFiles', files.value.slice(1, files.value.length)); + } +} + /** * Set spinner state. If routePath is not present navigate away. * If there's some error then re-render the page with a call to list. @@ -491,6 +528,9 @@ onBeforeMount(async () => { return; } + // clear previous file selections. + store.dispatch('files/clearAllSelectedFiles'); + // display the spinner while files are being fetched fetchingFilesSpinner.value = true; @@ -513,6 +553,20 @@ onBeforeMount(async () => { min-height: 500px; } +.hide-mobile { + @media screen and (max-width: 550px) { + display: none; + } +} + +@media screen and (max-width: 550px) { + // hide size, upload date columns on mobile screens + + :deep(.data:not(:nth-child(2))) { + display: none; + } +} + .position-relative { position: relative; } diff --git a/web/satellite/src/components/browser/FileBrowserHeader.vue b/web/satellite/src/components/browser/FileBrowserHeader.vue index af6c1c492..bc1fa0c8c 100644 --- a/web/satellite/src/components/browser/FileBrowserHeader.vue +++ b/web/satellite/src/components/browser/FileBrowserHeader.vue @@ -111,9 +111,9 @@ function fromFilesStore(prop: string): string { /** * Check if the trashcan to delete selected files/folder should be displayed. */ -const filesToDelete = computed((): string => { +const filesToDelete = computed((): boolean => { return (!!store.state.files.selectedAnchorFile || ( - store.state.files.unselectedAnchorFile && + !!store.state.files.unselectedAnchorFile && (store.state.files.selectedFiles.length > 0 || store.state.files.shiftSelectedFiles.length > 0) )); @@ -219,7 +219,8 @@ function cancelDeleteSelection(): void { } &__functional { - padding: 0 10px; + padding: 0; + width: 50px; position: relative; cursor: pointer; diff --git a/web/satellite/src/components/browser/FileEntry.vue b/web/satellite/src/components/browser/FileEntry.vue index ede99d7a8..c53b44c1d 100644 --- a/web/satellite/src/components/browser/FileEntry.vue +++ b/web/satellite/src/components/browser/FileEntry.vue @@ -4,11 +4,13 @@