From 154e0d9e68c276361186af39da3e49fa18a75e52 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 4 Sep 2024 14:58:57 +0200 Subject: [PATCH] Select all checkbox tiles view (#11518) * Add select all checkbox to tiles view --- ...ment-add-select-all-checkbox-to-tiles-view | 5 + .../components/OcCheckbox/OcCheckbox.spec.ts | 10 +- .../src/components/OcCheckbox/OcCheckbox.vue | 9 -- .../src/components/Groups/GroupsList.vue | 4 +- .../src/components/Spaces/SpacesList.vue | 4 +- .../src/components/Users/UsersList.vue | 4 +- .../__snapshots__/SpacesList.spec.ts.snap | 6 +- .../views/__snapshots__/Users.spec.ts.snap | 4 +- .../src/components/Search/List.vue | 2 +- .../components/Shares/SharedWithMeSection.vue | 2 +- .../web-app-files/src/views/Favorites.vue | 2 +- .../src/views/shares/SharedViaLink.vue | 2 +- .../src/views/shares/SharedWithOthers.vue | 2 +- .../src/views/spaces/GenericSpace.vue | 2 +- .../src/views/spaces/GenericTrash.vue | 2 +- .../src/views/spaces/Projects.vue | 2 +- .../__snapshots__/Projects.spec.ts.snap | 2 +- .../components/FilesList/ResourceTable.vue | 4 +- .../components/FilesList/ResourceTiles.vue | 122 +++++++++++++----- .../web-pkg/src/components/ItemFilter.vue | 2 +- .../__snapshots__/ResourceTiles.spec.ts.snap | 8 +- 21 files changed, 127 insertions(+), 73 deletions(-) create mode 100644 changelog/unreleased/enhancement-add-select-all-checkbox-to-tiles-view diff --git a/changelog/unreleased/enhancement-add-select-all-checkbox-to-tiles-view b/changelog/unreleased/enhancement-add-select-all-checkbox-to-tiles-view new file mode 100644 index 00000000000..f19d8be027b --- /dev/null +++ b/changelog/unreleased/enhancement-add-select-all-checkbox-to-tiles-view @@ -0,0 +1,5 @@ +Enhancement: Add select all checkbox to tiles view + +We have added a select all checkbox to the tiles view to allow users to select all resources at once. + +https://github.com/owncloud/web/pull/11518 diff --git a/packages/design-system/src/components/OcCheckbox/OcCheckbox.spec.ts b/packages/design-system/src/components/OcCheckbox/OcCheckbox.spec.ts index fe3dc37e101..bab450461b3 100644 --- a/packages/design-system/src/components/OcCheckbox/OcCheckbox.spec.ts +++ b/packages/design-system/src/components/OcCheckbox/OcCheckbox.spec.ts @@ -10,6 +10,7 @@ describe('OcCheckbox', () => { } }) } + const checkboxSelector = "input[type='checkbox']" describe('input id', () => { @@ -28,11 +29,12 @@ describe('OcCheckbox', () => { expect(checkBoxLabelElement.attributes('for')).toBe('test-id') expect(checkBoxLabelElement.text()).toBe('test label') }) - it("should hide label if 'hideLabel' prop is enabled", () => { - const wrapper = getWrapperWithProps({ hideLabel: true }) + it("should hide label if 'labelHidden' prop is enabled", () => { + const wrapper = getWrapperWithProps({ labelHidden: true }) const checkBoxLabelElement = wrapper.find('label') - expect(checkBoxLabelElement.exists()).toBeTruthy() - expect(checkBoxLabelElement.attributes('class')).toContain('oc-invisible-sr') + expect(checkBoxLabelElement.exists()).toBeFalsy() + const checkboxElement = wrapper.find(checkboxSelector) + expect(checkboxElement.attributes('aria-label')).toContain('test label') }) it('should have cursor pointer property if not disabled', () => { const wrapper = getWrapperWithProps({ disabled: false }) diff --git a/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue b/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue index 6f1ecbce810..43f5b5db7b2 100644 --- a/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue +++ b/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue @@ -84,14 +84,6 @@ export default defineComponent({ type: Boolean, default: false }, - /** - * Is the label of the Checkbox visually hidden? - **/ - hideLabel: { - type: Boolean, - required: false, - default: false - }, /** * Size of the Checkbox. Valid values are `small`, `medium` and `large`. * If not specified, defaults to `medium` @@ -132,7 +124,6 @@ export default defineComponent({ }, labelClasses() { return { - 'oc-invisible-sr': this.hideLabel, 'oc-cursor-pointer': !this.disabled } }, diff --git a/packages/web-app-admin-settings/src/components/Groups/GroupsList.vue b/packages/web-app-admin-settings/src/components/Groups/GroupsList.vue index c5f3b817db3..57dfdafb990 100644 --- a/packages/web-app-admin-settings/src/components/Groups/GroupsList.vue +++ b/packages/web-app-admin-settings/src/components/Groups/GroupsList.vue @@ -27,7 +27,7 @@ class="oc-ml-s" :label="$gettext('Select all groups')" :model-value="allGroupsSelected" - hide-label + :label-hidden="true" @update:model-value=" allGroupsSelected ? unselectAllGroups() : selectGroups(paginatedItems) " @@ -40,7 +40,7 @@ :model-value="isGroupSelected(rowData.item)" :option="rowData.item" :label="getSelectGroupLabel(rowData.item)" - hide-label + :label-hidden="true" @update:model-value="selectGroup(rowData.item)" @click.stop="rowClicked([rowData.item, $event])" /> diff --git a/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue b/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue index 9cd1b12062c..e0b1e66f482 100644 --- a/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue +++ b/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue @@ -28,7 +28,7 @@ class="oc-ml-s" :label="$gettext('Select all spaces')" :model-value="allSpacesSelected" - hide-label + :label-hidden="true" @update:model-value=" allSpacesSelected ? unselectAllSpaces() : selectSpaces(paginatedItems) " @@ -41,7 +41,7 @@ :model-value="isSpaceSelected(item)" :option="item" :label="getSelectSpaceLabel(item)" - hide-label + :label-hidden="true" @update:model-value="selectSpace(item)" @click.stop="fileClicked([item, $event])" /> diff --git a/packages/web-app-admin-settings/src/components/Users/UsersList.vue b/packages/web-app-admin-settings/src/components/Users/UsersList.vue index 5d802634628..00579fc9b0a 100644 --- a/packages/web-app-admin-settings/src/components/Users/UsersList.vue +++ b/packages/web-app-admin-settings/src/components/Users/UsersList.vue @@ -27,7 +27,7 @@ class="oc-ml-s" :label="$gettext('Select all users')" :model-value="allUsersSelected" - hide-label + :label-hidden="true" @update:model-value=" allUsersSelected ? unselectAllUsers() : selectUsers(paginatedItems) " @@ -40,7 +40,7 @@ :model-value="isUserSelected(item)" :option="item" :label="getSelectUserLabel(item)" - hide-label + :label-hidden="true" @update:model-value="selectUser(item)" @click.stop="rowClicked([item, $event])" /> diff --git a/packages/web-app-admin-settings/tests/unit/components/Spaces/__snapshots__/SpacesList.spec.ts.snap b/packages/web-app-admin-settings/tests/unit/components/Spaces/__snapshots__/SpacesList.spec.ts.snap index 8fa1176cbef..1dda8d66a47 100644 --- a/packages/web-app-admin-settings/tests/unit/components/Spaces/__snapshots__/SpacesList.spec.ts.snap +++ b/packages/web-app-admin-settings/tests/unit/components/Spaces/__snapshots__/SpacesList.spec.ts.snap @@ -16,7 +16,7 @@ exports[`SpacesList > should render all spaces in a table 1`] = ` -
+
@@ -60,7 +60,7 @@ exports[`SpacesList > should render all spaces in a table 1`] = ` - + 1 Some space @@ -86,7 +86,7 @@ exports[`SpacesList > should render all spaces in a table 1`] = ` - + 2 Another space diff --git a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap index 09991ff9dd5..5329f9a8340 100644 --- a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap +++ b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap @@ -91,7 +91,7 @@ exports[`Users view > list view > renders list initially 1`] = ` -
+
@@ -118,7 +118,7 @@ exports[`Users view > list view > renders list initially 1`] = ` - + diff --git a/packages/web-app-files/src/components/Search/List.vue b/packages/web-app-files/src/components/Search/List.vue index 2e36d1dcdf2..7a372443a2b 100644 --- a/packages/web-app-files/src/components/Search/List.vue +++ b/packages/web-app-files/src/components/Search/List.vue @@ -96,7 +96,7 @@ different files view states > lists all available proje -
+
diff --git a/packages/web-pkg/src/components/FilesList/ResourceTable.vue b/packages/web-pkg/src/components/FilesList/ResourceTable.vue index 37ab5f73f4d..5af42aba952 100644 --- a/packages/web-pkg/src/components/FilesList/ResourceTable.vue +++ b/packages/web-pkg/src/components/FilesList/ResourceTable.vue @@ -43,7 +43,7 @@ size="large" :disabled="resources.length === disabledResources.length" :label="allResourcesCheckboxLabel" - :hide-label="true" + :label-hidden="true" :model-value="areAllResourcesSelected" @click.stop="toggleSelectionAll" /> @@ -53,7 +53,7 @@
-
- - - - - - - -
  • - - - - -
  • -
    -
    +
    + +
    + + + + + + + +
  • + + + + +
  • +
    +
    +
  • { + return props.resources.filter((resource) => props.selectedIds.includes(resource.id)) + }) + const isResourceClickable = (resource: Resource) => { if (isResourceDisabled(resource)) { return false @@ -363,10 +378,31 @@ export default defineComponent({ return resource.processing === true } + const disabledResourceIds = computed(() => { + return ( + props.resources + ?.filter((resource) => isResourceDisabled(resource) === true) + ?.map((resource) => resource.id) || [] + ) + }) + const emitSelect = (selectedIds: string[]) => { emit('update:selectedIds', selectedIds) } + const toggleSelectionAll = () => { + if (unref(areAllResourcesSelected)) { + return emit('update:selectedIds', []) + } + + emit( + 'update:selectedIds', + props.resources + .filter((resource) => !unref(disabledResourceIds).includes(resource.id)) + .map((resource) => resource.id) + ) + } + const showContextMenu = ( event: MouseEvent, item: Resource, @@ -544,6 +580,15 @@ export default defineComponent({ return unref(viewWidth) / unref(maxTilesCurrent) - unref(gapSizePixels) }) + const areAllResourcesSelected = computed(() => { + const allResourcesDisabled = unref(disabledResourceIds).length === props.resources.length + const allSelected = + unref(selectedResources).length === + props.resources.length - unref(disabledResourceIds).length + + return !allResourcesDisabled && allSelected + }) + watch( tileSizePixels, (px: number) => { @@ -590,7 +635,10 @@ export default defineComponent({ isFilePicker, isLocationPicker, isResourceDisabled, - isSpaceResource + isSpaceResource, + areAllResourcesSelected, + disabledResourceIds, + toggleSelectionAll } }, data() { @@ -609,6 +657,10 @@ export default defineComponent({ justify-content: flex-start; row-gap: 1rem; + &-controls { + border-bottom: 1px solid var(--oc-color-border); + } + &-item-drop-highlight { background-color: var(--oc-color-input-border) !important; } diff --git a/packages/web-pkg/src/components/ItemFilter.vue b/packages/web-pkg/src/components/ItemFilter.vue index 1e50bdf4e62..f971ba25ebd 100644 --- a/packages/web-pkg/src/components/ItemFilter.vue +++ b/packages/web-pkg/src/components/ItemFilter.vue @@ -38,7 +38,7 @@ class="item-filter-checkbox oc-mr-s" :label="$gettext('Toggle selection')" :model-value="isItemSelected(item)" - hide-label + :label-hidden="true" @update:model-value="toggleItemSelection(item)" @click.stop /> diff --git a/packages/web-pkg/tests/unit/components/FilesList/__snapshots__/ResourceTiles.spec.ts.snap b/packages/web-pkg/tests/unit/components/FilesList/__snapshots__/ResourceTiles.spec.ts.snap index 4ee9df9fa90..909eba780d7 100644 --- a/packages/web-pkg/tests/unit/components/FilesList/__snapshots__/ResourceTiles.spec.ts.snap +++ b/packages/web-pkg/tests/unit/components/FilesList/__snapshots__/ResourceTiles.spec.ts.snap @@ -2,7 +2,9 @@ exports[`ResourceTiles component > renders a footer slot 1`] = ` "
    - +
    + +
    @@ -11,7 +13,9 @@ exports[`ResourceTiles component > renders a footer slot 1`] = ` exports[`ResourceTiles component > renders an array of spaces correctly 1`] = ` "
    - +
    + +