Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions lib/Controller/FolderController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<Http::STATUS_OK, array<string, GroupFoldersFolder>, array{}>
* @throws OCSNotFoundException Storage not found
* @throws OCSBadRequestException Wrong limit used
Expand All @@ -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.');
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down
16 changes: 16 additions & 0 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 3 additions & 2 deletions src/settings/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ export class Api {
return generateUrl(`apps/groupfolders/${endpoint}`)
}

async listFolders(offset = 0, limit?: number): Promise<Folder[]> {
async listFolders(offset = 0, limit?: number, orderBy?: string): Promise<Folder[]> {
const response = await axios.get<OCSResponse<Folder[]>>(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
Expand Down
4 changes: 2 additions & 2 deletions src/settings/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se

componentDidMount() {
// list first pageSize + 1 folders so we know if there are more pages
this.api.listFolders(0, pageSize + 1).then((folders) => {
this.api.listFolders(0, pageSize + 1, this.state.sort).then((folders) => {
this.setState({ folders })
})
this.api.listGroups().then((groups) => {
Expand Down Expand Up @@ -178,7 +178,7 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
async goToPage(page: number) {
const loadedPage = Math.floor(this.state.folders.length / pageSize)
if (loadedPage <= page) {
const folders = await this.api.listFolders(this.state.folders.length, (page + 1) * pageSize - this.state.folders.length + 1)
const folders = await this.api.listFolders(this.state.folders.length, (page + 1) * pageSize - this.state.folders.length + 1, this.state.sort)
this.setState({
folders: [...this.state.folders, ...folders],
currentPage: page,
Expand Down
2 changes: 2 additions & 0 deletions src/types/openapi/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ export interface operations {
offset?: number;
/** @description Number of items to return. */
limit?: number | null;
/** @description The key to order by */
orderBy?: "mount_point" | "quota" | "groups" | "acl" | null;
};
header: {
/** @description Required to be true for the API request to pass */
Expand Down
Loading