Skip to content

Commit

Permalink
feat: implement file sorting
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Bianchi <[email protected]>
  • Loading branch information
v-bianchi committed Sep 30, 2024
1 parent b2a69f4 commit 523ce99
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 38 deletions.
10 changes: 9 additions & 1 deletion lib/Controller/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ public function validate(?string $type = null, $identifier = null): DataResponse
* @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)
* @param string|null $sortBy Name of the column to sort by
* @param string|null $sortDirection Ascending or descending order
* @return DataResponse<Http::STATUS_OK, array{pagination: LibresignPagination, data: ?LibresignFile[]}, array{}>
*
* 200: OK
Expand All @@ -212,6 +214,8 @@ public function list(
?array $status = null,
?int $start = null,
?int $end = null,
?string $sortBy = null,
?string $sortDirection = null,
): DataResponse {
$filter = array_filter([
'signer_uuid' => $signer_uuid,
Expand All @@ -220,9 +224,13 @@ public function list(
'start' => $start,
'end' => $end,
], static function ($var) { return $var !== null; });
$sort = [
'sortBy' => $sortBy,
'sortDirection' => $sortDirection,
];
$return = $this->fileService
->setMe($this->userSession->getUser())
->listAssociatedFilesOfSignFlow($page, $length, $filter);
->listAssociatedFilesOfSignFlow($page, $length, $filter, $sort);
return new DataResponse($return, Http::STATUS_OK);
}

Expand Down
15 changes: 13 additions & 2 deletions lib/Db/SignRequestMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,12 @@ public function getFilesAssociatedFilesWithMeFormatted(
array $filter,
?int $page = null,
?int $length = null,
?array $sort = [],
): array {
$filter['email'] = $user->getEMailAddress();
$filter['length'] = $length;
$filter['page'] = $page;
$pagination = $this->getFilesAssociatedFilesWithMeStmt($user->getUID(), $filter);
$pagination = $this->getFilesAssociatedFilesWithMeStmt($user->getUID(), $filter, $sort);
$pagination->setMaxPerPage($length);
$pagination->setCurrentPage($page);
$currentPageResults = $pagination->getCurrentPageResults();
Expand Down Expand Up @@ -493,7 +494,11 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, ?arra
return $qb;
}

private function getFilesAssociatedFilesWithMeStmt(string $userId, ?array $filter = []): Pagination {
private function getFilesAssociatedFilesWithMeStmt(
string $userId,
?array $filter = [],
?array $sort = [],
): Pagination {
$qb = $this->getFilesAssociatedFilesWithMeQueryBuilder($userId, $filter);
$qb->select(
'f.id',
Expand All @@ -504,6 +509,12 @@ private function getFilesAssociatedFilesWithMeStmt(string $userId, ?array $filte
'f.status',
'f.metadata',
);
if (!empty($sort) && in_array($sort['sortBy'], ['name', 'status', 'created_at'])) {
$qb->orderBy(
$qb->func()->lower('f.' . $sort['sortBy']),
$sort['sortDirection'] == 'asc' ? 'asc' : 'desc'
);
}
$qb->selectAlias('f.created_at', 'request_date');

$countQueryBuilderModifier = function (IQueryBuilder $qb): int {
Expand Down
8 changes: 7 additions & 1 deletion lib/Service/FileService.php
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,12 @@ public function setFileByPath(string $path): self {
*
* @psalm-return array{data: array, pagination: array}
*/
public function listAssociatedFilesOfSignFlow($page = null, $length = null, array $filter = []): array {
public function listAssociatedFilesOfSignFlow(
$page = null,
$length = null,
array $filter = [],
array $sort = [],
): array {
$page = $page ?? 1;
$length = $length ?? (int)$this->appConfig->getAppValue('length_of_page', '100');

Expand All @@ -441,6 +446,7 @@ public function listAssociatedFilesOfSignFlow($page = null, $length = null, arra
$filter,
$page,
$length,
$sort,
);

$signers = $this->signRequestMapper->getByMultipleFileId(array_column($return['data'], 'id'));
Expand Down
8 changes: 4 additions & 4 deletions src/Components/File/File.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
@load="backgroundFailed = false">
<FileIcon v-else v-once :size="128" />
<div class="enDot">
<div :class="filesStore.files[currentNodeId].statusText !== 'none' ? 'dot ' + statusToClass(filesStore.files[currentNodeId].status) : '' " />
<span>{{ filesStore.files[currentNodeId].statusText !== 'none' ? filesStore.files[currentNodeId].statusText : '' }}</span>
<div :class="filesStore.files.get(currentNodeId).statusText !== 'none' ? 'dot ' + statusToClass(filesStore.files.get(currentNodeId).status) : '' " />
<span>{{ filesStore.files.get(currentNodeId).statusText !== 'none' ? filesStore.files.get(currentNodeId).statusText : '' }}</span>
</div>
<h1>{{ filesStore.files[currentNodeId].name }}</h1>
<h1>{{ filesStore.files.get(currentNodeId).name }}</h1>
</div>
</template>

Expand Down Expand Up @@ -60,7 +60,7 @@ export default {
return null
}
let previewUrl = ''
if (this.filesStore.files[this.currentNodeId]?.uuid?.length > 0) {
if (this.filesStore.files.get(this.currentNodeId)?.uuid?.length > 0) {
previewUrl = generateOcsUrl('/apps/libresign/api/v1/file/thumbnail/{nodeId}', {
nodeId: this.currentNodeId,
})
Expand Down
53 changes: 29 additions & 24 deletions src/store/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const useFilesStore = function(...args) {
const store = defineStore('files', {
state: () => {
return {
files: {},
files: new Map(),
selectedNodeId: 0,
identifyingSigner: false,
loading: false,
Expand All @@ -30,7 +30,7 @@ export const useFilesStore = function(...args) {

actions: {
addFile(file) {
set(this.files, file.nodeId, file)
this.files.set(file.nodeId, file)
this.hydrateFile(file.nodeId)
},
selectFile(nodeId) {
Expand All @@ -44,13 +44,13 @@ export const useFilesStore = function(...args) {
sidebarStore.activeRequestSignatureTab()
},
getFile() {
return this.files[this.selectedNodeId] ?? {}
return this.files.get(this.selectedNodeId) ?? {}
},
async flushSelectedFile() {
const files = await this.getAllFiles({
nodeId: this.selectedNodeId,
})
this.addFile(files[this.selectedNodeId])
this.addFile(files.get(this.selectedNodeId))
},
enableIdentifySigner() {
this.identifyingSigner = true
Expand All @@ -65,7 +65,7 @@ export const useFilesStore = function(...args) {
if (!Object.hasOwn(this.getFile(), 'signers')) {
return false
}
return this.files[this.selectedNodeId].signers.length > 0
return this.files.get(this.selectedNodeId).signers.length > 0
},
isPartialSigned() {
if (this.selectedNodeId === 0) {
Expand All @@ -74,7 +74,7 @@ export const useFilesStore = function(...args) {
if (!Object.hasOwn(this.getFile(), 'signers')) {
return false
}
return this.files[this.selectedNodeId].signers
return this.files.get(this.selectedNodeId).signers
.filter(signer => signer.signed?.length > 0).length > 0
},
isFullSigned() {
Expand All @@ -84,15 +84,15 @@ export const useFilesStore = function(...args) {
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
return this.files.get(this.selectedNodeId).signers.length > 0
&& this.files.get(this.selectedNodeId).signers
.filter(signer => signer.signed?.length > 0).length === this.files.get(this.selectedNodeId).signers.length
},
getSubtitle() {
if (this.selectedNodeId === 0) {
return ''
}
const file = this.files[this.selectedNodeId]
const file = this.files.get(this.selectedNodeId)
if ((file?.requested_by?.userId ?? '').length === 0 || file?.request_date.length === 0) {
return ''
}
Expand All @@ -102,18 +102,18 @@ export const useFilesStore = function(...args) {
})
},
async hydrateFile(nodeId) {
if (Object.hasOwn(this.files[nodeId], 'uuid')) {
if (Object.hasOwn(this.files.get(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)
this.files.set(nodeId, response.data.ocs.data)
this.addUniqueIdentifierToAllSigners(this.files.get(nodeId).signers)
})
.catch(() => {
set(this.files[nodeId], 'signers', [])
set(this.files.get(nodeId), 'signers', [])
})
},
addUniqueIdentifierToAllSigners(signers) {
Expand All @@ -134,17 +134,17 @@ export const useFilesStore = function(...args) {
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)
for (let i = this.files.get(this.selectedNodeId).signers.length - 1; i >= 0; i--) {
if (this.files.get(this.selectedNodeId).signers[i].identify === signer.identify) {
this.files.get(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)
if (this.files.get(this.selectedNodeId).signers[i].signRequestId === signer.identify) {
this.files.get(this.selectedNodeId).signers.splice(i, 1)
break
}
}
this.files[this.selectedNodeId].signers.push(signer)
this.files.get(this.selectedNodeId).signers.push(signer)
},
async deleteSigner(signer) {
if (!isNaN(signer.signRequestId)) {
Expand All @@ -155,9 +155,9 @@ export const useFilesStore = function(...args) {
}))
}
set(
this.files[this.selectedNodeId],
this.files.get(this.selectedNodeId),
'signers',
this.files[this.selectedNodeId].signers.filter((i) => i.identify !== signer.identify),
this.files.get(this.selectedNodeId).signers.filter((i) => i.identify !== signer.identify),
)
},
async getAllFiles(filter) {
Expand All @@ -172,9 +172,14 @@ export const useFilesStore = function(...args) {
filter.end = Math.floor(end / 1000)
}
const { sortingMode, sortingDirection } = useFilesSortingStore()
// TODO: pass sortingMode and sortingDirection to API call
if (sortingMode) {
filter.sortBy = sortingMode
}
if (sortingDirection) {
filter.sortDirection = sortingDirection
}
const response = await axios.get(generateOcsUrl('/apps/libresign/api/v1/file/list'), { params: filter })
this.files = {}
this.files = new Map()
response.data.ocs.data.data.forEach(file => {
this.addFile(file)
})
Expand Down
2 changes: 1 addition & 1 deletion src/store/filesSorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const DEFAULT_SORTING_DIRECTION = 'asc'

export const useFilesSortingStore = defineStore('filesSorting', {
state: () => ({
sortingMode: 'basename',
sortingMode: 'name',
sortingDirection: DEFAULT_SORTING_DIRECTION,
}),

Expand Down
2 changes: 1 addition & 1 deletion src/views/FilesList/FilesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export default {
return this.dirContentsFiltered
},
isEmptyDir() {
return this.filesStore.files.length === 0
return this.filesStore.files.size === 0
},
isRefreshing() {
return !this.isEmptyDir
Expand Down
6 changes: 3 additions & 3 deletions src/views/FilesList/FilesListTableHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<span class="files-list__row-icon" />

<!-- Name -->
<FilesListTableHeaderButton :name="t('files', 'Name')" mode="basename" />
<FilesListTableHeaderButton :name="t('files', 'Name')" mode="name" />
</th>

<!-- Actions -->
Expand Down Expand Up @@ -59,8 +59,8 @@ export default {
sort: true,
},
{
title: t('libresign', 'Modified'),
id: 'modified',
title: t('libresign', 'Created at'),
id: 'created_at',
sort: true,
},
],
Expand Down
2 changes: 1 addition & 1 deletion src/views/FilesList/VirtualList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
:class="userConfigStore.grid_view ? 'files-list__tbody--grid' : 'files-list__tbody--list'"
data-cy-files-list-tbody>
<component :is="dataComponent"
v-for="item in filesStore.files"
v-for="item in filesStore.files.values()"
:key="item.nodeId"
:source="item"
:loading="loading" />
Expand Down

0 comments on commit 523ce99

Please sign in to comment.