From 02cf17bb517dad95fb63c0d0d727f39d6c16b623 Mon Sep 17 00:00:00 2001 From: Victor Bianchi Date: Mon, 30 Sep 2024 12:20:05 -0300 Subject: [PATCH] feat: filter files according to status and modified values Signed-off-by: Victor Bianchi --- lib/Controller/FileController.php | 10 +++++-- lib/Db/SignRequestMapper.php | 12 +++++++- src/store/files.js | 16 ++++++++-- src/store/filesSorting.js | 3 +- src/store/filters.js | 3 +- .../FileListFilter/FileListFilterModified.vue | 30 ++++++++----------- .../FileListFilter/FileListFilterStatus.vue | 1 + 7 files changed, 50 insertions(+), 25 deletions(-) diff --git a/lib/Controller/FileController.php b/lib/Controller/FileController.php index c38ec2d9f9..bf3d416bd0 100644 --- a/lib/Controller/FileController.php +++ b/lib/Controller/FileController.php @@ -192,9 +192,11 @@ public function validate(?string $type = null, $identifier = null): DataResponse * * @param string|null $signer_uuid Signer UUID * @param string|null $nodeId The nodeId (also called fileId). Is the id of a file at Nextcloud - * @param int|null $status Status could be one of 0 = draft, 1 = able to sign, 2 = partial signed, 3 = signed, 4 = deleted. + * @param list|null $status Status could be none or many of 0 = draft, 1 = able to sign, 2 = partial signed, 3 = signed, 4 = deleted. * @param int|null $page the number of page to return * @param int|null $length Total of elements to return + * @param int|null $start Start date of signature request (UNIX timestamp) + * @param int|null $end End date of signature request (UNIX timestamp) * @return DataResponse * * 200: OK @@ -207,12 +209,16 @@ public function list( ?int $length = null, ?string $signer_uuid = null, ?string $nodeId = null, - ?int $status = null, + ?array $status = null, + ?int $start = null, + ?int $end = null, ): DataResponse { $filter = array_filter([ 'signer_uuid' => $signer_uuid, 'nodeId' => $nodeId, 'status' => $status, + 'start' => $start, + 'end' => $end, ], static function ($var) { return $var !== null; }); $return = $this->fileService ->setMe($this->userSession->getUser()) diff --git a/lib/Db/SignRequestMapper.php b/lib/Db/SignRequestMapper.php index 88ddfd0ab6..56aaf2a316 100644 --- a/lib/Db/SignRequestMapper.php +++ b/lib/Db/SignRequestMapper.php @@ -472,7 +472,17 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, ?arra } if (!empty($filter['status'])) { $qb->andWhere( - $qb->expr()->eq('f.status', $qb->createNamedParameter($filter['status'], IQueryBuilder::PARAM_INT)) + $qb->expr()->in('f.status', $qb->createNamedParameter($filter['status'], IQueryBuilder::PARAM_INT_ARRAY)) + ); + } + if (!empty($filter['start'])) { + $qb->andWhere( + $qb->expr()->gte('f.created_at', $qb->createNamedParameter($filter['start'], IQueryBuilder::PARAM_INT)) + ); + } + if (!empty($filter['end'])) { + $qb->andWhere( + $qb->expr()->lte('f.created_at', $qb->createNamedParameter($filter['end'], IQueryBuilder::PARAM_INT)) ); } if (isset($filter['length']) && isset($filter['page'])) { diff --git a/src/store/files.js b/src/store/files.js index affa56fb66..1c57e5e75c 100644 --- a/src/store/files.js +++ b/src/store/files.js @@ -4,17 +4,17 @@ */ import { defineStore } from 'pinia' -import { subscribe } from '@nextcloud/event-bus' import { set } from 'vue' import axios from '@nextcloud/axios' +import { subscribe } from '@nextcloud/event-bus' import Moment from '@nextcloud/moment' import { generateOcsUrl } from '@nextcloud/router' +import { useFilesSortingStore } from './filesSorting.js' +import { useFiltersStore } from './filters.js' import { useSidebarStore } from './sidebar.js' import { useSignStore } from './sign.js' -import { useFiltersStore } from './filters.js' -import { useFilesSortingStore } from './filesSorting.js' export const useFilesStore = function(...args) { const store = defineStore('files', { @@ -161,8 +161,18 @@ export const useFilesStore = function(...args) { ) }, async getAllFiles(filter) { + if (!filter) filter = {} const { chips } = useFiltersStore() + if (chips?.status?.length) { + filter.status = chips.status.map(c => c.id) + } + if (chips?.modified?.length) { + const { start, end } = chips.modified[0] + filter.start = Math.floor(start / 1000) + filter.end = Math.floor(end / 1000) + } const { sortingMode, sortingDirection } = useFilesSortingStore() + // TODO: pass sortingMode and sortingDirection to API call const response = await axios.get(generateOcsUrl('/apps/libresign/api/v1/file/list'), { params: filter }) this.files = {} response.data.ocs.data.data.forEach(file => { diff --git a/src/store/filesSorting.js b/src/store/filesSorting.js index 226dd5bb29..70f8904a3e 100644 --- a/src/store/filesSorting.js +++ b/src/store/filesSorting.js @@ -3,9 +3,10 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { emit } from '@nextcloud/event-bus' import { defineStore } from 'pinia' +import { emit } from '@nextcloud/event-bus' + const DEFAULT_SORTING_DIRECTION = 'asc' export const useFilesSortingStore = defineStore('filesSorting', { diff --git a/src/store/filters.js b/src/store/filters.js index 55bf76899b..750d1f694b 100644 --- a/src/store/filters.js +++ b/src/store/filters.js @@ -3,9 +3,10 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { emit } from '@nextcloud/event-bus' import { defineStore } from 'pinia' +import { emit } from '@nextcloud/event-bus' + import logger from '../helpers/logger.js' export const useFiltersStore = defineStore('filter', { diff --git a/src/views/FilesList/FileListFilter/FileListFilterModified.vue b/src/views/FilesList/FileListFilter/FileListFilterModified.vue index e725c0ce39..1ec88dd242 100644 --- a/src/views/FilesList/FileListFilter/FileListFilterModified.vue +++ b/src/views/FilesList/FileListFilter/FileListFilterModified.vue @@ -28,6 +28,7 @@ import FileListFilter from './FileListFilter.vue' import { useFiltersStore } from '../../../store/filters.js' const startOfToday = () => (new Date()).setHours(0, 0, 0, 0) +const endOfToday = () => (new Date()).setHours(23, 59, 59, 999) export default { name: 'FileListFilterModified', @@ -47,43 +48,36 @@ export default { data() { return { selectedOption: null, - timeRangeEnd: null, - timeRangeStart: null, timePresets: [ { id: 'today', label: t('libresign', 'Today'), - start: '', - end: '', - filter: (time) => time > startOfToday(), + start: startOfToday(), + end: endOfToday(), }, { id: 'last-7', label: t('libresign', 'Last 7 days'), - start: '', - end: '', - filter: (time) => time > (startOfToday() - (7 * 24 * 60 * 60 * 1000)), + start: startOfToday() - (7 * 24 * 60 * 60 * 1000), + end: endOfToday(), }, { id: 'last-30', label: t('libresign', 'Last 30 days'), - start: '', - end: '', - filter: (time) => time > (startOfToday() - (30 * 24 * 60 * 60 * 1000)), + start: startOfToday() - (30 * 24 * 60 * 60 * 1000), + end: endOfToday(), }, { id: 'this-year', label: t('libresign', 'This year ({year})', { year: (new Date()).getFullYear() }), - start: '', - end: '', - filter: (time) => time > (new Date(startOfToday())).setMonth(0, 1), + start: (new Date(startOfToday())).setMonth(0, 1), + end: endOfToday(), }, { 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)), + start: (new Date(startOfToday())).setFullYear((new Date()).getFullYear() - 1, 0, 1), + end: (new Date(startOfToday())).setMonth(0, 1), }, ], } @@ -112,6 +106,8 @@ export default { const chips = [] if (preset) { chips.push({ + start: preset.start, + end: preset.end, icon: calendarSvg, text: preset.label, onclick: () => this.setPreset(), diff --git a/src/views/FilesList/FileListFilter/FileListFilterStatus.vue b/src/views/FilesList/FileListFilter/FileListFilterStatus.vue index d68fa5fda7..6af5c717ce 100644 --- a/src/views/FilesList/FileListFilter/FileListFilterStatus.vue +++ b/src/views/FilesList/FileListFilter/FileListFilterStatus.vue @@ -104,6 +104,7 @@ export default { if (presets && presets.length > 0) { for (const preset of presets) { chips.push({ + id: preset.id, icon: preset.icon, text: preset.label, onclick: () => this.setPreset(presets.filter(({ id }) => id !== preset.id)),