mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
R: Upgrade SubstituteCst dialog
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run
This commit is contained in:
parent
381567491f
commit
2632921dbb
|
@ -4,14 +4,8 @@ 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 { ILibraryItem, ILibraryItemData, LibraryItemID } from '@/features/library/models/library';
|
import { ILibraryItem, ILibraryItemData, LibraryItemID } from '@/features/library/models/library';
|
||||||
import {
|
import { IArgument, ICstSubstituteEx, IOperation, OperationID, OperationType } from '@/features/oss/models/oss';
|
||||||
IArgument,
|
import { schemaCstSubstitute } from '@/features/rsform/backend/api';
|
||||||
ICstSubstituteEx,
|
|
||||||
IOperation,
|
|
||||||
OperationID,
|
|
||||||
OperationType,
|
|
||||||
schemaCstSubstitute
|
|
||||||
} from '@/features/oss/models/oss';
|
|
||||||
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';
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* Module: Schema of Synthesis Operations.
|
* Module: Schema of Synthesis Operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { ILibraryItem, ILibraryItemData, LibraryItemID } from '@/features/library/models/library';
|
import { ILibraryItem, ILibraryItemData, LibraryItemID } from '@/features/library/models/library';
|
||||||
|
import { ICstSubstitute } from '@/features/rsform/backend/api';
|
||||||
import { IConstituenta } from '@/features/rsform/models/rsform';
|
import { IConstituenta } from '@/features/rsform/models/rsform';
|
||||||
|
|
||||||
import { Graph } from '../../../models/Graph';
|
import { Graph } from '../../../models/Graph';
|
||||||
|
@ -53,26 +51,6 @@ export interface IArgument {
|
||||||
argument: OperationID;
|
argument: OperationID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 data, used in merging multiple {@link IConstituenta}.
|
|
||||||
*/
|
|
||||||
export interface ICstSubstitutions {
|
|
||||||
substitutions: ICstSubstitute[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents substitution for multi synthesis table.
|
* Represents substitution for multi synthesis table.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ILibraryItem, LibraryItemID } from '@/features/library/models/library';
|
import { ILibraryItem, LibraryItemID } from '@/features/library/models/library';
|
||||||
|
import { ICstSubstitute } from '@/features/rsform/backend/api';
|
||||||
import { ConstituentaID, CstClass, CstType, IConstituenta, IRSForm } from '@/features/rsform/models/rsform';
|
import { ConstituentaID, CstClass, CstType, IConstituenta, IRSForm } from '@/features/rsform/models/rsform';
|
||||||
import { AliasMapping, ParsingStatus } from '@/features/rsform/models/rslang';
|
import { AliasMapping, ParsingStatus } from '@/features/rsform/models/rslang';
|
||||||
import {
|
import {
|
||||||
|
@ -18,7 +19,7 @@ import { TextMatcher } from '@/utils/utils';
|
||||||
import { Graph } from '../../../models/Graph';
|
import { Graph } from '../../../models/Graph';
|
||||||
import { IOperationPosition } from '../backend/api';
|
import { IOperationPosition } from '../backend/api';
|
||||||
import { describeSubstitutionError } from '../labels';
|
import { describeSubstitutionError } from '../labels';
|
||||||
import { ICstSubstitute, IOperation, IOperationSchema, OperationID, OperationType, SubstitutionErrorType } from './oss';
|
import { IOperation, IOperationSchema, OperationID, OperationType, SubstitutionErrorType } from './oss';
|
||||||
import { Position2D } from './ossLayout';
|
import { Position2D } from './ossLayout';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,8 +9,7 @@ import {
|
||||||
LibraryItemID,
|
LibraryItemID,
|
||||||
VersionID
|
VersionID
|
||||||
} from '@/features/library/models/library';
|
} from '@/features/library/models/library';
|
||||||
import { ICstSubstitute, ICstSubstitutions } from '@/features/oss/models/oss';
|
import { errorMsg, infoMsg } from '@/utils/labels';
|
||||||
import { infoMsg } from '@/utils/labels';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ConstituentaID,
|
ConstituentaID,
|
||||||
|
@ -127,6 +126,19 @@ export interface IProduceStructureResponse {
|
||||||
schema: IRSFormDTO;
|
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.
|
* Represents input data for inline synthesis.
|
||||||
*/
|
*/
|
||||||
|
@ -146,6 +158,18 @@ export interface ICheckConstituentaDTO {
|
||||||
definition_formal: string;
|
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: 'rsform',
|
||||||
|
|
||||||
|
@ -214,8 +238,8 @@ export const rsformsApi = {
|
||||||
successMessage: infoMsg.changesSaved
|
successMessage: infoMsg.changesSaved
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
cstSubstitute: ({ itemID, data }: { itemID: LibraryItemID; data: ICstSubstitutions }) =>
|
cstSubstitute: ({ itemID, data }: { itemID: LibraryItemID; data: ICstSubstitutionsDTO }) =>
|
||||||
axiosPatch<ICstSubstitutions, IRSFormDTO>({
|
axiosPatch<ICstSubstitutionsDTO, IRSFormDTO>({
|
||||||
endpoint: `/api/rsforms/${itemID}/substitute`,
|
endpoint: `/api/rsforms/${itemID}/substitute`,
|
||||||
request: {
|
request: {
|
||||||
data: data,
|
data: data,
|
||||||
|
@ -229,7 +253,7 @@ export const rsformsApi = {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
produceStructure: ({ itemID, data }: { itemID: LibraryItemID; data: ITargetCst }) =>
|
produceStructure: ({ itemID, data }: { itemID: LibraryItemID; data: ITargetCst }) =>
|
||||||
axiosPost<ITargetCst, IProduceStructureResponse>({
|
axiosPatch<ITargetCst, IProduceStructureResponse>({
|
||||||
endpoint: `/api/rsforms/${itemID}/produce-structure`,
|
endpoint: `/api/rsforms/${itemID}/produce-structure`,
|
||||||
request: {
|
request: {
|
||||||
data: data,
|
data: data,
|
||||||
|
|
|
@ -3,9 +3,8 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useUpdateTimestamp } from '@/features/library/backend/useUpdateTimestamp';
|
import { useUpdateTimestamp } from '@/features/library/backend/useUpdateTimestamp';
|
||||||
import { LibraryItemID } from '@/features/library/models/library';
|
import { LibraryItemID } from '@/features/library/models/library';
|
||||||
import { ossApi } from '@/features/oss/backend/api';
|
import { ossApi } from '@/features/oss/backend/api';
|
||||||
import { ICstSubstitutions } from '@/features/oss/models/oss';
|
|
||||||
|
|
||||||
import { rsformsApi } from './api';
|
import { ICstSubstitutionsDTO, rsformsApi } from './api';
|
||||||
|
|
||||||
export const useCstSubstitute = () => {
|
export const useCstSubstitute = () => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
@ -27,6 +26,6 @@ export const useCstSubstitute = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
cstSubstitute: (data: { itemID: LibraryItemID; data: ICstSubstitutions }) => mutation.mutateAsync(data)
|
cstSubstitute: (data: { itemID: LibraryItemID; data: ICstSubstitutionsDTO }) => mutation.mutateAsync(data)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,10 +11,11 @@ import { CProps } from '@/components/props';
|
||||||
import { NoData } from '@/components/View';
|
import { NoData } from '@/components/View';
|
||||||
import SelectLibraryItem from '@/features/library/components/SelectLibraryItem';
|
import SelectLibraryItem from '@/features/library/components/SelectLibraryItem';
|
||||||
import { ILibraryItem } from '@/features/library/models/library';
|
import { ILibraryItem } from '@/features/library/models/library';
|
||||||
import { ICstSubstitute, IMultiSubstitution } from '@/features/oss/models/oss';
|
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 { ConstituentaID, IConstituenta, IRSForm } from '../models/rsform';
|
import { ConstituentaID, IConstituenta, IRSForm } from '../models/rsform';
|
||||||
import BadgeConstituenta from './BadgeConstituenta';
|
import BadgeConstituenta from './BadgeConstituenta';
|
||||||
import SelectConstituenta from './SelectConstituenta';
|
import SelectConstituenta from './SelectConstituenta';
|
||||||
|
|
|
@ -7,11 +7,10 @@ import { Loader } from '@/components/Loader';
|
||||||
import { ModalForm } from '@/components/Modal';
|
import { ModalForm } from '@/components/Modal';
|
||||||
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/Tabs';
|
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/Tabs';
|
||||||
import { LibraryItemID } from '@/features/library/models/library';
|
import { LibraryItemID } from '@/features/library/models/library';
|
||||||
import { ICstSubstitute } from '@/features/oss/models/oss';
|
|
||||||
import { useRSForm } from '@/features/rsform/backend/useRSForm';
|
import { useRSForm } from '@/features/rsform/backend/useRSForm';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { IInlineSynthesisDTO } from '../../backend/api';
|
import { ICstSubstitute, IInlineSynthesisDTO } from '../../backend/api';
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
||||||
import TabConstituents from './TabConstituents';
|
import TabConstituents from './TabConstituents';
|
||||||
import TabSource from './TabSource';
|
import TabSource from './TabSource';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { LibraryItemID } from '@/features/library/models/library';
|
import { LibraryItemID } from '@/features/library/models/library';
|
||||||
import { ICstSubstitute } from '@/features/oss/models/oss';
|
|
||||||
|
|
||||||
|
import { ICstSubstitute } from '../../backend/api';
|
||||||
import { useRSFormSuspense } from '../../backend/useRSForm';
|
import { useRSFormSuspense } from '../../backend/useRSForm';
|
||||||
import PickSubstitutions from '../../components/PickSubstitutions';
|
import PickSubstitutions from '../../components/PickSubstitutions';
|
||||||
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
import { ConstituentaID, IRSForm } from '../../models/rsform';
|
||||||
|
|
|
@ -1,29 +1,42 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useState } from 'react';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|
||||||
|
import { ErrorField } from '@/components/Input';
|
||||||
import { ModalForm } from '@/components/Modal';
|
import { ModalForm } from '@/components/Modal';
|
||||||
import { HelpTopic } from '@/features/help/models/helpTopic';
|
import { HelpTopic } from '@/features/help/models/helpTopic';
|
||||||
import { ICstSubstitute, ICstSubstitutions } from '@/features/oss/models/oss';
|
|
||||||
import PickSubstitutions from '@/features/rsform/components/PickSubstitutions';
|
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
|
import { ICstSubstitutionsDTO, schemaCstSubstitutions } from '../backend/api';
|
||||||
|
import { useCstSubstitute } from '../backend/useCstSubstitute';
|
||||||
|
import PickSubstitutions from '../components/PickSubstitutions';
|
||||||
import { IRSForm } from '../models/rsform';
|
import { IRSForm } from '../models/rsform';
|
||||||
|
|
||||||
export interface DlgSubstituteCstProps {
|
export interface DlgSubstituteCstProps {
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
onSubstitute: (data: ICstSubstitutions) => void;
|
onSubstitute: (data: ICstSubstitutionsDTO) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DlgSubstituteCst() {
|
function DlgSubstituteCst() {
|
||||||
const { onSubstitute, schema } = useDialogsStore(state => state.props as DlgSubstituteCstProps);
|
const { onSubstitute, schema } = useDialogsStore(state => state.props as DlgSubstituteCstProps);
|
||||||
const [substitutions, setSubstitutions] = useState<ICstSubstitute[]>([]);
|
const { cstSubstitute } = useCstSubstitute();
|
||||||
const canSubmit = substitutions.length > 0;
|
|
||||||
|
|
||||||
function handleSubmit() {
|
const {
|
||||||
onSubstitute({ substitutions: substitutions });
|
handleSubmit,
|
||||||
return true;
|
control,
|
||||||
|
formState: { errors, isValid }
|
||||||
|
} = useForm<ICstSubstitutionsDTO>({
|
||||||
|
resolver: zodResolver(schemaCstSubstitutions),
|
||||||
|
defaultValues: {
|
||||||
|
substitutions: []
|
||||||
|
},
|
||||||
|
mode: 'onChange'
|
||||||
|
});
|
||||||
|
|
||||||
|
function onSubmit(data: ICstSubstitutionsDTO) {
|
||||||
|
return cstSubstitute({ itemID: schema.id, data: data }).then(() => onSubstitute(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -31,18 +44,25 @@ function DlgSubstituteCst() {
|
||||||
header='Отождествление'
|
header='Отождествление'
|
||||||
submitText='Отождествить'
|
submitText='Отождествить'
|
||||||
submitInvalidTooltip='Выберите две различные конституенты'
|
submitInvalidTooltip='Выберите две различные конституенты'
|
||||||
canSubmit={canSubmit}
|
canSubmit={isValid}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('w-[40rem]', 'px-6 pb-3')}
|
className={clsx('w-[40rem]', 'px-6 pb-3')}
|
||||||
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
|
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
|
||||||
>
|
>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name='substitutions'
|
||||||
|
render={({ field }) => (
|
||||||
<PickSubstitutions
|
<PickSubstitutions
|
||||||
allowSelfSubstitution
|
allowSelfSubstitution
|
||||||
value={substitutions}
|
value={field.value}
|
||||||
onChange={setSubstitutions}
|
onChange={field.onChange}
|
||||||
rows={6}
|
rows={6}
|
||||||
schemas={[schema]}
|
schemas={[schema]}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ErrorField className='mt-2' error={errors.substitutions} />
|
||||||
</ModalForm>
|
</ModalForm>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@ import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
||||||
import { describeAccessMode, labelAccessMode, tooltipText } from '@/utils/labels';
|
import { describeAccessMode, labelAccessMode, tooltipText } from '@/utils/labels';
|
||||||
import { generatePageQR, promptUnsaved, sharePage } from '@/utils/utils';
|
import { generatePageQR, promptUnsaved, sharePage } from '@/utils/utils';
|
||||||
|
|
||||||
import { useCstSubstitute } from '../../backend/useCstSubstitute';
|
|
||||||
import { useDownloadRSForm } from '../../backend/useDownloadRSForm';
|
import { useDownloadRSForm } from '../../backend/useDownloadRSForm';
|
||||||
import { useInlineSynthesis } from '../../backend/useInlineSynthesis';
|
import { useInlineSynthesis } from '../../backend/useInlineSynthesis';
|
||||||
import { useMutatingRSForm } from '../../backend/useMutatingRSForm';
|
import { useMutatingRSForm } from '../../backend/useMutatingRSForm';
|
||||||
|
@ -66,7 +65,6 @@ function MenuRSTabs() {
|
||||||
const { restoreOrder } = useRestoreOrder();
|
const { restoreOrder } = useRestoreOrder();
|
||||||
const { produceStructure } = useProduceStructure();
|
const { produceStructure } = useProduceStructure();
|
||||||
const { inlineSynthesis } = useInlineSynthesis();
|
const { inlineSynthesis } = useInlineSynthesis();
|
||||||
const { cstSubstitute } = useCstSubstitute();
|
|
||||||
const { download } = useDownloadRSForm();
|
const { download } = useDownloadRSForm();
|
||||||
|
|
||||||
const showInlineSynthesis = useDialogsStore(state => state.showInlineSynthesis);
|
const showInlineSynthesis = useDialogsStore(state => state.showInlineSynthesis);
|
||||||
|
@ -167,9 +165,7 @@ function MenuRSTabs() {
|
||||||
showSubstituteCst({
|
showSubstituteCst({
|
||||||
schema: controller.schema,
|
schema: controller.schema,
|
||||||
onSubstitute: data =>
|
onSubstitute: data =>
|
||||||
void cstSubstitute({ itemID: controller.schema.id, data }).then(() =>
|
|
||||||
controller.setSelected(prev => prev.filter(id => !data.substitutions.find(sub => sub.original === id)))
|
controller.setSelected(prev => prev.filter(id => !data.substitutions.find(sub => sub.original === id)))
|
||||||
)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,8 @@ export const errorMsg = {
|
||||||
privacyNotAccepted: 'Примите политику обработки персональных данных',
|
privacyNotAccepted: 'Примите политику обработки персональных данных',
|
||||||
loginFormat: 'Имя пользователя должно содержать только буквы и цифры',
|
loginFormat: 'Имя пользователя должно содержать только буквы и цифры',
|
||||||
invalidLocation: 'Некорректный формат пути',
|
invalidLocation: 'Некорректный формат пути',
|
||||||
versionTaken: 'Версия с таким шифром уже существует'
|
versionTaken: 'Версия с таким шифром уже существует',
|
||||||
|
emptySubstitutions: 'Выберите хотя бы одно отождествление'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue
Block a user