R: Refine feature boundaries and dependencies
This commit is contained in:
parent
53a795d3ec
commit
6bb02c6462
|
@ -7,3 +7,18 @@ export const DELAYS = {
|
||||||
staleMedium: 1 * 60 * 60 * 1000,
|
staleMedium: 1 * 60 * 60 * 1000,
|
||||||
staleLong: 24 * 60 * 60 * 1000
|
staleLong: 24 * 60 * 60 * 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** API keys for local cache. */
|
||||||
|
export const KEYS = {
|
||||||
|
oss: 'oss',
|
||||||
|
rsform: 'rsform',
|
||||||
|
library: 'library',
|
||||||
|
users: 'users',
|
||||||
|
cctext: 'cctext',
|
||||||
|
|
||||||
|
composite: {
|
||||||
|
libraryList: ['library', 'list'],
|
||||||
|
ossItem: ({ itemID }: { itemID?: number }) => [KEYS.oss, 'item', itemID],
|
||||||
|
rsItem: ({ itemID, version }: { itemID?: number; version?: number }) => [KEYS.rsform, 'item', itemID, version ?? '']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -1,77 +1,17 @@
|
||||||
import { queryOptions } from '@tanstack/react-query';
|
import { queryOptions } from '@tanstack/react-query';
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||||
import { DELAYS } from '@/backend/configuration';
|
import { DELAYS } from '@/backend/configuration';
|
||||||
import { errorMsg, infoMsg } from '@/utils/labels';
|
import { infoMsg } from '@/utils/labels';
|
||||||
|
|
||||||
/**
|
import {
|
||||||
* Represents CurrentUser information.
|
IChangePasswordDTO,
|
||||||
*/
|
ICurrentUser,
|
||||||
export interface ICurrentUser {
|
IPasswordTokenDTO,
|
||||||
id: number | null;
|
IRequestPasswordDTO,
|
||||||
username: string;
|
IResetPasswordDTO,
|
||||||
is_staff: boolean;
|
IUserLoginDTO
|
||||||
editor: number[];
|
} from './types';
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents login data, used to authenticate users.
|
|
||||||
*/
|
|
||||||
export const schemaUserLogin = z.object({
|
|
||||||
username: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
password: z.string().nonempty(errorMsg.requiredField)
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents login data, used to authenticate users.
|
|
||||||
*/
|
|
||||||
export type IUserLoginDTO = z.infer<typeof schemaUserLogin>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data needed to update password for current user.
|
|
||||||
*/
|
|
||||||
export const schemaChangePassword = z
|
|
||||||
.object({
|
|
||||||
old_password: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
new_password: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
new_password2: z.string().nonempty(errorMsg.requiredField)
|
|
||||||
})
|
|
||||||
.refine(schema => schema.new_password === schema.new_password2, {
|
|
||||||
path: ['new_password2'],
|
|
||||||
message: errorMsg.passwordsMismatch
|
|
||||||
})
|
|
||||||
.refine(schema => schema.old_password !== schema.new_password, {
|
|
||||||
path: ['new_password'],
|
|
||||||
message: errorMsg.passwordsSame
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data needed to update password for current user.
|
|
||||||
*/
|
|
||||||
export type IChangePasswordDTO = z.infer<typeof schemaChangePassword>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents password reset request data.
|
|
||||||
*/
|
|
||||||
export interface IRequestPasswordDTO {
|
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents password reset data.
|
|
||||||
*/
|
|
||||||
export interface IResetPasswordDTO {
|
|
||||||
password: string;
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents password token data.
|
|
||||||
*/
|
|
||||||
export interface IPasswordTokenDTO {
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication API.
|
* Authentication API.
|
||||||
|
|
71
rsconcept/frontend/src/features/auth/backend/types.ts
Normal file
71
rsconcept/frontend/src/features/auth/backend/types.ts
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents CurrentUser information.
|
||||||
|
*/
|
||||||
|
export interface ICurrentUser {
|
||||||
|
id: number | null;
|
||||||
|
username: string;
|
||||||
|
is_staff: boolean;
|
||||||
|
editor: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents login data, used to authenticate users.
|
||||||
|
*/
|
||||||
|
export const schemaUserLogin = z.object({
|
||||||
|
username: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
password: z.string().nonempty(errorMsg.requiredField)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents login data, used to authenticate users.
|
||||||
|
*/
|
||||||
|
export type IUserLoginDTO = z.infer<typeof schemaUserLogin>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data needed to update password for current user.
|
||||||
|
*/
|
||||||
|
export const schemaChangePassword = z
|
||||||
|
.object({
|
||||||
|
old_password: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
new_password: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
new_password2: z.string().nonempty(errorMsg.requiredField)
|
||||||
|
})
|
||||||
|
.refine(schema => schema.new_password === schema.new_password2, {
|
||||||
|
path: ['new_password2'],
|
||||||
|
message: errorMsg.passwordsMismatch
|
||||||
|
})
|
||||||
|
.refine(schema => schema.old_password !== schema.new_password, {
|
||||||
|
path: ['new_password'],
|
||||||
|
message: errorMsg.passwordsSame
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data needed to update password for current user.
|
||||||
|
*/
|
||||||
|
export type IChangePasswordDTO = z.infer<typeof schemaChangePassword>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents password reset request data.
|
||||||
|
*/
|
||||||
|
export interface IRequestPasswordDTO {
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents password reset data.
|
||||||
|
*/
|
||||||
|
export interface IResetPasswordDTO {
|
||||||
|
password: string;
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents password token data.
|
||||||
|
*/
|
||||||
|
export interface IPasswordTokenDTO {
|
||||||
|
token: string;
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { authApi, IChangePasswordDTO } from './api';
|
import { authApi } from './api';
|
||||||
|
import { IChangePasswordDTO } from './types';
|
||||||
|
|
||||||
export const useChangePassword = () => {
|
export const useChangePassword = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { authApi, IUserLoginDTO } from './api';
|
import { authApi } from './api';
|
||||||
|
import { IUserLoginDTO } from './types';
|
||||||
|
|
||||||
export const useLogin = () => {
|
export const useLogin = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { authApi, IRequestPasswordDTO } from './api';
|
import { authApi } from './api';
|
||||||
|
import { IRequestPasswordDTO } from './types';
|
||||||
|
|
||||||
export const useRequestPasswordReset = () => {
|
export const useRequestPasswordReset = () => {
|
||||||
const mutation = useMutation({
|
const mutation = useMutation({
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { authApi, IPasswordTokenDTO, IResetPasswordDTO } from './api';
|
import { authApi } from './api';
|
||||||
|
import { IPasswordTokenDTO, IResetPasswordDTO } from './types';
|
||||||
|
|
||||||
export const useResetPassword = () => {
|
export const useResetPassword = () => {
|
||||||
const validateMutation = useMutation({
|
const validateMutation = useMutation({
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { TextInput } from '@/components/Input';
|
||||||
import useQueryStrings from '@/hooks/useQueryStrings';
|
import useQueryStrings from '@/hooks/useQueryStrings';
|
||||||
import { resources } from '@/utils/constants';
|
import { resources } from '@/utils/constants';
|
||||||
|
|
||||||
import { IUserLoginDTO, schemaUserLogin } from '../backend/api';
|
import { IUserLoginDTO, schemaUserLogin } from '../backend/types';
|
||||||
import { useAuthSuspense } from '../backend/useAuth';
|
import { useAuthSuspense } from '../backend/useAuth';
|
||||||
import { useLogin } from '../backend/useLogin';
|
import { useLogin } from '../backend/useLogin';
|
||||||
import { ExpectedAnonymous } from '../components/ExpectedAnonymous';
|
import { ExpectedAnonymous } from '../components/ExpectedAnonymous';
|
||||||
|
|
|
@ -1,139 +1,25 @@
|
||||||
import { queryOptions } from '@tanstack/react-query';
|
import { queryOptions } from '@tanstack/react-query';
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { axiosDelete, axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
import { axiosDelete, axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||||
import { DELAYS } from '@/backend/configuration';
|
import { DELAYS, KEYS } from '@/backend/configuration';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
import { IRSFormDTO, rsformsApi } from '@/features/rsform/backend/api';
|
import { infoMsg } from '@/utils/labels';
|
||||||
import { errorMsg, infoMsg } from '@/utils/labels';
|
|
||||||
|
|
||||||
import { AccessPolicy, ILibraryItem, IVersionInfo, LibraryItemID, LibraryItemType, VersionID } from '../models/library';
|
import { AccessPolicy, ILibraryItem, IVersionInfo } from '../models/library';
|
||||||
import { validateLocation } from '../models/libraryAPI';
|
import {
|
||||||
|
ICloneLibraryItemDTO,
|
||||||
/**
|
ICreateLibraryItemDTO,
|
||||||
* Represents update data for renaming Location.
|
IRenameLocationDTO,
|
||||||
*/
|
IUpdateLibraryItemDTO,
|
||||||
export interface IRenameLocationDTO {
|
IVersionCreatedResponse,
|
||||||
target: string;
|
IVersionCreateDTO,
|
||||||
new_location: string;
|
IVersionUpdateDTO
|
||||||
}
|
} from './types';
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used for cloning {@link IRSForm}.
|
|
||||||
*/
|
|
||||||
export const schemaCloneLibraryItem = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
item_type: z.nativeEnum(LibraryItemType),
|
|
||||||
title: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
alias: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
comment: z.string(),
|
|
||||||
visible: z.boolean(),
|
|
||||||
read_only: z.boolean(),
|
|
||||||
location: z.string().refine(data => validateLocation(data), { message: errorMsg.invalidLocation }),
|
|
||||||
access_policy: z.nativeEnum(AccessPolicy),
|
|
||||||
|
|
||||||
items: z.array(z.number()).optional()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used for cloning {@link IRSForm}.
|
|
||||||
*/
|
|
||||||
export type ICloneLibraryItemDTO = z.infer<typeof schemaCloneLibraryItem>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used for creating {@link IRSForm}.
|
|
||||||
*/
|
|
||||||
export const schemaCreateLibraryItem = 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().refine(data => validateLocation(data), { message: errorMsg.invalidLocation }),
|
|
||||||
access_policy: z.nativeEnum(AccessPolicy),
|
|
||||||
|
|
||||||
file: z.instanceof(File).optional(),
|
|
||||||
fileName: z.string().optional()
|
|
||||||
})
|
|
||||||
.refine(data => !!data.file || !!data.title, {
|
|
||||||
path: ['title'],
|
|
||||||
message: errorMsg.requiredField
|
|
||||||
})
|
|
||||||
.refine(data => !!data.file || !!data.alias, {
|
|
||||||
path: ['alias'],
|
|
||||||
message: errorMsg.requiredField
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used for creating {@link IRSForm}.
|
|
||||||
*/
|
|
||||||
export type ICreateLibraryItemDTO = z.infer<typeof schemaCreateLibraryItem>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents update data for editing {@link ILibraryItem}.
|
|
||||||
*/
|
|
||||||
export const schemaUpdateLibraryItem = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
item_type: z.nativeEnum(LibraryItemType),
|
|
||||||
title: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
alias: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
comment: z.string(),
|
|
||||||
visible: z.boolean(),
|
|
||||||
read_only: z.boolean()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents update data for editing {@link ILibraryItem}.
|
|
||||||
*/
|
|
||||||
export type IUpdateLibraryItemDTO = z.infer<typeof schemaUpdateLibraryItem>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create version metadata in persistent storage.
|
|
||||||
*/
|
|
||||||
export const schemaVersionCreate = z.object({
|
|
||||||
version: z.string(),
|
|
||||||
description: z.string(),
|
|
||||||
items: z.array(z.number()).optional()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create version metadata in persistent storage.
|
|
||||||
*/
|
|
||||||
export type IVersionCreateDTO = z.infer<typeof schemaVersionCreate>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data response when creating {@link IVersionInfo}.
|
|
||||||
*/
|
|
||||||
export interface IVersionCreatedResponse {
|
|
||||||
version: number;
|
|
||||||
schema: IRSFormDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents version data, intended to update version metadata in persistent storage.
|
|
||||||
*/
|
|
||||||
export const schemaVersionUpdate = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
version: z.string().nonempty(errorMsg.requiredField),
|
|
||||||
description: z.string()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents version data, intended to update version metadata in persistent storage.
|
|
||||||
*/
|
|
||||||
export type IVersionUpdateDTO = z.infer<typeof schemaVersionUpdate>;
|
|
||||||
|
|
||||||
export const libraryApi = {
|
export const libraryApi = {
|
||||||
baseKey: 'library',
|
baseKey: KEYS.library,
|
||||||
libraryListKey: ['library', 'list'],
|
libraryListKey: KEYS.composite.libraryList,
|
||||||
|
|
||||||
getItemQueryOptions: ({ itemID, itemType }: { itemID: LibraryItemID; itemType: LibraryItemType }) => {
|
|
||||||
return itemType === LibraryItemType.RSFORM
|
|
||||||
? rsformsApi.getRSFormQueryOptions({ itemID })
|
|
||||||
: ossApi.getOssQueryOptions({ itemID });
|
|
||||||
},
|
|
||||||
getLibraryQueryOptions: ({ isAdmin }: { isAdmin: boolean }) =>
|
getLibraryQueryOptions: ({ isAdmin }: { isAdmin: boolean }) =>
|
||||||
queryOptions({
|
queryOptions({
|
||||||
queryKey: [...libraryApi.libraryListKey, isAdmin ? 'admin' : 'user'],
|
queryKey: [...libraryApi.libraryListKey, isAdmin ? 'admin' : 'user'],
|
||||||
|
@ -178,7 +64,7 @@ export const libraryApi = {
|
||||||
successMessage: infoMsg.changesSaved
|
successMessage: infoMsg.changesSaved
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
setOwner: ({ itemID, owner }: { itemID: LibraryItemID; owner: number }) =>
|
setOwner: ({ itemID, owner }: { itemID: number; owner: number }) =>
|
||||||
axiosPatch({
|
axiosPatch({
|
||||||
endpoint: `/api/library/${itemID}/set-owner`,
|
endpoint: `/api/library/${itemID}/set-owner`,
|
||||||
request: {
|
request: {
|
||||||
|
@ -186,7 +72,7 @@ export const libraryApi = {
|
||||||
successMessage: infoMsg.changesSaved
|
successMessage: infoMsg.changesSaved
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
setLocation: ({ itemID, location }: { itemID: LibraryItemID; location: string }) =>
|
setLocation: ({ itemID, location }: { itemID: number; location: string }) =>
|
||||||
axiosPatch({
|
axiosPatch({
|
||||||
endpoint: `/api/library/${itemID}/set-location`,
|
endpoint: `/api/library/${itemID}/set-location`,
|
||||||
request: {
|
request: {
|
||||||
|
@ -194,7 +80,7 @@ export const libraryApi = {
|
||||||
successMessage: infoMsg.moveComplete
|
successMessage: infoMsg.moveComplete
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
setAccessPolicy: ({ itemID, policy }: { itemID: LibraryItemID; policy: AccessPolicy }) =>
|
setAccessPolicy: ({ itemID, policy }: { itemID: number; policy: AccessPolicy }) =>
|
||||||
axiosPatch({
|
axiosPatch({
|
||||||
endpoint: `/api/library/${itemID}/set-access-policy`,
|
endpoint: `/api/library/${itemID}/set-access-policy`,
|
||||||
request: {
|
request: {
|
||||||
|
@ -202,7 +88,7 @@ export const libraryApi = {
|
||||||
successMessage: infoMsg.changesSaved
|
successMessage: infoMsg.changesSaved
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
setEditors: ({ itemID, editors }: { itemID: LibraryItemID; editors: number[] }) =>
|
setEditors: ({ itemID, editors }: { itemID: number; editors: number[] }) =>
|
||||||
axiosPatch({
|
axiosPatch({
|
||||||
endpoint: `/api/library/${itemID}/set-editors`,
|
endpoint: `/api/library/${itemID}/set-editors`,
|
||||||
request: {
|
request: {
|
||||||
|
@ -211,7 +97,7 @@ export const libraryApi = {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
deleteItem: (target: LibraryItemID) =>
|
deleteItem: (target: number) =>
|
||||||
axiosDelete({
|
axiosDelete({
|
||||||
endpoint: `/api/library/${target}`,
|
endpoint: `/api/library/${target}`,
|
||||||
request: {
|
request: {
|
||||||
|
@ -235,7 +121,7 @@ export const libraryApi = {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
versionCreate: ({ itemID, data }: { itemID: LibraryItemID; data: IVersionCreateDTO }) =>
|
versionCreate: ({ itemID, data }: { itemID: number; data: IVersionCreateDTO }) =>
|
||||||
axiosPost<IVersionCreateDTO, IVersionCreatedResponse>({
|
axiosPost<IVersionCreateDTO, IVersionCreatedResponse>({
|
||||||
endpoint: `/api/library/${itemID}/create-version`,
|
endpoint: `/api/library/${itemID}/create-version`,
|
||||||
request: {
|
request: {
|
||||||
|
@ -243,7 +129,7 @@ export const libraryApi = {
|
||||||
successMessage: infoMsg.newVersion(data.version)
|
successMessage: infoMsg.newVersion(data.version)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
versionRestore: ({ versionID }: { versionID: VersionID }) =>
|
versionRestore: ({ versionID }: { versionID: number }) =>
|
||||||
axiosPatch<undefined, IRSFormDTO>({
|
axiosPatch<undefined, IRSFormDTO>({
|
||||||
endpoint: `/api/versions/${versionID}/restore`,
|
endpoint: `/api/versions/${versionID}/restore`,
|
||||||
request: {
|
request: {
|
||||||
|
@ -258,7 +144,7 @@ export const libraryApi = {
|
||||||
successMessage: infoMsg.changesSaved
|
successMessage: infoMsg.changesSaved
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
versionDelete: (data: { itemID: LibraryItemID; versionID: VersionID }) =>
|
versionDelete: (data: { itemID: number; versionID: number }) =>
|
||||||
axiosDelete({
|
axiosDelete({
|
||||||
endpoint: `/api/versions/${data.versionID}`,
|
endpoint: `/api/versions/${data.versionID}`,
|
||||||
request: {
|
request: {
|
||||||
|
|
122
rsconcept/frontend/src/features/library/backend/types.ts
Normal file
122
rsconcept/frontend/src/features/library/backend/types.ts
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
|
import { AccessPolicy, LibraryItemType } from '../models/library';
|
||||||
|
import { validateLocation } from '../models/libraryAPI';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents update data for renaming Location.
|
||||||
|
*/
|
||||||
|
export interface IRenameLocationDTO {
|
||||||
|
target: string;
|
||||||
|
new_location: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used for cloning {@link IRSForm}.
|
||||||
|
*/
|
||||||
|
export const schemaCloneLibraryItem = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
item_type: z.nativeEnum(LibraryItemType),
|
||||||
|
title: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
alias: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
comment: z.string(),
|
||||||
|
visible: z.boolean(),
|
||||||
|
read_only: z.boolean(),
|
||||||
|
location: z.string().refine(data => validateLocation(data), { message: errorMsg.invalidLocation }),
|
||||||
|
access_policy: z.nativeEnum(AccessPolicy),
|
||||||
|
|
||||||
|
items: z.array(z.number()).optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used for cloning {@link IRSForm}.
|
||||||
|
*/
|
||||||
|
export type ICloneLibraryItemDTO = z.infer<typeof schemaCloneLibraryItem>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used for creating {@link IRSForm}.
|
||||||
|
*/
|
||||||
|
export const schemaCreateLibraryItem = 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().refine(data => validateLocation(data), { message: errorMsg.invalidLocation }),
|
||||||
|
access_policy: z.nativeEnum(AccessPolicy),
|
||||||
|
|
||||||
|
file: z.instanceof(File).optional(),
|
||||||
|
fileName: z.string().optional()
|
||||||
|
})
|
||||||
|
.refine(data => !!data.file || !!data.title, {
|
||||||
|
path: ['title'],
|
||||||
|
message: errorMsg.requiredField
|
||||||
|
})
|
||||||
|
.refine(data => !!data.file || !!data.alias, {
|
||||||
|
path: ['alias'],
|
||||||
|
message: errorMsg.requiredField
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used for creating {@link IRSForm}.
|
||||||
|
*/
|
||||||
|
export type ICreateLibraryItemDTO = z.infer<typeof schemaCreateLibraryItem>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents update data for editing {@link ILibraryItem}.
|
||||||
|
*/
|
||||||
|
export const schemaUpdateLibraryItem = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
item_type: z.nativeEnum(LibraryItemType),
|
||||||
|
title: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
alias: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
comment: z.string(),
|
||||||
|
visible: z.boolean(),
|
||||||
|
read_only: z.boolean()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents update data for editing {@link ILibraryItem}.
|
||||||
|
*/
|
||||||
|
export type IUpdateLibraryItemDTO = z.infer<typeof schemaUpdateLibraryItem>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create version metadata in persistent storage.
|
||||||
|
*/
|
||||||
|
export const schemaVersionCreate = z.object({
|
||||||
|
version: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
items: z.array(z.number()).optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create version metadata in persistent storage.
|
||||||
|
*/
|
||||||
|
export type IVersionCreateDTO = z.infer<typeof schemaVersionCreate>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data response when creating {@link IVersionInfo}.
|
||||||
|
*/
|
||||||
|
export interface IVersionCreatedResponse {
|
||||||
|
version: number;
|
||||||
|
schema: IRSFormDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents version data, intended to update version metadata in persistent storage.
|
||||||
|
*/
|
||||||
|
export const schemaVersionUpdate = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
version: z.string().nonempty(errorMsg.requiredField),
|
||||||
|
description: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents version data, intended to update version metadata in persistent storage.
|
||||||
|
*/
|
||||||
|
export type IVersionUpdateDTO = z.infer<typeof schemaVersionUpdate>;
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { ICloneLibraryItemDTO, libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
import { ICloneLibraryItemDTO } from './types';
|
||||||
|
|
||||||
export const useCloneItem = () => {
|
export const useCloneItem = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { ICreateLibraryItemDTO, libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
import { ICreateLibraryItemDTO } from './types';
|
||||||
|
|
||||||
export const useCreateItem = () => {
|
export const useCreateItem = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
import { LibraryItemID } from '../models/library';
|
|
||||||
import { libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
|
||||||
export const useDeleteItem = () => {
|
export const useDeleteItem = () => {
|
||||||
|
@ -17,16 +15,16 @@ export const useDeleteItem = () => {
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() =>
|
() =>
|
||||||
void Promise.allSettled([
|
void Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.resetQueries({ queryKey: rsformsApi.getRSFormQueryOptions({ itemID: variables }).queryKey }),
|
client.resetQueries({ queryKey: KEYS.composite.rsItem({ itemID: variables }) }),
|
||||||
client.resetQueries({ queryKey: ossApi.getOssQueryOptions({ itemID: variables }).queryKey })
|
client.resetQueries({ queryKey: KEYS.composite.ossItem({ itemID: variables }) })
|
||||||
]).catch(console.error),
|
]).catch(console.error),
|
||||||
PARAMETER.navigationDuration
|
PARAMETER.navigationDuration
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
deleteItem: (target: LibraryItemID) => mutation.mutateAsync(target),
|
deleteItem: (target: number) => mutation.mutateAsync(target),
|
||||||
isPending: mutation.isPending
|
isPending: mutation.isPending
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import { useIsMutating } from '@tanstack/react-query';
|
import { useIsMutating } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { libraryApi } from './api';
|
|
||||||
|
|
||||||
export const useMutatingLibrary = () => {
|
export const useMutatingLibrary = () => {
|
||||||
const countMutations = useIsMutating({ mutationKey: [libraryApi.baseKey] });
|
const countMutations = useIsMutating({ mutationKey: [KEYS.library] });
|
||||||
const countOss = useIsMutating({ mutationKey: [ossApi.baseKey] });
|
const countOss = useIsMutating({ mutationKey: [KEYS.oss] });
|
||||||
const countRSForm = useIsMutating({ mutationKey: [rsformsApi.baseKey] });
|
const countRSForm = useIsMutating({ mutationKey: [KEYS.rsform] });
|
||||||
return countMutations + countOss + countRSForm !== 0;
|
return countMutations + countOss + countRSForm !== 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { IRenameLocationDTO, libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
import { IRenameLocationDTO } from './types';
|
||||||
|
|
||||||
export const useRenameLocation = () => {
|
export const useRenameLocation = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -12,9 +12,9 @@ export const useRenameLocation = () => {
|
||||||
mutationFn: libraryApi.renameLocation,
|
mutationFn: libraryApi.renameLocation,
|
||||||
onSuccess: () =>
|
onSuccess: () =>
|
||||||
Promise.allSettled([
|
Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [libraryApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.library] }),
|
||||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.rsform] }),
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] })
|
client.invalidateQueries({ queryKey: [KEYS.oss] })
|
||||||
])
|
])
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { IOperationSchemaDTO, ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
import { IOperationSchemaDTO } from '@/features/oss/backend/types';
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
import { AccessPolicy, ILibraryItem, LibraryItemID } from '../models/library';
|
import { AccessPolicy, ILibraryItem } from '../models/library';
|
||||||
import { libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
|
||||||
export const useSetAccessPolicy = () => {
|
export const useSetAccessPolicy = () => {
|
||||||
|
@ -12,26 +13,28 @@ export const useSetAccessPolicy = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'set-location'],
|
mutationKey: [libraryApi.baseKey, 'set-location'],
|
||||||
mutationFn: libraryApi.setAccessPolicy,
|
mutationFn: libraryApi.setAccessPolicy,
|
||||||
onSuccess: (_, variables) => {
|
onSuccess: (_, variables) => {
|
||||||
const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
const ossKey = KEYS.composite.ossItem({ itemID: variables.itemID });
|
||||||
const ossData: IOperationSchemaDTO | undefined = client.getQueryData(ossKey);
|
const ossData: IOperationSchemaDTO | undefined = client.getQueryData(ossKey);
|
||||||
if (ossData) {
|
if (ossData) {
|
||||||
client.setQueryData(ossKey, { ...ossData, access_policy: variables.policy });
|
client.setQueryData(ossKey, { ...ossData, access_policy: variables.policy });
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
client.invalidateQueries({ queryKey: KEYS.composite.libraryList }),
|
||||||
...ossData.items
|
...ossData.items
|
||||||
.map(item => {
|
.map(item => {
|
||||||
if (!item.result) {
|
if (!item.result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
const itemKey = KEYS.composite.rsItem({ itemID: item.result });
|
||||||
return client.invalidateQueries({ queryKey: itemKey });
|
return client.invalidateQueries({ queryKey: itemKey });
|
||||||
})
|
})
|
||||||
.filter(item => !!item)
|
.filter(item => !!item)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
const rsKey = KEYS.composite.rsItem({ itemID: variables.itemID });
|
||||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, access_policy: variables.policy }));
|
client.setQueryData(rsKey, (prev: IRSFormDTO | undefined) =>
|
||||||
|
!prev ? undefined : { ...prev, access_policy: variables.policy }
|
||||||
|
);
|
||||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||||
prev?.map(item => (item.id === variables.itemID ? { ...item, access_policy: variables.policy } : item))
|
prev?.map(item => (item.id === variables.itemID ? { ...item, access_policy: variables.policy } : item))
|
||||||
);
|
);
|
||||||
|
@ -39,6 +42,6 @@ export const useSetAccessPolicy = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setAccessPolicy: (data: { itemID: LibraryItemID; policy: AccessPolicy }) => mutation.mutateAsync(data)
|
setAccessPolicy: (data: { itemID: number; policy: AccessPolicy }) => mutation.mutateAsync(data)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
import { IOperationSchemaDTO } from '@/features/oss/backend/types';
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
import { libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
|
||||||
|
@ -11,8 +12,8 @@ export const useSetEditors = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'set-location'],
|
mutationKey: [libraryApi.baseKey, 'set-location'],
|
||||||
mutationFn: libraryApi.setEditors,
|
mutationFn: libraryApi.setEditors,
|
||||||
onSuccess: (_, variables) => {
|
onSuccess: (_, variables) => {
|
||||||
const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
const ossKey = KEYS.composite.ossItem({ itemID: variables.itemID });
|
||||||
const ossData = client.getQueryData(ossKey);
|
const ossData: IOperationSchemaDTO | undefined = client.getQueryData(ossKey);
|
||||||
if (ossData) {
|
if (ossData) {
|
||||||
client.setQueryData(ossKey, { ...ossData, editors: variables.editors });
|
client.setQueryData(ossKey, { ...ossData, editors: variables.editors });
|
||||||
return Promise.allSettled(
|
return Promise.allSettled(
|
||||||
|
@ -21,15 +22,17 @@ export const useSetEditors = () => {
|
||||||
if (!item.result) {
|
if (!item.result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
const itemKey = KEYS.composite.rsItem({ itemID: item.result });
|
||||||
return client.invalidateQueries({ queryKey: itemKey });
|
return client.invalidateQueries({ queryKey: itemKey });
|
||||||
})
|
})
|
||||||
.filter(item => !!item)
|
.filter(item => !!item)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
const rsKey = KEYS.composite.rsItem({ itemID: variables.itemID });
|
||||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, editors: variables.editors }));
|
client.setQueryData(rsKey, (prev: IRSFormDTO | undefined) =>
|
||||||
|
!prev ? undefined : { ...prev, editors: variables.editors }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { IOperationSchemaDTO, ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
import { IOperationSchemaDTO } from '@/features/oss/backend/types';
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
import { ILibraryItem, LibraryItemID } from '../models/library';
|
import { ILibraryItem } from '../models/library';
|
||||||
import { libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
|
||||||
export const useSetLocation = () => {
|
export const useSetLocation = () => {
|
||||||
|
@ -12,7 +13,7 @@ export const useSetLocation = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'set-location'],
|
mutationKey: [libraryApi.baseKey, 'set-location'],
|
||||||
mutationFn: libraryApi.setLocation,
|
mutationFn: libraryApi.setLocation,
|
||||||
onSuccess: (_, variables) => {
|
onSuccess: (_, variables) => {
|
||||||
const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
const ossKey = KEYS.composite.ossItem({ itemID: variables.itemID });
|
||||||
const ossData: IOperationSchemaDTO | undefined = client.getQueryData(ossKey);
|
const ossData: IOperationSchemaDTO | undefined = client.getQueryData(ossKey);
|
||||||
if (ossData) {
|
if (ossData) {
|
||||||
client.setQueryData(ossKey, { ...ossData, location: variables.location });
|
client.setQueryData(ossKey, { ...ossData, location: variables.location });
|
||||||
|
@ -23,15 +24,17 @@ export const useSetLocation = () => {
|
||||||
if (!item.result) {
|
if (!item.result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
const itemKey = KEYS.composite.rsItem({ itemID: item.result });
|
||||||
return client.invalidateQueries({ queryKey: itemKey });
|
return client.invalidateQueries({ queryKey: itemKey });
|
||||||
})
|
})
|
||||||
.filter(item => !!item)
|
.filter(item => !!item)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
const rsKey = KEYS.composite.rsItem({ itemID: variables.itemID });
|
||||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, location: variables.location }));
|
client.setQueryData(rsKey, (prev: IRSFormDTO | undefined) =>
|
||||||
|
!prev ? undefined : { ...prev, location: variables.location }
|
||||||
|
);
|
||||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||||
prev?.map(item => (item.id === variables.itemID ? { ...item, location: variables.location } : item))
|
prev?.map(item => (item.id === variables.itemID ? { ...item, location: variables.location } : item))
|
||||||
);
|
);
|
||||||
|
@ -39,6 +42,6 @@ export const useSetLocation = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setLocation: (data: { itemID: LibraryItemID; location: string }) => mutation.mutateAsync(data)
|
setLocation: (data: { itemID: number; location: string }) => mutation.mutateAsync(data)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { IOperationSchemaDTO, ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
import { IOperationSchemaDTO } from '@/features/oss/backend/types';
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
import { ILibraryItem } from '../models/library';
|
import { ILibraryItem } from '../models/library';
|
||||||
import { libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
@ -12,7 +13,7 @@ export const useSetOwner = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'set-owner'],
|
mutationKey: [libraryApi.baseKey, 'set-owner'],
|
||||||
mutationFn: libraryApi.setOwner,
|
mutationFn: libraryApi.setOwner,
|
||||||
onSuccess: (_, variables) => {
|
onSuccess: (_, variables) => {
|
||||||
const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
const ossKey = KEYS.composite.ossItem({ itemID: variables.itemID });
|
||||||
const ossData: IOperationSchemaDTO | undefined = client.getQueryData(ossKey);
|
const ossData: IOperationSchemaDTO | undefined = client.getQueryData(ossKey);
|
||||||
if (ossData) {
|
if (ossData) {
|
||||||
client.setQueryData(ossKey, { ...ossData, owner: variables.owner });
|
client.setQueryData(ossKey, { ...ossData, owner: variables.owner });
|
||||||
|
@ -23,15 +24,17 @@ export const useSetOwner = () => {
|
||||||
if (!item.result) {
|
if (!item.result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
const itemKey = KEYS.composite.rsItem({ itemID: item.result });
|
||||||
return client.invalidateQueries({ queryKey: itemKey });
|
return client.invalidateQueries({ queryKey: itemKey });
|
||||||
})
|
})
|
||||||
.filter(item => !!item)
|
.filter(item => !!item)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
const rsKey = KEYS.composite.rsItem({ itemID: variables.itemID });
|
||||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, owner: variables.owner }));
|
client.setQueryData(rsKey, (prev: IRSFormDTO | undefined) =>
|
||||||
|
!prev ? undefined : { ...prev, owner: variables.owner }
|
||||||
|
);
|
||||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||||
prev?.map(item => (item.id === variables.itemID ? { ...item, owner: variables.owner } : item))
|
prev?.map(item => (item.id === variables.itemID ? { ...item, owner: variables.owner } : item))
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { IOperationSchemaDTO, ossApi } from '@/features/oss/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { IRSFormDTO } from '@/features/rsform/backend/api';
|
import { IOperationSchemaDTO } from '@/features/oss/backend/types';
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
import { ILibraryItem, LibraryItemType } from '../models/library';
|
import { ILibraryItem, LibraryItemType } from '../models/library';
|
||||||
import { IUpdateLibraryItemDTO, libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
import { IUpdateLibraryItemDTO } from './types';
|
||||||
|
|
||||||
export const useUpdateItem = () => {
|
export const useUpdateItem = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -12,7 +14,10 @@ export const useUpdateItem = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'update-item'],
|
mutationKey: [libraryApi.baseKey, 'update-item'],
|
||||||
mutationFn: libraryApi.updateItem,
|
mutationFn: libraryApi.updateItem,
|
||||||
onSuccess: (data: ILibraryItem) => {
|
onSuccess: (data: ILibraryItem) => {
|
||||||
const itemKey = libraryApi.getItemQueryOptions({ itemID: data.id, itemType: data.item_type }).queryKey;
|
const itemKey =
|
||||||
|
data.item_type === LibraryItemType.RSFORM
|
||||||
|
? KEYS.composite.rsItem({ itemID: data.id })
|
||||||
|
: KEYS.composite.ossItem({ itemID: data.id });
|
||||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||||
prev?.map(item => (item.id === data.id ? data : item))
|
prev?.map(item => (item.id === data.id ? data : item))
|
||||||
);
|
);
|
||||||
|
@ -23,9 +28,7 @@ export const useUpdateItem = () => {
|
||||||
const schema: IRSFormDTO | undefined = client.getQueryData(itemKey);
|
const schema: IRSFormDTO | undefined = client.getQueryData(itemKey);
|
||||||
if (schema) {
|
if (schema) {
|
||||||
return Promise.allSettled(
|
return Promise.allSettled(
|
||||||
schema.oss.map(item =>
|
schema.oss.map(item => client.invalidateQueries({ queryKey: KEYS.composite.ossItem({ itemID: item.id }) }))
|
||||||
client.invalidateQueries({ queryKey: ossApi.getOssQueryOptions({ itemID: item.id }).queryKey })
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
|
||||||
import { LibraryItemID } from '../models/library';
|
import { libraryApi } from './api';
|
||||||
import { IVersionCreateDTO, libraryApi } from './api';
|
import { IVersionCreateDTO } from './types';
|
||||||
import { useUpdateTimestamp } from './useUpdateTimestamp';
|
import { useUpdateTimestamp } from './useUpdateTimestamp';
|
||||||
|
|
||||||
export const useVersionCreate = () => {
|
export const useVersionCreate = () => {
|
||||||
|
@ -13,12 +13,12 @@ export const useVersionCreate = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'create-version'],
|
mutationKey: [libraryApi.baseKey, 'create-version'],
|
||||||
mutationFn: libraryApi.versionCreate,
|
mutationFn: libraryApi.versionCreate,
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.schema.id }).queryKey, data.schema);
|
client.setQueryData(KEYS.composite.rsItem({ itemID: data.schema.id }), data.schema);
|
||||||
updateTimestamp(data.schema.id);
|
updateTimestamp(data.schema.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
versionCreate: (data: { itemID: LibraryItemID; data: IVersionCreateDTO }) =>
|
versionCreate: (data: { itemID: number; data: IVersionCreateDTO }) =>
|
||||||
mutation.mutateAsync(data).then(response => response.version)
|
mutation.mutateAsync(data).then(response => response.version)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { IRSFormDTO, rsformsApi } from '@/features/rsform/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
import { LibraryItemID, VersionID } from '../models/library';
|
|
||||||
import { libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
|
||||||
export const useVersionDelete = () => {
|
export const useVersionDelete = () => {
|
||||||
|
@ -11,19 +11,17 @@ export const useVersionDelete = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'delete-version'],
|
mutationKey: [libraryApi.baseKey, 'delete-version'],
|
||||||
mutationFn: libraryApi.versionDelete,
|
mutationFn: libraryApi.versionDelete,
|
||||||
onSuccess: (_, variables) => {
|
onSuccess: (_, variables) => {
|
||||||
client.setQueryData(
|
client.setQueryData(KEYS.composite.rsItem({ itemID: variables.itemID }), (prev: IRSFormDTO | undefined) =>
|
||||||
rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey,
|
!prev
|
||||||
(prev: IRSFormDTO | undefined) =>
|
? undefined
|
||||||
!prev
|
: {
|
||||||
? undefined
|
...prev,
|
||||||
: {
|
versions: prev.versions.filter(version => version.id !== variables.versionID)
|
||||||
...prev,
|
}
|
||||||
versions: prev.versions.filter(version => version.id !== variables.versionID)
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
versionDelete: (data: { itemID: LibraryItemID; versionID: VersionID }) => mutation.mutateAsync(data)
|
versionDelete: (data: { itemID: number; versionID: number }) => mutation.mutateAsync(data)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
|
||||||
import { VersionID } from '../models/library';
|
|
||||||
import { libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
|
||||||
export const useVersionRestore = () => {
|
export const useVersionRestore = () => {
|
||||||
|
@ -11,11 +10,11 @@ export const useVersionRestore = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'restore-version'],
|
mutationKey: [libraryApi.baseKey, 'restore-version'],
|
||||||
mutationFn: libraryApi.versionRestore,
|
mutationFn: libraryApi.versionRestore,
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
client.setQueryData(KEYS.composite.rsItem({ itemID: data.id }), data);
|
||||||
return client.invalidateQueries({ queryKey: [libraryApi.baseKey] });
|
return client.invalidateQueries({ queryKey: [libraryApi.baseKey] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
versionRestore: (data: { versionID: VersionID }) => mutation.mutateAsync(data)
|
versionRestore: (data: { versionID: number }) => mutation.mutateAsync(data)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { IRSFormDTO, rsformsApi } from '@/features/rsform/backend/api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
import { IRSFormDTO } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
import { IVersionUpdateDTO, libraryApi } from './api';
|
import { libraryApi } from './api';
|
||||||
|
import { IVersionUpdateDTO } from './types';
|
||||||
|
|
||||||
export const useVersionUpdate = () => {
|
export const useVersionUpdate = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -10,19 +12,15 @@ export const useVersionUpdate = () => {
|
||||||
mutationKey: [libraryApi.baseKey, 'update-version'],
|
mutationKey: [libraryApi.baseKey, 'update-version'],
|
||||||
mutationFn: libraryApi.versionUpdate,
|
mutationFn: libraryApi.versionUpdate,
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(
|
client.setQueryData(KEYS.composite.rsItem({ itemID: data.item }), (prev: IRSFormDTO | undefined) =>
|
||||||
rsformsApi.getRSFormQueryOptions({ itemID: data.item }).queryKey,
|
!prev
|
||||||
(prev: IRSFormDTO | undefined) =>
|
? undefined
|
||||||
!prev
|
: {
|
||||||
? undefined
|
...prev,
|
||||||
: {
|
versions: prev.versions.map(version =>
|
||||||
...prev,
|
version.id === data.id ? { ...version, description: data.description, version: data.version } : version
|
||||||
versions: prev.versions.map(version =>
|
)
|
||||||
version.id === data.id
|
}
|
||||||
? { ...version, description: data.description, version: data.version }
|
|
||||||
: version
|
|
||||||
)
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { ModalForm } from '@/components/Modal';
|
||||||
import { useAuthSuspense } from '@/features/auth';
|
import { useAuthSuspense } from '@/features/auth';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { ICloneLibraryItemDTO, schemaCloneLibraryItem } from '../backend/api';
|
import { ICloneLibraryItemDTO, schemaCloneLibraryItem } from '../backend/types';
|
||||||
import { useCloneItem } from '../backend/useCloneItem';
|
import { useCloneItem } from '../backend/useCloneItem';
|
||||||
import { SelectAccessPolicy } from '../components/SelectAccessPolicy';
|
import { SelectAccessPolicy } from '../components/SelectAccessPolicy';
|
||||||
import { SelectLocationContext } from '../components/SelectLocationContext';
|
import { SelectLocationContext } from '../components/SelectLocationContext';
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { ModalForm } from '@/components/Modal';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { errorMsg } from '@/utils/labels';
|
import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
import { IVersionCreateDTO, schemaVersionCreate } from '../backend/api';
|
import { IVersionCreateDTO, schemaVersionCreate } from '../backend/types';
|
||||||
import { useVersionCreate } from '../backend/useVersionCreate';
|
import { useVersionCreate } from '../backend/useVersionCreate';
|
||||||
import { IVersionInfo } from '../models/library';
|
import { IVersionInfo } from '../models/library';
|
||||||
import { nextVersion } from '../models/libraryAPI';
|
import { nextVersion } from '../models/libraryAPI';
|
||||||
|
|
|
@ -9,11 +9,11 @@ import { MiniButton } from '@/components/Control';
|
||||||
import { IconReset, IconSave } from '@/components/Icons';
|
import { IconReset, IconSave } from '@/components/Icons';
|
||||||
import { TextArea, TextInput } from '@/components/Input';
|
import { TextArea, TextInput } from '@/components/Input';
|
||||||
import { ModalView } from '@/components/Modal';
|
import { ModalView } from '@/components/Modal';
|
||||||
import { useRSFormSuspense } from '@/features/rsform/backend/useRSForm';
|
import { useRSFormSuspense } from '@/features/rsform';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { errorMsg } from '@/utils/labels';
|
import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
import { IVersionUpdateDTO, schemaVersionUpdate } from '../../backend/api';
|
import { IVersionUpdateDTO, schemaVersionUpdate } from '../../backend/types';
|
||||||
import { useMutatingLibrary } from '../../backend/useMutatingLibrary';
|
import { useMutatingLibrary } from '../../backend/useMutatingLibrary';
|
||||||
import { useVersionDelete } from '../../backend/useVersionDelete';
|
import { useVersionDelete } from '../../backend/useVersionDelete';
|
||||||
import { useVersionUpdate } from '../../backend/useVersionUpdate';
|
import { useVersionUpdate } from '../../backend/useVersionUpdate';
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
export { libraryApi } from './backend/api';
|
|
||||||
export { useDeleteItem } from './backend/useDeleteItem';
|
export { useDeleteItem } from './backend/useDeleteItem';
|
||||||
export { useLibrary, useLibrarySuspense } from './backend/useLibrary';
|
export { useLibrary, useLibrarySuspense } from './backend/useLibrary';
|
||||||
export { useMutatingLibrary } from './backend/useMutatingLibrary';
|
export { useMutatingLibrary } from './backend/useMutatingLibrary';
|
||||||
|
|
|
@ -31,22 +31,12 @@ export enum LocationHead {
|
||||||
|
|
||||||
export const BASIC_SCHEMAS = '/L/Базовые';
|
export const BASIC_SCHEMAS = '/L/Базовые';
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link LibraryItem} identifier type.
|
|
||||||
*/
|
|
||||||
export type LibraryItemID = number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link Version} identifier type.
|
|
||||||
*/
|
|
||||||
export type VersionID = number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents library item version information.
|
* Represents library item version information.
|
||||||
*/
|
*/
|
||||||
export interface IVersionInfo {
|
export interface IVersionInfo {
|
||||||
id: VersionID;
|
id: number;
|
||||||
item: LibraryItemID;
|
item: number;
|
||||||
version: string;
|
version: string;
|
||||||
description: string;
|
description: string;
|
||||||
time_create: string;
|
time_create: string;
|
||||||
|
@ -56,7 +46,7 @@ export interface IVersionInfo {
|
||||||
* Represents library item common data typical for all item types.
|
* Represents library item common data typical for all item types.
|
||||||
*/
|
*/
|
||||||
export interface ILibraryItem {
|
export interface ILibraryItem {
|
||||||
id: LibraryItemID;
|
id: number;
|
||||||
item_type: LibraryItemType;
|
item_type: LibraryItemType;
|
||||||
title: string;
|
title: string;
|
||||||
alias: string;
|
alias: string;
|
||||||
|
@ -86,7 +76,7 @@ export interface ILibraryItemReference extends Pick<ILibraryItem, 'id' | 'alias'
|
||||||
* Represents {@link ILibraryItem} extended data with versions.
|
* Represents {@link ILibraryItem} extended data with versions.
|
||||||
*/
|
*/
|
||||||
export interface ILibraryItemVersioned extends ILibraryItemData {
|
export interface ILibraryItemVersioned extends ILibraryItemData {
|
||||||
version?: VersionID;
|
version?: number;
|
||||||
versions: IVersionInfo[];
|
versions: IVersionInfo[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { Label, TextArea, TextInput } from '@/components/Input';
|
||||||
import { useAuthSuspense } from '@/features/auth';
|
import { useAuthSuspense } from '@/features/auth';
|
||||||
import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
||||||
|
|
||||||
import { ICreateLibraryItemDTO, schemaCreateLibraryItem } from '../../backend/api';
|
import { ICreateLibraryItemDTO, schemaCreateLibraryItem } from '../../backend/types';
|
||||||
import { useCreateItem } from '../../backend/useCreateItem';
|
import { useCreateItem } from '../../backend/useCreateItem';
|
||||||
import { SelectAccessPolicy } from '../../components/SelectAccessPolicy';
|
import { SelectAccessPolicy } from '../../components/SelectAccessPolicy';
|
||||||
import { SelectItemType } from '../../components/SelectItemType';
|
import { SelectItemType } from '../../components/SelectItemType';
|
||||||
|
|
|
@ -3,16 +3,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ILibraryItem } from '@/features/library/models/library';
|
import { ILibraryItem } from '@/features/library/models/library';
|
||||||
import {
|
|
||||||
IOperation,
|
|
||||||
IOperationSchema,
|
|
||||||
IOperationSchemaStats,
|
|
||||||
OperationID,
|
|
||||||
OperationType
|
|
||||||
} from '@/features/oss/models/oss';
|
|
||||||
import { Graph } from '@/models/Graph';
|
import { Graph } from '@/models/Graph';
|
||||||
|
|
||||||
import { IOperationSchemaDTO } from './api';
|
import { IOperation, IOperationSchema, IOperationSchemaStats, OperationType } from '../models/oss';
|
||||||
|
import { IOperationSchemaDTO } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads data into an {@link IOperationSchema} based on {@link IOperationSchemaDTO}.
|
* Loads data into an {@link IOperationSchema} based on {@link IOperationSchemaDTO}.
|
||||||
|
@ -21,7 +15,7 @@ import { IOperationSchemaDTO } from './api';
|
||||||
export class OssLoader {
|
export class OssLoader {
|
||||||
private oss: IOperationSchemaDTO;
|
private oss: IOperationSchemaDTO;
|
||||||
private graph: Graph = new Graph();
|
private graph: Graph = new Graph();
|
||||||
private operationByID = new Map<OperationID, IOperation>();
|
private operationByID = new Map<number, IOperation>();
|
||||||
private schemaIDs: number[] = [];
|
private schemaIDs: number[] = [];
|
||||||
private items: ILibraryItem[];
|
private items: ILibraryItem[];
|
||||||
|
|
||||||
|
@ -72,7 +66,7 @@ export class OssLoader {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private inferConsolidation(operationID: OperationID): boolean {
|
private inferConsolidation(operationID: number): boolean {
|
||||||
const inputs = this.graph.expandInputs([operationID]);
|
const inputs = this.graph.expandInputs([operationID]);
|
||||||
if (inputs.length === 0) {
|
if (inputs.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,157 +1,29 @@
|
||||||
import { queryOptions } from '@tanstack/react-query';
|
import { queryOptions } from '@tanstack/react-query';
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||||
import { DELAYS } from '@/backend/configuration';
|
import { DELAYS, KEYS } from '@/backend/configuration';
|
||||||
import { ILibraryItem, ILibraryItemData } from '@/features/library/models/library';
|
|
||||||
import { IArgument, ICstSubstituteEx, IOperation, OperationID, OperationType } from '@/features/oss/models/oss';
|
|
||||||
import { schemaCstSubstitute } from '@/features/rsform/backend/api';
|
|
||||||
import { IConstituentaReference, ITargetCst } from '@/features/rsform/models/rsform';
|
import { IConstituentaReference, ITargetCst } from '@/features/rsform/models/rsform';
|
||||||
import { infoMsg } from '@/utils/labels';
|
import { infoMsg } from '@/utils/labels';
|
||||||
|
|
||||||
/**
|
import {
|
||||||
* Represents {@link IOperation} data from server.
|
ICstRelocateDTO,
|
||||||
*/
|
IInputCreatedResponse,
|
||||||
export interface IOperationDTO extends Omit<IOperation, 'substitutions' | 'arguments'> {}
|
IInputUpdateDTO,
|
||||||
|
IOperationCreatedResponse,
|
||||||
/**
|
IOperationCreateDTO,
|
||||||
* Represents backend data for {@link IOperationSchema}.
|
IOperationDeleteDTO,
|
||||||
*/
|
IOperationPosition,
|
||||||
export interface IOperationSchemaDTO extends ILibraryItemData {
|
IOperationSchemaDTO,
|
||||||
items: IOperationDTO[];
|
IOperationUpdateDTO,
|
||||||
arguments: IArgument[];
|
ITargetOperation
|
||||||
substitutions: ICstSubstituteEx[];
|
} from './types';
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} position.
|
|
||||||
*/
|
|
||||||
export const schemaOperationPosition = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
position_x: z.number(),
|
|
||||||
position_y: z.number()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} position.
|
|
||||||
*/
|
|
||||||
export type IOperationPosition = z.infer<typeof schemaOperationPosition>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in creation process.
|
|
||||||
*/
|
|
||||||
export const schemaOperationCreate = z.object({
|
|
||||||
positions: z.array(schemaOperationPosition),
|
|
||||||
item_data: z.object({
|
|
||||||
alias: z.string().nonempty(),
|
|
||||||
operation_type: z.nativeEnum(OperationType),
|
|
||||||
title: z.string(),
|
|
||||||
comment: z.string(),
|
|
||||||
position_x: z.number(),
|
|
||||||
position_y: z.number(),
|
|
||||||
result: z.number().nullable()
|
|
||||||
}),
|
|
||||||
arguments: z.array(z.number()),
|
|
||||||
create_schema: z.boolean()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in creation process.
|
|
||||||
*/
|
|
||||||
export type IOperationCreateDTO = z.infer<typeof schemaOperationCreate>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data response when creating {@link IOperation}.
|
|
||||||
*/
|
|
||||||
export interface IOperationCreatedResponse {
|
|
||||||
new_operation: IOperationDTO;
|
|
||||||
oss: IOperationSchemaDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents target {@link IOperation}.
|
|
||||||
*/
|
|
||||||
export interface ITargetOperation {
|
|
||||||
positions: IOperationPosition[];
|
|
||||||
target: OperationID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in destruction process.
|
|
||||||
*/
|
|
||||||
export const schemaOperationDelete = z.object({
|
|
||||||
target: z.number(),
|
|
||||||
positions: z.array(schemaOperationPosition),
|
|
||||||
keep_constituents: z.boolean(),
|
|
||||||
delete_schema: z.boolean()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in destruction process.
|
|
||||||
*/
|
|
||||||
export type IOperationDeleteDTO = z.infer<typeof schemaOperationDelete>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data response when creating {@link IRSForm} for Input {@link IOperation}.
|
|
||||||
*/
|
|
||||||
export interface IInputCreatedResponse {
|
|
||||||
new_schema: ILibraryItem;
|
|
||||||
oss: IOperationSchemaDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in setInput process.
|
|
||||||
*/
|
|
||||||
export const schemaInputUpdate = z.object({
|
|
||||||
target: z.number(),
|
|
||||||
positions: z.array(schemaOperationPosition),
|
|
||||||
input: z.number().nullable()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in setInput process.
|
|
||||||
*/
|
|
||||||
export type IInputUpdateDTO = z.infer<typeof schemaInputUpdate>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in update process.
|
|
||||||
*/
|
|
||||||
export const schemaOperationUpdate = z.object({
|
|
||||||
target: z.number(),
|
|
||||||
positions: z.array(schemaOperationPosition),
|
|
||||||
item_data: z.object({
|
|
||||||
alias: z.string().nonempty(),
|
|
||||||
title: z.string(),
|
|
||||||
comment: z.string()
|
|
||||||
}),
|
|
||||||
arguments: z.array(z.number()),
|
|
||||||
substitutions: z.array(schemaCstSubstitute)
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IOperation} data, used in update process.
|
|
||||||
*/
|
|
||||||
export type IOperationUpdateDTO = z.infer<typeof schemaOperationUpdate>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used relocating {@link IConstituenta}s between {@link ILibraryItem}s.
|
|
||||||
*/
|
|
||||||
export const schemaCstRelocate = z.object({
|
|
||||||
destination: z.number(),
|
|
||||||
items: z.array(z.number()).refine(data => data.length > 0)
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used relocating {@link IConstituenta}s between {@link ILibraryItem}s.
|
|
||||||
*/
|
|
||||||
export type ICstRelocateDTO = z.infer<typeof schemaCstRelocate>;
|
|
||||||
|
|
||||||
export const ossApi = {
|
export const ossApi = {
|
||||||
baseKey: 'oss',
|
baseKey: KEYS.oss,
|
||||||
|
|
||||||
getOssQueryOptions: ({ itemID }: { itemID?: number }) => {
|
getOssQueryOptions: ({ itemID }: { itemID?: number }) => {
|
||||||
return queryOptions({
|
return queryOptions({
|
||||||
queryKey: [ossApi.baseKey, 'item', itemID],
|
queryKey: KEYS.composite.ossItem({ itemID }),
|
||||||
staleTime: DELAYS.staleShort,
|
staleTime: DELAYS.staleShort,
|
||||||
queryFn: meta =>
|
queryFn: meta =>
|
||||||
!itemID
|
!itemID
|
||||||
|
|
143
rsconcept/frontend/src/features/oss/backend/types.ts
Normal file
143
rsconcept/frontend/src/features/oss/backend/types.ts
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { ILibraryItem, ILibraryItemData } from '@/features/library/models/library';
|
||||||
|
import { schemaCstSubstitute } from '@/features/rsform/backend/types';
|
||||||
|
|
||||||
|
import { IArgument, ICstSubstituteEx, IOperation, OperationType } from '../models/oss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data from server.
|
||||||
|
*/
|
||||||
|
export interface IOperationDTO extends Omit<IOperation, 'substitutions' | 'arguments'> {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents backend data for {@link IOperationSchema}.
|
||||||
|
*/
|
||||||
|
export interface IOperationSchemaDTO extends ILibraryItemData {
|
||||||
|
items: IOperationDTO[];
|
||||||
|
arguments: IArgument[];
|
||||||
|
substitutions: ICstSubstituteEx[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} position.
|
||||||
|
*/
|
||||||
|
export const schemaOperationPosition = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
position_x: z.number(),
|
||||||
|
position_y: z.number()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} position.
|
||||||
|
*/
|
||||||
|
export type IOperationPosition = z.infer<typeof schemaOperationPosition>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in creation process.
|
||||||
|
*/
|
||||||
|
export const schemaOperationCreate = z.object({
|
||||||
|
positions: z.array(schemaOperationPosition),
|
||||||
|
item_data: z.object({
|
||||||
|
alias: z.string().nonempty(),
|
||||||
|
operation_type: z.nativeEnum(OperationType),
|
||||||
|
title: z.string(),
|
||||||
|
comment: z.string(),
|
||||||
|
position_x: z.number(),
|
||||||
|
position_y: z.number(),
|
||||||
|
result: z.number().nullable()
|
||||||
|
}),
|
||||||
|
arguments: z.array(z.number()),
|
||||||
|
create_schema: z.boolean()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in creation process.
|
||||||
|
*/
|
||||||
|
export type IOperationCreateDTO = z.infer<typeof schemaOperationCreate>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data response when creating {@link IOperation}.
|
||||||
|
*/
|
||||||
|
export interface IOperationCreatedResponse {
|
||||||
|
new_operation: IOperationDTO;
|
||||||
|
oss: IOperationSchemaDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents target {@link IOperation}.
|
||||||
|
*/
|
||||||
|
export interface ITargetOperation {
|
||||||
|
positions: IOperationPosition[];
|
||||||
|
target: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in destruction process.
|
||||||
|
*/
|
||||||
|
export const schemaOperationDelete = z.object({
|
||||||
|
target: z.number(),
|
||||||
|
positions: z.array(schemaOperationPosition),
|
||||||
|
keep_constituents: z.boolean(),
|
||||||
|
delete_schema: z.boolean()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in destruction process.
|
||||||
|
*/
|
||||||
|
export type IOperationDeleteDTO = z.infer<typeof schemaOperationDelete>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data response when creating {@link IRSForm} for Input {@link IOperation}.
|
||||||
|
*/
|
||||||
|
export interface IInputCreatedResponse {
|
||||||
|
new_schema: ILibraryItem;
|
||||||
|
oss: IOperationSchemaDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in setInput process.
|
||||||
|
*/
|
||||||
|
export const schemaInputUpdate = z.object({
|
||||||
|
target: z.number(),
|
||||||
|
positions: z.array(schemaOperationPosition),
|
||||||
|
input: z.number().nullable()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in setInput process.
|
||||||
|
*/
|
||||||
|
export type IInputUpdateDTO = z.infer<typeof schemaInputUpdate>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in update process.
|
||||||
|
*/
|
||||||
|
export const schemaOperationUpdate = z.object({
|
||||||
|
target: z.number(),
|
||||||
|
positions: z.array(schemaOperationPosition),
|
||||||
|
item_data: z.object({
|
||||||
|
alias: z.string().nonempty(),
|
||||||
|
title: z.string(),
|
||||||
|
comment: z.string()
|
||||||
|
}),
|
||||||
|
arguments: z.array(z.number()),
|
||||||
|
substitutions: z.array(schemaCstSubstitute)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data, used in update process.
|
||||||
|
*/
|
||||||
|
export type IOperationUpdateDTO = z.infer<typeof schemaOperationUpdate>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used relocating {@link IConstituenta}s between {@link ILibraryItem}s.
|
||||||
|
*/
|
||||||
|
export const schemaCstRelocate = z.object({
|
||||||
|
destination: z.number(),
|
||||||
|
items: z.array(z.number()).refine(data => data.length > 0)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used relocating {@link IConstituenta}s between {@link ILibraryItem}s.
|
||||||
|
*/
|
||||||
|
export type ICstRelocateDTO = z.infer<typeof schemaCstRelocate>;
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { ITargetOperation, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { ITargetOperation } from './types';
|
||||||
|
|
||||||
export const useInputCreate = () => {
|
export const useInputCreate = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -13,8 +13,8 @@ export const useInputCreate = () => {
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.oss.id }).queryKey, data.oss);
|
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.oss.id }).queryKey, data.oss);
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
client.invalidateQueries({ queryKey: KEYS.composite.libraryList }),
|
||||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
client.invalidateQueries({ queryKey: [KEYS.rsform] })
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { IInputUpdateDTO, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { IInputUpdateDTO } from './types';
|
||||||
|
|
||||||
export const useInputUpdate = () => {
|
export const useInputUpdate = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -13,8 +13,8 @@ export const useInputUpdate = () => {
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
client.invalidateQueries({ queryKey: KEYS.composite.libraryList }),
|
||||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
client.invalidateQueries({ queryKey: [KEYS.rsform] })
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { useIsMutating } from '@tanstack/react-query';
|
import { useIsMutating } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
|
||||||
import { ossApi } from './api';
|
|
||||||
|
|
||||||
export const useMutatingOss = () => {
|
export const useMutatingOss = () => {
|
||||||
const countLibrary = useIsMutating({ mutationKey: [libraryApi.baseKey] });
|
const countLibrary = useIsMutating({ mutationKey: [KEYS.library] });
|
||||||
const countOss = useIsMutating({ mutationKey: [ossApi.baseKey] });
|
const countOss = useIsMutating({ mutationKey: [KEYS.oss] });
|
||||||
return countLibrary + countOss !== 0;
|
return countLibrary + countOss !== 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { queryClient } from '@/backend/queryClient';
|
||||||
import { useLibrary, useLibrarySuspense } from '@/features/library/backend/useLibrary';
|
import { useLibrary, useLibrarySuspense } from '@/features/library/backend/useLibrary';
|
||||||
|
|
||||||
import { queryClient } from '../../../backend/queryClient';
|
|
||||||
import { ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
import { OssLoader } from './OssLoader';
|
import { OssLoader } from './OssLoader';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
|
|
||||||
import { IOperationCreateDTO, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { IOperationCreateDTO } from './types';
|
||||||
|
|
||||||
export const useOperationCreate = () => {
|
export const useOperationCreate = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { IOperationDeleteDTO, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { IOperationDeleteDTO } from './types';
|
||||||
|
|
||||||
export const useOperationDelete = () => {
|
export const useOperationDelete = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -13,8 +13,8 @@ export const useOperationDelete = () => {
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
client.invalidateQueries({ queryKey: KEYS.composite.libraryList }),
|
||||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
client.invalidateQueries({ queryKey: [KEYS.rsform] })
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { ITargetOperation, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { ITargetOperation } from './types';
|
||||||
|
|
||||||
export const useOperationExecute = () => {
|
export const useOperationExecute = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -13,8 +13,8 @@ export const useOperationExecute = () => {
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
client.invalidateQueries({ queryKey: KEYS.composite.libraryList }),
|
||||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
client.invalidateQueries({ queryKey: [KEYS.rsform] })
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { ILibraryItem } from '@/features/library/models/library';
|
import { ILibraryItem } from '@/features/library/models/library';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { IOperationUpdateDTO, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { IOperationUpdateDTO } from './types';
|
||||||
|
|
||||||
export const useOperationUpdate = () => {
|
export const useOperationUpdate = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -12,12 +12,12 @@ export const useOperationUpdate = () => {
|
||||||
mutationKey: [ossApi.baseKey, 'operation-update'],
|
mutationKey: [ossApi.baseKey, 'operation-update'],
|
||||||
mutationFn: ossApi.operationUpdate,
|
mutationFn: ossApi.operationUpdate,
|
||||||
onSuccess: (data, variables) => {
|
onSuccess: (data, variables) => {
|
||||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
client.setQueryData(KEYS.composite.ossItem({ itemID: data.id }), data);
|
||||||
const schemaID = data.items.find(item => item.id === variables.data.target)?.result;
|
const schemaID = data.items.find(item => item.id === variables.data.target)?.result;
|
||||||
if (!schemaID) {
|
if (!schemaID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
client.setQueryData(KEYS.composite.libraryList, (prev: ILibraryItem[] | undefined) =>
|
||||||
!prev
|
!prev
|
||||||
? undefined
|
? undefined
|
||||||
: prev.map(item =>
|
: prev.map(item =>
|
||||||
|
@ -25,7 +25,7 @@ export const useOperationUpdate = () => {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return client.invalidateQueries({
|
return client.invalidateQueries({
|
||||||
queryKey: rsformsApi.getRSFormQueryOptions({ itemID: schemaID }).queryKey
|
queryKey: KEYS.composite.rsItem({ itemID: schemaID })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { rsformsApi } from '@/features/rsform/backend/api';
|
|
||||||
|
|
||||||
import { ICstRelocateDTO, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { ICstRelocateDTO } from './types';
|
||||||
|
|
||||||
export const useRelocateConstituents = () => {
|
export const useRelocateConstituents = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -13,8 +13,8 @@ export const useRelocateConstituents = () => {
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
client.invalidateQueries({ queryKey: KEYS.composite.libraryList }),
|
||||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
client.invalidateQueries({ queryKey: [KEYS.rsform] })
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { useMutation } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
|
|
||||||
import { IOperationPosition, ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
import { IOperationPosition } from './types';
|
||||||
|
|
||||||
export const useUpdatePositions = () => {
|
export const useUpdatePositions = () => {
|
||||||
const { updateTimestamp } = useUpdateTimestamp();
|
const { updateTimestamp } = useUpdateTimestamp();
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { ModalForm } from '@/components/Modal';
|
||||||
import { ILibraryItem, LibraryItemType, PickSchema, useLibrary } from '@/features/library';
|
import { ILibraryItem, LibraryItemType, PickSchema, useLibrary } from '@/features/library';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IInputUpdateDTO, IOperationPosition, schemaInputUpdate } from '../backend/api';
|
import { IInputUpdateDTO, IOperationPosition, schemaInputUpdate } from '../backend/types';
|
||||||
import { useInputUpdate } from '../backend/useInputUpdate';
|
import { useInputUpdate } from '../backend/useInputUpdate';
|
||||||
import { IOperation, IOperationSchema } from '../models/oss';
|
import { IOperation, IOperationSchema } from '../models/oss';
|
||||||
import { sortItemsForOSS } from '../models/ossAPI';
|
import { sortItemsForOSS } from '../models/ossAPI';
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { TabLabel, TabList, TabPanel, Tabs } from '@/components/Tabs';
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IOperationCreateDTO, IOperationPosition, schemaOperationCreate } from '../../backend/api';
|
import { IOperationCreateDTO, IOperationPosition, schemaOperationCreate } from '../../backend/types';
|
||||||
import { useOperationCreate } from '../../backend/useOperationCreate';
|
import { useOperationCreate } from '../../backend/useOperationCreate';
|
||||||
import { describeOperationType, labelOperationType } from '../../labels';
|
import { describeOperationType, labelOperationType } from '../../labels';
|
||||||
import { IOperationSchema, OperationID, OperationType } from '../../models/oss';
|
import { IOperationSchema, OperationID, OperationType } from '../../models/oss';
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { Checkbox, Label, TextArea, TextInput } from '@/components/Input';
|
||||||
import { ILibraryItem, LibraryItemType, PickSchema, useLibrary } from '@/features/library';
|
import { ILibraryItem, LibraryItemType, PickSchema, useLibrary } from '@/features/library';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IOperationCreateDTO } from '../../backend/api';
|
import { IOperationCreateDTO } from '../../backend/types';
|
||||||
import { sortItemsForOSS } from '../../models/ossAPI';
|
import { sortItemsForOSS } from '../../models/ossAPI';
|
||||||
import { DlgCreateOperationProps } from './DlgCreateOperation';
|
import { DlgCreateOperationProps } from './DlgCreateOperation';
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { FlexColumn } from '@/components/Container';
|
||||||
import { Label, TextArea, TextInput } from '@/components/Input';
|
import { Label, TextArea, TextInput } from '@/components/Input';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IOperationCreateDTO } from '../../backend/api';
|
import { IOperationCreateDTO } from '../../backend/types';
|
||||||
import { PickMultiOperation } from '../../components/PickMultiOperation';
|
import { PickMultiOperation } from '../../components/PickMultiOperation';
|
||||||
import { DlgCreateOperationProps } from './DlgCreateOperation';
|
import { DlgCreateOperationProps } from './DlgCreateOperation';
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@ import { Controller, useForm } from 'react-hook-form';
|
||||||
import { Checkbox, TextInput } from '@/components/Input';
|
import { Checkbox, TextInput } from '@/components/Input';
|
||||||
import { ModalForm } from '@/components/Modal';
|
import { ModalForm } from '@/components/Modal';
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { IOperation, IOperationSchema } from '@/features/oss/models/oss';
|
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IOperationDeleteDTO, IOperationPosition, schemaOperationDelete } from '../backend/api';
|
import { IOperationDeleteDTO, IOperationPosition, schemaOperationDelete } from '../backend/types';
|
||||||
import { useOperationDelete } from '../backend/useOperationDelete';
|
import { useOperationDelete } from '../backend/useOperationDelete';
|
||||||
|
import { IOperation, IOperationSchema } from '../models/oss';
|
||||||
|
|
||||||
export interface DlgDeleteOperationProps {
|
export interface DlgDeleteOperationProps {
|
||||||
oss: IOperationSchema;
|
oss: IOperationSchema;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { TabLabel, TabList, TabPanel, Tabs } from '@/components/Tabs';
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IOperationPosition, IOperationUpdateDTO, schemaOperationUpdate } from '../../backend/api';
|
import { IOperationPosition, IOperationUpdateDTO, schemaOperationUpdate } from '../../backend/types';
|
||||||
import { useOperationUpdate } from '../../backend/useOperationUpdate';
|
import { useOperationUpdate } from '../../backend/useOperationUpdate';
|
||||||
import { IOperation, IOperationSchema, OperationType } from '../../models/oss';
|
import { IOperation, IOperationSchema, OperationType } from '../../models/oss';
|
||||||
import TabArguments from './TabArguments';
|
import TabArguments from './TabArguments';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { FlexColumn } from '@/components/Container';
|
||||||
import { Label } from '@/components/Input';
|
import { Label } from '@/components/Input';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IOperationUpdateDTO } from '../../backend/api';
|
import { IOperationUpdateDTO } from '../../backend/types';
|
||||||
import { PickMultiOperation } from '../../components/PickMultiOperation';
|
import { PickMultiOperation } from '../../components/PickMultiOperation';
|
||||||
import { DlgEditOperationProps } from './DlgEditOperation';
|
import { DlgEditOperationProps } from './DlgEditOperation';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { useFormContext } from 'react-hook-form';
|
||||||
|
|
||||||
import { TextArea, TextInput } from '@/components/Input';
|
import { TextArea, TextInput } from '@/components/Input';
|
||||||
|
|
||||||
import { IOperationUpdateDTO } from '../../backend/api';
|
import { IOperationUpdateDTO } from '../../backend/types';
|
||||||
|
|
||||||
function TabOperation() {
|
function TabOperation() {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
||||||
|
|
||||||
import { TextArea } from '@/components/Input';
|
import { TextArea } from '@/components/Input';
|
||||||
import { useRSForms } from '@/features/rsform/backend/useRSForms';
|
import { PickSubstitutions, useRSForms } from '@/features/rsform';
|
||||||
import PickSubstitutions from '@/features/rsform/components/PickSubstitutions';
|
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
|
|
||||||
import { IOperationUpdateDTO } from '../../backend/api';
|
import { IOperationUpdateDTO } from '../../backend/types';
|
||||||
import { SubstitutionValidator } from '../../models/ossAPI';
|
import { SubstitutionValidator } from '../../models/ossAPI';
|
||||||
import { DlgEditOperationProps } from './DlgEditOperation';
|
import { DlgEditOperationProps } from './DlgEditOperation';
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,10 @@ import { Loader } from '@/components/Loader';
|
||||||
import { ModalForm } from '@/components/Modal';
|
import { ModalForm } from '@/components/Modal';
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { ILibraryItem, SelectLibraryItem, useLibrary } from '@/features/library';
|
import { ILibraryItem, SelectLibraryItem, useLibrary } from '@/features/library';
|
||||||
import { useRSForm } from '@/features/rsform/backend/useRSForm';
|
import { PickMultiConstituenta, useRSForm } from '@/features/rsform';
|
||||||
import PickMultiConstituenta from '@/features/rsform/components/PickMultiConstituenta';
|
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { ICstRelocateDTO, IOperationPosition, schemaCstRelocate } from '../backend/api';
|
import { ICstRelocateDTO, IOperationPosition, schemaCstRelocate } from '../backend/types';
|
||||||
import { useRelocateConstituents } from '../backend/useRelocateConstituents';
|
import { useRelocateConstituents } from '../backend/useRelocateConstituents';
|
||||||
import { useUpdatePositions } from '../backend/useUpdatePositions';
|
import { useUpdatePositions } from '../backend/useUpdatePositions';
|
||||||
import { IOperation, IOperationSchema } from '../models/oss';
|
import { IOperation, IOperationSchema } from '../models/oss';
|
||||||
|
|
1
rsconcept/frontend/src/features/oss/index.ts
Normal file
1
rsconcept/frontend/src/features/oss/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { useFindPredecessor } from './backend/useFindPredecessor';
|
|
@ -1,11 +1,9 @@
|
||||||
/**
|
/**
|
||||||
* Module: Schema of Synthesis Operations.
|
* Module: Schema of Synthesis Operations.
|
||||||
*/
|
*/
|
||||||
import { ILibraryItem, ILibraryItemData } from '@/features/library/models/library';
|
import { ILibraryItemData } from '@/features/library/models/library';
|
||||||
import { ICstSubstitute } from '@/features/rsform/backend/api';
|
import { ICstSubstitute } from '@/features/rsform';
|
||||||
import { IConstituenta } from '@/features/rsform/models/rsform';
|
import { Graph } from '@/models/Graph';
|
||||||
|
|
||||||
import { Graph } from '../../../models/Graph';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents {@link IOperation} identifier type.
|
* Represents {@link IOperation} identifier type.
|
||||||
|
@ -51,17 +49,6 @@ export interface IArgument {
|
||||||
argument: OperationID;
|
argument: OperationID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents substitution for multi synthesis table.
|
|
||||||
*/
|
|
||||||
export interface IMultiSubstitution {
|
|
||||||
original_source: ILibraryItem;
|
|
||||||
original: IConstituenta;
|
|
||||||
substitution: IConstituenta;
|
|
||||||
substitution_source: ILibraryItem;
|
|
||||||
is_suggestion: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents {@link ICstSubstitute} extended data.
|
* Represents {@link ICstSubstitute} extended data.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ILibraryItem } from '@/features/library/models/library';
|
import { ILibraryItem } from '@/features/library/models/library';
|
||||||
import { ICstSubstitute } from '@/features/rsform/backend/api';
|
import { CstClass, CstType, IConstituenta, IRSForm } from '@/features/rsform';
|
||||||
import { ConstituentaID, CstClass, CstType, IConstituenta, IRSForm } from '@/features/rsform/models/rsform';
|
import { ICstSubstitute } from '@/features/rsform/backend/types';
|
||||||
import { AliasMapping, ParsingStatus } from '@/features/rsform/models/rslang';
|
import { AliasMapping, ParsingStatus } from '@/features/rsform/models/rslang';
|
||||||
import {
|
import {
|
||||||
applyAliasMapping,
|
applyAliasMapping,
|
||||||
|
@ -17,7 +17,7 @@ import { infoMsg } from '@/utils/labels';
|
||||||
import { TextMatcher } from '@/utils/utils';
|
import { TextMatcher } from '@/utils/utils';
|
||||||
|
|
||||||
import { Graph } from '../../../models/Graph';
|
import { Graph } from '../../../models/Graph';
|
||||||
import { IOperationPosition } from '../backend/api';
|
import { IOperationPosition } from '../backend/types';
|
||||||
import { describeSubstitutionError } from '../labels';
|
import { describeSubstitutionError } from '../labels';
|
||||||
import { IOperation, IOperationSchema, OperationID, OperationType, SubstitutionErrorType } from './oss';
|
import { IOperation, IOperationSchema, OperationID, OperationType, SubstitutionErrorType } from './oss';
|
||||||
import { Position2D } from './ossLayout';
|
import { Position2D } from './ossLayout';
|
||||||
|
@ -67,13 +67,13 @@ export class SubstitutionValidator {
|
||||||
|
|
||||||
private schemas: IRSForm[];
|
private schemas: IRSForm[];
|
||||||
private substitutions: ICstSubstitute[];
|
private substitutions: ICstSubstitute[];
|
||||||
private constituents = new Set<ConstituentaID>();
|
private constituents = new Set<number>();
|
||||||
private originals = new Set<ConstituentaID>();
|
private originals = new Set<number>();
|
||||||
private mapping: CrossMapping = new Map();
|
private mapping: CrossMapping = new Map();
|
||||||
|
|
||||||
private cstByID = new Map<ConstituentaID, IConstituenta>();
|
private cstByID = new Map<number, IConstituenta>();
|
||||||
private schemaByID = new Map<number, IRSForm>();
|
private schemaByID = new Map<number, IRSForm>();
|
||||||
private schemaByCst = new Map<ConstituentaID, IRSForm>();
|
private schemaByCst = new Map<number, IRSForm>();
|
||||||
|
|
||||||
constructor(schemas: IRSForm[], substitutions: ICstSubstitute[]) {
|
constructor(schemas: IRSForm[], substitutions: ICstSubstitute[]) {
|
||||||
this.schemas = schemas;
|
this.schemas = schemas;
|
||||||
|
@ -125,9 +125,9 @@ export class SubstitutionValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateSuggestions(): void {
|
private calculateSuggestions(): void {
|
||||||
const candidates = new Map<ConstituentaID, string>();
|
const candidates = new Map<number, string>();
|
||||||
const minors = new Set<ConstituentaID>();
|
const minors = new Set<number>();
|
||||||
const schemaByCst = new Map<ConstituentaID, IRSForm>();
|
const schemaByCst = new Map<number, IRSForm>();
|
||||||
for (const schema of this.schemas) {
|
for (const schema of this.schemas) {
|
||||||
for (const cst of schema.items) {
|
for (const cst of schema.items) {
|
||||||
if (this.originals.has(cst.id)) {
|
if (this.originals.has(cst.id)) {
|
||||||
|
@ -456,7 +456,7 @@ export function getRelocateCandidates(
|
||||||
return addedCst;
|
return addedCst;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unreachableBases: ConstituentaID[] = [];
|
const unreachableBases: number[] = [];
|
||||||
for (const cst of schema.items.filter(item => item.is_inherited)) {
|
for (const cst of schema.items.filter(item => item.is_inherited)) {
|
||||||
if (cst.parent_schema == destinationSchema) {
|
if (cst.parent_schema == destinationSchema) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import clsx from 'clsx';
|
||||||
|
|
||||||
import { FlexColumn } from '@/components/Container';
|
import { FlexColumn } from '@/components/Container';
|
||||||
import { EditorLibraryItem } from '@/features/library';
|
import { EditorLibraryItem } from '@/features/library';
|
||||||
import ToolbarRSFormCard from '@/features/rsform/pages/RSFormPage/EditorRSFormCard/ToolbarRSFormCard';
|
import { ToolbarRSFormCard } from '@/features/rsform';
|
||||||
import { useModificationStore } from '@/stores/modification';
|
import { useModificationStore } from '@/stores/modification';
|
||||||
import { globals } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { SubmitButton } from '@/components/Control';
|
||||||
import { IconSave } from '@/components/Icons';
|
import { IconSave } from '@/components/Icons';
|
||||||
import { TextArea, TextInput } from '@/components/Input';
|
import { TextArea, TextInput } from '@/components/Input';
|
||||||
import { LibraryItemType, ToolbarItemAccess, useUpdateItem } from '@/features/library';
|
import { LibraryItemType, ToolbarItemAccess, useUpdateItem } from '@/features/library';
|
||||||
import { IUpdateLibraryItemDTO, schemaUpdateLibraryItem } from '@/features/library/backend/api';
|
import { IUpdateLibraryItemDTO, schemaUpdateLibraryItem } from '@/features/library/backend/types';
|
||||||
import { useModificationStore } from '@/stores/modification';
|
import { useModificationStore } from '@/stores/modification';
|
||||||
import { globals } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,12 @@ import {
|
||||||
IconNewRSForm,
|
IconNewRSForm,
|
||||||
IconRSForm
|
IconRSForm
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
import { useMutatingOss } from '@/features/oss/backend/useMutatingOss';
|
|
||||||
import { IOperation, OperationID, OperationType } from '@/features/oss/models/oss';
|
|
||||||
import useClickedOutside from '@/hooks/useClickedOutside';
|
import useClickedOutside from '@/hooks/useClickedOutside';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
import { prepareTooltip } from '@/utils/utils';
|
import { prepareTooltip } from '@/utils/utils';
|
||||||
|
|
||||||
|
import { useMutatingOss } from '../../../backend/useMutatingOss';
|
||||||
|
import { IOperation, OperationType } from '../../../models/oss';
|
||||||
import { useOssEdit } from '../OssEditContext';
|
import { useOssEdit } from '../OssEditContext';
|
||||||
|
|
||||||
export interface ContextMenuData {
|
export interface ContextMenuData {
|
||||||
|
@ -29,12 +29,12 @@ export interface ContextMenuData {
|
||||||
interface NodeContextMenuProps extends ContextMenuData {
|
interface NodeContextMenuProps extends ContextMenuData {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onHide: () => void;
|
onHide: () => void;
|
||||||
onDelete: (target: OperationID) => void;
|
onDelete: (target: number) => void;
|
||||||
onCreateInput: (target: OperationID) => void;
|
onCreateInput: (target: number) => void;
|
||||||
onEditSchema: (target: OperationID) => void;
|
onEditSchema: (target: number) => void;
|
||||||
onEditOperation: (target: OperationID) => void;
|
onEditOperation: (target: number) => void;
|
||||||
onExecuteOperation: (target: OperationID) => void;
|
onExecuteOperation: (target: number) => void;
|
||||||
onRelocateConstituents: (target: OperationID) => void;
|
onRelocateConstituents: (target: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NodeContextMenu({
|
function NodeContextMenu({
|
||||||
|
|
|
@ -19,11 +19,11 @@ import {
|
||||||
IconShare
|
IconShare
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
import { useAuthSuspense } from '@/features/auth';
|
import { useAuthSuspense } from '@/features/auth';
|
||||||
import { useMutatingOss } from '@/features/oss/backend/useMutatingOss';
|
|
||||||
import { useRoleStore, UserRole } from '@/features/users';
|
import { useRoleStore, UserRole } from '@/features/users';
|
||||||
import { describeAccessMode as describeUserRole, labelAccessMode as labelUserRole } from '@/utils/labels';
|
import { describeAccessMode as describeUserRole, labelAccessMode as labelUserRole } from '@/utils/labels';
|
||||||
import { sharePage } from '@/utils/utils';
|
import { sharePage } from '@/utils/utils';
|
||||||
|
|
||||||
|
import { useMutatingOss } from '../../backend/useMutatingOss';
|
||||||
import { useOssEdit } from './OssEditContext';
|
import { useOssEdit } from './OssEditContext';
|
||||||
|
|
||||||
function MenuOssTabs() {
|
function MenuOssTabs() {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { usePreferencesStore } from '@/stores/preferences';
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { promptText } from '@/utils/labels';
|
import { promptText } from '@/utils/labels';
|
||||||
|
|
||||||
import { IOperationPosition } from '../../backend/api';
|
import { IOperationPosition } from '../../backend/types';
|
||||||
import { useOssSuspense } from '../../backend/useOSS';
|
import { useOssSuspense } from '../../backend/useOSS';
|
||||||
import { IOperationSchema, OperationID, OperationType } from '../../models/oss';
|
import { IOperationSchema, OperationID, OperationType } from '../../models/oss';
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ import OssTabs from './OssTabs';
|
||||||
|
|
||||||
const paramsSchema = z.object({
|
const paramsSchema = z.object({
|
||||||
id: z.coerce.number(),
|
id: z.coerce.number(),
|
||||||
tab: z.preprocess(v => (v ? Number(v) : undefined), z.nativeEnum(OssTabID).default(OssTabID.CARD))
|
tab: z.preprocess(v => (v ? Number(v) : undefined), z.nativeEnum(OssTabID).default(OssTabID.GRAPH))
|
||||||
});
|
});
|
||||||
|
|
||||||
export function OssPage() {
|
export function OssPage() {
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
import { Graph } from '@/models/Graph';
|
import { Graph } from '@/models/Graph';
|
||||||
|
|
||||||
import { ConstituentaID, CstType, IConstituenta, IRSForm, IRSFormStats } from '../models/rsform';
|
import { CstType, IConstituenta, IRSForm, IRSFormStats } from '../models/rsform';
|
||||||
import { inferClass, inferStatus, inferTemplate, isBaseSet, isFunctional } from '../models/rsformAPI';
|
import { inferClass, inferStatus, inferTemplate, isBaseSet, isFunctional } from '../models/rsformAPI';
|
||||||
import { ParsingStatus, ValueClass } from '../models/rslang';
|
import { ParsingStatus, ValueClass } from '../models/rslang';
|
||||||
import { extractGlobals, isSimpleExpression, splitTemplateDefinition } from '../models/rslangAPI';
|
import { extractGlobals, isSimpleExpression, splitTemplateDefinition } from '../models/rslangAPI';
|
||||||
import { IRSFormDTO } from './api';
|
import { IRSFormDTO } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads data into an {@link IRSForm} based on {@link IRSFormDTO}.
|
* Loads data into an {@link IRSForm} based on {@link IRSFormDTO}.
|
||||||
|
@ -21,7 +21,7 @@ export class RSFormLoader {
|
||||||
private schema: IRSFormDTO;
|
private schema: IRSFormDTO;
|
||||||
private graph: Graph = new Graph();
|
private graph: Graph = new Graph();
|
||||||
private cstByAlias = new Map<string, IConstituenta>();
|
private cstByAlias = new Map<string, IConstituenta>();
|
||||||
private cstByID = new Map<ConstituentaID, IConstituenta>();
|
private cstByID = new Map<number, IConstituenta>();
|
||||||
|
|
||||||
constructor(input: IRSFormDTO) {
|
constructor(input: IRSFormDTO) {
|
||||||
this.schema = input;
|
this.schema = input;
|
||||||
|
@ -61,7 +61,7 @@ export class RSFormLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private inferCstAttributes() {
|
private inferCstAttributes() {
|
||||||
const schemaByCst = new Map<ConstituentaID, number>();
|
const schemaByCst = new Map<number, number>();
|
||||||
const parents: number[] = [];
|
const parents: number[] = [];
|
||||||
this.schema.inheritance.forEach(item => {
|
this.schema.inheritance.forEach(item => {
|
||||||
if (item.child_source === this.schema.id) {
|
if (item.child_source === this.schema.id) {
|
||||||
|
@ -120,7 +120,7 @@ export class RSFormLoader {
|
||||||
return isSimpleExpression(expression);
|
return isSimpleExpression(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
private inferParent(target: IConstituenta): ConstituentaID | undefined {
|
private inferParent(target: IConstituenta): number | undefined {
|
||||||
const sources = this.extractSources(target);
|
const sources = this.extractSources(target);
|
||||||
if (sources.size !== 1 || sources.has(target.id)) {
|
if (sources.size !== 1 || sources.has(target.id)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -133,8 +133,8 @@ export class RSFormLoader {
|
||||||
return parent_id;
|
return parent_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private extractSources(target: IConstituenta): Set<ConstituentaID> {
|
private extractSources(target: IConstituenta): Set<number> {
|
||||||
const sources = new Set<ConstituentaID>();
|
const sources = new Set<number>();
|
||||||
if (!isFunctional(target.cst_type)) {
|
if (!isFunctional(target.cst_type)) {
|
||||||
const node = this.graph.at(target.id)!;
|
const node = this.graph.at(target.id)!;
|
||||||
node.inputs.forEach(id => {
|
node.inputs.forEach(id => {
|
||||||
|
|
|
@ -1,181 +1,31 @@
|
||||||
import { queryOptions } from '@tanstack/react-query';
|
import { queryOptions } from '@tanstack/react-query';
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||||
import { DELAYS } from '@/backend/configuration';
|
import { DELAYS, KEYS } from '@/backend/configuration';
|
||||||
import { ILibraryItemReference, ILibraryItemVersioned } from '@/features/library/models/library';
|
import { infoMsg } from '@/utils/labels';
|
||||||
import { errorMsg, infoMsg } from '@/utils/labels';
|
|
||||||
|
|
||||||
|
import { IConstituentaList, IConstituentaMeta, ITargetCst } from '../models/rsform';
|
||||||
|
import { IExpressionParse } from '../models/rslang';
|
||||||
import {
|
import {
|
||||||
ConstituentaID,
|
ICheckConstituentaDTO,
|
||||||
CstType,
|
ICstCreatedResponse,
|
||||||
IConstituentaList,
|
ICstCreateDTO,
|
||||||
IConstituentaMeta,
|
ICstMoveDTO,
|
||||||
IInheritanceInfo,
|
ICstRenameDTO,
|
||||||
ITargetCst,
|
ICstSubstitutionsDTO,
|
||||||
TermForm
|
ICstUpdateDTO,
|
||||||
} from '../models/rsform';
|
IInlineSynthesisDTO,
|
||||||
import { IArgumentInfo, IExpressionParse, ParsingStatus, ValueClass } from '../models/rslang';
|
IProduceStructureResponse,
|
||||||
|
IRSFormDTO,
|
||||||
/**
|
IRSFormUploadDTO
|
||||||
* Represents {@link IConstituenta} data from server.
|
} from './types';
|
||||||
*/
|
|
||||||
export interface IConstituentaDTO extends IConstituentaMeta {
|
|
||||||
parse: {
|
|
||||||
status: ParsingStatus;
|
|
||||||
valueClass: ValueClass;
|
|
||||||
typification: string;
|
|
||||||
syntaxTree: string;
|
|
||||||
args: IArgumentInfo[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data for {@link IRSForm} provided by backend.
|
|
||||||
*/
|
|
||||||
export interface IRSFormDTO extends ILibraryItemVersioned {
|
|
||||||
items: IConstituentaDTO[];
|
|
||||||
inheritance: IInheritanceInfo[];
|
|
||||||
oss: ILibraryItemReference[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used for uploading {@link IRSForm} as file.
|
|
||||||
*/
|
|
||||||
export interface IRSFormUploadDTO {
|
|
||||||
itemID: number;
|
|
||||||
load_metadata: boolean;
|
|
||||||
file: File;
|
|
||||||
fileName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IConstituenta} data, used in creation process.
|
|
||||||
*/
|
|
||||||
export interface ICstCreateDTO {
|
|
||||||
alias: string;
|
|
||||||
cst_type: CstType;
|
|
||||||
definition_raw: string;
|
|
||||||
term_raw: string;
|
|
||||||
convention: string;
|
|
||||||
definition_formal: string;
|
|
||||||
term_forms: TermForm[];
|
|
||||||
|
|
||||||
insert_after: ConstituentaID | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data response when creating {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export interface ICstCreatedResponse {
|
|
||||||
new_cst: IConstituentaMeta;
|
|
||||||
schema: IRSFormDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in updating persistent attributes in {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export const schemaCstUpdate = z.object({
|
|
||||||
target: z.number(),
|
|
||||||
item_data: z.object({
|
|
||||||
convention: z.string().optional(),
|
|
||||||
definition_formal: z.string().optional(),
|
|
||||||
definition_raw: z.string().optional(),
|
|
||||||
term_raw: z.string().optional(),
|
|
||||||
term_forms: z.array(z.object({ text: z.string(), tags: z.string() })).optional()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in updating persistent attributes in {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export type ICstUpdateDTO = z.infer<typeof schemaCstUpdate>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in renaming {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export const schemaCstRename = z.object({
|
|
||||||
target: z.number(),
|
|
||||||
alias: z.string(),
|
|
||||||
cst_type: z.nativeEnum(CstType)
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in renaming {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export type ICstRenameDTO = z.infer<typeof schemaCstRename>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in ordering a list of {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export interface ICstMoveDTO {
|
|
||||||
items: ConstituentaID[];
|
|
||||||
move_to: number; // Note: 0-base index
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data response when creating producing structure of {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export interface IProduceStructureResponse {
|
|
||||||
cst_list: ConstituentaID[];
|
|
||||||
schema: IRSFormDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in merging single {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export const schemaCstSubstitute = z.object({
|
|
||||||
original: z.number(),
|
|
||||||
substitution: z.number()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in merging single {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export type ICstSubstitute = z.infer<typeof schemaCstSubstitute>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents input data for inline synthesis.
|
|
||||||
*/
|
|
||||||
export const schemaInlineSynthesis = z.object({
|
|
||||||
receiver: z.number(),
|
|
||||||
source: z.number().nullable(),
|
|
||||||
items: z.array(z.number()),
|
|
||||||
substitutions: z.array(schemaCstSubstitute)
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents input data for inline synthesis.
|
|
||||||
*/
|
|
||||||
export type IInlineSynthesisDTO = z.infer<typeof schemaInlineSynthesis>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents {@link IConstituenta} data, used for checking expression.
|
|
||||||
*/
|
|
||||||
export interface ICheckConstituentaDTO {
|
|
||||||
alias: string;
|
|
||||||
cst_type: CstType;
|
|
||||||
definition_formal: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in renaming {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export const schemaCstSubstitutions = z.object({
|
|
||||||
substitutions: z.array(schemaCstSubstitute).min(1, { message: errorMsg.emptySubstitutions })
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data, used in merging multiple {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export type ICstSubstitutionsDTO = z.infer<typeof schemaCstSubstitutions>;
|
|
||||||
|
|
||||||
export const rsformsApi = {
|
export const rsformsApi = {
|
||||||
baseKey: 'rsform',
|
baseKey: KEYS.rsform,
|
||||||
|
|
||||||
getRSFormQueryOptions: ({ itemID, version }: { itemID?: number; version?: number }) => {
|
getRSFormQueryOptions: ({ itemID, version }: { itemID?: number; version?: number }) => {
|
||||||
return queryOptions({
|
return queryOptions({
|
||||||
queryKey: [rsformsApi.baseKey, 'item', itemID, version ?? ''],
|
queryKey: KEYS.composite.rsItem({ itemID, version }),
|
||||||
staleTime: DELAYS.staleShort,
|
staleTime: DELAYS.staleShort,
|
||||||
queryFn: meta =>
|
queryFn: meta =>
|
||||||
!itemID
|
!itemID
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { axiosPost } from '@/backend/apiTransport';
|
import { axiosPost } from '@/backend/apiTransport';
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents API result for text output.
|
* Represents API result for text output.
|
||||||
|
@ -23,7 +24,7 @@ export interface ILexemeResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cctextApi = {
|
export const cctextApi = {
|
||||||
baseKey: 'cctext',
|
baseKey: KEYS.cctext,
|
||||||
|
|
||||||
inflectText: (data: IWordFormDTO) =>
|
inflectText: (data: IWordFormDTO) =>
|
||||||
axiosPost<IWordFormDTO, ITextResult>({
|
axiosPost<IWordFormDTO, ITextResult>({
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { useIsMutating } from '@tanstack/react-query';
|
import { useIsMutating } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { cctextApi } from './api';
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
|
||||||
export const useIsProcessingCctext = () => {
|
export const useIsProcessingCctext = () => {
|
||||||
const countMutations = useIsMutating({ mutationKey: [cctextApi.baseKey] });
|
const countMutations = useIsMutating({ mutationKey: [KEYS.cctext] });
|
||||||
return countMutations !== 0;
|
return countMutations !== 0;
|
||||||
};
|
};
|
||||||
|
|
160
rsconcept/frontend/src/features/rsform/backend/types.ts
Normal file
160
rsconcept/frontend/src/features/rsform/backend/types.ts
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { ILibraryItemReference, ILibraryItemVersioned } from '@/features/library/models/library';
|
||||||
|
import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
|
import { CstType, IConstituentaMeta, IInheritanceInfo, TermForm } from '../models/rsform';
|
||||||
|
import { IArgumentInfo, ParsingStatus, ValueClass } from '../models/rslang';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IConstituenta} data from server.
|
||||||
|
*/
|
||||||
|
export interface IConstituentaDTO extends IConstituentaMeta {
|
||||||
|
parse: {
|
||||||
|
status: ParsingStatus;
|
||||||
|
valueClass: ValueClass;
|
||||||
|
typification: string;
|
||||||
|
syntaxTree: string;
|
||||||
|
args: IArgumentInfo[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data for {@link IRSForm} provided by backend.
|
||||||
|
*/
|
||||||
|
export interface IRSFormDTO extends ILibraryItemVersioned {
|
||||||
|
items: IConstituentaDTO[];
|
||||||
|
inheritance: IInheritanceInfo[];
|
||||||
|
oss: ILibraryItemReference[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used for uploading {@link IRSForm} as file.
|
||||||
|
*/
|
||||||
|
export interface IRSFormUploadDTO {
|
||||||
|
itemID: number;
|
||||||
|
load_metadata: boolean;
|
||||||
|
file: File;
|
||||||
|
fileName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IConstituenta} data, used in creation process.
|
||||||
|
*/
|
||||||
|
export interface ICstCreateDTO {
|
||||||
|
alias: string;
|
||||||
|
cst_type: CstType;
|
||||||
|
definition_raw: string;
|
||||||
|
term_raw: string;
|
||||||
|
convention: string;
|
||||||
|
definition_formal: string;
|
||||||
|
term_forms: TermForm[];
|
||||||
|
|
||||||
|
insert_after: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data response when creating {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export interface ICstCreatedResponse {
|
||||||
|
new_cst: IConstituentaMeta;
|
||||||
|
schema: IRSFormDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in updating persistent attributes in {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export const schemaCstUpdate = z.object({
|
||||||
|
target: z.number(),
|
||||||
|
item_data: z.object({
|
||||||
|
convention: z.string().optional(),
|
||||||
|
definition_formal: z.string().optional(),
|
||||||
|
definition_raw: z.string().optional(),
|
||||||
|
term_raw: z.string().optional(),
|
||||||
|
term_forms: z.array(z.object({ text: z.string(), tags: z.string() })).optional()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in updating persistent attributes in {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export type ICstUpdateDTO = z.infer<typeof schemaCstUpdate>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in renaming {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export const schemaCstRename = z.object({
|
||||||
|
target: z.number(),
|
||||||
|
alias: z.string(),
|
||||||
|
cst_type: z.nativeEnum(CstType)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in renaming {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export type ICstRenameDTO = z.infer<typeof schemaCstRename>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in ordering a list of {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export interface ICstMoveDTO {
|
||||||
|
items: number[];
|
||||||
|
move_to: number; // Note: 0-base index
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data response when creating producing structure of {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export interface IProduceStructureResponse {
|
||||||
|
cst_list: number[];
|
||||||
|
schema: IRSFormDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in merging single {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export const schemaCstSubstitute = z.object({
|
||||||
|
original: z.number(),
|
||||||
|
substitution: z.number()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in merging single {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export type ICstSubstitute = z.infer<typeof schemaCstSubstitute>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents input data for inline synthesis.
|
||||||
|
*/
|
||||||
|
export const schemaInlineSynthesis = z.object({
|
||||||
|
receiver: z.number(),
|
||||||
|
source: z.number().nullable(),
|
||||||
|
items: z.array(z.number()),
|
||||||
|
substitutions: z.array(schemaCstSubstitute)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents input data for inline synthesis.
|
||||||
|
*/
|
||||||
|
export type IInlineSynthesisDTO = z.infer<typeof schemaInlineSynthesis>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IConstituenta} data, used for checking expression.
|
||||||
|
*/
|
||||||
|
export interface ICheckConstituentaDTO {
|
||||||
|
alias: string;
|
||||||
|
cst_type: CstType;
|
||||||
|
definition_formal: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in renaming {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export const schemaCstSubstitutions = z.object({
|
||||||
|
substitutions: z.array(schemaCstSubstitute).min(1, { message: errorMsg.emptySubstitutions })
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in merging multiple {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export type ICstSubstitutionsDTO = z.infer<typeof schemaCstSubstitutions>;
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { ICheckConstituentaDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { ICheckConstituentaDTO } from './types';
|
||||||
|
|
||||||
export const useCheckConstituenta = () => {
|
export const useCheckConstituenta = () => {
|
||||||
const mutation = useMutation({
|
const mutation = useMutation({
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { ICstCreateDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { ICstCreateDTO } from './types';
|
||||||
|
|
||||||
export const useCstCreate = () => {
|
export const useCstCreate = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -16,7 +17,7 @@ export const useCstCreate = () => {
|
||||||
updateTimestamp(data.schema.id);
|
updateTimestamp(data.schema.id);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { IConstituentaList } from '../models/rsform';
|
import { IConstituentaList } from '../models/rsform';
|
||||||
import { rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
@ -17,7 +17,7 @@ export const useCstDelete = () => {
|
||||||
updateTimestamp(data.id);
|
updateTimestamp(data.id);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
|
|
||||||
import { ICstMoveDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { ICstMoveDTO } from './types';
|
||||||
|
|
||||||
export const useCstMove = () => {
|
export const useCstMove = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { ICstRenameDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { ICstRenameDTO } from './types';
|
||||||
|
|
||||||
export const useCstRename = () => {
|
export const useCstRename = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -16,7 +17,7 @@ export const useCstRename = () => {
|
||||||
updateTimestamp(data.schema.id);
|
updateTimestamp(data.schema.id);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { ICstSubstitutionsDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { ICstSubstitutionsDTO } from './types';
|
||||||
|
|
||||||
export const useCstSubstitute = () => {
|
export const useCstSubstitute = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -16,7 +17,7 @@ export const useCstSubstitute = () => {
|
||||||
updateTimestamp(data.id);
|
updateTimestamp(data.id);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { ICstUpdateDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { ICstUpdateDTO } from './types';
|
||||||
|
|
||||||
export const useCstUpdate = () => {
|
export const useCstUpdate = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -15,7 +16,7 @@ export const useCstUpdate = () => {
|
||||||
updateTimestamp(variables.itemID);
|
updateTimestamp(variables.itemID);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { IInlineSynthesisDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { IInlineSynthesisDTO } from './types';
|
||||||
|
|
||||||
export const useInlineSynthesis = () => {
|
export const useInlineSynthesis = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -16,7 +17,7 @@ export const useInlineSynthesis = () => {
|
||||||
updateTimestamp(data.id);
|
updateTimestamp(data.id);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { useIsMutating } from '@tanstack/react-query';
|
import { useIsMutating } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
|
|
||||||
import { rsformsApi } from './api';
|
|
||||||
|
|
||||||
export const useMutatingRSForm = () => {
|
export const useMutatingRSForm = () => {
|
||||||
const countLibrary = useIsMutating({ mutationKey: [libraryApi.baseKey] });
|
const countLibrary = useIsMutating({ mutationKey: [KEYS.library] });
|
||||||
const countRsform = useIsMutating({ mutationKey: [rsformsApi.baseKey] });
|
const countRsform = useIsMutating({ mutationKey: [KEYS.rsform] });
|
||||||
return countLibrary + countRsform !== 0;
|
return countLibrary + countRsform !== 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { ITargetCst } from '../models/rsform';
|
import { ITargetCst } from '../models/rsform';
|
||||||
import { rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
@ -17,7 +17,7 @@ export const useProduceStructure = () => {
|
||||||
updateTimestamp(data.schema.id);
|
updateTimestamp(data.schema.id);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { queryClient } from '../../../backend/queryClient';
|
import { queryClient } from '@/backend/queryClient';
|
||||||
|
|
||||||
import { rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
import { RSFormLoader } from './RSFormLoader';
|
import { RSFormLoader } from './RSFormLoader';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { useUpdateTimestamp } from '@/features/library';
|
import { useUpdateTimestamp } from '@/features/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export const useResetAliases = () => {
|
||||||
updateTimestamp(data.id);
|
updateTimestamp(data.id);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { libraryApi } from '@/features/library';
|
import { KEYS } from '@/backend/configuration';
|
||||||
import { ILibraryItem } from '@/features/library/models/library';
|
import { ILibraryItem } from '@/features/library/models/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
|
||||||
|
|
||||||
import { IRSFormUploadDTO, rsformsApi } from './api';
|
import { rsformsApi } from './api';
|
||||||
|
import { IRSFormUploadDTO } from './types';
|
||||||
|
|
||||||
export const useUploadTRS = () => {
|
export const useUploadTRS = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -12,13 +12,13 @@ export const useUploadTRS = () => {
|
||||||
mutationKey: [rsformsApi.baseKey, 'load-trs'],
|
mutationKey: [rsformsApi.baseKey, 'load-trs'],
|
||||||
mutationFn: rsformsApi.upload,
|
mutationFn: rsformsApi.upload,
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
client.setQueryData(KEYS.composite.rsItem({ itemID: data.id }), data);
|
||||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
client.setQueryData(KEYS.composite.libraryList, (prev: ILibraryItem[] | undefined) =>
|
||||||
prev?.map(item => (item.id === data.id ? data : item))
|
prev?.map(item => (item.id === data.id ? data : item))
|
||||||
);
|
);
|
||||||
|
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||||
client.invalidateQueries({
|
client.invalidateQueries({
|
||||||
queryKey: [rsformsApi.baseKey],
|
queryKey: [rsformsApi.baseKey],
|
||||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||||
|
|
|
@ -31,7 +31,7 @@ interface PickConstituentaProps extends CProps.Styling {
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<IConstituenta>();
|
const columnHelper = createColumnHelper<IConstituenta>();
|
||||||
|
|
||||||
function PickConstituenta({
|
export function PickConstituenta({
|
||||||
id,
|
id,
|
||||||
items,
|
items,
|
||||||
value,
|
value,
|
||||||
|
@ -102,5 +102,3 @@ function PickConstituenta({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PickConstituenta;
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { NoData } from '@/components/View';
|
||||||
import { Graph } from '@/models/Graph';
|
import { Graph } from '@/models/Graph';
|
||||||
|
|
||||||
import { describeConstituenta } from '../labels';
|
import { describeConstituenta } from '../labels';
|
||||||
import { ConstituentaID, IConstituenta, IRSForm } from '../models/rsform';
|
import { IConstituenta, IRSForm } from '../models/rsform';
|
||||||
import { isBasicConcept, matchConstituenta } from '../models/rsformAPI';
|
import { isBasicConcept, matchConstituenta } from '../models/rsformAPI';
|
||||||
import { CstMatchMode } from '../stores/cstSearch';
|
import { CstMatchMode } from '../stores/cstSearch';
|
||||||
import BadgeConstituenta from './BadgeConstituenta';
|
import BadgeConstituenta from './BadgeConstituenta';
|
||||||
|
@ -18,8 +18,8 @@ import ToolbarGraphSelection from './ToolbarGraphSelection';
|
||||||
|
|
||||||
interface PickMultiConstituentaProps extends CProps.Styling {
|
interface PickMultiConstituentaProps extends CProps.Styling {
|
||||||
id?: string;
|
id?: string;
|
||||||
value: ConstituentaID[];
|
value: number[];
|
||||||
onChange: (newValue: ConstituentaID[]) => void;
|
onChange: (newValue: number[]) => void;
|
||||||
|
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
items: IConstituenta[];
|
items: IConstituenta[];
|
||||||
|
@ -30,7 +30,7 @@ interface PickMultiConstituentaProps extends CProps.Styling {
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<IConstituenta>();
|
const columnHelper = createColumnHelper<IConstituenta>();
|
||||||
|
|
||||||
function PickMultiConstituenta({
|
export function PickMultiConstituenta({
|
||||||
id,
|
id,
|
||||||
schema,
|
schema,
|
||||||
items,
|
items,
|
||||||
|
@ -72,7 +72,7 @@ function PickMultiConstituenta({
|
||||||
onChange([]);
|
onChange([]);
|
||||||
} else {
|
} else {
|
||||||
const newRowSelection = typeof updater === 'function' ? updater(rowSelection) : updater;
|
const newRowSelection = typeof updater === 'function' ? updater(rowSelection) : updater;
|
||||||
const newSelection: ConstituentaID[] = [];
|
const newSelection: number[] = [];
|
||||||
filtered.forEach((cst, index) => {
|
filtered.forEach((cst, index) => {
|
||||||
if (newRowSelection[String(index)] === true) {
|
if (newRowSelection[String(index)] === true) {
|
||||||
newSelection.push(cst.id);
|
newSelection.push(cst.id);
|
||||||
|
@ -141,5 +141,3 @@ function PickMultiConstituenta({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PickMultiConstituenta;
|
|
||||||
|
|
|
@ -10,15 +10,22 @@ import { IconAccept, IconPageLeft, IconPageRight, IconRemove, IconReplace } from
|
||||||
import { CProps } from '@/components/props';
|
import { CProps } from '@/components/props';
|
||||||
import { NoData } from '@/components/View';
|
import { NoData } from '@/components/View';
|
||||||
import { ILibraryItem, SelectLibraryItem } from '@/features/library';
|
import { ILibraryItem, SelectLibraryItem } from '@/features/library';
|
||||||
import { IMultiSubstitution } from '@/features/oss/models/oss';
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
import { errorMsg } from '@/utils/labels';
|
import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
import { ICstSubstitute } from '../backend/api';
|
import { ICstSubstitute } from '../backend/types';
|
||||||
import { ConstituentaID, IConstituenta, IRSForm } from '../models/rsform';
|
import { IConstituenta, IRSForm } from '../models/rsform';
|
||||||
import BadgeConstituenta from './BadgeConstituenta';
|
import BadgeConstituenta from './BadgeConstituenta';
|
||||||
import SelectConstituenta from './SelectConstituenta';
|
import SelectConstituenta from './SelectConstituenta';
|
||||||
|
|
||||||
|
interface IMultiSubstitution {
|
||||||
|
original_source: ILibraryItem;
|
||||||
|
original: IConstituenta;
|
||||||
|
substitution: IConstituenta;
|
||||||
|
substitution_source: ILibraryItem;
|
||||||
|
is_suggestion: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface PickSubstitutionsProps extends CProps.Styling {
|
interface PickSubstitutionsProps extends CProps.Styling {
|
||||||
value: ICstSubstitute[];
|
value: ICstSubstitute[];
|
||||||
onChange: (newValue: ICstSubstitute[]) => void;
|
onChange: (newValue: ICstSubstitute[]) => void;
|
||||||
|
@ -34,7 +41,7 @@ interface PickSubstitutionsProps extends CProps.Styling {
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<IMultiSubstitution>();
|
const columnHelper = createColumnHelper<IMultiSubstitution>();
|
||||||
|
|
||||||
function PickSubstitutions({
|
export function PickSubstitutions({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
suggestions,
|
suggestions,
|
||||||
|
@ -81,7 +88,7 @@ function PickSubstitutions({
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
|
|
||||||
function getSchemaByCst(id: ConstituentaID): IRSForm | undefined {
|
function getSchemaByCst(id: number): IRSForm | undefined {
|
||||||
for (const schema of schemas) {
|
for (const schema of schemas) {
|
||||||
const cst = schema.cstByID.get(id);
|
const cst = schema.cstByID.get(id);
|
||||||
if (cst) {
|
if (cst) {
|
||||||
|
@ -91,7 +98,7 @@ function PickSubstitutions({
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConstituenta(id: ConstituentaID): IConstituenta | undefined {
|
function getConstituenta(id: number): IConstituenta | undefined {
|
||||||
for (const schema of schemas) {
|
for (const schema of schemas) {
|
||||||
const cst = schema.cstByID.get(id);
|
const cst = schema.cstByID.get(id);
|
||||||
if (cst) {
|
if (cst) {
|
||||||
|
@ -291,5 +298,3 @@ function PickSubstitutions({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PickSubstitutions;
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { Label } from '@/components/Input';
|
||||||
import { usePreferencesStore } from '@/stores/preferences';
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
|
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
import { IRSForm } from '../../models/rsform';
|
||||||
import { generateAlias, getCstTypePrefix, guessCstType } from '../../models/rsformAPI';
|
import { generateAlias, getCstTypePrefix, guessCstType } from '../../models/rsformAPI';
|
||||||
import { extractGlobals } from '../../models/rslangAPI';
|
import { extractGlobals } from '../../models/rslangAPI';
|
||||||
import { ccBracketMatching } from './bracketMatching';
|
import { ccBracketMatching } from './bracketMatching';
|
||||||
|
@ -41,7 +41,7 @@ interface RSInputProps
|
||||||
onChange?: (newValue: string) => void;
|
onChange?: (newValue: string) => void;
|
||||||
onAnalyze?: () => void;
|
onAnalyze?: () => void;
|
||||||
schema?: IRSForm;
|
schema?: IRSForm;
|
||||||
onOpenEdit?: (cstID: ConstituentaID) => void;
|
onOpenEdit?: (cstID: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RSInput = forwardRef<ReactCodeMirrorRef, RSInputProps>(
|
const RSInput = forwardRef<ReactCodeMirrorRef, RSInputProps>(
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { Extension } from '@codemirror/state';
|
import { Extension } from '@codemirror/state';
|
||||||
import { EditorView } from '@uiw/react-codemirror';
|
import { EditorView } from '@uiw/react-codemirror';
|
||||||
|
|
||||||
import { findAliasAt } from '@/utils/codemirror';
|
import { IRSForm } from '../../models/rsform';
|
||||||
|
import { findAliasAt } from './utils';
|
||||||
|
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
const navigationProducer = (schema: IRSForm, onOpenEdit: (cstID: number) => void) => {
|
||||||
|
|
||||||
const navigationProducer = (schema: IRSForm, onOpenEdit: (cstID: ConstituentaID) => void) => {
|
|
||||||
return EditorView.domEventHandlers({
|
return EditorView.domEventHandlers({
|
||||||
click: (event: MouseEvent, view: EditorView) => {
|
click: (event: MouseEvent, view: EditorView) => {
|
||||||
if (!event.ctrlKey && !event.metaKey) {
|
if (!event.ctrlKey && !event.metaKey) {
|
||||||
|
@ -34,6 +33,6 @@ const navigationProducer = (schema: IRSForm, onOpenEdit: (cstID: ConstituentaID)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export function rsNavigation(schema: IRSForm, onOpenEdit: (cstID: ConstituentaID) => void): Extension {
|
export function rsNavigation(schema: IRSForm, onOpenEdit: (cstID: number) => void): Extension {
|
||||||
return [navigationProducer(schema, onOpenEdit)];
|
return [navigationProducer(schema, onOpenEdit)];
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@ import { Extension } from '@codemirror/state';
|
||||||
import { hoverTooltip, TooltipView } from '@codemirror/view';
|
import { hoverTooltip, TooltipView } from '@codemirror/view';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { findAliasAt } from '@/utils/codemirror';
|
|
||||||
|
|
||||||
import { labelCstTypification } from '../../labels';
|
import { labelCstTypification } from '../../labels';
|
||||||
import { IConstituenta, IRSForm } from '../../models/rsform';
|
import { IConstituenta, IRSForm } from '../../models/rsform';
|
||||||
import { isBasicConcept } from '../../models/rsformAPI';
|
import { isBasicConcept } from '../../models/rsformAPI';
|
||||||
|
import { findAliasAt } from './utils';
|
||||||
|
|
||||||
const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
|
const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
|
||||||
return hoverTooltip((view, pos) => {
|
return hoverTooltip((view, pos) => {
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { syntaxTree } from '@codemirror/language';
|
||||||
|
import { EditorState } from '@uiw/react-codemirror';
|
||||||
|
|
||||||
|
import { findEnvelopingNodes } from '@/utils/codemirror';
|
||||||
|
|
||||||
|
import { GlobalTokens } from './rslang';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves globalID from position in Editor.
|
||||||
|
*/
|
||||||
|
export function findAliasAt(pos: number, state: EditorState) {
|
||||||
|
const { from: lineStart, to: lineEnd, text } = state.doc.lineAt(pos);
|
||||||
|
const nodes = findEnvelopingNodes(pos, pos, syntaxTree(state), GlobalTokens);
|
||||||
|
let alias = '';
|
||||||
|
let start = 0;
|
||||||
|
let end = 0;
|
||||||
|
nodes.forEach(node => {
|
||||||
|
if (node.to <= lineEnd && node.from >= lineStart) {
|
||||||
|
alias = text.slice(node.from - lineStart, node.to - lineStart);
|
||||||
|
start = node.from;
|
||||||
|
end = node.to;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { alias, start, end };
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ import { APP_COLORS } from '@/styling/colors';
|
||||||
import { CodeMirrorWrapper } from '@/utils/codemirror';
|
import { CodeMirrorWrapper } from '@/utils/codemirror';
|
||||||
|
|
||||||
import { ReferenceType } from '../../models/language';
|
import { ReferenceType } from '../../models/language';
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
import { IRSForm } from '../../models/rsform';
|
||||||
import { refsNavigation } from './clickNavigation';
|
import { refsNavigation } from './clickNavigation';
|
||||||
import { NaturalLanguage, ReferenceTokens } from './parse';
|
import { NaturalLanguage, ReferenceTokens } from './parse';
|
||||||
import { RefEntity } from './parse/parser.terms';
|
import { RefEntity } from './parse/parser.terms';
|
||||||
|
@ -67,7 +67,7 @@ interface RefsInputInputProps
|
||||||
onChange?: (newValue: string) => void;
|
onChange?: (newValue: string) => void;
|
||||||
|
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
onOpenEdit?: (cstID: ConstituentaID) => void;
|
onOpenEdit?: (cstID: number) => void;
|
||||||
|
|
||||||
label?: string;
|
label?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { Extension } from '@codemirror/state';
|
import { Extension } from '@codemirror/state';
|
||||||
import { EditorView } from '@uiw/react-codemirror';
|
import { EditorView } from '@uiw/react-codemirror';
|
||||||
|
|
||||||
import { findReferenceAt } from '@/utils/codemirror';
|
import { IRSForm } from '../../models/rsform';
|
||||||
|
import { findReferenceAt } from './utils';
|
||||||
|
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
const navigationProducer = (schema: IRSForm, onOpenEdit: (cstID: number) => void) => {
|
||||||
|
|
||||||
const navigationProducer = (schema: IRSForm, onOpenEdit: (cstID: ConstituentaID) => void) => {
|
|
||||||
return EditorView.domEventHandlers({
|
return EditorView.domEventHandlers({
|
||||||
click: (event: MouseEvent, view: EditorView) => {
|
click: (event: MouseEvent, view: EditorView) => {
|
||||||
if (!event.ctrlKey && !event.metaKey) {
|
if (!event.ctrlKey && !event.metaKey) {
|
||||||
|
@ -34,6 +33,6 @@ const navigationProducer = (schema: IRSForm, onOpenEdit: (cstID: ConstituentaID)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export function refsNavigation(schema: IRSForm, onOpenEdit: (cstID: ConstituentaID) => void): Extension {
|
export function refsNavigation(schema: IRSForm, onOpenEdit: (cstID: number) => void): Extension {
|
||||||
return [navigationProducer(schema, onOpenEdit)];
|
return [navigationProducer(schema, onOpenEdit)];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { hoverTooltip, TooltipView } from '@codemirror/view';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
import { findContainedNodes, findReferenceAt } from '@/utils/codemirror';
|
import { findContainedNodes } from '@/utils/codemirror';
|
||||||
|
|
||||||
import { colorFgGrammeme } from '../../colors';
|
import { colorFgGrammeme } from '../../colors';
|
||||||
import { labelGrammeme } from '../../labels';
|
import { labelGrammeme } from '../../labels';
|
||||||
|
@ -13,6 +13,7 @@ import { IEntityReference, ISyntacticReference } from '../../models/language';
|
||||||
import { parseGrammemes } from '../../models/languageAPI';
|
import { parseGrammemes } from '../../models/languageAPI';
|
||||||
import { IConstituenta, IRSForm } from '../../models/rsform';
|
import { IConstituenta, IRSForm } from '../../models/rsform';
|
||||||
import { RefEntity } from './parse/parser.terms';
|
import { RefEntity } from './parse/parser.terms';
|
||||||
|
import { findReferenceAt } from './utils';
|
||||||
|
|
||||||
export const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
|
export const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
|
||||||
return hoverTooltip((view, pos) => {
|
return hoverTooltip((view, pos) => {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { syntaxTree } from '@codemirror/language';
|
||||||
|
import { EditorState } from '@uiw/react-codemirror';
|
||||||
|
|
||||||
|
import { findEnvelopingNodes } from '@/utils/codemirror';
|
||||||
|
|
||||||
|
import { parseEntityReference, parseSyntacticReference } from '../../models/languageAPI';
|
||||||
|
import { ReferenceTokens } from './parse';
|
||||||
|
import { RefEntity } from './parse/parser.terms';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves reference from position in Editor.
|
||||||
|
*/
|
||||||
|
export function findReferenceAt(pos: number, state: EditorState) {
|
||||||
|
const nodes = findEnvelopingNodes(pos, pos, syntaxTree(state), ReferenceTokens);
|
||||||
|
if (nodes.length !== 1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const start = nodes[0].from;
|
||||||
|
const end = nodes[0].to;
|
||||||
|
const text = state.doc.sliceString(start, end);
|
||||||
|
if (nodes[0].type.id === RefEntity) {
|
||||||
|
return { ref: parseEntityReference(text), start, end };
|
||||||
|
} else {
|
||||||
|
return { ref: parseSyntacticReference(text), start, end };
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import { CProps } from '@/components/props';
|
||||||
|
|
||||||
import { describeConstituentaTerm } from '../labels';
|
import { describeConstituentaTerm } from '../labels';
|
||||||
import { describeConstituenta } from '../labels';
|
import { describeConstituenta } from '../labels';
|
||||||
import { ConstituentaID, IConstituenta } from '../models/rsform';
|
import { IConstituenta } from '../models/rsform';
|
||||||
import { matchConstituenta } from '../models/rsformAPI';
|
import { matchConstituenta } from '../models/rsformAPI';
|
||||||
import { CstMatchMode } from '../stores/cstSearch';
|
import { CstMatchMode } from '../stores/cstSearch';
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ function SelectConstituenta({
|
||||||
label: `${cst.alias}${cst.is_inherited ? '*' : ''}: ${describeConstituenta(cst)}`
|
label: `${cst.alias}${cst.is_inherited ? '*' : ''}: ${describeConstituenta(cst)}`
|
||||||
})) ?? [];
|
})) ?? [];
|
||||||
|
|
||||||
function filter(option: { value: ConstituentaID | undefined; label: string }, inputValue: string) {
|
function filter(option: { value: number | undefined; label: string }, inputValue: string) {
|
||||||
const cst = items?.find(item => item.id === option.value);
|
const cst = items?.find(item => item.id === option.value);
|
||||||
return !cst ? false : matchConstituenta(cst, inputValue, CstMatchMode.ALL);
|
return !cst ? false : matchConstituenta(cst, inputValue, CstMatchMode.ALL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,28 @@ import { Overlay } from '@/components/Container';
|
||||||
import { MiniButton } from '@/components/Control';
|
import { MiniButton } from '@/components/Control';
|
||||||
import { IconDestroy, IconSave, IconShare } from '@/components/Icons';
|
import { IconDestroy, IconSave, IconShare } from '@/components/Icons';
|
||||||
import { BadgeHelp, HelpTopic } from '@/features/help';
|
import { BadgeHelp, HelpTopic } from '@/features/help';
|
||||||
import { ILibraryItemEditor, MiniSelectorOSS, useMutatingLibrary } from '@/features/library';
|
import {
|
||||||
import { AccessPolicy, LibraryItemType } from '@/features/library';
|
AccessPolicy,
|
||||||
|
ILibraryItemEditor,
|
||||||
|
LibraryItemType,
|
||||||
|
MiniSelectorOSS,
|
||||||
|
useMutatingLibrary
|
||||||
|
} from '@/features/library';
|
||||||
import { useRoleStore, UserRole } from '@/features/users';
|
import { useRoleStore, UserRole } from '@/features/users';
|
||||||
import { useModificationStore } from '@/stores/modification';
|
import { useModificationStore } from '@/stores/modification';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
import { tooltipText } from '@/utils/labels';
|
import { tooltipText } from '@/utils/labels';
|
||||||
import { prepareTooltip, sharePage } from '@/utils/utils';
|
import { prepareTooltip, sharePage } from '@/utils/utils';
|
||||||
|
|
||||||
import { IRSForm } from '../../../models/rsform';
|
import { IRSForm } from '../models/rsform';
|
||||||
import { IRSEditContext } from '../RSEditContext';
|
import { IRSEditContext } from '../pages/RSFormPage/RSEditContext';
|
||||||
|
|
||||||
interface ToolbarRSFormCardProps {
|
interface ToolbarRSFormCardProps {
|
||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
controller: ILibraryItemEditor;
|
controller: ILibraryItemEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarRSFormCard({ controller, onSubmit }: ToolbarRSFormCardProps) {
|
export function ToolbarRSFormCard({ controller, onSubmit }: ToolbarRSFormCardProps) {
|
||||||
const role = useRoleStore(state => state.role);
|
const role = useRoleStore(state => state.role);
|
||||||
const { isModified } = useModificationStore();
|
const { isModified } = useModificationStore();
|
||||||
const isProcessing = useMutatingLibrary();
|
const isProcessing = useMutatingLibrary();
|
||||||
|
@ -73,5 +78,3 @@ function ToolbarRSFormCard({ controller, onSubmit }: ToolbarRSFormCardProps) {
|
||||||
</Overlay>
|
</Overlay>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ToolbarRSFormCard;
|
|
|
@ -6,7 +6,7 @@ import { ModalForm } from '@/components/Modal';
|
||||||
import usePartialUpdate from '@/hooks/usePartialUpdate';
|
import usePartialUpdate from '@/hooks/usePartialUpdate';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { ICstCreateDTO } from '../../backend/api';
|
import { ICstCreateDTO } from '../../backend/types';
|
||||||
import { CstType, IRSForm } from '../../models/rsform';
|
import { CstType, IRSForm } from '../../models/rsform';
|
||||||
import { generateAlias } from '../../models/rsformAPI';
|
import { generateAlias } from '../../models/rsformAPI';
|
||||||
import FormCreateCst from './FormCreateCst';
|
import FormCreateCst from './FormCreateCst';
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { TextArea, TextInput } from '@/components/Input';
|
||||||
import { BadgeHelp, HelpTopic } from '@/features/help';
|
import { BadgeHelp, HelpTopic } from '@/features/help';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
import { ICstCreateDTO } from '../../backend/api';
|
import { ICstCreateDTO } from '../../backend/types';
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
import { SelectCstType } from '../../components/SelectCstType';
|
import { SelectCstType } from '../../components/SelectCstType';
|
||||||
import { CstType, IRSForm } from '../../models/rsform';
|
import { CstType, IRSForm } from '../../models/rsform';
|
||||||
|
|
|
@ -11,7 +11,7 @@ import usePartialUpdate from '@/hooks/usePartialUpdate';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { promptText } from '@/utils/labels';
|
import { promptText } from '@/utils/labels';
|
||||||
|
|
||||||
import { ICstCreateDTO } from '../../backend/api';
|
import { ICstCreateDTO } from '../../backend/types';
|
||||||
import { useRSForm } from '../../backend/useRSForm';
|
import { useRSForm } from '../../backend/useRSForm';
|
||||||
import { CstType, IRSForm } from '../../models/rsform';
|
import { CstType, IRSForm } from '../../models/rsform';
|
||||||
import { generateAlias, validateNewAlias } from '../../models/rsformAPI';
|
import { generateAlias, validateNewAlias } from '../../models/rsformAPI';
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { IconAccept, IconRemove, IconReset } from '@/components/Icons';
|
||||||
import { NoData } from '@/components/View';
|
import { NoData } from '@/components/View';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
|
|
||||||
import PickConstituenta from '../../components/PickConstituenta';
|
import { PickConstituenta } from '../../components/PickConstituenta';
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
import { IConstituenta, IRSForm } from '../../models/rsform';
|
import { IConstituenta, IRSForm } from '../../models/rsform';
|
||||||
import { IArgumentValue } from '../../models/rslang';
|
import { IArgumentValue } from '../../models/rslang';
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { Dispatch, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { SelectSingle, TextArea } from '@/components/Input';
|
import { SelectSingle, TextArea } from '@/components/Input';
|
||||||
import { useTemplatesSuspense } from '@/features/library';
|
import { useTemplatesSuspense } from '@/features/library';
|
||||||
import PickConstituenta from '@/features/rsform/components/PickConstituenta';
|
|
||||||
|
|
||||||
|
import { PickConstituenta } from '../../components/PickConstituenta';
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
import { CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '../../models/rsform';
|
import { CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '../../models/rsform';
|
||||||
import { applyFilterCategory } from '../../models/rsformAPI';
|
import { applyFilterCategory } from '../../models/rsformAPI';
|
||||||
|
|
|
@ -9,13 +9,13 @@ import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { prefixes } from '@/utils/constants';
|
import { prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
import { useCstDelete } from '../../backend/useCstDelete';
|
import { useCstDelete } from '../../backend/useCstDelete';
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
import { IRSForm } from '../../models/rsform';
|
||||||
import ListConstituents from './ListConstituents';
|
import ListConstituents from './ListConstituents';
|
||||||
|
|
||||||
export interface DlgDeleteCstProps {
|
export interface DlgDeleteCstProps {
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
selected: ConstituentaID[];
|
selected: number[];
|
||||||
afterDelete: (initialSchema: IRSForm, deleted: ConstituentaID[]) => void;
|
afterDelete: (initialSchema: IRSForm, deleted: number[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DlgDeleteCst() {
|
function DlgDeleteCst() {
|
||||||
|
@ -23,7 +23,7 @@ function DlgDeleteCst() {
|
||||||
const { cstDelete } = useCstDelete();
|
const { cstDelete } = useCstDelete();
|
||||||
|
|
||||||
const [expandOut, setExpandOut] = useState(false);
|
const [expandOut, setExpandOut] = useState(false);
|
||||||
const expansion: ConstituentaID[] = schema.graph.expandAllOutputs(selected);
|
const expansion: number[] = schema.graph.expandAllOutputs(selected);
|
||||||
const hasInherited = selected.some(
|
const hasInherited = selected.some(
|
||||||
id => schema.inheritance.find(item => item.parent === id),
|
id => schema.inheritance.find(item => item.parent === id),
|
||||||
[selected, schema.inheritance]
|
[selected, schema.inheritance]
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { labelConstituenta } from '../../labels';
|
import { labelConstituenta } from '../../labels';
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
import { IRSForm } from '../../models/rsform';
|
||||||
|
|
||||||
interface ListConstituentsProps {
|
interface ListConstituentsProps {
|
||||||
list: ConstituentaID[];
|
list: number[];
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
prefix: string;
|
prefix: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user