ajout app
This commit is contained in:
450
Voltaserve/ui/src/client/api/file.ts
Normal file
450
Voltaserve/ui/src/client/api/file.ts
Normal file
@@ -0,0 +1,450 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import useSWR from 'swr'
|
||||
import { apiFetcher } from '@/client/fetcher'
|
||||
import { User } from '@/client/idp/user'
|
||||
import { getConfig } from '@/config/config'
|
||||
import { encodeQuery } from '@/helpers/query'
|
||||
import { getAccessTokenOrRedirect } from '@/infra/token'
|
||||
import { Group } from './group'
|
||||
import { PermissionType } from './permission'
|
||||
import { Download, Snapshot, Thumbnail } 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 enum SnapshotStatus {
|
||||
New = 'new',
|
||||
Processing = 'processing',
|
||||
Ready = 'ready',
|
||||
Error = 'error',
|
||||
}
|
||||
|
||||
export type File = {
|
||||
id: string
|
||||
workspaceId: string
|
||||
name: string
|
||||
type: FileType
|
||||
parentId: string
|
||||
version: number
|
||||
original?: Download
|
||||
preview?: Download
|
||||
thumbnail?: Thumbnail
|
||||
status: SnapshotStatus
|
||||
snapshots: Snapshot[]
|
||||
permission: PermissionType
|
||||
isShared: boolean
|
||||
createTime: string
|
||||
updateTime?: string
|
||||
}
|
||||
|
||||
export type CreateFolderOptions = {
|
||||
workspaceId: string
|
||||
name: string
|
||||
parentId: string
|
||||
}
|
||||
|
||||
export type List = {
|
||||
data: File[]
|
||||
totalPages: number
|
||||
totalElements: number
|
||||
page: number
|
||||
size: number
|
||||
query?: Query
|
||||
}
|
||||
|
||||
export type UserPermission = {
|
||||
id: string
|
||||
user: User
|
||||
permission: string
|
||||
}
|
||||
|
||||
export type GroupPermission = {
|
||||
id: string
|
||||
group: Group
|
||||
permission: string
|
||||
}
|
||||
|
||||
export type Query = {
|
||||
text: string
|
||||
type?: string
|
||||
createTimeAfter?: number
|
||||
createTimeBefore?: number
|
||||
updateTimeAfter?: number
|
||||
updateTimeBefore?: number
|
||||
}
|
||||
|
||||
export type ListOptions = {
|
||||
size?: number
|
||||
page?: number
|
||||
type?: FileType
|
||||
sortBy?: SortBy
|
||||
sortOrder?: SortOrder
|
||||
query?: Query
|
||||
}
|
||||
|
||||
export type MoveOptions = {
|
||||
ids: string[]
|
||||
}
|
||||
|
||||
export type CopyOptions = {
|
||||
ids: string[]
|
||||
}
|
||||
|
||||
export type BatchDeleteOptions = {
|
||||
ids: string[]
|
||||
}
|
||||
|
||||
export type BatchGetOptions = {
|
||||
ids: string[]
|
||||
}
|
||||
|
||||
export type RenameOptions = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export type GrantUserPermissionOptions = {
|
||||
ids: string[]
|
||||
userId: string
|
||||
permission: string
|
||||
}
|
||||
|
||||
export type RevokeUserPermissionOptions = {
|
||||
ids: string[]
|
||||
userId: string
|
||||
}
|
||||
|
||||
export type GrantGroupPermissionOptions = {
|
||||
ids: string[]
|
||||
groupId: string
|
||||
permission: string
|
||||
}
|
||||
|
||||
export type RevokeGroupPermissionOptions = {
|
||||
ids: string[]
|
||||
groupId: string
|
||||
}
|
||||
|
||||
export type UploadOptions = {
|
||||
workspaceId: string
|
||||
parentId?: string
|
||||
name?: string
|
||||
file: Blob
|
||||
request: XMLHttpRequest
|
||||
onProgress?: (value: number) => void
|
||||
}
|
||||
|
||||
export default class FileAPI {
|
||||
static async upload({
|
||||
workspaceId,
|
||||
parentId,
|
||||
name,
|
||||
request,
|
||||
file,
|
||||
onProgress,
|
||||
}: UploadOptions): Promise<File> {
|
||||
const params = new URLSearchParams({ workspace_id: workspaceId })
|
||||
if (parentId) {
|
||||
params.append('parent_id', parentId)
|
||||
}
|
||||
if (name) {
|
||||
params.append('name', name)
|
||||
}
|
||||
return this.doUpload(
|
||||
`${getConfig().apiURL}/files?${params}`,
|
||||
'POST',
|
||||
request,
|
||||
file,
|
||||
onProgress,
|
||||
)
|
||||
}
|
||||
|
||||
static async patch(
|
||||
id: string,
|
||||
request: XMLHttpRequest,
|
||||
file: Blob,
|
||||
onProgress?: (value: number) => void,
|
||||
): Promise<File> {
|
||||
return this.doUpload(
|
||||
`${getConfig().apiURL}/files/${id}`,
|
||||
'PATCH',
|
||||
request,
|
||||
file,
|
||||
onProgress,
|
||||
)
|
||||
}
|
||||
|
||||
private static async doUpload(
|
||||
url: string,
|
||||
method: string,
|
||||
request: XMLHttpRequest,
|
||||
file: Blob,
|
||||
onProgress?: (value: number) => void,
|
||||
) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return new Promise<File>((resolve, reject) => {
|
||||
request.open(method, url)
|
||||
request.setRequestHeader(
|
||||
'Authorization',
|
||||
`Bearer ${getAccessTokenOrRedirect()}`,
|
||||
)
|
||||
request.onloadend = () => {
|
||||
if (request.status <= 299) {
|
||||
try {
|
||||
resolve(JSON.parse(request.responseText))
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
reject(JSON.parse(request.responseText))
|
||||
} catch {
|
||||
reject(request.responseText)
|
||||
}
|
||||
}
|
||||
}
|
||||
request.upload.onprogress = (e) => {
|
||||
onProgress?.((e.loaded / e.total) * 100)
|
||||
}
|
||||
request.send(formData)
|
||||
})
|
||||
}
|
||||
|
||||
static async createFolder(options: CreateFolderOptions) {
|
||||
return apiFetcher({
|
||||
url: '/files/create_folder',
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<File>
|
||||
}
|
||||
|
||||
static async list(id: string, options: ListOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/list?${this.paramsFromListOptions(options)}`,
|
||||
method: 'GET',
|
||||
}) as Promise<List>
|
||||
}
|
||||
|
||||
static useList(
|
||||
id: string | undefined,
|
||||
options: ListOptions,
|
||||
swrOptions?: any,
|
||||
) {
|
||||
const url = `/files/${id}/list?${this.paramsFromListOptions(options)}`
|
||||
return useSWR<List | undefined>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }),
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async getPath(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/get_path`,
|
||||
method: 'GET',
|
||||
}) as Promise<File[]>
|
||||
}
|
||||
|
||||
static useGetPath(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = `/files/${id}/get_path`
|
||||
return useSWR<File[]>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<File[]>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async getIds(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/get_ids`,
|
||||
method: 'GET',
|
||||
}) as Promise<string[]>
|
||||
}
|
||||
|
||||
static async rename(id: string, options: RenameOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/rename`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<File>
|
||||
}
|
||||
|
||||
static async delete(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
static async batchDelete(options: BatchDeleteOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/batch_delete`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async move(id: string, options: MoveOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/move`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async copy(id: string, options: CopyOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/copy`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static useGetById(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = `/files/${id}`
|
||||
return useSWR(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<File>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async getById(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}`,
|
||||
method: 'GET',
|
||||
}) as Promise<File>
|
||||
}
|
||||
|
||||
static async batchGet(options: BatchGetOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/batch_get`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<File[]>
|
||||
}
|
||||
|
||||
static async getItemCount(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/get_item_count`,
|
||||
method: 'GET',
|
||||
}) as Promise<number>
|
||||
}
|
||||
|
||||
static useGetItemCount(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = `/files/${id}/get_item_count`
|
||||
return useSWR<number>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<number>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async grantUserPermission(options: GrantUserPermissionOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/grant_user_permission`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async revokeUserPermission(options: RevokeUserPermissionOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/revoke_user_permission`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async grantGroupPermission(options: GrantGroupPermissionOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/grant_group_permission`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async revokeGroupPermission(options: RevokeGroupPermissionOptions) {
|
||||
return apiFetcher({
|
||||
url: `/files/revoke_group_permission`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async getUserPermissions(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/files/${id}/get_user_permissions`,
|
||||
method: 'GET',
|
||||
}) as Promise<UserPermission[]>
|
||||
}
|
||||
|
||||
static useGetUserPermissions(
|
||||
id: string | null | undefined,
|
||||
swrOptions?: any,
|
||||
) {
|
||||
const url = `/files/${id}/get_user_permissions`
|
||||
return useSWR<UserPermission[]>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<UserPermission[]>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async getGroupPermissions(id: string) {
|
||||
return apiFetcher<GroupPermission[]>({
|
||||
url: `/files/${id}/get_group_permissions`,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
static useGetGroupPermissions(
|
||||
id: string | null | undefined,
|
||||
swrOptions?: any,
|
||||
) {
|
||||
const url = `/files/${id}/get_group_permissions`
|
||||
return useSWR<GroupPermission[]>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<GroupPermission[]>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static paramsFromListOptions(options?: ListOptions): URLSearchParams {
|
||||
const params: any = {}
|
||||
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)
|
||||
}
|
||||
}
|
164
Voltaserve/ui/src/client/api/group.ts
Normal file
164
Voltaserve/ui/src/client/api/group.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import useSWR from 'swr'
|
||||
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
|
||||
organization: Organization
|
||||
permission: string
|
||||
createTime: string
|
||||
updateTime?: string
|
||||
}
|
||||
|
||||
export type List = {
|
||||
data: Group[]
|
||||
totalPages: number
|
||||
totalElements: number
|
||||
page: number
|
||||
size: number
|
||||
}
|
||||
|
||||
export type ListOptions = {
|
||||
query?: string
|
||||
organizationId?: string
|
||||
size?: number
|
||||
page?: number
|
||||
sortBy?: SortBy
|
||||
sortOrder?: SortOrder
|
||||
}
|
||||
|
||||
export type CreateOptions = {
|
||||
name: string
|
||||
image?: string
|
||||
organizationId: string
|
||||
}
|
||||
|
||||
export type UpdateNameOptions = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export type AddMemberOptions = {
|
||||
userId: string
|
||||
}
|
||||
|
||||
export type RemoveMemberOptions = {
|
||||
userId: string
|
||||
}
|
||||
|
||||
export default class GroupAPI {
|
||||
static create(options: CreateOptions) {
|
||||
return apiFetcher({
|
||||
url: `/groups`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<Group>
|
||||
}
|
||||
|
||||
static updateName(id: string, options: UpdateNameOptions) {
|
||||
return apiFetcher({
|
||||
url: `/groups/${id}/update_name`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<Group>
|
||||
}
|
||||
|
||||
static async updateImage(id: string, file: any) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return apiFetcher<Group>({
|
||||
url: `/groups/${id}/update_image`,
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
}
|
||||
|
||||
static async getById(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/groups/${id}`,
|
||||
method: 'GET',
|
||||
}) as Promise<Group>
|
||||
}
|
||||
|
||||
static useGetById(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = `/groups/${id}`
|
||||
return useSWR<Group>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<Group>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async list(options?: ListOptions) {
|
||||
return apiFetcher<List>({
|
||||
url: `/groups?${this.paramsFromListOptions(options)}`,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
static useList(options?: ListOptions, swrOptions?: any) {
|
||||
const url = `/groups?${this.paramsFromListOptions(options)}`
|
||||
return useSWR<List>(
|
||||
url,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<List>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static delete(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/groups/${id}`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
static addMember(id: string, options: AddMemberOptions) {
|
||||
return apiFetcher({
|
||||
url: `/groups/${id}/add_member`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static removeMember(id: string, options: RemoveMemberOptions) {
|
||||
return apiFetcher({
|
||||
url: `/groups/${id}/remove_member`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static paramsFromListOptions(options?: ListOptions): URLSearchParams {
|
||||
const params: any = {}
|
||||
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)
|
||||
}
|
||||
}
|
129
Voltaserve/ui/src/client/api/invitation.ts
Normal file
129
Voltaserve/ui/src/client/api/invitation.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import useSWR from 'swr'
|
||||
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 = {
|
||||
id: string
|
||||
owner: User
|
||||
email: string[]
|
||||
organization: Organization
|
||||
status: InvitationStatus
|
||||
createTime: string
|
||||
updateTime?: string
|
||||
}
|
||||
|
||||
export type List = {
|
||||
data: Invitation[]
|
||||
totalPages: number
|
||||
totalElements: number
|
||||
page: number
|
||||
size: number
|
||||
}
|
||||
|
||||
export type CreateOptions = {
|
||||
organizationId: string
|
||||
emails: string[]
|
||||
}
|
||||
|
||||
export type ListOptions = {
|
||||
organizationId?: string
|
||||
size?: number
|
||||
page?: number
|
||||
sortBy?: SortBy
|
||||
sortOrder?: SortOrder
|
||||
}
|
||||
|
||||
export default class InvitationAPI {
|
||||
static async create(options: CreateOptions) {
|
||||
return apiFetcher({
|
||||
url: `/invitations`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static useGetIncoming(options?: ListOptions, swrOptions?: any) {
|
||||
const url = `/invitations/get_incoming?${this.paramsFromListOptions(
|
||||
options,
|
||||
)}`
|
||||
return useSWR<List>(
|
||||
url,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<List>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static useGetOutgoing(options?: ListOptions, swrOptions?: any) {
|
||||
const url = `/invitations/get_outgoing?${this.paramsFromListOptions(
|
||||
options,
|
||||
)}`
|
||||
return useSWR<List>(
|
||||
options?.organizationId ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<List>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async delete(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/invitations/${id}`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
static async resend(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/invitations/${id}/resend`,
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
static async accept(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/invitations/${id}/accept`,
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
static async decline(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/invitations/${id}/decline`,
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
static paramsFromListOptions(options?: ListOptions): URLSearchParams {
|
||||
const params: any = {}
|
||||
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)
|
||||
}
|
||||
}
|
22
Voltaserve/ui/src/client/api/notification.ts
Normal file
22
Voltaserve/ui/src/client/api/notification.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import useSWR from 'swr'
|
||||
import { apiFetcher } from '@/client/fetcher'
|
||||
import { Invitation } from './invitation'
|
||||
|
||||
export type NotificationType = 'new_invitation'
|
||||
|
||||
export type Notification = {
|
||||
type: NotificationType
|
||||
body: Invitation | any
|
||||
}
|
||||
|
||||
export default class NotificationAPI {
|
||||
static useGetAll(swrOptions?: any) {
|
||||
const url = `/notifications`
|
||||
return useSWR<Notification[]>(
|
||||
url,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<Notification[]>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
}
|
154
Voltaserve/ui/src/client/api/organization.ts
Normal file
154
Voltaserve/ui/src/client/api/organization.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import useSWR from 'swr'
|
||||
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
|
||||
permission: PermissionType
|
||||
createTime: string
|
||||
updateTime?: string
|
||||
}
|
||||
|
||||
export type List = {
|
||||
data: Organization[]
|
||||
totalPages: number
|
||||
totalElements: number
|
||||
page: number
|
||||
size: number
|
||||
}
|
||||
|
||||
export type ListOptions = {
|
||||
query?: string
|
||||
size?: number
|
||||
page?: number
|
||||
sortBy?: SortBy
|
||||
sortOrder?: SortOrder
|
||||
}
|
||||
|
||||
export type CreateOptions = {
|
||||
name: string
|
||||
image?: string
|
||||
}
|
||||
|
||||
export type UpdateNameOptions = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export type RemoveMemberOptions = {
|
||||
userId: string
|
||||
}
|
||||
|
||||
export default class OrganizationAPI {
|
||||
static async getById(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/organizations/${id}`,
|
||||
method: 'GET',
|
||||
}) as Promise<Organization>
|
||||
}
|
||||
|
||||
static useGetById(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = `/organizations/${id}`
|
||||
return useSWR<Organization>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<Organization>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async list(options?: ListOptions) {
|
||||
return apiFetcher({
|
||||
url: `/organizations?${this.paramsFromListOptions(options)}`,
|
||||
method: 'GET',
|
||||
}) as Promise<List>
|
||||
}
|
||||
|
||||
static useList(options?: ListOptions, swrOptions?: any) {
|
||||
const url = `/organizations?${this.paramsFromListOptions(options)}`
|
||||
return useSWR<List>(
|
||||
url,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<List>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async create(options: CreateOptions) {
|
||||
return apiFetcher({
|
||||
url: `/organizations`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<Organization>
|
||||
}
|
||||
|
||||
static async updateName(id: string, options: UpdateNameOptions) {
|
||||
return apiFetcher({
|
||||
url: `/organizations/${id}/update_name`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<Organization>
|
||||
}
|
||||
|
||||
static async updateImage(id: string, file: any) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return apiFetcher({
|
||||
url: `/organizations/${id}/update_image`,
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
}) as Promise<Organization>
|
||||
}
|
||||
|
||||
static async delete(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/organizations/${id}`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
static async leave(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/organizations/${id}/leave`,
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
static async removeMember(id: string, options: RemoveMemberOptions) {
|
||||
return apiFetcher({
|
||||
url: `/organizations/${id}/remove_member`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static paramsFromListOptions(options?: ListOptions): URLSearchParams {
|
||||
const params: any = {}
|
||||
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)
|
||||
}
|
||||
}
|
52
Voltaserve/ui/src/client/api/permission.ts
Normal file
52
Voltaserve/ui/src/client/api/permission.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
export const VIEWER_PERMISSION = 'viewer'
|
||||
export const EDITOR_PERMISSION = 'editor'
|
||||
export const OWNER_PERMISSION = 'owner'
|
||||
|
||||
export type PermissionType = 'viewer' | 'editor' | 'owner'
|
||||
|
||||
export function geViewerPermission(permission: string): boolean {
|
||||
return (
|
||||
getPermissionWeight(permission) >= getPermissionWeight(VIEWER_PERMISSION)
|
||||
)
|
||||
}
|
||||
|
||||
export function geEditorPermission(permission: string) {
|
||||
return (
|
||||
getPermissionWeight(permission) >= getPermissionWeight(EDITOR_PERMISSION)
|
||||
)
|
||||
}
|
||||
|
||||
export function geOwnerPermission(permission: string) {
|
||||
return (
|
||||
getPermissionWeight(permission) >= getPermissionWeight(OWNER_PERMISSION)
|
||||
)
|
||||
}
|
||||
|
||||
export function ltViewerPermission(permission: string): boolean {
|
||||
return (
|
||||
getPermissionWeight(permission) < getPermissionWeight(VIEWER_PERMISSION)
|
||||
)
|
||||
}
|
||||
|
||||
export function ltEditorPermission(permission: string) {
|
||||
return (
|
||||
getPermissionWeight(permission) < getPermissionWeight(EDITOR_PERMISSION)
|
||||
)
|
||||
}
|
||||
|
||||
export function ltOwnerPermission(permission: string) {
|
||||
return getPermissionWeight(permission) < getPermissionWeight(OWNER_PERMISSION)
|
||||
}
|
||||
|
||||
export function getPermissionWeight(permission: string) {
|
||||
switch (permission) {
|
||||
case VIEWER_PERMISSION:
|
||||
return 1
|
||||
case EDITOR_PERMISSION:
|
||||
return 2
|
||||
case OWNER_PERMISSION:
|
||||
return 3
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
24
Voltaserve/ui/src/client/api/snapshot.ts
Normal file
24
Voltaserve/ui/src/client/api/snapshot.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export type Snapshot = {
|
||||
version: number
|
||||
original: Download
|
||||
preview?: Download
|
||||
text?: Download
|
||||
thumbnail?: Thumbnail
|
||||
}
|
||||
|
||||
export type Download = {
|
||||
extension: string
|
||||
size: number
|
||||
image?: ImageProps
|
||||
}
|
||||
|
||||
export type ImageProps = {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export type Thumbnail = {
|
||||
base64: string
|
||||
width: number
|
||||
height: number
|
||||
}
|
44
Voltaserve/ui/src/client/api/storage.ts
Normal file
44
Voltaserve/ui/src/client/api/storage.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import useSWR from 'swr'
|
||||
import { apiFetcher } from '@/client/fetcher'
|
||||
|
||||
export type StorageUsage = {
|
||||
bytes: number
|
||||
maxBytes: number
|
||||
percentage: number
|
||||
}
|
||||
|
||||
export default class StorageAPI {
|
||||
static useGetAccountUsage(swrOptions?: any) {
|
||||
const url = `/storage/get_account_usage`
|
||||
return useSWR<StorageUsage>(
|
||||
url,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<StorageUsage>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static useGetWorkspaceUsage(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = id
|
||||
? `/storage/get_workspace_usage?${new URLSearchParams({
|
||||
id,
|
||||
})}`
|
||||
: null
|
||||
return useSWR<StorageUsage>(
|
||||
url,
|
||||
() => apiFetcher({ url: url!, method: 'GET' }) as Promise<StorageUsage>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static useGetFileUsage(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = `/storage/get_file_usage?${new URLSearchParams({
|
||||
id: id!,
|
||||
})}`
|
||||
return useSWR<StorageUsage>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<StorageUsage>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
}
|
86
Voltaserve/ui/src/client/api/user.ts
Normal file
86
Voltaserve/ui/src/client/api/user.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import useSWR from 'swr'
|
||||
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
|
||||
email: string
|
||||
fullName: string
|
||||
picture?: string
|
||||
}
|
||||
|
||||
export type List = {
|
||||
data: User[]
|
||||
totalPages: number
|
||||
totalElements: number
|
||||
page: number
|
||||
size: number
|
||||
}
|
||||
|
||||
export type ListOptions = {
|
||||
query?: string
|
||||
organizationId?: string
|
||||
groupId?: string
|
||||
nonGroupMembersOnly?: boolean
|
||||
size?: number
|
||||
page?: number
|
||||
sortBy?: SortBy
|
||||
sortOrder?: SortOrder
|
||||
}
|
||||
|
||||
export default class UserAPI {
|
||||
static async list(options?: ListOptions) {
|
||||
return apiFetcher({
|
||||
url: `/users?${this.paramsFromListOptions(options)}`,
|
||||
method: 'GET',
|
||||
}) as Promise<List>
|
||||
}
|
||||
|
||||
static useList(options?: ListOptions, swrOptions?: any) {
|
||||
const url = `/users?${this.paramsFromListOptions(options)}`
|
||||
return useSWR<List>(
|
||||
url,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<List>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static paramsFromListOptions(options?: ListOptions): URLSearchParams {
|
||||
const params: any = {}
|
||||
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?.nonGroupMembersOnly) {
|
||||
params.non_group_members_only = options.nonGroupMembersOnly.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)
|
||||
}
|
||||
}
|
156
Voltaserve/ui/src/client/api/workspace.ts
Normal file
156
Voltaserve/ui/src/client/api/workspace.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import useSWR from 'swr'
|
||||
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
|
||||
permission: PermissionType
|
||||
storageCapacity: number
|
||||
rootId: string
|
||||
organization: Organization
|
||||
createTime: string
|
||||
updateTime?: string
|
||||
}
|
||||
|
||||
export type List = {
|
||||
data: Workspace[]
|
||||
totalPages: number
|
||||
totalElements: number
|
||||
page: number
|
||||
size: number
|
||||
}
|
||||
|
||||
export interface CreateOptions {
|
||||
name: string
|
||||
image?: string
|
||||
organizationId: string
|
||||
storageCapacity: number
|
||||
}
|
||||
|
||||
export type ListOptions = {
|
||||
query?: string
|
||||
size?: number
|
||||
page?: number
|
||||
sortBy?: SortBy
|
||||
sortOrder?: SortOrder
|
||||
}
|
||||
|
||||
export interface UpdateNameOptions {
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface StorageCapacityOptions {
|
||||
storageCapacity: number
|
||||
}
|
||||
|
||||
export default class WorkspaceAPI {
|
||||
static async getById(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/workspaces/${id}`,
|
||||
method: 'GET',
|
||||
}) as Promise<Workspace>
|
||||
}
|
||||
|
||||
static useGetById(id: string | null | undefined, swrOptions?: any) {
|
||||
const url = `/workspaces/${id}`
|
||||
return useSWR<Workspace>(
|
||||
id ? url : null,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<Workspace>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static useList(options?: ListOptions, swrOptions?: any) {
|
||||
const url = `/workspaces?${this.paramsFromListOptions(options)}`
|
||||
return useSWR<List>(
|
||||
url,
|
||||
() => apiFetcher({ url, method: 'GET' }) as Promise<List>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async list(options?: ListOptions) {
|
||||
return apiFetcher({
|
||||
url: `/workspaces?${this.paramsFromListOptions(options)}`,
|
||||
method: 'GET',
|
||||
}) as Promise<List>
|
||||
}
|
||||
|
||||
static async create(options: CreateOptions) {
|
||||
return apiFetcher({
|
||||
url: '/workspaces',
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<Workspace>
|
||||
}
|
||||
|
||||
static async updateName(id: string, options: UpdateNameOptions) {
|
||||
return apiFetcher({
|
||||
url: `/workspaces/${id}/update_name`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<Workspace>
|
||||
}
|
||||
|
||||
static async updateStorageCapacity(
|
||||
id: string,
|
||||
options: StorageCapacityOptions,
|
||||
) {
|
||||
return apiFetcher({
|
||||
url: `/workspaces/${id}/update_storage_capacity`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<Workspace>
|
||||
}
|
||||
|
||||
static async updateImage(id: string, file: any) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return apiFetcher({
|
||||
url: `/workspaces/${id}/update_image`,
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
}) as Promise<Workspace>
|
||||
}
|
||||
|
||||
static async delete(id: string) {
|
||||
return apiFetcher({
|
||||
url: `/workspaces/${id}`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
static paramsFromListOptions(options?: ListOptions): URLSearchParams {
|
||||
const params: any = {}
|
||||
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)
|
||||
}
|
||||
}
|
15
Voltaserve/ui/src/client/error.ts
Normal file
15
Voltaserve/ui/src/client/error.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export type ErrorResponse = {
|
||||
code: string
|
||||
status: number
|
||||
message: string
|
||||
userMessage: string
|
||||
moreInfo: string
|
||||
}
|
||||
|
||||
export function errorToString(value: any): string {
|
||||
if (value.code && value.message && value.userMessage && value.moreInfo) {
|
||||
const error = value as ErrorResponse
|
||||
return error.userMessage
|
||||
}
|
||||
return value.toString()
|
||||
}
|
94
Voltaserve/ui/src/client/fetcher.ts
Normal file
94
Voltaserve/ui/src/client/fetcher.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { getConfig } from '@/config/config'
|
||||
import { getAccessToken, getAccessTokenOrRedirect } from '@/infra/token'
|
||||
import store from '@/store/configure-store'
|
||||
import { errorOccurred } from '@/store/ui/error'
|
||||
import { errorToString } from './error'
|
||||
|
||||
export type FetcherOptions = {
|
||||
url: string
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD'
|
||||
body?: BodyInit | null
|
||||
contentType?: string
|
||||
redirect?: boolean
|
||||
authenticate?: boolean
|
||||
}
|
||||
|
||||
export function apiFetcher<T>(options: FetcherOptions) {
|
||||
return fetcher<T>({ ...options, url: `${getConfig().apiURL}${options.url}` })
|
||||
}
|
||||
|
||||
export function idpFetcher<T>(options: FetcherOptions) {
|
||||
return fetcher<T>({
|
||||
...options,
|
||||
url: `${getConfig().idpURL}${options.url}`,
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetcher<T>({
|
||||
url,
|
||||
method,
|
||||
body,
|
||||
contentType,
|
||||
redirect,
|
||||
authenticate = true,
|
||||
}: FetcherOptions): Promise<T | undefined> {
|
||||
const headers: HeadersInit = {}
|
||||
if (!contentType) {
|
||||
headers['Content-Type'] = 'application/json'
|
||||
}
|
||||
if (authenticate) {
|
||||
headers['Authorization'] = `Bearer ${
|
||||
redirect ? getAccessTokenOrRedirect() : getAccessToken()
|
||||
}`
|
||||
}
|
||||
const response = await baseFetcher(
|
||||
url,
|
||||
{
|
||||
method,
|
||||
body,
|
||||
headers,
|
||||
credentials: authenticate ? 'include' : undefined,
|
||||
},
|
||||
redirect,
|
||||
)
|
||||
try {
|
||||
if (response) {
|
||||
return (await response.json()) as T
|
||||
}
|
||||
} catch {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
|
||||
export async function baseFetcher(
|
||||
url: string,
|
||||
init?: RequestInit,
|
||||
redirect = true,
|
||||
) {
|
||||
try {
|
||||
const response = await fetch(url, init)
|
||||
return handleResponse(response, redirect)
|
||||
} catch (error) {
|
||||
const message = 'Unexpected error occurred.'
|
||||
store.dispatch(errorOccurred(message))
|
||||
throw new Error(message)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleResponse(response: Response, redirect = true) {
|
||||
if (response.status <= 299) {
|
||||
return response
|
||||
} else {
|
||||
if (response.status === 401 && redirect) {
|
||||
window.location.href = '/sign-in'
|
||||
}
|
||||
let message
|
||||
try {
|
||||
message = errorToString(await response.json())
|
||||
} catch {
|
||||
message = 'Oops! something went wrong.'
|
||||
}
|
||||
store.dispatch(errorOccurred(message))
|
||||
throw new Error(message)
|
||||
}
|
||||
}
|
58
Voltaserve/ui/src/client/idp/account.ts
Normal file
58
Voltaserve/ui/src/client/idp/account.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { idpFetcher } from '@/client/fetcher'
|
||||
import { User } from './user'
|
||||
|
||||
export type CreateOptions = {
|
||||
email: string
|
||||
password: string
|
||||
fullName: string
|
||||
picture?: string
|
||||
}
|
||||
|
||||
export type SendResetPasswordEmailOptions = {
|
||||
email: string
|
||||
}
|
||||
|
||||
export type ResetPasswordOptions = {
|
||||
token: string
|
||||
newPassword: string
|
||||
}
|
||||
|
||||
export type ConfirmEmailOptions = {
|
||||
token: string
|
||||
}
|
||||
|
||||
export default class AccountAPI {
|
||||
static async create(options: CreateOptions) {
|
||||
return idpFetcher({
|
||||
url: `/accounts`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
redirect: false,
|
||||
authenticate: false,
|
||||
}) as Promise<User>
|
||||
}
|
||||
|
||||
static async sendResetPasswordEmail(options: SendResetPasswordEmailOptions) {
|
||||
return idpFetcher({
|
||||
url: `/accounts/send_reset_password_email`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async resetPassword(options: ResetPasswordOptions) {
|
||||
return idpFetcher({
|
||||
url: `/accounts/reset_password`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async confirmEmail(options: ConfirmEmailOptions) {
|
||||
return idpFetcher({
|
||||
url: `/accounts/confirm_email`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
}
|
66
Voltaserve/ui/src/client/idp/token.ts
Normal file
66
Voltaserve/ui/src/client/idp/token.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { baseFetcher } from '@/client/fetcher'
|
||||
import { getConfig } from '@/config/config'
|
||||
|
||||
export type GrantType = 'password' | 'refresh_token'
|
||||
|
||||
export type Token = {
|
||||
access_token: string
|
||||
expires_in: number
|
||||
token_type: string
|
||||
refresh_token: string
|
||||
}
|
||||
|
||||
export type ExchangeOptions = {
|
||||
grant_type: GrantType
|
||||
username?: string
|
||||
password?: string
|
||||
refresh_token?: string
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export default class TokenAPI {
|
||||
static async exchange(options: ExchangeOptions) {
|
||||
const formBody = []
|
||||
formBody.push(`grant_type=${options.grant_type}`)
|
||||
if (options.grant_type === 'password') {
|
||||
if (options.username && options.password) {
|
||||
formBody.push(`username=${encodeURIComponent(options.username)}`)
|
||||
formBody.push(`password=${encodeURIComponent(options.password)}`)
|
||||
} else {
|
||||
throw new Error('Username or password missing!')
|
||||
}
|
||||
}
|
||||
if (options.grant_type === 'refresh_token') {
|
||||
if (options.refresh_token) {
|
||||
formBody.push(
|
||||
`refresh_token=${encodeURIComponent(options.refresh_token)}`,
|
||||
)
|
||||
} else {
|
||||
throw new Error('Refresh token missing!')
|
||||
}
|
||||
}
|
||||
if (options.locale) {
|
||||
formBody.push(`&locale=${encodeURIComponent(options.locale)}`)
|
||||
}
|
||||
const response = await baseFetcher(
|
||||
`${getConfig().idpURL}/token`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: formBody.join('&'),
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
},
|
||||
false,
|
||||
)
|
||||
try {
|
||||
if (response) {
|
||||
return (await response.json()) as Token
|
||||
} else {
|
||||
throw new Error('No response')
|
||||
}
|
||||
} catch {
|
||||
throw new Error('Failed to parse token')
|
||||
}
|
||||
}
|
||||
}
|
104
Voltaserve/ui/src/client/idp/user.ts
Normal file
104
Voltaserve/ui/src/client/idp/user.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import useSWR from 'swr'
|
||||
import { idpFetcher } from '@/client/fetcher'
|
||||
|
||||
export type User = {
|
||||
id: string
|
||||
username: string
|
||||
email: string
|
||||
fullName: string
|
||||
picture?: string
|
||||
pendingEmail?: string
|
||||
}
|
||||
|
||||
export type UpdateFullNameOptions = {
|
||||
fullName: string
|
||||
}
|
||||
|
||||
export type UpdateEmailRequestOptions = {
|
||||
email: string
|
||||
}
|
||||
|
||||
export type UpdateEmailConfirmationOptions = {
|
||||
token: string
|
||||
}
|
||||
|
||||
export type UpdatePasswordOptions = {
|
||||
currentPassword: string
|
||||
newPassword: string
|
||||
}
|
||||
|
||||
export type DeleteOptions = {
|
||||
password: string
|
||||
}
|
||||
|
||||
export default class UserAPI {
|
||||
static useGet(swrOptions?: any) {
|
||||
const url = `/user`
|
||||
return useSWR<User>(
|
||||
url,
|
||||
() => idpFetcher({ url, method: 'GET' }) as Promise<User>,
|
||||
swrOptions,
|
||||
)
|
||||
}
|
||||
|
||||
static async updateFullName(options: UpdateFullNameOptions) {
|
||||
return idpFetcher({
|
||||
url: `/user/update_full_name`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<User>
|
||||
}
|
||||
|
||||
static async updateEmailRequest(options: UpdateEmailRequestOptions) {
|
||||
return idpFetcher({
|
||||
url: `/user/update_email_request`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<User>
|
||||
}
|
||||
|
||||
static async updateEmailConfirmation(
|
||||
options: UpdateEmailConfirmationOptions,
|
||||
) {
|
||||
return idpFetcher({
|
||||
url: `/user/update_email_confirmation`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<User>
|
||||
}
|
||||
|
||||
static async updatePassword(options: UpdatePasswordOptions) {
|
||||
return idpFetcher({
|
||||
url: `/user/update_password`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options),
|
||||
}) as Promise<User>
|
||||
}
|
||||
|
||||
static async delete(options: DeleteOptions) {
|
||||
return idpFetcher({
|
||||
url: `/user`,
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify(options),
|
||||
})
|
||||
}
|
||||
|
||||
static async updatePicture(file: File) {
|
||||
const body = new FormData()
|
||||
body.append('file', file)
|
||||
return idpFetcher({
|
||||
url: `/user/update_picture`,
|
||||
method: 'POST',
|
||||
body,
|
||||
contentType: 'multipart/form-data',
|
||||
}) as Promise<User>
|
||||
}
|
||||
|
||||
static async deletePicture() {
|
||||
return idpFetcher({
|
||||
url: `/user/delete_picture`,
|
||||
method: 'POST',
|
||||
}) as Promise<User>
|
||||
}
|
||||
}
|
7
Voltaserve/ui/src/client/options.ts
Normal file
7
Voltaserve/ui/src/client/options.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const REFRESH_INTERVAL = 5000
|
||||
|
||||
export function swrConfig() {
|
||||
return {
|
||||
refreshInterval: REFRESH_INTERVAL,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user