From c195d5f67019735dcdc5f97bd48838237a68f9dc Mon Sep 17 00:00:00 2001 From: Anass Bouassaba Date: Sun, 28 Jul 2024 02:48:29 +0200 Subject: [PATCH] fix(ui): revert changes (#245) --- ui/src/client/api/file.ts | 66 ++++++++++++++++-- ui/src/client/api/group.ts | 56 +++++++++++++++- ui/src/client/api/insights.ts | 42 +++++++++++- ui/src/client/api/invitation.ts | 54 +++++++++++++-- ui/src/client/api/organization.ts | 53 +++++++++++++-- ui/src/client/api/query-helpers.ts | 36 ---------- ui/src/client/api/snapshot.ts | 56 ++++++++++++++-- ui/src/client/api/task.ts | 53 +++++++++++++-- ui/src/client/api/types/queries.ts | 49 -------------- ui/src/client/api/user.ts | 67 +++++++++++++++++-- ui/src/client/api/workspace.ts | 53 +++++++++++++-- ui/src/components/common/group-selector.tsx | 3 +- .../common/organization-selector.tsx | 6 +- ui/src/components/common/user-selector.tsx | 3 +- ui/src/components/file/file-browse.tsx | 4 +- ui/src/components/file/file-create.tsx | 3 +- ui/src/components/file/file-search-filter.tsx | 2 +- ui/src/components/file/file-toolbar.tsx | 3 +- .../file/list/list-draggable-droppable.tsx | 3 +- .../insights-overview-chart.tsx | 3 +- .../insights-overview-entities.tsx | 3 +- ui/src/components/snapshot/snapshot-list.tsx | 3 +- ui/src/components/task/task-list.tsx | 3 +- ui/src/components/upload/upload-worker.ts | 3 +- ui/src/local-storage/index.ts | 2 +- .../account/account-invitations-page.tsx | 3 +- ui/src/pages/group/group-list-page.tsx | 3 +- ui/src/pages/group/group-members-page.tsx | 3 +- .../organization-invitations-page.tsx | 3 +- .../organization/organization-list-page.tsx | 3 +- .../organization-members-page.tsx | 3 +- .../pages/workspace/workspace-list-page.tsx | 3 +- ui/src/store/ui/files.ts | 3 +- 33 files changed, 491 insertions(+), 162 deletions(-) delete mode 100644 ui/src/client/api/query-helpers.ts delete mode 100644 ui/src/client/api/types/queries.ts diff --git a/ui/src/client/api/file.ts b/ui/src/client/api/file.ts index 96c5e9fd9..d0cc358f0 100644 --- a/ui/src/client/api/file.ts +++ b/ui/src/client/api/file.ts @@ -8,16 +8,33 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { FileType, ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' import { User } from '@/client/idp/user' import { getConfig } from '@/config/config' import { getAccessTokenOrRedirect } from '@/infra/token' +import { encodeQuery } from '@/lib/helpers/query' import { Group } from './group' import { PermissionType } from './permission' import { Snapshot } from './snapshot' +export enum FileType { + File = 'file', + Folder = 'folder', +} + +export enum SortBy { + Name = 'name', + Kind = 'kind', + Size = 'size', + DateCreated = 'date_created', + DateModified = 'date_modified', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type File = { id: string workspaceId: string @@ -61,6 +78,15 @@ export type Query = { updateTimeBefore?: number } +export type ListOptions = { + size?: number + page?: number + type?: FileType + sortBy?: SortBy + sortOrder?: SortOrder + query?: Query +} + export type MoveManyOptions = { sourceIds: string[] targetId: string @@ -129,6 +155,15 @@ export type PatchOptions = { onProgress?: (value: number) => void } +type ListQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + type?: string + query?: string +} + export default class FileAPI { static async create({ type, @@ -217,7 +252,7 @@ export default class FileAPI { static async list(id: string, options: ListOptions) { return apiFetcher({ - url: `/files/${id}/list?${paramsFromListOptions(options)}`, + url: `/files/${id}/list?${this.paramsFromListOptions(options)}`, method: 'GET', }) as Promise } @@ -227,7 +262,7 @@ export default class FileAPI { options: ListOptions, swrOptions?: SWRConfiguration, ) { - const url = `/files/${id}/list?${paramsFromListOptions(options)}` + const url = `/files/${id}/list?${this.paramsFromListOptions(options)}` return useSWR( id ? url : null, () => apiFetcher({ url, method: 'GET' }), @@ -235,6 +270,29 @@ export default class FileAPI { ) } + static paramsFromListOptions(options?: ListOptions): URLSearchParams { + const params: ListQueryParams = {} + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + if (options?.type) { + params.type = options.type + } + if (options?.query) { + params.query = encodeQuery(JSON.stringify(options.query)) + } + return new URLSearchParams(params) + } + static useGetPath( id: string | null | undefined, swrOptions?: SWRConfiguration, diff --git a/ui/src/client/api/group.ts b/ui/src/client/api/group.ts index 3c6e889c0..4c80581de 100644 --- a/ui/src/client/api/group.ts +++ b/ui/src/client/api/group.ts @@ -8,11 +8,20 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' import { Organization } from './organization' +export enum SortBy { + Name = 'name', + DateCreated = 'date_created', + DateModified = 'date_modified', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type Group = { id: string name: string @@ -30,6 +39,15 @@ export type List = { size: number } +export type ListOptions = { + query?: string + organizationId?: string + size?: number + page?: number + sortBy?: SortBy + sortOrder?: SortOrder +} + export type CreateOptions = { name: string image?: string @@ -48,6 +66,15 @@ export type RemoveMemberOptions = { userId: string } +type ListQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string + organization_id?: string +} + export default class GroupAPI { static create(options: CreateOptions) { return apiFetcher({ @@ -75,7 +102,7 @@ export default class GroupAPI { } static useList(options?: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/groups?${paramsFromListOptions(options)}` + const url = `/groups?${this.paramsFromListOptions(options)}` return useSWR( url, () => apiFetcher({ url, method: 'GET' }) as Promise, @@ -83,6 +110,29 @@ export default class GroupAPI { ) } + static paramsFromListOptions(options?: ListOptions): URLSearchParams { + const params: ListQueryParams = {} + if (options?.query) { + params.query = encodeURIComponent(options.query.toString()) + } + if (options?.organizationId) { + params.organization_id = options.organizationId.toString() + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } + static delete(id: string) { return apiFetcher({ url: `/groups/${id}`, diff --git a/ui/src/client/api/insights.ts b/ui/src/client/api/insights.ts index 5af4d1b0e..ff0d9c07b 100644 --- a/ui/src/client/api/insights.ts +++ b/ui/src/client/api/insights.ts @@ -8,8 +8,6 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { SortBy, SortOrder } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' import { Snapshot } from './snapshot' @@ -51,6 +49,24 @@ export type ListEntitiesOptions = { sortOrder?: SortOrder } +export enum SortBy { + Name = 'name', + Frequency = 'frequency', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + +type ListEntitiesQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string +} + export default class InsightsAPI { static create(id: string, options: CreateOptions, showError = true) { return apiFetcher({ @@ -113,11 +129,31 @@ export default class InsightsAPI { options?: ListEntitiesOptions, swrOptions?: SWRConfiguration, ) { - const url = `/insights/${id}/entities?${paramsFromListOptions(options)}` + const url = `/insights/${id}/entities?${this.paramsFromListOptions(options)}` return useSWR( id ? url : null, () => apiFetcher({ url, method: 'GET' }) as Promise, swrOptions, ) } + + static paramsFromListOptions(options?: ListEntitiesOptions): URLSearchParams { + const params: ListEntitiesQueryParams = {} + if (options?.query) { + params.query = encodeURIComponent(options.query.toString()) + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } } diff --git a/ui/src/client/api/invitation.ts b/ui/src/client/api/invitation.ts index 01ad0a4bc..294f4e51e 100644 --- a/ui/src/client/api/invitation.ts +++ b/ui/src/client/api/invitation.ts @@ -8,12 +8,21 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' import { User } from '@/client/idp/user' import { Organization } from './organization' +export enum SortBy { + Email = 'email', + DateCreated = 'date_created', + DateModified = 'date_modified', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type InvitationStatus = 'pending' | 'accepted' | 'declined' export type Invitation = { @@ -39,6 +48,23 @@ export type CreateOptions = { emails: string[] } +export type ListOptions = { + organizationId?: string + size?: number + page?: number + sortBy?: SortBy + sortOrder?: SortOrder +} + +type ListQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string + organization_id?: string +} + export default class InvitationAPI { static async create(options: CreateOptions) { return apiFetcher({ @@ -49,7 +75,7 @@ export default class InvitationAPI { } static useGetIncoming(options?: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/invitations/incoming?${paramsFromListOptions(options)}` + const url = `/invitations/incoming?${this.paramsFromListOptions(options)}` return useSWR( url, () => apiFetcher({ url, method: 'GET' }) as Promise, @@ -67,7 +93,7 @@ export default class InvitationAPI { } static useGetOutgoing(options?: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/invitations/outgoing?${paramsFromListOptions(options)}` + const url = `/invitations/outgoing?${this.paramsFromListOptions(options)}` return useSWR( options?.organizationId ? url : null, () => apiFetcher({ url, method: 'GET' }) as Promise, @@ -75,6 +101,26 @@ export default class InvitationAPI { ) } + static paramsFromListOptions(options?: ListOptions): URLSearchParams { + const params: ListQueryParams = {} + if (options?.organizationId) { + params.organization_id = options.organizationId.toString() + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } + static async delete(id: string) { return apiFetcher({ url: `/invitations/${id}`, diff --git a/ui/src/client/api/organization.ts b/ui/src/client/api/organization.ts index cf0b5f6c7..b85974723 100644 --- a/ui/src/client/api/organization.ts +++ b/ui/src/client/api/organization.ts @@ -8,11 +8,20 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' import { PermissionType } from './permission' +export enum SortBy { + Name = 'name', + DateCreated = 'date_created', + DateModified = 'date_modified', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type Organization = { id: string name: string @@ -29,6 +38,14 @@ export type List = { size: number } +export type ListOptions = { + query?: string + size?: number + page?: number + sortBy?: SortBy + sortOrder?: SortOrder +} + export type CreateOptions = { name: string image?: string @@ -42,6 +59,14 @@ export type RemoveMemberOptions = { userId: string } +type ListQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string +} + export default class OrganizationAPI { static useGet(id: string | null | undefined, swrOptions?: SWRConfiguration) { const url = `/organizations/${id}` @@ -54,13 +79,13 @@ export default class OrganizationAPI { static async list(options?: ListOptions) { return apiFetcher({ - url: `/organizations?${paramsFromListOptions(options)}`, + url: `/organizations?${this.paramsFromListOptions(options)}`, method: 'GET', }) as Promise } static useList(options?: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/organizations?${paramsFromListOptions(options)}` + const url = `/organizations?${this.paramsFromListOptions(options)}` return useSWR( url, () => apiFetcher({ url, method: 'GET' }) as Promise, @@ -68,6 +93,26 @@ export default class OrganizationAPI { ) } + static paramsFromListOptions(options?: ListOptions): URLSearchParams { + const params: ListQueryParams = {} + if (options?.query) { + params.query = encodeURIComponent(options.query.toString()) + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } + static async create(options: CreateOptions) { return apiFetcher({ url: `/organizations`, diff --git a/ui/src/client/api/query-helpers.ts b/ui/src/client/api/query-helpers.ts deleted file mode 100644 index bdab47db0..000000000 --- a/ui/src/client/api/query-helpers.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ListOptions, ListQueryParams } from '@/client/api/types/queries' -import { encodeQuery } from '@/lib/helpers/query' - -export const paramsFromListOptions = ( - options?: ListOptions, -): URLSearchParams => { - const params: ListQueryParams = {} - if (options?.query) { - params.query = encodeQuery(JSON.stringify(options.query)) - } - if (options?.page) { - params.page = options.page.toString() - } - if (options?.size) { - params.size = options.size.toString() - } - if (options?.sortBy) { - params.sort_by = options.sortBy.toString() - } - if (options?.sortOrder) { - params.sort_order = options.sortOrder.toString() - } - if (options?.organizationId) { - params.organization_id = options.organizationId.toString() - } - if (options?.type) { - params.type = options.type - } - if (options?.groupId) { - params.group_id = options.groupId.toString() - } - if (options?.excludeGroupMembers) { - params.exclude_group_members = options.excludeGroupMembers.toString() - } - return new URLSearchParams(params) -} diff --git a/ui/src/client/api/snapshot.ts b/ui/src/client/api/snapshot.ts index fe2bf2778..695ab9334 100644 --- a/ui/src/client/api/snapshot.ts +++ b/ui/src/client/api/snapshot.ts @@ -8,8 +8,6 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '../fetcher' export type Snapshot = { @@ -45,6 +43,27 @@ export type List = { size: number } +export type ListOptions = { + fileId: string + query?: string + organizationId?: string + size?: number + page?: number + sortBy?: SortBy + sortOrder?: SortOrder +} + +export enum SortBy { + Version = 'version', + DateCreated = 'date_created', + DateModified = 'date_modified', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type TaskInfo = { id: string isPending: boolean @@ -61,6 +80,15 @@ export type ImageProps = { height: number } +export type ListQueryParams = { + file_id: string + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string +} + export type ActivateOptions = { fileId: string } @@ -72,13 +100,13 @@ export type DetachOptions = { export default class SnapshotAPI { static async list(options: ListOptions) { return apiFetcher({ - url: `/snapshots?${paramsFromListOptions(options)}`, + url: `/snapshots?${this.paramsFromListOptions(options)}`, method: 'GET', }) as Promise } static useList(options: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/snapshots?${paramsFromListOptions(options)}` + const url = `/snapshots?${this.paramsFromListOptions(options)}` return useSWR( url, () => apiFetcher({ url, method: 'GET' }), @@ -86,6 +114,26 @@ export default class SnapshotAPI { ) } + static paramsFromListOptions(options: ListOptions): URLSearchParams { + const params: ListQueryParams = { file_id: options.fileId } + if (options?.query) { + params.query = encodeURIComponent(options.query.toString()) + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } + static async activate(id: string, options: ActivateOptions) { return apiFetcher({ url: `/snapshots/${id}/activate`, diff --git a/ui/src/client/api/task.ts b/ui/src/client/api/task.ts index d1d45c1fc..163b8167e 100644 --- a/ui/src/client/api/task.ts +++ b/ui/src/client/api/task.ts @@ -8,10 +8,19 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' +export enum SortBy { + Name = 'name', + DateCreated = 'date_created', + DateModified = 'date_modified', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type Task = { id: string name: string @@ -42,6 +51,22 @@ export type List = { size: number } +export type ListOptions = { + query?: string + size?: number + page?: number + sortBy?: SortBy + sortOrder?: SortOrder +} + +type ListQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string +} + export default class TaskAPI { static useGet(id: string | null | undefined, swrOptions?: SWRConfiguration) { const url = `/tasks/${id}` @@ -54,13 +79,13 @@ export default class TaskAPI { static async list(options?: ListOptions) { return apiFetcher({ - url: `/tasks?${paramsFromListOptions(options)}`, + url: `/tasks?${this.paramsFromListOptions(options)}`, method: 'GET', }) as Promise } static useList(options?: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/tasks?${paramsFromListOptions(options)}` + const url = `/tasks?${this.paramsFromListOptions(options)}` return useSWR( url, () => apiFetcher({ url, method: 'GET' }) as Promise, @@ -68,6 +93,26 @@ export default class TaskAPI { ) } + static paramsFromListOptions(options?: ListOptions): URLSearchParams { + const params: ListQueryParams = {} + if (options?.query) { + params.query = encodeURIComponent(options.query.toString()) + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } + static useGetCount(swrOptions?: SWRConfiguration) { const url = '/tasks/count' return useSWR( diff --git a/ui/src/client/api/types/queries.ts b/ui/src/client/api/types/queries.ts deleted file mode 100644 index fa8e2381c..000000000 --- a/ui/src/client/api/types/queries.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Query } from '@/client/api/file' - -export type ListQueryParams = { - file_id?: string - page?: string - size?: string - sort_by?: string - sort_order?: string - query?: string - type?: string - organization_id?: string - group_id?: string - exclude_group_members?: string -} - -export type ListOptions = { - fileId?: string - type?: FileType - query?: string | Query - organizationId?: string - groupId?: string - excludeGroupMembers?: boolean - size?: number - page?: number - sortBy?: SortBy - sortOrder?: SortOrder -} - -export enum SortBy { - Name = 'name', - DateCreated = 'date_created', - DateModified = 'date_modified', - Frequency = 'frequency', - Kind = 'kind', - Size = 'size', - Email = 'email', - FullName = 'full_name', - Version = 'version', -} - -export enum SortOrder { - Asc = 'asc', - Desc = 'desc', -} - -export enum FileType { - File = 'file', - Folder = 'folder', -} diff --git a/ui/src/client/api/user.ts b/ui/src/client/api/user.ts index 91724964e..42d92f049 100644 --- a/ui/src/client/api/user.ts +++ b/ui/src/client/api/user.ts @@ -8,10 +8,18 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' +export enum SortBy { + Email = 'email', + FullName = 'full_name', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type User = { id: string username: string @@ -28,20 +36,71 @@ export type List = { size: number } +export type ListOptions = { + query?: string + organizationId?: string + groupId?: string + excludeGroupMembers?: boolean + size?: number + page?: number + sortBy?: SortBy + sortOrder?: SortOrder +} + +type ListQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string + organization_id?: string + group_id?: string + exclude_group_members?: string +} + export default class UserAPI { static async list(options?: ListOptions) { return apiFetcher({ - url: `/users?${paramsFromListOptions(options)}`, + url: `/users?${this.paramsFromListOptions(options)}`, method: 'GET', }) as Promise } static useList(options?: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/users?${paramsFromListOptions(options)}` + const url = `/users?${this.paramsFromListOptions(options)}` return useSWR( url, () => apiFetcher({ url, method: 'GET' }) as Promise, swrOptions, ) } + + static paramsFromListOptions(options?: ListOptions): URLSearchParams { + const params: ListQueryParams = {} + if (options?.query) { + params.query = encodeURIComponent(options.query.toString()) + } + if (options?.organizationId) { + params.organization_id = options.organizationId.toString() + } + if (options?.groupId) { + params.group_id = options.groupId.toString() + } + if (options?.excludeGroupMembers) { + params.exclude_group_members = options.excludeGroupMembers.toString() + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } } diff --git a/ui/src/client/api/workspace.ts b/ui/src/client/api/workspace.ts index 35174ff29..ad8afe7f7 100644 --- a/ui/src/client/api/workspace.ts +++ b/ui/src/client/api/workspace.ts @@ -8,12 +8,21 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import useSWR, { SWRConfiguration } from 'swr' -import { paramsFromListOptions } from '@/client/api/query-helpers' -import { ListOptions } from '@/client/api/types/queries' import { apiFetcher } from '@/client/fetcher' import { Organization } from './organization' import { PermissionType } from './permission' +export enum SortBy { + Name = 'name', + DateCreated = 'date_created', + DateModified = 'date_modified', +} + +export enum SortOrder { + Asc = 'asc', + Desc = 'desc', +} + export type Workspace = { id: string name: string @@ -40,6 +49,14 @@ export interface CreateOptions { storageCapacity: number } +export type ListOptions = { + query?: string + size?: number + page?: number + sortBy?: SortBy + sortOrder?: SortOrder +} + export interface PatchNameOptions { name: string } @@ -48,6 +65,14 @@ export interface PatchStorageCapacityOptions { storageCapacity: number } +type ListQueryParams = { + page?: string + size?: string + sort_by?: string + sort_order?: string + query?: string +} + export default class WorkspaceAPI { static useGet(id: string | null | undefined, swrOptions?: SWRConfiguration) { const url = `/workspaces/${id}` @@ -59,7 +84,7 @@ export default class WorkspaceAPI { } static useList(options?: ListOptions, swrOptions?: SWRConfiguration) { - const url = `/workspaces?${paramsFromListOptions(options)}` + const url = `/workspaces?${this.paramsFromListOptions(options)}` return useSWR( url, () => apiFetcher({ url, method: 'GET' }) as Promise, @@ -69,11 +94,31 @@ export default class WorkspaceAPI { static async list(options?: ListOptions) { return apiFetcher({ - url: `/workspaces?${paramsFromListOptions(options)}`, + url: `/workspaces?${this.paramsFromListOptions(options)}`, method: 'GET', }) as Promise } + static paramsFromListOptions(options?: ListOptions): URLSearchParams { + const params: ListQueryParams = {} + if (options?.query) { + params.query = encodeURIComponent(options.query.toString()) + } + if (options?.page) { + params.page = options.page.toString() + } + if (options?.size) { + params.size = options.size.toString() + } + if (options?.sortBy) { + params.sort_by = options.sortBy.toString() + } + if (options?.sortOrder) { + params.sort_order = options.sortOrder.toString() + } + return new URLSearchParams(params) + } + static async create(options: CreateOptions) { return apiFetcher({ url: '/workspaces', diff --git a/ui/src/components/common/group-selector.tsx b/ui/src/components/common/group-selector.tsx index b40375027..fd54709fa 100644 --- a/ui/src/components/common/group-selector.tsx +++ b/ui/src/components/common/group-selector.tsx @@ -26,8 +26,7 @@ import { Radio, } from '@chakra-ui/react' import cx from 'classnames' -import GroupAPI, { Group } from '@/client/api/group' -import { SortOrder } from '@/client/api/types/queries' +import GroupAPI, { Group, SortOrder } from '@/client/api/group' import { swrConfig } from '@/client/options' import Pagination from '@/lib/components/pagination' import SearchInput from '@/lib/components/search-input' diff --git a/ui/src/components/common/organization-selector.tsx b/ui/src/components/common/organization-selector.tsx index d7332851e..a381368e9 100644 --- a/ui/src/components/common/organization-selector.tsx +++ b/ui/src/components/common/organization-selector.tsx @@ -26,8 +26,10 @@ import { Radio, } from '@chakra-ui/react' import cx from 'classnames' -import OrganizationAPI, { Organization } from '@/client/api/organization' -import { SortOrder } from '@/client/api/types/queries' +import OrganizationAPI, { + Organization, + SortOrder, +} from '@/client/api/organization' import { swrConfig } from '@/client/options' import Pagination from '@/lib/components/pagination' import SearchInput from '@/lib/components/search-input' diff --git a/ui/src/components/common/user-selector.tsx b/ui/src/components/common/user-selector.tsx index 7d12e7287..c8346d337 100644 --- a/ui/src/components/common/user-selector.tsx +++ b/ui/src/components/common/user-selector.tsx @@ -26,8 +26,7 @@ import { Radio, } from '@chakra-ui/react' import cx from 'classnames' -import { SortOrder } from '@/client/api/types/queries' -import UserAPI, { User } from '@/client/api/user' +import UserAPI, { SortOrder, User } from '@/client/api/user' import { swrConfig } from '@/client/options' import Pagination from '@/lib/components/pagination' import SearchInput from '@/lib/components/search-input' diff --git a/ui/src/components/file/file-browse.tsx b/ui/src/components/file/file-browse.tsx index ea9677b3a..f09c3298e 100644 --- a/ui/src/components/file/file-browse.tsx +++ b/ui/src/components/file/file-browse.tsx @@ -11,8 +11,7 @@ import { useCallback, useEffect, useState } from 'react' import { useParams } from 'react-router-dom' import { Button } from '@chakra-ui/react' import cx from 'classnames' -import FileAPI, { File } from '@/client/api/file' -import { FileType } from '@/client/api/types/queries' +import FileAPI, { File, FileType } from '@/client/api/file' import WorkspaceAPI from '@/client/api/workspace' import Path from '@/components/common/path' import FolderSvg from '@/components/file/list/item/icon/icon-folder/assets/icon-folder.svg' @@ -130,7 +129,6 @@ const FileBrowse = ({ onChange }: FileBrowseProps) => { > Directory {f.name} diff --git a/ui/src/components/file/file-create.tsx b/ui/src/components/file/file-create.tsx index 7c6f22d66..709206760 100644 --- a/ui/src/components/file/file-create.tsx +++ b/ui/src/components/file/file-create.tsx @@ -32,8 +32,7 @@ import { } from 'formik' import * as Yup from 'yup' import cx from 'classnames' -import FileAPI from '@/client/api/file' -import { FileType } from '@/client/api/types/queries' +import FileAPI, { FileType } from '@/client/api/file' import { useAppDispatch, useAppSelector } from '@/store/hook' import { createModalDidClose } from '@/store/ui/files' diff --git a/ui/src/components/file/file-search-filter.tsx b/ui/src/components/file/file-search-filter.tsx index 3339ec80f..83635db8b 100644 --- a/ui/src/components/file/file-search-filter.tsx +++ b/ui/src/components/file/file-search-filter.tsx @@ -33,7 +33,7 @@ import { import * as Yup from 'yup' import { Select } from 'chakra-react-select' import cx from 'classnames' -import { FileType } from '@/client/api/types/queries' +import { FileType } from '@/client/api/file' import { decodeFileQuery, encodeFileQuery } from '@/lib/helpers/query' import { useAppDispatch, useAppSelector } from '@/store/hook' import { modalDidClose } from '@/store/ui/search-filter' diff --git a/ui/src/components/file/file-toolbar.tsx b/ui/src/components/file/file-toolbar.tsx index 2fbe33a60..063e85a3b 100644 --- a/ui/src/components/file/file-toolbar.tsx +++ b/ui/src/components/file/file-toolbar.tsx @@ -21,9 +21,8 @@ import { Tooltip, } from '@chakra-ui/react' import cx from 'classnames' -import FileAPI, { List } from '@/client/api/file' +import FileAPI, { List, SortBy, SortOrder } from '@/client/api/file' import { ltEditorPermission } from '@/client/api/permission' -import { SortBy, SortOrder } from '@/client/api/types/queries' import { IconAdd, IconMoreVert, diff --git a/ui/src/components/file/list/list-draggable-droppable.tsx b/ui/src/components/file/list/list-draggable-droppable.tsx index ccd96660a..da9d08837 100644 --- a/ui/src/components/file/list/list-draggable-droppable.tsx +++ b/ui/src/components/file/list/list-draggable-droppable.tsx @@ -17,8 +17,7 @@ import { useDroppable, } from '@dnd-kit/core' import cx from 'classnames' -import FileAPI from '@/client/api/file' -import { FileType } from '@/client/api/types/queries' +import FileAPI, { FileType } from '@/client/api/file' import store from '@/store/configure-store' import { useAppDispatch, useAppSelector } from '@/store/hook' import { hiddenUpdated, selectionUpdated } from '@/store/ui/files' diff --git a/ui/src/components/insights/insights-overview/insights-overview-chart.tsx b/ui/src/components/insights/insights-overview/insights-overview-chart.tsx index 295a9cd06..ec5a3f3b4 100644 --- a/ui/src/components/insights/insights-overview/insights-overview-chart.tsx +++ b/ui/src/components/insights/insights-overview/insights-overview-chart.tsx @@ -11,8 +11,7 @@ import { useMemo } from 'react' import { useColorMode } from '@chakra-ui/react' import { ResponsivePie } from '@nivo/pie' import cx from 'classnames' -import InsightsAPI from '@/client/api/insights' -import { SortBy, SortOrder } from '@/client/api/types/queries' +import InsightsAPI, { SortBy, SortOrder } from '@/client/api/insights' import { swrConfig } from '@/client/options' import { useAppSelector } from '@/store/hook' diff --git a/ui/src/components/insights/insights-overview/insights-overview-entities.tsx b/ui/src/components/insights/insights-overview/insights-overview-entities.tsx index 3367d989f..d7e69a0c8 100644 --- a/ui/src/components/insights/insights-overview/insights-overview-entities.tsx +++ b/ui/src/components/insights/insights-overview/insights-overview-entities.tsx @@ -10,8 +10,7 @@ import { useCallback, useEffect, useState } from 'react' import { Badge, Table, Tbody, Td, Tooltip, Tr } from '@chakra-ui/react' import cx from 'classnames' -import InsightsAPI from '@/client/api/insights' -import { SortBy, SortOrder } from '@/client/api/types/queries' +import InsightsAPI, { SortBy, SortOrder } from '@/client/api/insights' import { swrConfig } from '@/client/options' import Pagination from '@/lib/components/pagination' import SearchInput from '@/lib/components/search-input' diff --git a/ui/src/components/snapshot/snapshot-list.tsx b/ui/src/components/snapshot/snapshot-list.tsx index 4160fb09f..455b251d2 100644 --- a/ui/src/components/snapshot/snapshot-list.tsx +++ b/ui/src/components/snapshot/snapshot-list.tsx @@ -25,8 +25,7 @@ import { Tr, } from '@chakra-ui/react' import cx from 'classnames' -import SnapshotAPI, { Snapshot } from '@/client/api/snapshot' -import { SortOrder } from '@/client/api/types/queries' +import SnapshotAPI, { Snapshot, SortOrder } from '@/client/api/snapshot' import { swrConfig } from '@/client/options' import Pagination from '@/lib/components/pagination' import SectionSpinner from '@/lib/components/section-spinner' diff --git a/ui/src/components/task/task-list.tsx b/ui/src/components/task/task-list.tsx index e7b4f286d..a848fd4e5 100644 --- a/ui/src/components/task/task-list.tsx +++ b/ui/src/components/task/task-list.tsx @@ -9,8 +9,7 @@ // licenses/AGPL.txt. import { useEffect, useState } from 'react' import cx from 'classnames' -import TaskAPI from '@/client/api/task' -import { SortOrder } from '@/client/api/types/queries' +import TaskAPI, { SortOrder } from '@/client/api/task' import { swrConfig } from '@/client/options' import Pagination from '@/lib/components/pagination' import { useAppDispatch } from '@/store/hook' diff --git a/ui/src/components/upload/upload-worker.ts b/ui/src/components/upload/upload-worker.ts index c54d6e68c..e1baf4841 100644 --- a/ui/src/components/upload/upload-worker.ts +++ b/ui/src/components/upload/upload-worker.ts @@ -8,8 +8,7 @@ // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. import { FileWithPath } from 'react-dropzone' -import FileAPI from '@/client/api/file' -import { FileType } from '@/client/api/types/queries' +import FileAPI, { FileType } from '@/client/api/file' import { errorToString } from '@/client/error' import store from '@/store/configure-store' import { diff --git a/ui/src/local-storage/index.ts b/ui/src/local-storage/index.ts index 591d90d51..c850efc99 100644 --- a/ui/src/local-storage/index.ts +++ b/ui/src/local-storage/index.ts @@ -7,7 +7,7 @@ // the Business Source License, use of this software will be governed // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. -import { SortBy, SortOrder } from '@/client/api/types/queries' +import { SortBy, SortOrder } from '@/client/api/file' import { FileViewType } from '@/types/file' const ICON_SCALE_KEY = 'voltaserve_file_icon_scale' diff --git a/ui/src/pages/account/account-invitations-page.tsx b/ui/src/pages/account/account-invitations-page.tsx index 0a0c08c2f..d90da629d 100644 --- a/ui/src/pages/account/account-invitations-page.tsx +++ b/ui/src/pages/account/account-invitations-page.tsx @@ -26,8 +26,7 @@ import { } from '@chakra-ui/react' import cx from 'classnames' import { Helmet } from 'react-helmet-async' -import InvitationAPI from '@/client/api/invitation' -import { SortBy, SortOrder } from '@/client/api/types/queries' +import InvitationAPI, { SortBy, SortOrder } from '@/client/api/invitation' import UserAPI from '@/client/idp/user' import { swrConfig } from '@/client/options' import { incomingInvitationPaginationStorage } from '@/infra/pagination' diff --git a/ui/src/pages/group/group-list-page.tsx b/ui/src/pages/group/group-list-page.tsx index 2f8ac3346..22b981bb5 100644 --- a/ui/src/pages/group/group-list-page.tsx +++ b/ui/src/pages/group/group-list-page.tsx @@ -28,8 +28,7 @@ import { } from '@chakra-ui/react' import cx from 'classnames' import { Helmet } from 'react-helmet-async' -import GroupAPI from '@/client/api/group' -import { SortOrder } from '@/client/api/types/queries' +import GroupAPI, { SortOrder } from '@/client/api/group' import { swrConfig } from '@/client/options' import { CreateGroupButton } from '@/components/app-bar/app-bar-buttons' import { groupPaginationStorage } from '@/infra/pagination' diff --git a/ui/src/pages/group/group-members-page.tsx b/ui/src/pages/group/group-members-page.tsx index 8568e8311..eb03068ae 100644 --- a/ui/src/pages/group/group-members-page.tsx +++ b/ui/src/pages/group/group-members-page.tsx @@ -34,8 +34,7 @@ import cx from 'classnames' import { Helmet } from 'react-helmet-async' import GroupAPI from '@/client/api/group' import { geEditorPermission } from '@/client/api/permission' -import { SortBy, SortOrder } from '@/client/api/types/queries' -import UserAPI from '@/client/api/user' +import UserAPI, { SortBy, SortOrder } from '@/client/api/user' import { User as IdPUser } from '@/client/idp/user' import { swrConfig } from '@/client/options' import GroupAddMember from '@/components/group/group-add-member' diff --git a/ui/src/pages/organization/organization-invitations-page.tsx b/ui/src/pages/organization/organization-invitations-page.tsx index 30db54431..bd49deb03 100644 --- a/ui/src/pages/organization/organization-invitations-page.tsx +++ b/ui/src/pages/organization/organization-invitations-page.tsx @@ -27,10 +27,9 @@ import { } from '@chakra-ui/react' import cx from 'classnames' import { Helmet } from 'react-helmet-async' -import InvitationAPI from '@/client/api/invitation' +import InvitationAPI, { SortBy, SortOrder } from '@/client/api/invitation' import OrganizationAPI from '@/client/api/organization' import { geEditorPermission } from '@/client/api/permission' -import { SortBy, SortOrder } from '@/client/api/types/queries' import { swrConfig } from '@/client/options' import OrganizationInviteMembers from '@/components/organization/organization-invite-members' import OrganizationStatus from '@/components/organization/organization-status' diff --git a/ui/src/pages/organization/organization-list-page.tsx b/ui/src/pages/organization/organization-list-page.tsx index a18fe1502..a0b9eac06 100644 --- a/ui/src/pages/organization/organization-list-page.tsx +++ b/ui/src/pages/organization/organization-list-page.tsx @@ -28,8 +28,7 @@ import { } from '@chakra-ui/react' import cx from 'classnames' import { Helmet } from 'react-helmet-async' -import OrganizationAPI from '@/client/api/organization' -import { SortOrder } from '@/client/api/types/queries' +import OrganizationAPI, { SortOrder } from '@/client/api/organization' import { swrConfig } from '@/client/options' import { CreateOrganizationButton } from '@/components/app-bar/app-bar-buttons' import { organizationPaginationStorage } from '@/infra/pagination' diff --git a/ui/src/pages/organization/organization-members-page.tsx b/ui/src/pages/organization/organization-members-page.tsx index 535f84288..3aba15c74 100644 --- a/ui/src/pages/organization/organization-members-page.tsx +++ b/ui/src/pages/organization/organization-members-page.tsx @@ -34,8 +34,7 @@ import cx from 'classnames' import { Helmet } from 'react-helmet-async' import OrganizationAPI from '@/client/api/organization' import { geEditorPermission } from '@/client/api/permission' -import { SortBy, SortOrder } from '@/client/api/types/queries' -import UserAPI, { User } from '@/client/api/user' +import UserAPI, { SortBy, SortOrder, User } from '@/client/api/user' import { swrConfig } from '@/client/options' import OrganizationInviteMembers from '@/components/organization/organization-invite-members' import OrganizationRemoveMember from '@/components/organization/organization-remove-member' diff --git a/ui/src/pages/workspace/workspace-list-page.tsx b/ui/src/pages/workspace/workspace-list-page.tsx index 18506a0ea..2a9934ef5 100644 --- a/ui/src/pages/workspace/workspace-list-page.tsx +++ b/ui/src/pages/workspace/workspace-list-page.tsx @@ -28,8 +28,7 @@ import { } from '@chakra-ui/react' import cx from 'classnames' import { Helmet } from 'react-helmet-async' -import { SortOrder } from '@/client/api/types/queries' -import WorkspaceAPI from '@/client/api/workspace' +import WorkspaceAPI, { SortOrder } from '@/client/api/workspace' import { swrConfig } from '@/client/options' import { CreateWorkspaceButton } from '@/components/app-bar/app-bar-buttons' import { workspacePaginationStorage } from '@/infra/pagination' diff --git a/ui/src/store/ui/files.ts b/ui/src/store/ui/files.ts index 6cfb97724..ff5b1e5c3 100644 --- a/ui/src/store/ui/files.ts +++ b/ui/src/store/ui/files.ts @@ -9,8 +9,7 @@ // licenses/AGPL.txt. import { KeyedMutator } from 'swr' import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import { List } from '@/client/api/file' -import { SortBy, SortOrder } from '@/client/api/types/queries' +import { List, SortBy, SortOrder } from '@/client/api/file' import { loadFileSortBy, loadFileSortOrder,