From a7567ab6f5caa65cb77f77087ab1741c5bab3a6f Mon Sep 17 00:00:00 2001 From: Victor Bianchi Date: Thu, 26 Sep 2024 14:46:01 -0300 Subject: [PATCH] feat: implement file filtering logic WIP Signed-off-by: Victor Bianchi --- src/store/files.js | 344 +++++++++--------- src/store/filesSorting.js | 3 + src/store/filters.js | 3 +- .../FileListFilter/FileListFilterModified.vue | 10 + 4 files changed, 196 insertions(+), 164 deletions(-) diff --git a/src/store/files.js b/src/store/files.js index b5ee266762..affa56fb66 100644 --- a/src/store/files.js +++ b/src/store/files.js @@ -4,6 +4,7 @@ */ import { defineStore } from 'pinia' +import { subscribe } from '@nextcloud/event-bus' import { set } from 'vue' import axios from '@nextcloud/axios' @@ -12,174 +13,191 @@ import { generateOcsUrl } from '@nextcloud/router' import { useSidebarStore } from './sidebar.js' import { useSignStore } from './sign.js' +import { useFiltersStore } from './filters.js' +import { useFilesSortingStore } from './filesSorting.js' -export const useFilesStore = defineStore('files', { - state: () => { - return { - files: {}, - selectedNodeId: 0, - identifyingSigner: false, - loading: false, - filterActive: 'all', - } - }, - - actions: { - addFile(file) { - set(this.files, file.nodeId, file) - this.hydrateFile(file.nodeId) - }, - selectFile(nodeId) { - this.selectedNodeId = nodeId ?? 0 - if (this.selectedNodeId === 0) { - const signStore = useSignStore() - signStore.reset() - return - } - const sidebarStore = useSidebarStore() - sidebarStore.activeRequestSignatureTab() - }, - getFile() { - return this.files[this.selectedNodeId] ?? {} - }, - async flushSelectedFile() { - const files = await this.getAllFiles({ - nodeId: this.selectedNodeId, - }) - this.addFile(files[this.selectedNodeId]) - }, - enableIdentifySigner() { - this.identifyingSigner = true - }, - disableIdentifySigner() { - this.identifyingSigner = false - }, - hasSigners() { - if (this.selectedNodeId === 0) { - return false - } - if (!Object.hasOwn(this.getFile(), 'signers')) { - return false - } - return this.files[this.selectedNodeId].signers.length > 0 - }, - isPartialSigned() { - if (this.selectedNodeId === 0) { - return false - } - if (!Object.hasOwn(this.getFile(), 'signers')) { - return false - } - return this.files[this.selectedNodeId].signers - .filter(signer => signer.signed?.length > 0).length > 0 - }, - isFullSigned() { - if (this.selectedNodeId === 0) { - return false +export const useFilesStore = function(...args) { + const store = defineStore('files', { + state: () => { + return { + files: {}, + selectedNodeId: 0, + identifyingSigner: false, + loading: false, + filterActive: 'all', } - if (!Object.hasOwn(this.getFile(), 'signers')) { - return false - } - return this.files[this.selectedNodeId].signers.length > 0 - && this.files[this.selectedNodeId].signers - .filter(signer => signer.signed?.length > 0).length === this.files[this.selectedNodeId].signers.length - }, - getSubtitle() { - if (this.selectedNodeId === 0) { - return '' - } - const file = this.files[this.selectedNodeId] - if ((file?.requested_by?.userId ?? '').length === 0 || file?.request_date.length === 0) { - return '' - } - return t('libresign', 'Requested by {name}, at {date}', { - name: file.requested_by.userId, - date: Moment(Date.parse(file.request_date)).format('LL LTS'), - }) }, - async hydrateFile(nodeId) { - if (Object.hasOwn(this.files[nodeId], 'uuid')) { - return - } - await axios.get(generateOcsUrl('/apps/libresign/api/v1/file/validate/file_id/{fileId}', { - fileId: nodeId, - })) - .then((response) => { - set(this.files, nodeId, response.data.ocs.data) - this.addUniqueIdentifierToAllSigners(this.files[nodeId].signers) + + actions: { + addFile(file) { + set(this.files, file.nodeId, file) + this.hydrateFile(file.nodeId) + }, + selectFile(nodeId) { + this.selectedNodeId = nodeId ?? 0 + if (this.selectedNodeId === 0) { + const signStore = useSignStore() + signStore.reset() + return + } + const sidebarStore = useSidebarStore() + sidebarStore.activeRequestSignatureTab() + }, + getFile() { + return this.files[this.selectedNodeId] ?? {} + }, + async flushSelectedFile() { + const files = await this.getAllFiles({ + nodeId: this.selectedNodeId, }) - .catch(() => { - set(this.files[nodeId], 'signers', []) + this.addFile(files[this.selectedNodeId]) + }, + enableIdentifySigner() { + this.identifyingSigner = true + }, + disableIdentifySigner() { + this.identifyingSigner = false + }, + hasSigners() { + if (this.selectedNodeId === 0) { + return false + } + if (!Object.hasOwn(this.getFile(), 'signers')) { + return false + } + return this.files[this.selectedNodeId].signers.length > 0 + }, + isPartialSigned() { + if (this.selectedNodeId === 0) { + return false + } + if (!Object.hasOwn(this.getFile(), 'signers')) { + return false + } + return this.files[this.selectedNodeId].signers + .filter(signer => signer.signed?.length > 0).length > 0 + }, + isFullSigned() { + if (this.selectedNodeId === 0) { + return false + } + if (!Object.hasOwn(this.getFile(), 'signers')) { + return false + } + return this.files[this.selectedNodeId].signers.length > 0 + && this.files[this.selectedNodeId].signers + .filter(signer => signer.signed?.length > 0).length === this.files[this.selectedNodeId].signers.length + }, + getSubtitle() { + if (this.selectedNodeId === 0) { + return '' + } + const file = this.files[this.selectedNodeId] + if ((file?.requested_by?.userId ?? '').length === 0 || file?.request_date.length === 0) { + return '' + } + return t('libresign', 'Requested by {name}, at {date}', { + name: file.requested_by.userId, + date: Moment(Date.parse(file.request_date)).format('LL LTS'), }) - }, - addUniqueIdentifierToAllSigners(signers) { - if (signers === undefined) { - return - } - signers.map(signer => this.addIdentifierToSigner(signer)) - }, - addIdentifierToSigner(signer) { - // generate unique code to new signer to be possible delete or edit - if ((signer.identify === undefined || signer.identify === '') && signer.signRequestId === undefined) { - signer.identify = btoa(JSON.stringify(signer)) - } - if (signer.signRequestId) { - signer.identify = signer.signRequestId - } - }, - signerUpdate(signer) { - this.addIdentifierToSigner(signer) - // Remove if already exists - for (let i = this.files[this.selectedNodeId].signers.length - 1; i >= 0; i--) { - if (this.files[this.selectedNodeId].signers[i].identify === signer.identify) { - this.files[this.selectedNodeId].signers.splice(i, 1) - break - } - if (this.files[this.selectedNodeId].signers[i].signRequestId === signer.identify) { - this.files[this.selectedNodeId].signers.splice(i, 1) - break + }, + async hydrateFile(nodeId) { + if (Object.hasOwn(this.files[nodeId], 'uuid')) { + return } - } - this.files[this.selectedNodeId].signers.push(signer) - }, - async deleteSigner(signer) { - if (!isNaN(signer.signRequestId)) { - await axios.delete(generateOcsUrl('/apps/libresign/api/{apiVersion}/sign/file_id/{fileId}/{signRequestId}', { - apiVersion: 'v1', - fileId: this.selectedNodeId, - signRequestId: signer.signRequestId, + await axios.get(generateOcsUrl('/apps/libresign/api/v1/file/validate/file_id/{fileId}', { + fileId: nodeId, })) - } - set( - this.files[this.selectedNodeId], - 'signers', - this.files[this.selectedNodeId].signers.filter((i) => i.identify !== signer.identify), - ) - }, - async getAllFiles(filter) { - const response = await axios.get(generateOcsUrl('/apps/libresign/api/v1/file/list'), { params: filter }) - this.files = {} - response.data.ocs.data.data.forEach(file => { - this.addFile(file) - }) - return this.files - }, - filter(type) { - this.filterActive = type - if (type === 'pending') { - return Object.values(this.files).filter( - (a) => (a.status === 1 || a.status === 2)).sort( - (a, b) => (a.request_date < b.request_date) ? 1 : -1) - } - if (type === 'signed') { - return Object.values(this.files).filter( - (a) => (a.status === 3)).sort( - (a, b) => (a.request_date < b.request_date) ? 1 : -1) - } - if (type === 'all') { - this.filterActive = 'all' - return Object.values(this.files).sort((a, b) => (a.request_date < b.request_date) ? 1 : -1) - } + .then((response) => { + set(this.files, nodeId, response.data.ocs.data) + this.addUniqueIdentifierToAllSigners(this.files[nodeId].signers) + }) + .catch(() => { + set(this.files[nodeId], 'signers', []) + }) + }, + addUniqueIdentifierToAllSigners(signers) { + if (signers === undefined) { + return + } + signers.map(signer => this.addIdentifierToSigner(signer)) + }, + addIdentifierToSigner(signer) { + // generate unique code to new signer to be possible delete or edit + if ((signer.identify === undefined || signer.identify === '') && signer.signRequestId === undefined) { + signer.identify = btoa(JSON.stringify(signer)) + } + if (signer.signRequestId) { + signer.identify = signer.signRequestId + } + }, + signerUpdate(signer) { + this.addIdentifierToSigner(signer) + // Remove if already exists + for (let i = this.files[this.selectedNodeId].signers.length - 1; i >= 0; i--) { + if (this.files[this.selectedNodeId].signers[i].identify === signer.identify) { + this.files[this.selectedNodeId].signers.splice(i, 1) + break + } + if (this.files[this.selectedNodeId].signers[i].signRequestId === signer.identify) { + this.files[this.selectedNodeId].signers.splice(i, 1) + break + } + } + this.files[this.selectedNodeId].signers.push(signer) + }, + async deleteSigner(signer) { + if (!isNaN(signer.signRequestId)) { + await axios.delete(generateOcsUrl('/apps/libresign/api/{apiVersion}/sign/file_id/{fileId}/{signRequestId}', { + apiVersion: 'v1', + fileId: this.selectedNodeId, + signRequestId: signer.signRequestId, + })) + } + set( + this.files[this.selectedNodeId], + 'signers', + this.files[this.selectedNodeId].signers.filter((i) => i.identify !== signer.identify), + ) + }, + async getAllFiles(filter) { + const { chips } = useFiltersStore() + const { sortingMode, sortingDirection } = useFilesSortingStore() + const response = await axios.get(generateOcsUrl('/apps/libresign/api/v1/file/list'), { params: filter }) + this.files = {} + response.data.ocs.data.data.forEach(file => { + this.addFile(file) + }) + return this.files + }, + filter(type) { + this.filterActive = type + if (type === 'pending') { + return Object.values(this.files).filter( + (a) => (a.status === 1 || a.status === 2)).sort( + (a, b) => (a.request_date < b.request_date) ? 1 : -1) + } + if (type === 'signed') { + return Object.values(this.files).filter( + (a) => (a.status === 3)).sort( + (a, b) => (a.request_date < b.request_date) ? 1 : -1) + } + if (type === 'all') { + this.filterActive = 'all' + return Object.values(this.files).sort((a, b) => (a.request_date < b.request_date) ? 1 : -1) + } + }, }, - }, -}) + }) + + const filesStore = store(...args) + + // Make sure we only register the listeners once + if (!filesStore._initialized) { + subscribe('libresign:filters:update', filesStore.getAllFiles) + subscribe('libresign:sorting:update', filesStore.getAllFiles) + filesStore._initialized = true + } + + return filesStore +} diff --git a/src/store/filesSorting.js b/src/store/filesSorting.js index 05549f7b8c..226dd5bb29 100644 --- a/src/store/filesSorting.js +++ b/src/store/filesSorting.js @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +import { emit } from '@nextcloud/event-bus' import { defineStore } from 'pinia' const DEFAULT_SORTING_DIRECTION = 'asc' @@ -16,6 +17,7 @@ export const useFilesSortingStore = defineStore('filesSorting', { actions: { toggleSortingDirection() { this.sortingDirection = this.sortingDirection === 'asc' ? 'desc' : 'asc' + emit('libresign:sorting:update') }, toggleSortBy(key) { @@ -27,6 +29,7 @@ export const useFilesSortingStore = defineStore('filesSorting', { // else sort ASC by this new key this.sortingMode = key this.sortingDirection = DEFAULT_SORTING_DIRECTION + emit('libresign:sorting:update') }, }, }) diff --git a/src/store/filters.js b/src/store/filters.js index cb8c13e1a9..55bf76899b 100644 --- a/src/store/filters.js +++ b/src/store/filters.js @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +import { emit } from '@nextcloud/event-bus' import { defineStore } from 'pinia' import logger from '../helpers/logger.js' @@ -21,7 +22,7 @@ export const useFiltersStore = defineStore('filter', { actions: { onFilterUpdateChips(event) { this.chips = { ...this.chips, [event.id]: [...event.detail] } - + emit('libresign:filters:update') logger.debug('File list filter chips updated', { chips: event.detail }) }, }, diff --git a/src/views/FilesList/FileListFilter/FileListFilterModified.vue b/src/views/FilesList/FileListFilter/FileListFilterModified.vue index 8634199086..e725c0ce39 100644 --- a/src/views/FilesList/FileListFilter/FileListFilterModified.vue +++ b/src/views/FilesList/FileListFilter/FileListFilterModified.vue @@ -53,25 +53,35 @@ export default { { id: 'today', label: t('libresign', 'Today'), + start: '', + end: '', filter: (time) => time > startOfToday(), }, { id: 'last-7', label: t('libresign', 'Last 7 days'), + start: '', + end: '', filter: (time) => time > (startOfToday() - (7 * 24 * 60 * 60 * 1000)), }, { id: 'last-30', label: t('libresign', 'Last 30 days'), + start: '', + end: '', filter: (time) => time > (startOfToday() - (30 * 24 * 60 * 60 * 1000)), }, { id: 'this-year', label: t('libresign', 'This year ({year})', { year: (new Date()).getFullYear() }), + start: '', + end: '', filter: (time) => time > (new Date(startOfToday())).setMonth(0, 1), }, { id: 'last-year', + start: '', + end: '', label: t('libresign', 'Last year ({year})', { year: (new Date()).getFullYear() - 1 }), filter: (time) => (time > (new Date(startOfToday())).setFullYear((new Date()).getFullYear() - 1, 0, 1)) && (time < (new Date(startOfToday())).setMonth(0, 1)), },