2025-01-27 15:03:48 +03:00
|
|
|
import { queryOptions } from '@tanstack/react-query';
|
2025-02-04 23:34:02 +03:00
|
|
|
import { z } from 'zod';
|
2025-01-27 15:03:48 +03:00
|
|
|
|
2025-01-28 23:23:42 +03:00
|
|
|
import { axiosDelete, axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
2025-01-27 15:03:48 +03:00
|
|
|
import { DELAYS } from '@/backend/configuration';
|
2025-01-29 14:52:07 +03:00
|
|
|
import { ossApi } from '@/backend/oss/api';
|
2025-01-30 19:55:38 +03:00
|
|
|
import { IRSFormDTO, rsformsApi } from '@/backend/rsform/api';
|
2025-02-07 15:30:47 +03:00
|
|
|
import { AccessPolicy, ILibraryItem, IVersionInfo, LibraryItemID, LibraryItemType, VersionID } from '@/models/library';
|
2025-02-04 23:34:02 +03:00
|
|
|
import { validateLocation } from '@/models/libraryAPI';
|
2025-01-30 19:55:38 +03:00
|
|
|
import { ConstituentaID } from '@/models/rsform';
|
2025-01-27 15:03:48 +03:00
|
|
|
import { UserID } from '@/models/user';
|
2025-02-04 23:34:02 +03:00
|
|
|
import { errors, information } from '@/utils/labels';
|
2025-01-27 15:03:48 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents update data for renaming Location.
|
|
|
|
*/
|
|
|
|
export interface IRenameLocationDTO {
|
|
|
|
target: string;
|
|
|
|
new_location: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents data, used for cloning {@link IRSForm}.
|
|
|
|
*/
|
2025-02-06 14:10:18 +03:00
|
|
|
export interface ICloneLibraryItemDTO extends Omit<ILibraryItem, 'time_create' | 'time_update' | 'owner'> {
|
2025-01-27 15:03:48 +03:00
|
|
|
items?: ConstituentaID[];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents data, used for creating {@link IRSForm}.
|
|
|
|
*/
|
2025-02-04 23:34:02 +03:00
|
|
|
export const CreateLibraryItemSchema = z
|
|
|
|
.object({
|
|
|
|
item_type: z.nativeEnum(LibraryItemType),
|
|
|
|
title: z.string().optional(),
|
|
|
|
alias: z.string().optional(),
|
|
|
|
comment: z.string(),
|
|
|
|
visible: z.boolean(),
|
|
|
|
read_only: z.boolean(),
|
|
|
|
location: z.string(),
|
|
|
|
access_policy: z.nativeEnum(AccessPolicy),
|
|
|
|
|
|
|
|
file: z.instanceof(File).optional(),
|
|
|
|
fileName: z.string().optional()
|
|
|
|
})
|
|
|
|
.refine(data => validateLocation(data.location), {
|
|
|
|
path: ['location'],
|
|
|
|
message: errors.invalidLocation
|
|
|
|
})
|
|
|
|
.refine(data => !!data.file || !!data.title, {
|
|
|
|
path: ['title'],
|
|
|
|
message: errors.requiredField
|
|
|
|
})
|
|
|
|
.refine(data => !!data.file || !!data.alias, {
|
|
|
|
path: ['alias'],
|
|
|
|
message: errors.requiredField
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents data, used for creating {@link IRSForm}.
|
|
|
|
*/
|
|
|
|
export type ICreateLibraryItemDTO = z.infer<typeof CreateLibraryItemSchema>;
|
2025-01-27 15:03:48 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents update data for editing {@link ILibraryItem}.
|
|
|
|
*/
|
2025-02-06 00:26:55 +03:00
|
|
|
export const UpdateLibraryItemSchema = z.object({
|
|
|
|
id: z.number(),
|
|
|
|
item_type: z.nativeEnum(LibraryItemType),
|
|
|
|
title: z.string().nonempty(errors.requiredField),
|
|
|
|
alias: z.string().nonempty(errors.requiredField),
|
|
|
|
comment: z.string(),
|
|
|
|
visible: z.boolean(),
|
|
|
|
read_only: z.boolean()
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents update data for editing {@link ILibraryItem}.
|
|
|
|
*/
|
|
|
|
export type IUpdateLibraryItemDTO = z.infer<typeof UpdateLibraryItemSchema>;
|
2025-01-27 15:03:48 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create version metadata in persistent storage.
|
|
|
|
*/
|
2025-02-07 15:30:47 +03:00
|
|
|
export const VersionCreateSchema = z.object({
|
2025-02-06 14:10:18 +03:00
|
|
|
version: z.string(),
|
|
|
|
description: z.string(),
|
|
|
|
items: z.array(z.number()).optional()
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create version metadata in persistent storage.
|
|
|
|
*/
|
2025-02-07 15:30:47 +03:00
|
|
|
export type IVersionCreateDTO = z.infer<typeof VersionCreateSchema>;
|
2025-01-27 15:03:48 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents data response when creating {@link IVersionInfo}.
|
|
|
|
*/
|
|
|
|
export interface IVersionCreatedResponse {
|
|
|
|
version: number;
|
2025-01-30 19:55:38 +03:00
|
|
|
schema: IRSFormDTO;
|
2025-01-27 15:03:48 +03:00
|
|
|
}
|
|
|
|
|
2025-02-07 15:30:47 +03:00
|
|
|
/**
|
|
|
|
* Represents version data, intended to update version metadata in persistent storage.
|
|
|
|
*/
|
|
|
|
export const VersionUpdateSchema = z.object({
|
|
|
|
id: z.number(),
|
|
|
|
version: z.string().nonempty(errors.requiredField),
|
|
|
|
description: z.string()
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents version data, intended to update version metadata in persistent storage.
|
|
|
|
*/
|
|
|
|
export type IVersionUpdateDTO = z.infer<typeof VersionUpdateSchema>;
|
|
|
|
|
2025-01-27 15:03:48 +03:00
|
|
|
export const libraryApi = {
|
|
|
|
baseKey: 'library',
|
|
|
|
libraryListKey: ['library', 'list'],
|
|
|
|
|
2025-01-28 19:47:24 +03:00
|
|
|
getItemQueryOptions: ({ itemID, itemType }: { itemID: LibraryItemID; itemType: LibraryItemType }) => {
|
|
|
|
return itemType === LibraryItemType.RSFORM
|
|
|
|
? rsformsApi.getRSFormQueryOptions({ itemID })
|
|
|
|
: ossApi.getOssQueryOptions({ itemID });
|
|
|
|
},
|
2025-01-27 15:03:48 +03:00
|
|
|
getLibraryQueryOptions: ({ isAdmin }: { isAdmin: boolean }) =>
|
|
|
|
queryOptions({
|
2025-01-29 23:18:20 +03:00
|
|
|
queryKey: [...libraryApi.libraryListKey, isAdmin ? 'admin' : 'user'],
|
2025-01-27 15:03:48 +03:00
|
|
|
staleTime: DELAYS.staleMedium,
|
|
|
|
queryFn: meta =>
|
2025-01-28 19:47:24 +03:00
|
|
|
axiosGet<ILibraryItem[]>({
|
|
|
|
endpoint: isAdmin ? '/api/library/all' : '/api/library/active',
|
|
|
|
options: { signal: meta.signal }
|
|
|
|
})
|
2025-01-27 15:03:48 +03:00
|
|
|
}),
|
|
|
|
getTemplatesQueryOptions: () =>
|
|
|
|
queryOptions({
|
|
|
|
queryKey: [libraryApi.baseKey, 'templates'],
|
|
|
|
staleTime: DELAYS.staleMedium,
|
|
|
|
queryFn: meta =>
|
2025-01-28 19:47:24 +03:00
|
|
|
axiosGet<ILibraryItem[]>({
|
|
|
|
endpoint: '/api/library/templates',
|
|
|
|
options: { signal: meta.signal }
|
|
|
|
})
|
2025-01-27 15:03:48 +03:00
|
|
|
}),
|
|
|
|
|
2025-02-04 23:34:02 +03:00
|
|
|
createItem: (data: ICreateLibraryItemDTO) =>
|
|
|
|
axiosPost<ICreateLibraryItemDTO, ILibraryItem>({
|
2025-01-28 19:47:24 +03:00
|
|
|
endpoint: !data.file ? '/api/library' : '/api/rsforms/create-detailed',
|
|
|
|
request: {
|
|
|
|
data: data,
|
|
|
|
successMessage: information.newLibraryItem
|
|
|
|
},
|
|
|
|
options: !data.file
|
|
|
|
? undefined
|
|
|
|
: {
|
2025-01-27 15:03:48 +03:00
|
|
|
headers: {
|
|
|
|
'Content-Type': 'multipart/form-data'
|
|
|
|
}
|
2025-01-28 19:47:24 +03:00
|
|
|
}
|
|
|
|
}),
|
2025-02-04 23:34:02 +03:00
|
|
|
updateItem: (data: IUpdateLibraryItemDTO) =>
|
|
|
|
axiosPatch<IUpdateLibraryItemDTO, ILibraryItem>({
|
2025-01-28 19:47:24 +03:00
|
|
|
endpoint: `/api/library/${data.id}`,
|
|
|
|
request: {
|
|
|
|
data: data,
|
|
|
|
successMessage: information.changesSaved
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
setOwner: ({ itemID, owner }: { itemID: LibraryItemID; owner: UserID }) =>
|
|
|
|
axiosPatch({
|
|
|
|
endpoint: `/api/library/${itemID}/set-owner`,
|
|
|
|
request: {
|
|
|
|
data: { user: owner },
|
|
|
|
successMessage: information.changesSaved
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
setLocation: ({ itemID, location }: { itemID: LibraryItemID; location: string }) =>
|
|
|
|
axiosPatch({
|
|
|
|
endpoint: `/api/library/${itemID}/set-location`,
|
|
|
|
request: {
|
|
|
|
data: { location: location },
|
|
|
|
successMessage: information.moveComplete
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
setAccessPolicy: ({ itemID, policy }: { itemID: LibraryItemID; policy: AccessPolicy }) =>
|
|
|
|
axiosPatch({
|
|
|
|
endpoint: `/api/library/${itemID}/set-access-policy`,
|
|
|
|
request: {
|
|
|
|
data: { access_policy: policy },
|
|
|
|
successMessage: information.changesSaved
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
setEditors: ({ itemID, editors }: { itemID: LibraryItemID; editors: UserID[] }) =>
|
|
|
|
axiosPatch({
|
|
|
|
endpoint: `/api/library/${itemID}/set-editors`,
|
|
|
|
request: {
|
|
|
|
data: { users: editors },
|
|
|
|
successMessage: information.changesSaved
|
|
|
|
}
|
|
|
|
}),
|
2025-01-27 15:03:48 +03:00
|
|
|
|
|
|
|
deleteItem: (target: LibraryItemID) =>
|
2025-01-28 19:47:24 +03:00
|
|
|
axiosDelete({
|
|
|
|
endpoint: `/api/library/${target}`,
|
|
|
|
request: {
|
|
|
|
successMessage: information.itemDestroyed
|
|
|
|
}
|
|
|
|
}),
|
2025-02-06 14:10:18 +03:00
|
|
|
cloneItem: (data: ICloneLibraryItemDTO) =>
|
|
|
|
axiosPost<ICloneLibraryItemDTO, IRSFormDTO>({
|
2025-01-28 19:47:24 +03:00
|
|
|
endpoint: `/api/library/${data.id}/clone`,
|
|
|
|
request: {
|
|
|
|
data: data,
|
|
|
|
successMessage: newSchema => information.cloneComplete(newSchema.alias)
|
|
|
|
}
|
|
|
|
}),
|
2025-01-27 15:03:48 +03:00
|
|
|
renameLocation: (data: IRenameLocationDTO) =>
|
2025-01-28 19:47:24 +03:00
|
|
|
axiosPatch({
|
|
|
|
endpoint: '/api/library/rename-location',
|
|
|
|
request: {
|
|
|
|
data: data,
|
|
|
|
successMessage: information.locationRenamed
|
|
|
|
}
|
|
|
|
}),
|
2025-01-27 15:03:48 +03:00
|
|
|
|
2025-02-06 14:10:18 +03:00
|
|
|
versionCreate: ({ itemID, data }: { itemID: LibraryItemID; data: IVersionCreateDTO }) =>
|
|
|
|
axiosPost<IVersionCreateDTO, IVersionCreatedResponse>({
|
2025-01-28 19:47:24 +03:00
|
|
|
endpoint: `/api/library/${itemID}/create-version`,
|
|
|
|
request: {
|
|
|
|
data: data,
|
|
|
|
successMessage: information.newVersion(data.version)
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
versionRestore: ({ versionID }: { versionID: VersionID }) =>
|
2025-01-30 19:55:38 +03:00
|
|
|
axiosPatch<undefined, IRSFormDTO>({
|
2025-01-28 19:47:24 +03:00
|
|
|
endpoint: `/api/versions/${versionID}/restore`,
|
|
|
|
request: {
|
|
|
|
successMessage: information.versionRestored
|
|
|
|
}
|
|
|
|
}),
|
2025-02-07 15:30:47 +03:00
|
|
|
versionUpdate: (data: IVersionUpdateDTO) =>
|
|
|
|
axiosPatch<IVersionUpdateDTO, IVersionInfo>({
|
|
|
|
endpoint: `/api/versions/${data.id}`,
|
2025-01-28 19:47:24 +03:00
|
|
|
request: {
|
|
|
|
data: data,
|
|
|
|
successMessage: information.changesSaved
|
|
|
|
}
|
|
|
|
}),
|
2025-01-27 15:03:48 +03:00
|
|
|
versionDelete: (data: { itemID: LibraryItemID; versionID: VersionID }) =>
|
2025-01-28 19:47:24 +03:00
|
|
|
axiosDelete({
|
|
|
|
endpoint: `/api/versions/${data.versionID}`,
|
|
|
|
request: {
|
|
|
|
successMessage: information.versionDestroyed
|
|
|
|
}
|
|
|
|
})
|
2025-01-27 15:03:48 +03:00
|
|
|
};
|