diff --git a/lib/Controller/FolderController.php b/lib/Controller/FolderController.php index 97147ba17..83e12915e 100644 --- a/lib/Controller/FolderController.php +++ b/lib/Controller/FolderController.php @@ -40,6 +40,13 @@ class FolderController extends OCSController { private readonly ?IUser $user; + protected const ALLOWED_ORDER_BY = [ + 'mount_point', + 'quota', + 'groups', + 'acl', + ]; + public function __construct( string $AppName, IRequest $request, @@ -95,6 +102,7 @@ private function formatFolder(array $folder): array { * @param bool $applicable Filter by applicable groups * @param non-negative-int $offset Number of items to skip. * @param ?positive-int $limit Number of items to return. + * @param null|'mount_point'|'quota'|'groups'|'acl' $orderBy The key to order by * @return DataResponse, array{}> * @throws OCSNotFoundException Storage not found * @throws OCSBadRequestException Wrong limit used @@ -103,7 +111,7 @@ private function formatFolder(array $folder): array { */ #[NoAdminRequired] #[FrontpageRoute(verb: 'GET', url: '/folders')] - public function getFolders(bool $applicable = false, int $offset = 0, ?int $limit = null): DataResponse { + public function getFolders(bool $applicable = false, int $offset = 0, ?int $limit = null, ?string $orderBy = 'mount_point'): DataResponse { if ($limit !== null && $limit <= 0) { throw new OCSBadRequestException('The limit must be greater than 0.'); } @@ -119,8 +127,34 @@ public function getFolders(bool $applicable = false, int $offset = 0, ?int $limi $folders[(string)$id] = $this->formatFolder($folder); } - // Make sure the order is always the same, otherwise pagination could break. - ksort($folders); + $orderBy = in_array($orderBy, self::ALLOWED_ORDER_BY, true) + ? $orderBy + : 'mount_point'; + + // in case of equal orderBy value always fall back to the mount_point - same as on the frontend + /** + * @var GroupFoldersFolder $a + * @var GroupFoldersFolder $b + */ + uasort($folders, function (array $a, array $b) use ($orderBy) { + if ($orderBy === 'groups') { + if (($value = count($a['groups']) - count($b['groups'])) !== 0) { + return $value; + } + } else { + if (($value = strcmp((string)($a[$orderBy] ?? ''), (string)($b[$orderBy] ?? ''))) !== 0) { + return $value; + } + } + + // fallback to mount_point + if (($value = strcmp($a['mount_point'] ?? '', $b['mount_point'])) !== 0) { + return $value; + } + + // fallback to id + return $a['id'] - $b['id']; + }); $isAdmin = $this->delegationService->isAdminNextcloud() || $this->delegationService->isDelegatedAdmin(); if ($isAdmin && !$applicable) { @@ -242,7 +276,7 @@ public function addFolder(string $mountpoint): DataResponse { $id = $this->manager->createFolder(trim($mountpoint)); $this->checkFolderExists($id); - + /** @var InternalFolderOut */ $folder = $this->manager->getFolder($id, $storageId); diff --git a/openapi.json b/openapi.json index 437271632..6cc30696b 100644 --- a/openapi.json +++ b/openapi.json @@ -495,6 +495,22 @@ "minimum": 1 } }, + { + "name": "orderBy", + "in": "query", + "description": "The key to order by", + "schema": { + "type": "string", + "nullable": true, + "default": "mount_point", + "enum": [ + "mount_point", + "quota", + "groups", + "acl" + ] + } + }, { "name": "OCS-APIRequest", "in": "header", diff --git a/src/settings/Api.ts b/src/settings/Api.ts index 2d5ac382b..c62881471 100644 --- a/src/settings/Api.ts +++ b/src/settings/Api.ts @@ -15,14 +15,15 @@ export class Api { return generateUrl(`apps/groupfolders/${endpoint}`) } - async listFolders(offset = 0, limit?: number): Promise { + async listFolders(offset = 0, limit?: number, orderBy?: string): Promise { const response = await axios.get>(this.getUrl('folders'), { params: { offset, limit, + orderBy, }, }) - return Object.keys(response.data.ocs.data).map(id => response.data.ocs.data[id]) + return Object.values(response.data.ocs.data) } // Returns all NC groups diff --git a/src/settings/App.tsx b/src/settings/App.tsx index 9d489eab7..5c8cffda3 100644 --- a/src/settings/App.tsx +++ b/src/settings/App.tsx @@ -75,7 +75,7 @@ export class App extends Component implements OC.Plugin { + this.api.listFolders(0, pageSize + 1, this.state.sort).then((folders) => { this.setState({ folders }) }) this.api.listGroups().then((groups) => { @@ -178,7 +178,7 @@ export class App extends Component implements OC.Plugin