Remember sort order
This commit is contained in:
parent
6880f82c19
commit
36826a83c1
|
@ -5,9 +5,9 @@
|
||||||
<th class="selection">
|
<th class="selection">
|
||||||
<input type="checkbox" tabindex="-1" v-model="allSelected" :indeterminate="selectionIndeterminate">
|
<input type="checkbox" tabindex="-1" v-model="allSelected" :indeterminate="selectionIndeterminate">
|
||||||
</th>
|
</th>
|
||||||
<th class="sortcolumn" :class="{ sortactive: sort === 'name' }" @click="toggleSort('name')">Name</th>
|
<th class="sortcolumn" :class="{ sortactive: store.sortOrder === 'name' }" @click="store.toggleSort('name')">Name</th>
|
||||||
<th class="sortcolumn modified right" :class="{ sortactive: sort === 'modified' }" @click="toggleSort('modified')">Modified</th>
|
<th class="sortcolumn modified right" :class="{ sortactive: store.sortOrder === 'modified' }" @click="store.toggleSort('modified')">Modified</th>
|
||||||
<th class="sortcolumn size right" :class="{ sortactive: sort === 'size' }" @click="toggleSort('size')">Size</th>
|
<th class="sortcolumn size right" :class="{ sortactive: store.sortOrder === 'size' }" @click="store.toggleSort('size')">Size</th>
|
||||||
<th class="menu"></th>
|
<th class="menu"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<FileSize :doc=editing />
|
<FileSize :doc=editing />
|
||||||
<td class="menu"></td>
|
<td class="menu"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<template v-for="(doc, index) in sortedDocuments" :key="doc.key">
|
<template v-for="(doc, index) in documents" :key="doc.key">
|
||||||
<tr class="folder-change" v-if="showFolderBreadcrumb(index)">
|
<tr class="folder-change" v-if="showFolderBreadcrumb(index)">
|
||||||
<th colspan="5"><BreadCrumb :path="doc.loc ? doc.loc.split('/') : []" /></th>
|
<th colspan="5"><BreadCrumb :path="doc.loc ? doc.loc.split('/') : []" /></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -84,9 +84,10 @@ import { useMainStore } from '@/stores/main'
|
||||||
import { Doc } from '@/repositories/Document'
|
import { Doc } from '@/repositories/Document'
|
||||||
import FileRenameInput from './FileRenameInput.vue'
|
import FileRenameInput from './FileRenameInput.vue'
|
||||||
import { connect, controlUrl } from '@/repositories/WS'
|
import { connect, controlUrl } from '@/repositories/WS'
|
||||||
import { collator, formatSize } from '@/utils'
|
import { formatSize } from '@/utils'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import ContextMenu from '@imengyu/vue3-context-menu'
|
import ContextMenu from '@imengyu/vue3-context-menu'
|
||||||
|
import type { SortOrder } from '@/utils/docsort'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
path: Array<string>
|
path: Array<string>
|
||||||
|
@ -121,12 +122,6 @@ const rename = (doc: Doc, newName: string) => {
|
||||||
}
|
}
|
||||||
doc.name = newName // We should get an update from watch but this is quicker
|
doc.name = newName // We should get an update from watch but this is quicker
|
||||||
}
|
}
|
||||||
const sortedDocuments = computed(() => sorted(props.documents))
|
|
||||||
const showFolderBreadcrumb = (i: number) => {
|
|
||||||
const docs = sortedDocuments.value
|
|
||||||
const docloc = docs[i].loc
|
|
||||||
return i === 0 ? docloc !== loc.value : docloc !== docs[i - 1].loc
|
|
||||||
}
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
newFolder() {
|
newFolder() {
|
||||||
const now = Math.floor(Date.now() / 1000)
|
const now = Math.floor(Date.now() / 1000)
|
||||||
|
@ -144,8 +139,8 @@ defineExpose({
|
||||||
allSelected.value = !allSelected.value
|
allSelected.value = !allSelected.value
|
||||||
},
|
},
|
||||||
toggleSortColumn(column: number) {
|
toggleSortColumn(column: number) {
|
||||||
const columns = ['', 'name', 'modified', 'size', '']
|
const order = ['', 'name', 'modified', 'size', ''][column]
|
||||||
toggleSort(columns[column])
|
if (order) store.toggleSort(order as SortOrder)
|
||||||
},
|
},
|
||||||
isCursor() {
|
isCursor() {
|
||||||
return cursor.value !== null && editing.value === null
|
return cursor.value !== null && editing.value === null
|
||||||
|
@ -165,25 +160,25 @@ defineExpose({
|
||||||
},
|
},
|
||||||
cursorMove(d: number, select = false) {
|
cursorMove(d: number, select = false) {
|
||||||
// Move cursor up or down (keyboard navigation)
|
// Move cursor up or down (keyboard navigation)
|
||||||
const documents = sortedDocuments.value
|
const docs = props.documents
|
||||||
if (documents.length === 0) {
|
if (docs.length === 0) {
|
||||||
cursor.value = null
|
cursor.value = null
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const N = documents.length
|
const N = docs.length
|
||||||
const mod = (a: number, b: number) => ((a % b) + b) % b
|
const mod = (a: number, b: number) => ((a % b) + b) % b
|
||||||
const increment = (i: number, d: number) => mod(i + d, N + 1)
|
const increment = (i: number, d: number) => mod(i + d, N + 1)
|
||||||
const index =
|
const index =
|
||||||
cursor.value !== null ? documents.indexOf(cursor.value) : documents.length
|
cursor.value !== null ? docs.indexOf(cursor.value) : docs.length
|
||||||
const moveto = increment(index, d)
|
const moveto = increment(index, d)
|
||||||
cursor.value = documents[moveto] ?? null
|
cursor.value = docs[moveto] ?? null
|
||||||
const tr = cursor.value ? document.getElementById(`file-${cursor.value.key}`) : null
|
const tr = cursor.value ? document.getElementById(`file-${cursor.value.key}`) : null
|
||||||
if (select) {
|
if (select) {
|
||||||
// Go forwards, possibly wrapping over the end; the last entry is not toggled
|
// Go forwards, possibly wrapping over the end; the last entry is not toggled
|
||||||
let [begin, end] = d > 0 ? [index, moveto] : [moveto, index]
|
let [begin, end] = d > 0 ? [index, moveto] : [moveto, index]
|
||||||
for (let p = begin; p !== end; p = increment(p, 1)) {
|
for (let p = begin; p !== end; p = increment(p, 1)) {
|
||||||
if (p === N) continue
|
if (p === N) continue
|
||||||
const key = documents[p].key
|
const key = docs[p].key
|
||||||
if (store.selected.has(key)) store.selected.delete(key)
|
if (store.selected.has(key)) store.selected.delete(key)
|
||||||
else store.selected.add(key)
|
else store.selected.add(key)
|
||||||
}
|
}
|
||||||
|
@ -254,22 +249,10 @@ const mkdir = (doc: Doc, name: string) => {
|
||||||
doc.name = name
|
doc.name = name
|
||||||
doc.key = crypto.randomUUID()
|
doc.key = crypto.randomUUID()
|
||||||
}
|
}
|
||||||
|
const showFolderBreadcrumb = (i: number) => {
|
||||||
// Column sort
|
const docs = props.documents
|
||||||
const toggleSort = (name: string) => {
|
const docloc = docs[i].loc
|
||||||
sort.value = sort.value === name ? '' : name
|
return i === 0 ? docloc !== loc.value : docloc !== docs[i - 1].loc
|
||||||
}
|
|
||||||
const sort = ref<string>('')
|
|
||||||
const sortCompare = {
|
|
||||||
name: (a: Doc, b: Doc) => collator.compare(a.name, b.name),
|
|
||||||
modified: (a: Doc, b: Doc) => b.mtime - a.mtime,
|
|
||||||
size: (a: Doc, b: Doc) => b.size - a.size
|
|
||||||
}
|
|
||||||
const sorted = (documents: Doc[]) => {
|
|
||||||
const cmp = sortCompare[sort.value as keyof typeof sortCompare]
|
|
||||||
const sorted = [...documents]
|
|
||||||
if (cmp) sorted.sort(cmp)
|
|
||||||
return sorted
|
|
||||||
}
|
}
|
||||||
const selectionIndeterminate = computed({
|
const selectionIndeterminate = computed({
|
||||||
get: () => {
|
get: () => {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { collator } from '@/utils'
|
||||||
import { logoutUser } from '@/repositories/User'
|
import { logoutUser } from '@/repositories/User'
|
||||||
import { watchConnect } from '@/repositories/WS'
|
import { watchConnect } from '@/repositories/WS'
|
||||||
import { shallowRef } from 'vue'
|
import { shallowRef } from 'vue'
|
||||||
|
import { sorted, type SortOrder } from '@/utils/docsort'
|
||||||
|
|
||||||
type User = {
|
type User = {
|
||||||
username: string
|
username: string
|
||||||
|
@ -18,10 +19,15 @@ export const useMainStore = defineStore({
|
||||||
state: () => ({
|
state: () => ({
|
||||||
document: shallowRef<Doc[]>([]),
|
document: shallowRef<Doc[]>([]),
|
||||||
selected: new Set<FUID>(),
|
selected: new Set<FUID>(),
|
||||||
|
query: '' as string,
|
||||||
fileExplorer: null as any,
|
fileExplorer: null as any,
|
||||||
error: '' as string,
|
error: '' as string,
|
||||||
connected: false,
|
connected: false,
|
||||||
server: {} as Record<string, any>,
|
server: {} as Record<string, any>,
|
||||||
|
prefs: {
|
||||||
|
sortListing: '' as SortOrder,
|
||||||
|
sortFiltered: '' as SortOrder,
|
||||||
|
},
|
||||||
user: {
|
user: {
|
||||||
username: '',
|
username: '',
|
||||||
privileged: false,
|
privileged: false,
|
||||||
|
@ -29,6 +35,9 @@ export const useMainStore = defineStore({
|
||||||
isOpenLoginModal: false
|
isOpenLoginModal: false
|
||||||
} as User
|
} as User
|
||||||
}),
|
}),
|
||||||
|
persist: {
|
||||||
|
paths: ['prefs'],
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
updateRoot(root: FileEntry[]) {
|
updateRoot(root: FileEntry[]) {
|
||||||
const docs = []
|
const docs = []
|
||||||
|
@ -63,22 +72,16 @@ export const useMainStore = defineStore({
|
||||||
this.$reset()
|
this.$reset()
|
||||||
localStorage.clear()
|
localStorage.clear()
|
||||||
history.go() // Reload page
|
history.go() // Reload page
|
||||||
}
|
},
|
||||||
|
toggleSort(name: SortOrder) {
|
||||||
|
if (this.query) this.prefs.sortFiltered = this.prefs.sortFiltered === name ? '' : name
|
||||||
|
else this.prefs.sortListing = this.prefs.sortListing === name ? '' : name
|
||||||
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
isUserLogged(): boolean {
|
sortOrder(): SortOrder { return this.query ? this.prefs.sortFiltered : this.prefs.sortListing },
|
||||||
return this.user.isLoggedIn
|
isUserLogged(): boolean { return this.user.isLoggedIn },
|
||||||
},
|
recentDocuments(): Doc[] { return sorted(this.document, 'modified') },
|
||||||
recentDocuments(): Doc[] {
|
|
||||||
const ret = [...this.document]
|
|
||||||
ret.sort((a, b) => b.mtime - a.mtime)
|
|
||||||
return ret
|
|
||||||
},
|
|
||||||
largeDocuments(): Doc[] {
|
|
||||||
const ret = [...this.document]
|
|
||||||
ret.sort((a, b) => b.size - a.size)
|
|
||||||
return ret
|
|
||||||
},
|
|
||||||
selectedFiles(): SelectedItems {
|
selectedFiles(): SelectedItems {
|
||||||
const selected = this.selected
|
const selected = this.selected
|
||||||
const found = new Set<FUID>()
|
const found = new Set<FUID>()
|
||||||
|
|
15
frontend/src/utils/docsort.ts
Normal file
15
frontend/src/utils/docsort.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Doc } from '@/repositories/Document'
|
||||||
|
import { collator } from '@/utils'
|
||||||
|
|
||||||
|
export const ordering = {
|
||||||
|
name: (a: Doc, b: Doc) => collator.compare(a.name, b.name),
|
||||||
|
modified: (a: Doc, b: Doc) => b.mtime - a.mtime,
|
||||||
|
size: (a: Doc, b: Doc) => b.size - a.size
|
||||||
|
}
|
||||||
|
export type SortOrder = keyof typeof ordering | ''
|
||||||
|
export const sorted = (documents: Doc[], order: SortOrder) => {
|
||||||
|
if (!order) return documents
|
||||||
|
const sorted = [...documents]
|
||||||
|
sorted.sort(ordering[order])
|
||||||
|
return sorted
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import { watchEffect, ref, computed } from 'vue'
|
||||||
import { useMainStore } from '@/stores/main'
|
import { useMainStore } from '@/stores/main'
|
||||||
import Router from '@/router/index'
|
import Router from '@/router/index'
|
||||||
import { needleFormat, localeIncludes, collator } from '@/utils';
|
import { needleFormat, localeIncludes, collator } from '@/utils';
|
||||||
|
import { sorted } from '@/utils/docsort';
|
||||||
|
|
||||||
const store = useMainStore()
|
const store = useMainStore()
|
||||||
const fileExplorer = ref()
|
const fileExplorer = ref()
|
||||||
|
@ -24,7 +25,10 @@ const documents = computed(() => {
|
||||||
const loc = props.path.join('/')
|
const loc = props.path.join('/')
|
||||||
const query = props.query
|
const query = props.query
|
||||||
// List the current location
|
// List the current location
|
||||||
if (!query) return store.document.filter(doc => doc.loc === loc)
|
if (!query) return sorted(
|
||||||
|
store.document.filter(doc => doc.loc === loc),
|
||||||
|
store.prefs.sortListing,
|
||||||
|
)
|
||||||
// Find up to 100 newest documents that match the search
|
// Find up to 100 newest documents that match the search
|
||||||
const needle = needleFormat(query)
|
const needle = needleFormat(query)
|
||||||
let limit = 100
|
let limit = 100
|
||||||
|
@ -35,8 +39,11 @@ const documents = computed(() => {
|
||||||
if (--limit === 0) break
|
if (--limit === 0) break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Organize by folder, by relevance
|
|
||||||
const locsub = loc + '/'
|
const locsub = loc + '/'
|
||||||
|
// Custom sort override in effect?
|
||||||
|
const order = store.prefs.sortFiltered
|
||||||
|
if (order) return sorted(docs, order)
|
||||||
|
// Sort by relevance - current folder, then subfolders, then others
|
||||||
docs.sort((a, b) => (
|
docs.sort((a, b) => (
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
(b.loc === loc) - (a.loc === loc) ||
|
(b.loc === loc) - (a.loc === loc) ||
|
||||||
|
@ -54,5 +61,6 @@ const documents = computed(() => {
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
store.fileExplorer = fileExplorer.value
|
store.fileExplorer = fileExplorer.value
|
||||||
|
store.query = props.query
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user