mirror of https://github.com/nextcloud/server.git
feat(files): implement sorting per view
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>pull/36534/head
parent
0b4da6117f
commit
3c3050c76f
@ -0,0 +1,160 @@
|
||||
<!--
|
||||
- @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
|
||||
-
|
||||
- @author Gary Kim <gary@garykim.dev>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- 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/>.
|
||||
-
|
||||
-->
|
||||
<template>
|
||||
<NcButton :aria-label="sortAriaLabel(name)"
|
||||
:class="{'files-list__column-sort-button--active': sortingMode === mode}"
|
||||
class="files-list__column-sort-button"
|
||||
type="tertiary"
|
||||
@click="toggleSortBy(mode)">
|
||||
<!-- Sort icon before text as size is align right -->
|
||||
<MenuUp v-if="sortingMode !== mode || isAscSorting" slot="icon" />
|
||||
<MenuDown v-else slot="icon" />
|
||||
{{ name }}
|
||||
</NcButton>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { mapState } from 'pinia'
|
||||
import { translate } from '@nextcloud/l10n'
|
||||
import MenuDown from 'vue-material-design-icons/MenuDown.vue'
|
||||
import MenuUp from 'vue-material-design-icons/MenuUp.vue'
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
import Vue from 'vue'
|
||||
|
||||
import { useSortingStore } from '../store/sorting'
|
||||
|
||||
Vue.config.performance = true
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'FilesListHeaderButton',
|
||||
|
||||
components: {
|
||||
MenuDown,
|
||||
MenuUp,
|
||||
NcButton,
|
||||
},
|
||||
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
setup() {
|
||||
const sortingStore = useSortingStore()
|
||||
return {
|
||||
sortingStore,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(useSortingStore, ['filesSortingConfig']),
|
||||
|
||||
currentView() {
|
||||
return this.$navigation.active
|
||||
},
|
||||
|
||||
sortingMode() {
|
||||
return this.sortingStore.getSortingMode(this.currentView.id)
|
||||
|| this.currentView.defaultSortKey
|
||||
|| 'basename'
|
||||
},
|
||||
isAscSorting() {
|
||||
return this.sortingStore.isAscSorting(this.currentView.id) === true
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
sortAriaLabel(column) {
|
||||
const direction = this.isAscSorting
|
||||
? this.t('files', 'ascending')
|
||||
: this.t('files', 'descending')
|
||||
return this.t('files', 'Sort list by {column} ({direction})', {
|
||||
column,
|
||||
direction,
|
||||
})
|
||||
},
|
||||
|
||||
toggleSortBy(key) {
|
||||
// If we're already sorting by this key, flip the direction
|
||||
if (this.sortingMode === key) {
|
||||
this.sortingStore.toggleSortingDirection(this.currentView.id)
|
||||
return
|
||||
}
|
||||
// else sort ASC by this new key
|
||||
this.sortingStore.setSortingBy(key, this.currentView.id)
|
||||
},
|
||||
|
||||
toggleSortByCustomColumn(column) {
|
||||
if (!column.sort) {
|
||||
return
|
||||
}
|
||||
this.toggleSortBy(column.id)
|
||||
},
|
||||
|
||||
t: translate,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.files-list__column-sort-button {
|
||||
// Compensate for cells margin
|
||||
margin: 0 calc(var(--cell-margin) * -1);
|
||||
// Reverse padding
|
||||
padding: 0 4px 0 16px !important;
|
||||
|
||||
// Icon after text
|
||||
.button-vue__wrapper {
|
||||
flex-direction: row-reverse;
|
||||
// Take max inner width for text overflow ellipsis
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-vue__icon {
|
||||
transition-timing-function: linear;
|
||||
transition-duration: .1s;
|
||||
transition-property: opacity;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.button-vue__text {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&--active,
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
.button-vue__icon {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue