diff options
Diffstat (limited to 'apps/files/src/components/FilesListTableHeader.vue')
-rw-r--r-- | apps/files/src/components/FilesListTableHeader.vue | 89 |
1 files changed, 53 insertions, 36 deletions
diff --git a/apps/files/src/components/FilesListTableHeader.vue b/apps/files/src/components/FilesListTableHeader.vue index 148ce3bc4e5..23e631199eb 100644 --- a/apps/files/src/components/FilesListTableHeader.vue +++ b/apps/files/src/components/FilesListTableHeader.vue @@ -1,29 +1,12 @@ <!-- - - @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com> - - - - @author John Molakvoæ <skjnldsv@protonmail.com> - - - - @license AGPL-3.0-or-later - - - - This program is free software: you can redistribute it and/or modify - - it under the terms of the GNU Affero General Public License as - - published by the Free Software Foundation, either version 3 of the - - License, or (at your option) any later version. - - - - This program is distributed in the hope that it will be useful, - - but WITHOUT ANY WARRANTY; without even the implied warranty of - - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - - GNU Affero General Public License for more details. - - - - You should have received a copy of the GNU Affero General Public License - - along with this program. If not, see <http://www.gnu.org/licenses/>. - - - --> + - SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> <template> <tr class="files-list__row-head"> <th class="files-list__column files-list__row-checkbox" @keyup.esc.exact="resetSelection"> - <NcCheckboxRadioSwitch v-bind="selectAllBind" @update:checked="onToggleAll" /> + <NcCheckboxRadioSwitch v-bind="selectAllBind" data-cy-files-list-selection-checkbox @update:checked="onToggleAll" /> </th> <!-- Columns display --> @@ -41,6 +24,14 @@ <!-- Actions --> <th class="files-list__row-actions" /> + <!-- Mime --> + <th v-if="isMimeAvailable" + class="files-list__column files-list__row-mime" + :class="{ 'files-list__column--sortable': isMimeAvailable }" + :aria-sort="ariaSortForMode('mime')"> + <FilesListTableHeaderButton :name="t('files', 'File type')" mode="mime" /> + </th> + <!-- Size --> <th v-if="isSizeAvailable" class="files-list__column files-list__row-size" @@ -71,24 +62,28 @@ </template> <script lang="ts"> +import type { Node } from '@nextcloud/files' +import type { PropType } from 'vue' +import type { FileSource } from '../types.ts' + import { translate as t } from '@nextcloud/l10n' -import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js' -import Vue from 'vue' +import { useHotKey } from '@nextcloud/vue/composables/useHotKey' +import { defineComponent } from 'vue' +import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch' import { useFilesStore } from '../store/files.ts' +import { useNavigation } from '../composables/useNavigation' import { useSelectionStore } from '../store/selection.ts' -import FilesListTableHeaderActions from './FilesListTableHeaderActions.vue' import FilesListTableHeaderButton from './FilesListTableHeaderButton.vue' import filesSortingMixin from '../mixins/filesSorting.ts' -import logger from '../logger.js' +import logger from '../logger.ts' -export default Vue.extend({ +export default defineComponent({ name: 'FilesListTableHeader', components: { FilesListTableHeaderButton, NcCheckboxRadioSwitch, - FilesListTableHeaderActions, }, mixins: [ @@ -96,6 +91,10 @@ export default Vue.extend({ ], props: { + isMimeAvailable: { + type: Boolean, + default: false, + }, isMtimeAvailable: { type: Boolean, default: false, @@ -105,7 +104,7 @@ export default Vue.extend({ default: false, }, nodes: { - type: Array, + type: Array as PropType<Node[]>, required: true, }, filesListWidth: { @@ -117,17 +116,17 @@ export default Vue.extend({ setup() { const filesStore = useFilesStore() const selectionStore = useSelectionStore() + const { currentView } = useNavigation() + return { filesStore, selectionStore, + + currentView, } }, computed: { - currentView() { - return this.$navigation.active - }, - columns() { // Hide columns if the list is too small if (this.filesListWidth < 512) { @@ -168,8 +167,23 @@ export default Vue.extend({ }, }, + created() { + // ctrl+a selects all + useHotKey('a', this.onToggleAll, { + ctrl: true, + stop: true, + prevent: true, + }) + + // Escape key cancels selection + useHotKey('Escape', this.resetSelection, { + stop: true, + prevent: true, + }) + }, + methods: { - ariaSortForMode(mode: string): ARIAMixin['ariaSort'] { + ariaSortForMode(mode: string): 'ascending'|'descending'|null { if (this.sortingMode === mode) { return this.isAscSorting ? 'ascending' : 'descending' } @@ -181,13 +195,13 @@ export default Vue.extend({ 'files-list__column': true, 'files-list__column--sortable': !!column.sort, 'files-list__row-column-custom': true, - [`files-list__row-${this.currentView.id}-${column.id}`]: true, + [`files-list__row-${this.currentView?.id}-${column.id}`]: true, } }, - onToggleAll(selected) { + onToggleAll(selected = true) { if (selected) { - const selection = this.nodes.map(node => node.fileid.toString()) + const selection = this.nodes.map(node => node.source).filter(Boolean) as FileSource[] logger.debug('Added all nodes to selection', { selection }) this.selectionStore.setLastIndex(null) this.selectionStore.set(selection) @@ -198,6 +212,9 @@ export default Vue.extend({ }, resetSelection() { + if (this.isNoneSelected) { + return + } this.selectionStore.reset() }, |