mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
R: Refactor dialogs using zustand store
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
b260640ebf
commit
33ad3c6b95
|
@ -9,6 +9,7 @@ import { NavigationState } from '@/context/NavigationContext';
|
|||
import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { GlobalDialogs } from './GlobalDialogs';
|
||||
import { GlobalTooltips } from './GlobalTooltips';
|
||||
|
||||
function ApplicationLayout() {
|
||||
|
@ -29,6 +30,7 @@ function ApplicationLayout() {
|
|||
pauseOnFocusLoss={false}
|
||||
/>
|
||||
|
||||
<GlobalDialogs />
|
||||
<GlobalTooltips />
|
||||
|
||||
<Navigation />
|
||||
|
|
83
rsconcept/frontend/src/app/GlobalDialogs.tsx
Normal file
83
rsconcept/frontend/src/app/GlobalDialogs.tsx
Normal file
|
@ -0,0 +1,83 @@
|
|||
'use client';
|
||||
|
||||
import DlgChangeInputSchema from '@/dialogs/DlgChangeInputSchema';
|
||||
import DlgChangeLocation from '@/dialogs/DlgChangeLocation';
|
||||
import DlgCloneLibraryItem from '@/dialogs/DlgCloneLibraryItem';
|
||||
import DlgCreateCst from '@/dialogs/DlgCreateCst';
|
||||
import DlgCreateOperation from '@/dialogs/DlgCreateOperation';
|
||||
import DlgCreateVersion from '@/dialogs/DlgCreateVersion';
|
||||
import DlgCstTemplate from '@/dialogs/DlgCstTemplate';
|
||||
import DlgDeleteCst from '@/dialogs/DlgDeleteCst';
|
||||
import DlgDeleteOperation from '@/dialogs/DlgDeleteOperation';
|
||||
import DlgEditEditors from '@/dialogs/DlgEditEditors';
|
||||
import DlgEditOperation from '@/dialogs/DlgEditOperation';
|
||||
import DlgEditReference from '@/dialogs/DlgEditReference';
|
||||
import DlgEditVersions from '@/dialogs/DlgEditVersions';
|
||||
import DlgEditWordForms from '@/dialogs/DlgEditWordForms';
|
||||
import DlgGraphParams from '@/dialogs/DlgGraphParams';
|
||||
import DlgInlineSynthesis from '@/dialogs/DlgInlineSynthesis';
|
||||
import DlgRelocateConstituents from '@/dialogs/DlgRelocateConstituents';
|
||||
import DlgRenameCst from '@/dialogs/DlgRenameCst';
|
||||
import DlgShowAST from '@/dialogs/DlgShowAST';
|
||||
import DlgShowQR from '@/dialogs/DlgShowQR';
|
||||
import DlgShowTypeGraph from '@/dialogs/DlgShowTypeGraph';
|
||||
import DlgSubstituteCst from '@/dialogs/DlgSubstituteCst';
|
||||
import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm';
|
||||
import { DialogType } from '@/models/miscellaneous';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
export const GlobalDialogs = () => {
|
||||
const active = useDialogsStore(state => state.active);
|
||||
|
||||
if (active === undefined) {
|
||||
return null;
|
||||
}
|
||||
switch (active) {
|
||||
case DialogType.CONSTITUENTA_TEMPLATE:
|
||||
return <DlgCstTemplate />;
|
||||
case DialogType.CREATE_CONSTITUENTA:
|
||||
return <DlgCreateCst />;
|
||||
case DialogType.CREATE_OPERATION:
|
||||
return <DlgCreateOperation />;
|
||||
case DialogType.DELETE_CONSTITUENTA:
|
||||
return <DlgDeleteCst />;
|
||||
case DialogType.EDIT_EDITORS:
|
||||
return <DlgEditEditors />;
|
||||
case DialogType.EDIT_OPERATION:
|
||||
return <DlgEditOperation />;
|
||||
case DialogType.EDIT_REFERENCE:
|
||||
return <DlgEditReference />;
|
||||
case DialogType.EDIT_VERSIONS:
|
||||
return <DlgEditVersions />;
|
||||
case DialogType.EDIT_WORD_FORMS:
|
||||
return <DlgEditWordForms />;
|
||||
case DialogType.INLINE_SYNTHESIS:
|
||||
return <DlgInlineSynthesis />;
|
||||
case DialogType.SHOW_AST:
|
||||
return <DlgShowAST />;
|
||||
case DialogType.SHOW_TYPE_GRAPH:
|
||||
return <DlgShowTypeGraph />;
|
||||
case DialogType.CHANGE_INPUT_SCHEMA:
|
||||
return <DlgChangeInputSchema />;
|
||||
case DialogType.CHANGE_LOCATION:
|
||||
return <DlgChangeLocation />;
|
||||
case DialogType.CLONE_LIBRARY_ITEM:
|
||||
return <DlgCloneLibraryItem />;
|
||||
case DialogType.CREATE_VERSION:
|
||||
return <DlgCreateVersion />;
|
||||
case DialogType.DELETE_OPERATION:
|
||||
return <DlgDeleteOperation />;
|
||||
case DialogType.GRAPH_PARAMETERS:
|
||||
return <DlgGraphParams />;
|
||||
case DialogType.RELOCATE_CONSTITUENTS:
|
||||
return <DlgRelocateConstituents />;
|
||||
case DialogType.RENAME_CONSTITUENTA:
|
||||
return <DlgRenameCst />;
|
||||
case DialogType.SHOW_QR_CODE:
|
||||
return <DlgShowQR />;
|
||||
case DialogType.SUBSTITUTE_CONSTITUENTS:
|
||||
return <DlgSubstituteCst />;
|
||||
case DialogType.UPLOAD_RSFORM:
|
||||
return <DlgUploadRSForm />;
|
||||
}
|
||||
};
|
|
@ -9,13 +9,13 @@ import { EditorView } from 'codemirror';
|
|||
import { forwardRef, useRef, useState } from 'react';
|
||||
|
||||
import Label from '@/components/ui/Label';
|
||||
import DlgEditReference from '@/dialogs/DlgEditReference';
|
||||
import { ReferenceType } from '@/models/language';
|
||||
import { DialogType } from '@/models/miscellaneous';
|
||||
import { ConstituentaID, IRSForm } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { usePreferencesStore } from '@/stores/preferences';
|
||||
import { APP_COLORS } from '@/styling/color';
|
||||
import { CodeMirrorWrapper } from '@/utils/codemirror';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
|
||||
import { refsNavigation } from './clickNavigation';
|
||||
import { NaturalLanguage, ReferenceTokens } from './parse';
|
||||
|
@ -96,7 +96,10 @@ const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
|
|||
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
|
||||
const [showEditor, setShowEditor] = useState(false);
|
||||
const showEditReference = useDialogsStore(state => state.showEditReference);
|
||||
const activeDialog = useDialogsStore(state => state.active);
|
||||
const isActive = activeDialog === DialogType.EDIT_REFERENCE;
|
||||
|
||||
const [currentType, setCurrentType] = useState<ReferenceType>(ReferenceType.ENTITY);
|
||||
const [refText, setRefText] = useState('');
|
||||
const [hintText, setHintText] = useState('');
|
||||
|
@ -146,7 +149,7 @@ const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
|
|||
}
|
||||
|
||||
function handleInput(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||
if (!thisRef.current?.view) {
|
||||
if (!thisRef.current?.view || !schema) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
|
@ -174,7 +177,17 @@ const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
|
|||
setMainRefs(mainNodes.map(node => wrap.getText(node.from, node.to)));
|
||||
setBasePosition(mainNodes.filter(node => node.to <= selection.from).length);
|
||||
|
||||
setShowEditor(true);
|
||||
showEditReference({
|
||||
schema: schema,
|
||||
initial: {
|
||||
type: currentType,
|
||||
refRaw: refText,
|
||||
text: hintText,
|
||||
basePosition: basePosition,
|
||||
mainRefs: mainRefs
|
||||
},
|
||||
onSave: handleInputReference
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,27 +200,8 @@ const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
|
|||
wrap.replaceWith(referenceText);
|
||||
}
|
||||
|
||||
function hideEditReference() {
|
||||
setShowEditor(false);
|
||||
setTimeout(() => thisRef.current?.view?.focus(), PARAMETER.refreshTimeout);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={clsx('flex flex-col gap-2', cursor)}>
|
||||
{showEditor && schema ? (
|
||||
<DlgEditReference
|
||||
hideWindow={hideEditReference}
|
||||
schema={schema}
|
||||
initial={{
|
||||
type: currentType,
|
||||
refRaw: refText,
|
||||
text: hintText,
|
||||
basePosition: basePosition,
|
||||
mainRefs: mainRefs
|
||||
}}
|
||||
onSave={handleInputReference}
|
||||
/>
|
||||
) : null}
|
||||
<Label text={label} />
|
||||
<CodeMirror
|
||||
id={id}
|
||||
|
@ -215,10 +209,10 @@ const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
|
|||
basicSetup={editorSetup}
|
||||
theme={customTheme}
|
||||
extensions={editorExtensions}
|
||||
value={isFocused ? value : value !== initialValue || showEditor ? value : resolved}
|
||||
value={isFocused ? value : value !== initialValue || isActive ? value : resolved}
|
||||
indentWithTab={false}
|
||||
onChange={handleChange}
|
||||
editable={!disabled && !showEditor}
|
||||
editable={!disabled && !isActive}
|
||||
onKeyDown={handleInput}
|
||||
onFocus={handleFocusIn}
|
||||
onBlur={handleFocusOut}
|
||||
|
|
|
@ -4,6 +4,7 @@ import clsx from 'clsx';
|
|||
|
||||
import useEscapeKey from '@/hooks/useEscapeKey';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
import { prepareTooltip } from '@/utils/labels';
|
||||
|
||||
|
@ -32,9 +33,6 @@ export interface ModalProps extends CProps.Styling {
|
|||
/** Indicates that the modal window should be scrollable. */
|
||||
overflowVisible?: boolean;
|
||||
|
||||
/** Callback to be called when the modal window is closed. */
|
||||
hideWindow: () => void;
|
||||
|
||||
/** Callback to be called before submit. */
|
||||
beforeSubmit?: () => boolean;
|
||||
|
||||
|
@ -65,7 +63,6 @@ function Modal({
|
|||
canSubmit,
|
||||
overflowVisible,
|
||||
|
||||
hideWindow,
|
||||
beforeSubmit,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
|
@ -75,10 +72,11 @@ function Modal({
|
|||
hideHelpWhen,
|
||||
...restProps
|
||||
}: React.PropsWithChildren<ModalProps>) {
|
||||
useEscapeKey(hideWindow);
|
||||
const hideDialog = useDialogsStore(state => state.hideDialog);
|
||||
useEscapeKey(hideDialog);
|
||||
|
||||
const handleCancel = () => {
|
||||
hideWindow();
|
||||
hideDialog();
|
||||
onCancel?.();
|
||||
};
|
||||
|
||||
|
@ -87,7 +85,7 @@ function Modal({
|
|||
return;
|
||||
}
|
||||
onSubmit?.();
|
||||
hideWindow();
|
||||
hideDialog();
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -95,7 +93,7 @@ function Modal({
|
|||
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} />
|
||||
<div
|
||||
className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')}
|
||||
onClick={hideWindow}
|
||||
onClick={hideDialog}
|
||||
/>
|
||||
<div
|
||||
className={clsx(
|
||||
|
|
|
@ -7,19 +7,21 @@ import { IconReset } from '@/components/Icons';
|
|||
import PickSchema from '@/components/select/PickSchema';
|
||||
import Label from '@/components/ui/Label';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import { useLibrary } from '@/context/LibraryContext';
|
||||
import { ILibraryItem, LibraryItemID, LibraryItemType } from '@/models/library';
|
||||
import { IOperation, IOperationSchema } from '@/models/oss';
|
||||
import { IOperation, IOperationSchema, OperationID } from '@/models/oss';
|
||||
import { sortItemsForOSS } from '@/models/ossAPI';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
interface DlgChangeInputSchemaProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgChangeInputSchemaProps {
|
||||
oss: IOperationSchema;
|
||||
target: IOperation;
|
||||
onSubmit: (newSchema: LibraryItemID | undefined) => void;
|
||||
onSubmit: (target: OperationID, newSchema: LibraryItemID | undefined) => void;
|
||||
}
|
||||
|
||||
function DlgChangeInputSchema({ oss, hideWindow, target, onSubmit }: DlgChangeInputSchemaProps) {
|
||||
function DlgChangeInputSchema() {
|
||||
const { oss, target, onSubmit } = useDialogsStore(state => state.props as DlgChangeInputSchemaProps);
|
||||
const [selected, setSelected] = useState<LibraryItemID | undefined>(target.result ?? undefined);
|
||||
const library = useLibrary();
|
||||
const sortedItems = sortItemsForOSS(oss, library.items);
|
||||
|
@ -38,9 +40,8 @@ function DlgChangeInputSchema({ oss, hideWindow, target, onSubmit }: DlgChangeIn
|
|||
overflowVisible
|
||||
header='Выбор концептуальной схемы'
|
||||
submitText='Подтвердить выбор'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={isValid}
|
||||
onSubmit={() => onSubmit(selected)}
|
||||
onSubmit={() => onSubmit(target.id, selected)}
|
||||
className={clsx('w-[35rem]', 'pb-3 px-6 cc-column')}
|
||||
>
|
||||
<div className='flex justify-between gap-3 items-center'>
|
||||
|
|
|
@ -6,20 +6,22 @@ import { useState } from 'react';
|
|||
import SelectLocationContext from '@/components/select/SelectLocationContext';
|
||||
import SelectLocationHead from '@/components/select/SelectLocationHead';
|
||||
import Label from '@/components/ui/Label';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import TextArea from '@/components/ui/TextArea';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
import { useLibrary } from '@/context/LibraryContext';
|
||||
import { LocationHead } from '@/models/library';
|
||||
import { combineLocation, validateLocation } from '@/models/libraryAPI';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { limits } from '@/utils/constants';
|
||||
|
||||
interface DlgChangeLocationProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgChangeLocationProps {
|
||||
initial: string;
|
||||
onChangeLocation: (newLocation: string) => void;
|
||||
}
|
||||
|
||||
function DlgChangeLocation({ hideWindow, initial, onChangeLocation }: DlgChangeLocationProps) {
|
||||
function DlgChangeLocation() {
|
||||
const { initial, onChangeLocation } = useDialogsStore(state => state.props as DlgChangeLocationProps);
|
||||
const { user } = useAuth();
|
||||
const [head, setHead] = useState<LocationHead>(initial.substring(0, 2) as LocationHead);
|
||||
const [body, setBody] = useState<string>(initial.substring(3));
|
||||
|
@ -40,7 +42,6 @@ function DlgChangeLocation({ hideWindow, initial, onChangeLocation }: DlgChangeL
|
|||
header='Изменение расположения'
|
||||
submitText='Переместить'
|
||||
submitInvalidTooltip={`Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.location_len}`}
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={isValid}
|
||||
onSubmit={() => onChangeLocation(location)}
|
||||
className={clsx('w-[35rem]', 'pb-3 px-6 flex gap-3 h-[9rem]')}
|
||||
|
|
|
@ -12,7 +12,7 @@ import SelectLocationHead from '@/components/select/SelectLocationHead';
|
|||
import Checkbox from '@/components/ui/Checkbox';
|
||||
import Label from '@/components/ui/Label';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import TextArea from '@/components/ui/TextArea';
|
||||
import TextInput from '@/components/ui/TextInput';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
|
@ -21,18 +21,23 @@ import { useConceptNavigation } from '@/context/NavigationContext';
|
|||
import { AccessPolicy, ILibraryItem, LocationHead } from '@/models/library';
|
||||
import { cloneTitle, combineLocation, validateLocation } from '@/models/libraryAPI';
|
||||
import { ConstituentaID, IRSFormCloneData } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { information } from '@/utils/labels';
|
||||
|
||||
interface DlgCloneLibraryItemProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgCloneLibraryItemProps {
|
||||
base: ILibraryItem;
|
||||
initialLocation: string;
|
||||
selected: ConstituentaID[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
function DlgCloneLibraryItem({ hideWindow, base, initialLocation, selected, totalCount }: DlgCloneLibraryItemProps) {
|
||||
function DlgCloneLibraryItem() {
|
||||
const { base, initialLocation, selected, totalCount } = useDialogsStore(
|
||||
state => state.props as DlgCloneLibraryItemProps
|
||||
);
|
||||
const router = useConceptNavigation();
|
||||
const { user } = useAuth();
|
||||
|
||||
const [title, setTitle] = useState(cloneTitle(base));
|
||||
const [alias, setAlias] = useState(base.alias);
|
||||
const [comment, setComment] = useState(base.comment);
|
||||
|
@ -77,7 +82,6 @@ function DlgCloneLibraryItem({ hideWindow, base, initialLocation, selected, tota
|
|||
return (
|
||||
<Modal
|
||||
header='Создание копии концептуальной схемы'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={canSubmit}
|
||||
submitText='Создать'
|
||||
onSubmit={handleSubmit}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export { default } from './DlgConstituentaTemplate';
|
|
@ -2,20 +2,22 @@
|
|||
|
||||
import { useState } from 'react';
|
||||
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import usePartialUpdate from '@/hooks/usePartialUpdate';
|
||||
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
|
||||
import { generateAlias } from '@/models/rsformAPI';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
import FormCreateCst from './FormCreateCst';
|
||||
|
||||
interface DlgCreateCstProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgCreateCstProps {
|
||||
initial?: ICstCreateData;
|
||||
schema: IRSForm;
|
||||
onCreate: (data: ICstCreateData) => void;
|
||||
}
|
||||
|
||||
function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstProps) {
|
||||
function DlgCreateCst() {
|
||||
const { initial, schema, onCreate } = useDialogsStore(state => state.props as DlgCreateCstProps);
|
||||
const [validated, setValidated] = useState(false);
|
||||
const [cstData, updateCstData] = usePartialUpdate(
|
||||
initial || {
|
||||
|
@ -35,7 +37,6 @@ function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstPro
|
|||
return (
|
||||
<Modal
|
||||
header='Создание конституенты'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={validated}
|
||||
onSubmit={handleSubmit}
|
||||
submitText='Создать'
|
||||
|
|
|
@ -10,13 +10,13 @@ import { useLibrary } from '@/context/LibraryContext';
|
|||
import { LibraryItemID } from '@/models/library';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { IOperationCreateData, IOperationSchema, OperationID, OperationType } from '@/models/oss';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { describeOperationType, labelOperationType } from '@/utils/labels';
|
||||
|
||||
import TabInputOperation from './TabInputOperation';
|
||||
import TabSynthesisOperation from './TabSynthesisOperation';
|
||||
|
||||
interface DlgCreateOperationProps {
|
||||
hideWindow: () => void;
|
||||
export interface DlgCreateOperationProps {
|
||||
oss: IOperationSchema;
|
||||
onCreate: (data: IOperationCreateData) => void;
|
||||
initialInputs: OperationID[];
|
||||
|
@ -27,7 +27,8 @@ export enum TabID {
|
|||
SYNTHESIS = 1
|
||||
}
|
||||
|
||||
function DlgCreateOperation({ hideWindow, oss, onCreate, initialInputs }: DlgCreateOperationProps) {
|
||||
function DlgCreateOperation() {
|
||||
const { oss, onCreate, initialInputs } = useDialogsStore(state => state.props as DlgCreateOperationProps);
|
||||
const library = useLibrary();
|
||||
const [activeTab, setActiveTab] = useState(initialInputs.length > 0 ? TabID.SYNTHESIS : TabID.INPUT);
|
||||
|
||||
|
@ -98,7 +99,6 @@ function DlgCreateOperation({ hideWindow, oss, onCreate, initialInputs }: DlgCre
|
|||
<Modal
|
||||
header='Создание операции'
|
||||
submitText='Создать'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={isValid}
|
||||
onSubmit={handleSubmit}
|
||||
className='w-[40rem] px-6 h-[32rem]'
|
||||
|
|
|
@ -4,21 +4,23 @@ import clsx from 'clsx';
|
|||
import { useState } from 'react';
|
||||
|
||||
import Checkbox from '@/components/ui/Checkbox';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import TextArea from '@/components/ui/TextArea';
|
||||
import TextInput from '@/components/ui/TextInput';
|
||||
import { IVersionCreateData, IVersionInfo } from '@/models/library';
|
||||
import { nextVersion } from '@/models/libraryAPI';
|
||||
import { ConstituentaID } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
interface DlgCreateVersionProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgCreateVersionProps {
|
||||
versions: IVersionInfo[];
|
||||
onCreate: (data: IVersionCreateData) => void;
|
||||
selected: ConstituentaID[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
function DlgCreateVersion({ hideWindow, versions, selected, totalCount, onCreate }: DlgCreateVersionProps) {
|
||||
function DlgCreateVersion() {
|
||||
const { versions, selected, totalCount, onCreate } = useDialogsStore(state => state.props as DlgCreateVersionProps);
|
||||
const [version, setVersion] = useState(versions.length > 0 ? nextVersion(versions[0].version) : '1.0.0');
|
||||
const [description, setDescription] = useState('');
|
||||
const [onlySelected, setOnlySelected] = useState(false);
|
||||
|
@ -39,7 +41,6 @@ function DlgCreateVersion({ hideWindow, versions, selected, totalCount, onCreate
|
|||
return (
|
||||
<Modal
|
||||
header='Создание версии'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={canSubmit}
|
||||
onSubmit={handleSubmit}
|
||||
submitText='Создать'
|
||||
|
|
|
@ -4,7 +4,7 @@ import clsx from 'clsx';
|
|||
import { useEffect, useState } from 'react';
|
||||
import { TabList, TabPanel, Tabs } from 'react-tabs';
|
||||
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import TabLabel from '@/components/ui/TabLabel';
|
||||
import { useLibrary } from '@/context/LibraryContext';
|
||||
import usePartialUpdate from '@/hooks/usePartialUpdate';
|
||||
|
@ -12,13 +12,14 @@ import { HelpTopic } from '@/models/miscellaneous';
|
|||
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
|
||||
import { generateAlias, validateNewAlias } from '@/models/rsformAPI';
|
||||
import { inferTemplatedType, substituteTemplateArgs } from '@/models/rslangAPI';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { prompts } from '@/utils/labels';
|
||||
|
||||
import FormCreateCst from '../DlgCreateCst/FormCreateCst';
|
||||
import TabArguments, { IArgumentsState } from './TabArguments';
|
||||
import TabTemplate, { ITemplateState } from './TabTemplate';
|
||||
|
||||
interface DlgConstituentaTemplateProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgCstTemplateProps {
|
||||
schema: IRSForm;
|
||||
onCreate: (data: ICstCreateData) => void;
|
||||
insertAfter?: number;
|
||||
|
@ -30,7 +31,8 @@ export enum TabID {
|
|||
CONSTITUENTA = 2
|
||||
}
|
||||
|
||||
function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }: DlgConstituentaTemplateProps) {
|
||||
function DlgCstTemplate() {
|
||||
const { schema, onCreate, insertAfter } = useDialogsStore(state => state.props as DlgCstTemplateProps);
|
||||
const { retrieveTemplate } = useLibrary();
|
||||
const [activeTab, setActiveTab] = useState(TabID.TEMPLATE);
|
||||
|
||||
|
@ -128,7 +130,6 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
|
|||
header='Создание конституенты из шаблона'
|
||||
submitText='Создать'
|
||||
className='w-[43rem] h-[35rem] px-6'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={validated}
|
||||
beforeSubmit={handlePrompt}
|
||||
onSubmit={handleSubmit}
|
||||
|
@ -164,4 +165,4 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
|
|||
);
|
||||
}
|
||||
|
||||
export default DlgConstituentaTemplate;
|
||||
export default DlgCstTemplate;
|
1
rsconcept/frontend/src/dialogs/DlgCstTemplate/index.tsx
Normal file
1
rsconcept/frontend/src/dialogs/DlgCstTemplate/index.tsx
Normal file
|
@ -0,0 +1 @@
|
|||
export { default } from './DlgCstTemplate';
|
|
@ -4,19 +4,22 @@ import clsx from 'clsx';
|
|||
import { useState } from 'react';
|
||||
|
||||
import Checkbox from '@/components/ui/Checkbox';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import { ConstituentaID, IRSForm } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { prefixes } from '@/utils/constants';
|
||||
|
||||
import ListConstituents from './ListConstituents';
|
||||
|
||||
interface DlgDeleteCstProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgDeleteCstProps {
|
||||
schema: IRSForm;
|
||||
selected: ConstituentaID[];
|
||||
onDelete: (items: ConstituentaID[]) => void;
|
||||
}
|
||||
|
||||
function DlgDeleteCst({ hideWindow, selected, schema, onDelete }: DlgDeleteCstProps) {
|
||||
function DlgDeleteCst() {
|
||||
const { selected, schema, onDelete } = useDialogsStore(state => state.props as DlgDeleteCstProps);
|
||||
const hideDialog = useDialogsStore(state => state.hideDialog);
|
||||
const [expandOut, setExpandOut] = useState(false);
|
||||
const expansion: ConstituentaID[] = schema.graph.expandAllOutputs(selected);
|
||||
const hasInherited = selected.some(
|
||||
|
@ -25,7 +28,7 @@ function DlgDeleteCst({ hideWindow, selected, schema, onDelete }: DlgDeleteCstPr
|
|||
);
|
||||
|
||||
function handleSubmit() {
|
||||
hideWindow();
|
||||
hideDialog();
|
||||
if (expandOut) {
|
||||
onDelete(selected.concat(expansion));
|
||||
} else {
|
||||
|
@ -38,7 +41,6 @@ function DlgDeleteCst({ hideWindow, selected, schema, onDelete }: DlgDeleteCstPr
|
|||
canSubmit
|
||||
header='Удаление конституент'
|
||||
submitText={expandOut ? 'Удалить с зависимыми' : 'Удалить'}
|
||||
hideWindow={hideWindow}
|
||||
onSubmit={handleSubmit}
|
||||
className={clsx('cc-column', 'max-w-[60vw] min-w-[30rem]', 'px-6')}
|
||||
>
|
||||
|
|
|
@ -4,22 +4,24 @@ import clsx from 'clsx';
|
|||
import { useState } from 'react';
|
||||
|
||||
import Checkbox from '@/components/ui/Checkbox';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import TextInput from '@/components/ui/TextInput';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { IOperation } from '@/models/oss';
|
||||
import { IOperation, OperationID } from '@/models/oss';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
interface DlgDeleteOperationProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgDeleteOperationProps {
|
||||
target: IOperation;
|
||||
onSubmit: (keepConstituents: boolean, deleteSchema: boolean) => void;
|
||||
onSubmit: (targetID: OperationID, keepConstituents: boolean, deleteSchema: boolean) => void;
|
||||
}
|
||||
|
||||
function DlgDeleteOperation({ hideWindow, target, onSubmit }: DlgDeleteOperationProps) {
|
||||
function DlgDeleteOperation() {
|
||||
const { target, onSubmit } = useDialogsStore(state => state.props as DlgDeleteOperationProps);
|
||||
const [keepConstituents, setKeepConstituents] = useState(false);
|
||||
const [deleteSchema, setDeleteSchema] = useState(false);
|
||||
|
||||
function handleSubmit() {
|
||||
onSubmit(keepConstituents, deleteSchema);
|
||||
onSubmit(target.id, keepConstituents, deleteSchema);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -27,7 +29,6 @@ function DlgDeleteOperation({ hideWindow, target, onSubmit }: DlgDeleteOperation
|
|||
overflowVisible
|
||||
header='Удаление операции'
|
||||
submitText='Подтвердить удаление'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={true}
|
||||
onSubmit={handleSubmit}
|
||||
className={clsx('w-[35rem]', 'pb-3 px-6 cc-column', 'select-none')}
|
||||
|
|
|
@ -10,16 +10,17 @@ import MiniButton from '@/components/ui/MiniButton';
|
|||
import Modal from '@/components/ui/Modal';
|
||||
import { useUsers } from '@/context/UsersContext';
|
||||
import { UserID } from '@/models/user';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
import TableUsers from './TableUsers';
|
||||
|
||||
interface DlgEditEditorsProps {
|
||||
export interface DlgEditEditorsProps {
|
||||
editors: UserID[];
|
||||
setEditors: (newValue: UserID[]) => void;
|
||||
hideWindow: () => void;
|
||||
}
|
||||
|
||||
function DlgEditEditors({ hideWindow, editors, setEditors }: DlgEditEditorsProps) {
|
||||
function DlgEditEditors() {
|
||||
const { editors, setEditors } = useDialogsStore(state => state.props as DlgEditEditorsProps);
|
||||
const [selected, setSelected] = useState<UserID[]>(editors);
|
||||
const { users } = useUsers();
|
||||
const filtered = users.filter(user => !selected.includes(user.id));
|
||||
|
@ -41,7 +42,6 @@ function DlgEditEditors({ hideWindow, editors, setEditors }: DlgEditEditorsProps
|
|||
canSubmit
|
||||
header='Список редакторов'
|
||||
submitText='Сохранить список'
|
||||
hideWindow={hideWindow}
|
||||
className='flex flex-col w-[35rem] px-6 gap-3 pb-6'
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
|
|
|
@ -19,13 +19,13 @@ import {
|
|||
} from '@/models/oss';
|
||||
import { SubstitutionValidator } from '@/models/ossAPI';
|
||||
import { ConstituentaID } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
import TabArguments from './TabArguments';
|
||||
import TabOperation from './TabOperation';
|
||||
import TabSynthesis from './TabSynthesis';
|
||||
|
||||
interface DlgEditOperationProps {
|
||||
hideWindow: () => void;
|
||||
export interface DlgEditOperationProps {
|
||||
oss: IOperationSchema;
|
||||
target: IOperation;
|
||||
onSubmit: (data: IOperationUpdateData) => void;
|
||||
|
@ -37,7 +37,8 @@ export enum TabID {
|
|||
SUBSTITUTION = 2
|
||||
}
|
||||
|
||||
function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperationProps) {
|
||||
function DlgEditOperation() {
|
||||
const { oss, target, onSubmit } = useDialogsStore(state => state.props as DlgEditOperationProps);
|
||||
const [activeTab, setActiveTab] = useState(TabID.CARD);
|
||||
|
||||
const [alias, setAlias] = useState(target.alias);
|
||||
|
@ -142,7 +143,6 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
|||
<Modal
|
||||
header='Редактирование операции'
|
||||
submitText='Сохранить'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={canSubmit}
|
||||
onSubmit={handleSubmit}
|
||||
className='w-[40rem] px-6 h-[32rem]'
|
||||
|
|
|
@ -9,6 +9,7 @@ import TabLabel from '@/components/ui/TabLabel';
|
|||
import { ReferenceType } from '@/models/language';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { IRSForm } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { labelReferenceType } from '@/utils/labels';
|
||||
|
||||
import TabEntityReference from './TabEntityReference';
|
||||
|
@ -22,8 +23,7 @@ export interface IReferenceInputState {
|
|||
basePosition: number;
|
||||
}
|
||||
|
||||
interface DlgEditReferenceProps {
|
||||
hideWindow: () => void;
|
||||
export interface DlgEditReferenceProps {
|
||||
schema: IRSForm;
|
||||
initial: IReferenceInputState;
|
||||
onSave: (newRef: string) => void;
|
||||
|
@ -34,7 +34,8 @@ export enum TabID {
|
|||
SYNTACTIC = 1
|
||||
}
|
||||
|
||||
function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditReferenceProps) {
|
||||
function DlgEditReference() {
|
||||
const { schema, initial, onSave } = useDialogsStore(state => state.props as DlgEditReferenceProps);
|
||||
const [activeTab, setActiveTab] = useState(initial.type === ReferenceType.ENTITY ? TabID.ENTITY : TabID.SYNTACTIC);
|
||||
const [reference, setReference] = useState('');
|
||||
const [isValid, setIsValid] = useState(false);
|
||||
|
@ -43,7 +44,6 @@ function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditRefere
|
|||
<Modal
|
||||
header='Редактирование ссылки'
|
||||
submitText='Сохранить ссылку'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={isValid}
|
||||
onSubmit={() => onSave(reference)}
|
||||
className='w-[40rem] px-6 h-[32rem]'
|
||||
|
|
|
@ -7,21 +7,21 @@ import MiniButton from '@/components/ui/MiniButton';
|
|||
import Modal from '@/components/ui/Modal';
|
||||
import TextArea from '@/components/ui/TextArea';
|
||||
import TextInput from '@/components/ui/TextInput';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
import { IVersionData, IVersionInfo, VersionID } from '@/models/library';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
import TableVersions from './TableVersions';
|
||||
|
||||
interface DlgEditVersionsProps {
|
||||
hideWindow: () => void;
|
||||
export interface DlgEditVersionsProps {
|
||||
versions: IVersionInfo[];
|
||||
onDelete: (versionID: VersionID) => void;
|
||||
onUpdate: (versionID: VersionID, data: IVersionData) => void;
|
||||
}
|
||||
|
||||
function DlgEditVersions({ hideWindow, versions, onDelete, onUpdate }: DlgEditVersionsProps) {
|
||||
const { processing } = useRSForm();
|
||||
function DlgEditVersions() {
|
||||
const { versions, onDelete, onUpdate } = useDialogsStore(state => state.props as DlgEditVersionsProps);
|
||||
const [selected, setSelected] = useState<IVersionInfo | undefined>(undefined);
|
||||
const processing = false; // TODO: fix processing hook and versions update
|
||||
|
||||
const [version, setVersion] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
|
@ -54,12 +54,7 @@ function DlgEditVersions({ hideWindow, versions, onDelete, onUpdate }: DlgEditVe
|
|||
}, [selected]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
readonly
|
||||
header='Редактирование версий'
|
||||
hideWindow={hideWindow}
|
||||
className='flex flex-col w-[40rem] px-6 gap-3 pb-6'
|
||||
>
|
||||
<Modal readonly header='Редактирование версий' className='flex flex-col w-[40rem] px-6 gap-3 pb-6'>
|
||||
<TableVersions
|
||||
processing={processing}
|
||||
items={versions}
|
||||
|
|
|
@ -14,18 +14,19 @@ import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '@/models/lang
|
|||
import { parseGrammemes, wordFormEquals } from '@/models/languageAPI';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { IConstituenta, TermForm } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { prompts } from '@/utils/labels';
|
||||
import { IGrammemeOption, SelectorGrammemes, SelectorGrammemesList } from '@/utils/selectors';
|
||||
|
||||
import TableWordForms from './TableWordForms';
|
||||
|
||||
interface DlgEditWordFormsProps {
|
||||
hideWindow: () => void;
|
||||
export interface DlgEditWordFormsProps {
|
||||
target: IConstituenta;
|
||||
onSave: (data: TermForm[]) => void;
|
||||
}
|
||||
|
||||
function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps) {
|
||||
function DlgEditWordForms() {
|
||||
const { target, onSave } = useDialogsStore(state => state.props as DlgEditWordFormsProps);
|
||||
const textProcessor = useConceptText();
|
||||
|
||||
const [term, setTerm] = useState('');
|
||||
|
@ -123,7 +124,6 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
|
|||
<Modal
|
||||
canSubmit
|
||||
header='Редактирование словоформ'
|
||||
hideWindow={hideWindow}
|
||||
submitText='Сохранить'
|
||||
onSubmit={handleSubmit}
|
||||
className='flex flex-col w-[40rem] px-6'
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
'use client';
|
||||
|
||||
import Checkbox from '@/components/ui/Checkbox';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import usePartialUpdate from '@/hooks/usePartialUpdate';
|
||||
import { GraphFilterParams } from '@/models/miscellaneous';
|
||||
import { CstType } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { labelCstType } from '@/utils/labels';
|
||||
|
||||
interface DlgGraphParamsProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgGraphParamsProps {
|
||||
initial: GraphFilterParams;
|
||||
onConfirm: (params: GraphFilterParams) => void;
|
||||
}
|
||||
|
||||
function DlgGraphParams({ hideWindow, initial, onConfirm }: DlgGraphParamsProps) {
|
||||
function DlgGraphParams() {
|
||||
const { initial, onConfirm } = useDialogsStore(state => state.props as DlgGraphParamsProps);
|
||||
const [params, updateParams] = usePartialUpdate(initial);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
canSubmit
|
||||
hideWindow={hideWindow}
|
||||
header='Настройки графа термов'
|
||||
onSubmit={() => onConfirm(params)}
|
||||
submitText='Применить'
|
||||
|
|
|
@ -4,18 +4,19 @@ import clsx from 'clsx';
|
|||
import { useEffect, useState } from 'react';
|
||||
import { TabList, TabPanel, Tabs } from 'react-tabs';
|
||||
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import TabLabel from '@/components/ui/TabLabel';
|
||||
import useRSFormDetails from '@/hooks/useRSFormDetails';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { ICstSubstitute } from '@/models/oss';
|
||||
import { ConstituentaID, IInlineSynthesisData, IRSForm } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
import TabConstituents from './TabConstituents';
|
||||
import TabSchema from './TabSchema';
|
||||
import TabSubstitutions from './TabSubstitutions';
|
||||
|
||||
interface DlgInlineSynthesisProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgInlineSynthesisProps {
|
||||
receiver: IRSForm;
|
||||
onInlineSynthesis: (data: IInlineSynthesisData) => void;
|
||||
}
|
||||
|
@ -26,7 +27,8 @@ export enum TabID {
|
|||
SUBSTITUTIONS = 2
|
||||
}
|
||||
|
||||
function DlgInlineSynthesis({ hideWindow, receiver, onInlineSynthesis }: DlgInlineSynthesisProps) {
|
||||
function DlgInlineSynthesis() {
|
||||
const { receiver, onInlineSynthesis } = useDialogsStore(state => state.props as DlgInlineSynthesisProps);
|
||||
const [activeTab, setActiveTab] = useState(TabID.SCHEMA);
|
||||
|
||||
const [donorID, setDonorID] = useState<LibraryItemID | undefined>(undefined);
|
||||
|
@ -60,7 +62,6 @@ function DlgInlineSynthesis({ hideWindow, receiver, onInlineSynthesis }: DlgInli
|
|||
header='Импорт концептуальной схем'
|
||||
submitText='Добавить конституенты'
|
||||
className='w-[40rem] h-[33rem] px-6'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={validated}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { RelocateUpIcon } from '@/components/DomainIcons';
|
|||
import PickMultiConstituenta from '@/components/select/PickMultiConstituenta';
|
||||
import SelectLibraryItem from '@/components/select/SelectLibraryItem';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import DataLoader from '@/components/wrap/DataLoader';
|
||||
import { useLibrary } from '@/context/LibraryContext';
|
||||
import useRSFormDetails from '@/hooks/useRSFormDetails';
|
||||
|
@ -16,15 +16,17 @@ import { HelpTopic } from '@/models/miscellaneous';
|
|||
import { ICstRelocateData, IOperation, IOperationSchema } from '@/models/oss';
|
||||
import { getRelocateCandidates } from '@/models/ossAPI';
|
||||
import { ConstituentaID } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { prefixes } from '@/utils/constants';
|
||||
|
||||
interface DlgRelocateConstituentsProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgRelocateConstituentsProps {
|
||||
oss: IOperationSchema;
|
||||
initialTarget?: IOperation;
|
||||
onSubmit: (data: ICstRelocateData) => void;
|
||||
}
|
||||
|
||||
function DlgRelocateConstituents({ oss, hideWindow, initialTarget, onSubmit }: DlgRelocateConstituentsProps) {
|
||||
function DlgRelocateConstituents() {
|
||||
const { oss, initialTarget, onSubmit } = useDialogsStore(state => state.props as DlgRelocateConstituentsProps);
|
||||
const library = useLibrary();
|
||||
|
||||
const [directionUp, setDirectionUp] = useState(true);
|
||||
|
@ -88,7 +90,6 @@ function DlgRelocateConstituents({ oss, hideWindow, initialTarget, onSubmit }: D
|
|||
<Modal
|
||||
header='Перенос конституент'
|
||||
submitText='Переместить'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={isValid}
|
||||
onSubmit={handleSubmit}
|
||||
className={clsx('w-[40rem] h-[33rem]', 'py-3 px-6')}
|
||||
|
|
|
@ -3,25 +3,26 @@
|
|||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import SelectSingle from '@/components/ui/SelectSingle';
|
||||
import TextInput from '@/components/ui/TextInput';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
import usePartialUpdate from '@/hooks/usePartialUpdate';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { CstType, ICstRenameData } from '@/models/rsform';
|
||||
import { CstType, ICstRenameData, IRSForm } from '@/models/rsform';
|
||||
import { generateAlias, validateNewAlias } from '@/models/rsformAPI';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { labelCstType } from '@/utils/labels';
|
||||
import { SelectorCstType } from '@/utils/selectors';
|
||||
|
||||
interface DlgRenameCstProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgRenameCstProps {
|
||||
schema: IRSForm;
|
||||
initial: ICstRenameData;
|
||||
allowChangeType: boolean;
|
||||
onRename: (data: ICstRenameData) => void;
|
||||
}
|
||||
|
||||
function DlgRenameCst({ hideWindow, initial, allowChangeType, onRename }: DlgRenameCstProps) {
|
||||
const { schema } = useRSForm();
|
||||
function DlgRenameCst() {
|
||||
const { schema, initial, allowChangeType, onRename } = useDialogsStore(state => state.props as DlgRenameCstProps);
|
||||
const [validated, setValidated] = useState(false);
|
||||
const [cstData, updateData] = usePartialUpdate(initial);
|
||||
|
||||
|
@ -42,7 +43,6 @@ function DlgRenameCst({ hideWindow, initial, allowChangeType, onRename }: DlgRen
|
|||
header='Переименование конституенты'
|
||||
submitText='Переименовать'
|
||||
submitInvalidTooltip='Введите незанятое имя, соответствующее типу'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={validated}
|
||||
onSubmit={() => onRename(cstData)}
|
||||
className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex gap-3 justify-center items-center ')}
|
||||
|
|
|
@ -3,19 +3,21 @@
|
|||
import { useState } from 'react';
|
||||
import { ReactFlowProvider } from 'reactflow';
|
||||
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import Overlay from '@/components/ui/Overlay';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { SyntaxTree } from '@/models/rslang';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
import ASTFlow from './ASTFlow';
|
||||
|
||||
interface DlgShowASTProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgShowASTProps {
|
||||
syntaxTree: SyntaxTree;
|
||||
expression: string;
|
||||
}
|
||||
|
||||
function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) {
|
||||
function DlgShowAST() {
|
||||
const { syntaxTree, expression } = useDialogsStore(state => state.props as DlgShowASTProps);
|
||||
const [hoverID, setHoverID] = useState<number | undefined>(undefined);
|
||||
const hoverNode = syntaxTree.find(node => node.uid === hoverID);
|
||||
|
||||
|
@ -24,7 +26,6 @@ function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) {
|
|||
return (
|
||||
<Modal
|
||||
readonly
|
||||
hideWindow={hideWindow}
|
||||
className='flex flex-col justify-stretch w-[calc(100dvw-3rem)] h-[calc(100dvh-6rem)]'
|
||||
helpTopic={HelpTopic.UI_FORMULA_TREE}
|
||||
>
|
||||
|
|
|
@ -3,19 +3,17 @@
|
|||
import clsx from 'clsx';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
interface DlgShowQRProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgShowQRProps {
|
||||
target: string;
|
||||
}
|
||||
|
||||
function DlgShowQR({ hideWindow, target }: DlgShowQRProps) {
|
||||
function DlgShowQR() {
|
||||
const { target } = useDialogsStore(state => state.props as DlgShowQRProps);
|
||||
return (
|
||||
<Modal
|
||||
readonly
|
||||
hideWindow={hideWindow}
|
||||
className={clsx('w-[30rem]', 'py-12 pr-3 pl-6 flex gap-3 justify-center items-center')}
|
||||
>
|
||||
<Modal readonly className={clsx('w-[30rem]', 'py-12 pr-3 pl-6 flex gap-3 justify-center items-center')}>
|
||||
<div className='bg-[#ffffff] p-4 border'>
|
||||
<QRCodeSVG value={target} size={256} />
|
||||
</div>
|
||||
|
|
|
@ -3,19 +3,22 @@
|
|||
import { toast } from 'react-toastify';
|
||||
import { ReactFlowProvider } from 'reactflow';
|
||||
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { ITypeInfo } from '@/models/rslang';
|
||||
import { TMGraph } from '@/models/TMGraph';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { errors } from '@/utils/labels';
|
||||
|
||||
import MGraphFlow from './MGraphFlow';
|
||||
|
||||
interface DlgShowTypeGraphProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgShowTypeGraphProps {
|
||||
items: ITypeInfo[];
|
||||
}
|
||||
|
||||
function DlgShowTypeGraph({ hideWindow, items }: DlgShowTypeGraphProps) {
|
||||
function DlgShowTypeGraph() {
|
||||
const { items } = useDialogsStore(state => state.props as DlgShowTypeGraphProps);
|
||||
const hideDialog = useDialogsStore(state => state.hideDialog);
|
||||
const graph = (() => {
|
||||
const result = new TMGraph();
|
||||
items.forEach(item => result.addConstituenta(item.alias, item.result, item.args));
|
||||
|
@ -24,7 +27,7 @@ function DlgShowTypeGraph({ hideWindow, items }: DlgShowTypeGraphProps) {
|
|||
|
||||
if (graph.nodes.length === 0) {
|
||||
toast.error(errors.typeStructureFailed);
|
||||
hideWindow();
|
||||
hideDialog();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -32,7 +35,6 @@ function DlgShowTypeGraph({ hideWindow, items }: DlgShowTypeGraphProps) {
|
|||
<Modal
|
||||
header='Граф ступеней'
|
||||
readonly
|
||||
hideWindow={hideWindow}
|
||||
className='flex flex-col justify-stretch w-[calc(100dvw-3rem)] h-[calc(100dvh-6rem)]'
|
||||
helpTopic={HelpTopic.UI_TYPE_GRAPH}
|
||||
>
|
||||
|
|
|
@ -4,18 +4,20 @@ import clsx from 'clsx';
|
|||
import { useState } from 'react';
|
||||
|
||||
import PickSubstitutions from '@/components/select/PickSubstitutions';
|
||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { ICstSubstitute, ICstSubstituteData } from '@/models/oss';
|
||||
import { IRSForm } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { prefixes } from '@/utils/constants';
|
||||
|
||||
interface DlgSubstituteCstProps extends Pick<ModalProps, 'hideWindow'> {
|
||||
export interface DlgSubstituteCstProps {
|
||||
schema: IRSForm;
|
||||
onSubstitute: (data: ICstSubstituteData) => void;
|
||||
}
|
||||
|
||||
function DlgSubstituteCst({ hideWindow, onSubstitute, schema }: DlgSubstituteCstProps) {
|
||||
function DlgSubstituteCst() {
|
||||
const { onSubstitute, schema } = useDialogsStore(state => state.props as DlgSubstituteCstProps);
|
||||
const [substitutions, setSubstitutions] = useState<ICstSubstitute[]>([]);
|
||||
const canSubmit = substitutions.length > 0;
|
||||
|
||||
|
@ -31,7 +33,6 @@ function DlgSubstituteCst({ hideWindow, onSubstitute, schema }: DlgSubstituteCst
|
|||
header='Отождествление'
|
||||
submitText='Отождествить'
|
||||
submitInvalidTooltip='Выберите две различные конституенты'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={canSubmit}
|
||||
onSubmit={handleSubmit}
|
||||
className={clsx('w-[40rem]', 'px-6 pb-3')}
|
||||
|
|
|
@ -6,16 +6,16 @@ import { toast } from 'react-toastify';
|
|||
import Checkbox from '@/components/ui/Checkbox';
|
||||
import FileInput from '@/components/ui/FileInput';
|
||||
import Modal from '@/components/ui/Modal';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
import { IRSFormUploadData } from '@/models/rsform';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
||||
|
||||
interface DlgUploadRSFormProps {
|
||||
hideWindow: () => void;
|
||||
export interface DlgUploadRSFormProps {
|
||||
upload: (data: IRSFormUploadData, callback: () => void) => void;
|
||||
}
|
||||
|
||||
function DlgUploadRSForm({ hideWindow }: DlgUploadRSFormProps) {
|
||||
const { upload } = useRSForm();
|
||||
function DlgUploadRSForm() {
|
||||
const { upload } = useDialogsStore(state => state.props as DlgUploadRSFormProps);
|
||||
const [loadMetadata, setLoadMetadata] = useState(false);
|
||||
const [file, setFile] = useState<File | undefined>();
|
||||
|
||||
|
@ -42,7 +42,6 @@ function DlgUploadRSForm({ hideWindow }: DlgUploadRSFormProps) {
|
|||
return (
|
||||
<Modal
|
||||
header='Импорт схемы из Экстеора'
|
||||
hideWindow={hideWindow}
|
||||
canSubmit={!!file}
|
||||
onSubmit={handleSubmit}
|
||||
submitText='Загрузить'
|
||||
|
|
|
@ -224,3 +224,32 @@ export interface Position2D {
|
|||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents global dialog.
|
||||
*/
|
||||
export enum DialogType {
|
||||
CONSTITUENTA_TEMPLATE = 1,
|
||||
CREATE_CONSTITUENTA,
|
||||
CREATE_OPERATION,
|
||||
DELETE_CONSTITUENTA,
|
||||
EDIT_EDITORS,
|
||||
EDIT_OPERATION,
|
||||
EDIT_REFERENCE,
|
||||
EDIT_VERSIONS,
|
||||
EDIT_WORD_FORMS,
|
||||
INLINE_SYNTHESIS,
|
||||
SHOW_AST,
|
||||
SHOW_TYPE_GRAPH,
|
||||
CHANGE_INPUT_SCHEMA,
|
||||
CHANGE_LOCATION,
|
||||
CLONE_LIBRARY_ITEM,
|
||||
CREATE_VERSION,
|
||||
DELETE_OPERATION,
|
||||
GRAPH_PARAMETERS,
|
||||
RELOCATE_CONSTITUENTS,
|
||||
RENAME_CONSTITUENTA,
|
||||
SHOW_QR_CODE,
|
||||
SUBSTITUTE_CONSTITUENTS,
|
||||
UPLOAD_RSFORM
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import fileDownload from 'js-file-download';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { IconCSV } from '@/components/Icons';
|
||||
|
@ -9,9 +8,9 @@ import MiniButton from '@/components/ui/MiniButton';
|
|||
import Overlay from '@/components/ui/Overlay';
|
||||
import DataLoader from '@/components/wrap/DataLoader';
|
||||
import { useLibrary } from '@/context/LibraryContext';
|
||||
import DlgChangeLocation from '@/dialogs/DlgChangeLocation';
|
||||
import { IRenameLocationData } from '@/models/library';
|
||||
import { useAppLayoutStore } from '@/stores/appLayout';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { useLibraryFilter, useLibrarySearchStore } from '@/stores/librarySearch';
|
||||
import { information } from '@/utils/labels';
|
||||
import { convertToCSV } from '@/utils/utils';
|
||||
|
@ -31,10 +30,9 @@ function LibraryPage() {
|
|||
const filter = useLibraryFilter();
|
||||
const items = library.applyFilter(filter);
|
||||
|
||||
const [showRenameLocation, setShowRenameLocation] = useState(false);
|
||||
const showChangeLocation = useDialogsStore(state => state.showChangeLocation);
|
||||
|
||||
const handleRenameLocation = useCallback(
|
||||
(newLocation: string) => {
|
||||
function handleRenameLocation(newLocation: string) {
|
||||
const data: IRenameLocationData = {
|
||||
target: location,
|
||||
new_location: newLocation
|
||||
|
@ -43,11 +41,9 @@ function LibraryPage() {
|
|||
setLocation(newLocation);
|
||||
toast.success(information.locationRenamed);
|
||||
});
|
||||
},
|
||||
[location, setLocation, library]
|
||||
);
|
||||
}
|
||||
|
||||
const handleDownloadCSV = useCallback(() => {
|
||||
function handleDownloadCSV() {
|
||||
if (items.length === 0) {
|
||||
toast.error(information.noDataToExport);
|
||||
return;
|
||||
|
@ -58,17 +54,10 @@ function LibraryPage() {
|
|||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}, [items]);
|
||||
}
|
||||
|
||||
return (
|
||||
<DataLoader isLoading={library.loading} error={library.loadingError} hasNoData={library.items.length === 0}>
|
||||
{showRenameLocation ? (
|
||||
<DlgChangeLocation
|
||||
initial={location}
|
||||
onChangeLocation={handleRenameLocation}
|
||||
hideWindow={() => setShowRenameLocation(false)}
|
||||
/>
|
||||
) : null}
|
||||
<Overlay
|
||||
position={noNavigation ? 'top-[0.25rem] right-[3rem]' : 'top-[0.25rem] right-0'}
|
||||
layer='z-tooltip'
|
||||
|
@ -86,7 +75,7 @@ function LibraryPage() {
|
|||
<ViewSideLocation
|
||||
isVisible={folderMode}
|
||||
folderTree={library.folders}
|
||||
onRenameLocation={() => setShowRenameLocation(true)}
|
||||
onRenameLocation={() => showChangeLocation({ initial: location, onChangeLocation: handleRenameLocation })}
|
||||
/>
|
||||
|
||||
<TableLibraryItems items={items} />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { urls } from '@/app/urls';
|
||||
|
@ -8,13 +8,6 @@ import { useAuth } from '@/context/AuthContext';
|
|||
import { useLibrary } from '@/context/LibraryContext';
|
||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
||||
import { useOSS } from '@/context/OssContext';
|
||||
import DlgChangeInputSchema from '@/dialogs/DlgChangeInputSchema';
|
||||
import DlgChangeLocation from '@/dialogs/DlgChangeLocation';
|
||||
import DlgCreateOperation from '@/dialogs/DlgCreateOperation';
|
||||
import DlgDeleteOperation from '@/dialogs/DlgDeleteOperation';
|
||||
import DlgEditEditors from '@/dialogs/DlgEditEditors';
|
||||
import DlgEditOperation from '@/dialogs/DlgEditOperation';
|
||||
import DlgRelocateConstituents from '@/dialogs/DlgRelocateConstituents';
|
||||
import { AccessPolicy, ILibraryItemEditor, LibraryItemID } from '@/models/library';
|
||||
import { Position2D } from '@/models/miscellaneous';
|
||||
import { calculateInsertPosition } from '@/models/miscellaneousAPI';
|
||||
|
@ -30,6 +23,7 @@ import {
|
|||
OperationType
|
||||
} from '@/models/oss';
|
||||
import { UserID, UserRole } from '@/models/user';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { usePreferencesStore } from '@/stores/preferences';
|
||||
import { useRoleStore } from '@/stores/role';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
|
@ -106,24 +100,18 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
|
||||
const [showTooltip, setShowTooltip] = useState(true);
|
||||
|
||||
const [showEditEditors, setShowEditEditors] = useState(false);
|
||||
const [showEditLocation, setShowEditLocation] = useState(false);
|
||||
const [showEditInput, setShowEditInput] = useState(false);
|
||||
const [showEditOperation, setShowEditOperation] = useState(false);
|
||||
const [showDeleteOperation, setShowDeleteOperation] = useState(false);
|
||||
const [showRelocateConstituents, setShowRelocateConstituents] = useState(false);
|
||||
|
||||
const [showCreateOperation, setShowCreateOperation] = useState(false);
|
||||
const [insertPosition, setInsertPosition] = useState<Position2D>({ x: 0, y: 0 });
|
||||
const [initialInputs, setInitialInputs] = useState<OperationID[]>([]);
|
||||
const [createCallback, setCreateCallback] = useState<((newID: OperationID) => void) | undefined>(undefined);
|
||||
|
||||
const showEditEditors = useDialogsStore(state => state.showEditEditors);
|
||||
const showEditLocation = useDialogsStore(state => state.showChangeLocation);
|
||||
const showEditInput = useDialogsStore(state => state.showChangeInputSchema);
|
||||
const showEditOperation = useDialogsStore(state => state.showEditOperation);
|
||||
const showDeleteOperation = useDialogsStore(state => state.showDeleteOperation);
|
||||
const showRelocateConstituents = useDialogsStore(state => state.showRelocateConstituents);
|
||||
const showCreateOperation = useDialogsStore(state => state.showCreateOperation);
|
||||
|
||||
const [positions, setPositions] = useState<IOperationPosition[]>([]);
|
||||
const [targetOperationID, setTargetOperationID] = useState<OperationID | undefined>(undefined);
|
||||
const targetOperation = useMemo(
|
||||
() => (targetOperationID ? model.schema?.operationByID.get(targetOperationID) : undefined),
|
||||
[model, targetOperationID]
|
||||
);
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
|
@ -146,14 +134,6 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model]
|
||||
);
|
||||
|
||||
const promptEditors = useCallback(() => {
|
||||
setShowEditEditors(true);
|
||||
}, []);
|
||||
|
||||
const promptLocation = useCallback(() => {
|
||||
setShowEditLocation(true);
|
||||
}, []);
|
||||
|
||||
const share = useCallback(() => {
|
||||
const currentRef = window.location.href;
|
||||
const url = currentRef.includes('?') ? currentRef + '&share' : currentRef + '?share';
|
||||
|
@ -177,7 +157,7 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model]
|
||||
);
|
||||
|
||||
const setEditors = useCallback(
|
||||
const handleSetEditors = useCallback(
|
||||
(newEditors: UserID[]) => {
|
||||
model.setEditors(newEditors, () => toast.success(information.changesSaved));
|
||||
},
|
||||
|
@ -212,17 +192,6 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model]
|
||||
);
|
||||
|
||||
const promptCreateOperation = useCallback(
|
||||
({ defaultX, defaultY, inputs, positions, callback }: ICreateOperationPrompt) => {
|
||||
setInsertPosition({ x: defaultX, y: defaultY });
|
||||
setInitialInputs(inputs);
|
||||
setPositions(positions);
|
||||
setCreateCallback(() => callback);
|
||||
setShowCreateOperation(true);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const handleCreateOperation = useCallback(
|
||||
(data: IOperationCreateData) => {
|
||||
const target = calculateInsertPosition(
|
||||
|
@ -245,12 +214,6 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model, positions, insertPosition, createCallback]
|
||||
);
|
||||
|
||||
const promptEditOperation = useCallback((target: OperationID, positions: IOperationPosition[]) => {
|
||||
setPositions(positions);
|
||||
setTargetOperationID(target);
|
||||
setShowEditOperation(true);
|
||||
}, []);
|
||||
|
||||
const handleEditOperation = useCallback(
|
||||
(data: IOperationUpdateData) => {
|
||||
data.positions = positions;
|
||||
|
@ -276,26 +239,17 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model]
|
||||
);
|
||||
|
||||
const promptDeleteOperation = useCallback((target: OperationID, positions: IOperationPosition[]) => {
|
||||
setPositions(positions);
|
||||
setTargetOperationID(target);
|
||||
setShowDeleteOperation(true);
|
||||
}, []);
|
||||
|
||||
const deleteOperation = useCallback(
|
||||
(keepConstituents: boolean, deleteSchema: boolean) => {
|
||||
if (!targetOperationID) {
|
||||
return;
|
||||
}
|
||||
const handleDeleteOperation = useCallback(
|
||||
(targetID: OperationID, keepConstituents: boolean, deleteSchema: boolean) => {
|
||||
const data: IOperationDeleteData = {
|
||||
target: targetOperationID,
|
||||
target: targetID,
|
||||
positions: positions,
|
||||
keep_constituents: keepConstituents,
|
||||
delete_schema: deleteSchema
|
||||
};
|
||||
model.deleteOperation(data, () => toast.success(information.operationDestroyed));
|
||||
},
|
||||
[model, targetOperationID, positions]
|
||||
[model, positions]
|
||||
);
|
||||
|
||||
const createInput = useCallback(
|
||||
|
@ -316,44 +270,18 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model, library.items, router]
|
||||
);
|
||||
|
||||
const promptEditInput = useCallback((target: OperationID, positions: IOperationPosition[]) => {
|
||||
setPositions(positions);
|
||||
setTargetOperationID(target);
|
||||
setShowEditInput(true);
|
||||
}, []);
|
||||
|
||||
const setTargetInput = useCallback(
|
||||
(newInput: LibraryItemID | undefined) => {
|
||||
if (!targetOperationID) {
|
||||
return;
|
||||
}
|
||||
(target: OperationID, newInput: LibraryItemID | undefined) => {
|
||||
const data: IOperationSetInputData = {
|
||||
target: targetOperationID,
|
||||
target: target,
|
||||
positions: positions,
|
||||
input: newInput ?? null
|
||||
};
|
||||
model.setInput(data, () => toast.success(information.changesSaved));
|
||||
},
|
||||
[model, targetOperationID, positions]
|
||||
[model, positions]
|
||||
);
|
||||
|
||||
const executeOperation = useCallback(
|
||||
(target: OperationID, positions: IOperationPosition[]) => {
|
||||
const data = {
|
||||
target: target,
|
||||
positions: positions
|
||||
};
|
||||
model.executeOperation(data, () => toast.success(information.operationExecuted));
|
||||
},
|
||||
[model]
|
||||
);
|
||||
|
||||
const promptRelocateConstituents = useCallback((target: OperationID | undefined, positions: IOperationPosition[]) => {
|
||||
setPositions(positions);
|
||||
setTargetOperationID(target);
|
||||
setShowRelocateConstituents(true);
|
||||
}, []);
|
||||
|
||||
const handleRelocateConstituents = useCallback(
|
||||
(data: ICstRelocateData) => {
|
||||
if (
|
||||
|
@ -372,6 +300,92 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model, positions]
|
||||
);
|
||||
|
||||
const executeOperation = useCallback(
|
||||
(target: OperationID, positions: IOperationPosition[]) => {
|
||||
const data = {
|
||||
target: target,
|
||||
positions: positions
|
||||
};
|
||||
model.executeOperation(data, () => toast.success(information.operationExecuted));
|
||||
},
|
||||
[model]
|
||||
);
|
||||
|
||||
const promptEditors = useCallback(() => {
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
showEditEditors({ editors: model.schema.editors, setEditors: handleSetEditors });
|
||||
}, [model.schema, showEditEditors, handleSetEditors]);
|
||||
|
||||
const promptLocation = useCallback(() => {
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
showEditLocation({ initial: model.schema.location, onChangeLocation: handleSetLocation });
|
||||
}, [model.schema, showEditLocation, handleSetLocation]);
|
||||
|
||||
const promptCreateOperation = useCallback(
|
||||
({ defaultX, defaultY, inputs, positions, callback }: ICreateOperationPrompt) => {
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
setInsertPosition({ x: defaultX, y: defaultY });
|
||||
setPositions(positions);
|
||||
setCreateCallback(() => callback);
|
||||
showCreateOperation({ oss: model.schema, onCreate: handleCreateOperation, initialInputs: inputs });
|
||||
},
|
||||
[model.schema, showCreateOperation, handleCreateOperation]
|
||||
);
|
||||
|
||||
const promptEditOperation = useCallback(
|
||||
(target: OperationID, positions: IOperationPosition[]) => {
|
||||
const operation = model.schema?.operationByID.get(target);
|
||||
if (!model.schema || !operation) {
|
||||
return;
|
||||
}
|
||||
setPositions(positions);
|
||||
showEditOperation({ oss: model.schema, target: operation, onSubmit: handleEditOperation });
|
||||
},
|
||||
[model.schema, showEditOperation, handleEditOperation]
|
||||
);
|
||||
|
||||
const promptDeleteOperation = useCallback(
|
||||
(target: OperationID, positions: IOperationPosition[]) => {
|
||||
const operation = model.schema?.operationByID.get(target);
|
||||
if (!model.schema || !operation) {
|
||||
return;
|
||||
}
|
||||
setPositions(positions);
|
||||
showDeleteOperation({ target: operation, onSubmit: handleDeleteOperation });
|
||||
},
|
||||
[model.schema, showDeleteOperation, handleDeleteOperation]
|
||||
);
|
||||
|
||||
const promptEditInput = useCallback(
|
||||
(target: OperationID, positions: IOperationPosition[]) => {
|
||||
const operation = model.schema?.operationByID.get(target);
|
||||
if (!model.schema || !operation) {
|
||||
return;
|
||||
}
|
||||
setPositions(positions);
|
||||
showEditInput({ oss: model.schema, target: operation, onSubmit: setTargetInput });
|
||||
},
|
||||
[model.schema, showEditInput, setTargetInput]
|
||||
);
|
||||
|
||||
const promptRelocateConstituents = useCallback(
|
||||
(target: OperationID | undefined, positions: IOperationPosition[]) => {
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
const operation = target ? model.schema?.operationByID.get(target) : undefined;
|
||||
setPositions(positions);
|
||||
showRelocateConstituents({ oss: model.schema, initialTarget: operation, onSubmit: handleRelocateConstituents });
|
||||
},
|
||||
[model.schema, showRelocateConstituents, handleRelocateConstituents]
|
||||
);
|
||||
|
||||
return (
|
||||
<OssEditContext
|
||||
value={{
|
||||
|
@ -405,64 +419,6 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
promptRelocateConstituents
|
||||
}}
|
||||
>
|
||||
{model.schema ? (
|
||||
<>
|
||||
{showEditEditors ? (
|
||||
<DlgEditEditors
|
||||
hideWindow={() => setShowEditEditors(false)}
|
||||
editors={model.schema.editors}
|
||||
setEditors={setEditors}
|
||||
/>
|
||||
) : null}
|
||||
{showEditLocation ? (
|
||||
<DlgChangeLocation
|
||||
hideWindow={() => setShowEditLocation(false)}
|
||||
initial={model.schema.location}
|
||||
onChangeLocation={handleSetLocation}
|
||||
/>
|
||||
) : null}
|
||||
{showCreateOperation ? (
|
||||
<DlgCreateOperation
|
||||
hideWindow={() => setShowCreateOperation(false)}
|
||||
oss={model.schema}
|
||||
onCreate={handleCreateOperation}
|
||||
initialInputs={initialInputs}
|
||||
/>
|
||||
) : null}
|
||||
{showEditInput ? (
|
||||
<DlgChangeInputSchema
|
||||
hideWindow={() => setShowEditInput(false)}
|
||||
oss={model.schema}
|
||||
target={targetOperation!}
|
||||
onSubmit={setTargetInput}
|
||||
/>
|
||||
) : null}
|
||||
{showEditOperation ? (
|
||||
<DlgEditOperation
|
||||
hideWindow={() => setShowEditOperation(false)}
|
||||
oss={model.schema}
|
||||
target={targetOperation!}
|
||||
onSubmit={handleEditOperation}
|
||||
/>
|
||||
) : null}
|
||||
{showDeleteOperation ? (
|
||||
<DlgDeleteOperation
|
||||
hideWindow={() => setShowDeleteOperation(false)}
|
||||
target={targetOperation!}
|
||||
onSubmit={deleteOperation}
|
||||
/>
|
||||
) : null}
|
||||
{showRelocateConstituents ? (
|
||||
<DlgRelocateConstituents
|
||||
hideWindow={() => setShowRelocateConstituents(false)}
|
||||
initialTarget={targetOperation}
|
||||
oss={model.schema}
|
||||
onSubmit={handleRelocateConstituents}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{children}
|
||||
</OssEditContext>
|
||||
);
|
||||
|
|
|
@ -12,10 +12,10 @@ import Overlay from '@/components/ui/Overlay';
|
|||
import SubmitButton from '@/components/ui/SubmitButton';
|
||||
import TextArea from '@/components/ui/TextArea';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
import DlgShowTypeGraph from '@/dialogs/DlgShowTypeGraph';
|
||||
import { ConstituentaID, CstType, IConstituenta, ICstUpdateData } from '@/models/rsform';
|
||||
import { isBaseSet, isBasicConcept, isFunctional } from '@/models/rsformAPI';
|
||||
import { IExpressionParse, ParsingStatus } from '@/models/rslang';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { errors, information, labelCstTypification } from '@/utils/labels';
|
||||
|
||||
import EditorRSExpression from '../EditorRSExpression';
|
||||
|
@ -56,7 +56,6 @@ function FormConstituenta({
|
|||
const [expression, setExpression] = useState(state?.definition_formal ?? '');
|
||||
const [convention, setConvention] = useState(state?.convention ?? '');
|
||||
const [typification, setTypification] = useState('N/A');
|
||||
const [showTypification, setShowTypification] = useState(false);
|
||||
const [localParse, setLocalParse] = useState<IExpressionParse | undefined>(undefined);
|
||||
const typeInfo = state
|
||||
? {
|
||||
|
@ -72,6 +71,8 @@ function FormConstituenta({
|
|||
const isElementary = !!state && isBaseSet(state.cst_type);
|
||||
const showConvention = !state || !!state.convention || forceComment || isBasic;
|
||||
|
||||
const showTypification = useDialogsStore(state => state.showShowTypeGraph);
|
||||
|
||||
useEffect(() => {
|
||||
if (state) {
|
||||
setConvention(state.convention);
|
||||
|
@ -142,14 +143,11 @@ function FormConstituenta({
|
|||
}
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
setShowTypification(true);
|
||||
showTypification({ items: typeInfo ? [typeInfo] : [] });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='mx-0 md:mx-auto pt-[2rem] xs:pt-0'>
|
||||
{showTypification && state ? (
|
||||
<DlgShowTypeGraph items={typeInfo ? [typeInfo] : []} hideWindow={() => setShowTypification(false)} />
|
||||
) : null}
|
||||
{state ? (
|
||||
<ControlsOverlay
|
||||
disabled={disabled}
|
||||
|
|
|
@ -11,13 +11,13 @@ import { parser as rslangParser } from '@/components/RSInput/rslang/parserAST';
|
|||
import { RSTextWrapper } from '@/components/RSInput/textEditing';
|
||||
import Overlay from '@/components/ui/Overlay';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
import DlgShowAST from '@/dialogs/DlgShowAST';
|
||||
import useCheckConstituenta from '@/hooks/useCheckConstituenta';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { ConstituentaID, IConstituenta } from '@/models/rsform';
|
||||
import { getDefinitionPrefix } from '@/models/rsformAPI';
|
||||
import { IExpressionParse, IRSErrorDescription, SyntaxTree } from '@/models/rslang';
|
||||
import { IExpressionParse, IRSErrorDescription } from '@/models/rslang';
|
||||
import { TokenID } from '@/models/rslang';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { usePreferencesStore } from '@/stores/preferences';
|
||||
import { transformAST } from '@/utils/codemirror';
|
||||
import { errors, labelTypification } from '@/utils/labels';
|
||||
|
@ -64,9 +64,7 @@ function EditorRSExpression({
|
|||
const rsInput = useRef<ReactCodeMirrorRef>(null);
|
||||
|
||||
const showControls = usePreferencesStore(state => state.showExpressionControls);
|
||||
const [syntaxTree, setSyntaxTree] = useState<SyntaxTree>([]);
|
||||
const [expression, setExpression] = useState('');
|
||||
const [showAST, setShowAST] = useState(false);
|
||||
const showAST = useDialogsStore(state => state.showShowAST);
|
||||
|
||||
useEffect(() => {
|
||||
setIsModified(false);
|
||||
|
@ -131,17 +129,13 @@ function EditorRSExpression({
|
|||
if (event.ctrlKey) {
|
||||
const tree = rslangParser.parse(value);
|
||||
const ast = transformAST(tree);
|
||||
setSyntaxTree(ast);
|
||||
setExpression(value);
|
||||
setShowAST(true);
|
||||
showAST({ syntaxTree: ast, expression: value });
|
||||
} else {
|
||||
handleCheckExpression(parse => {
|
||||
if (!parse.astText) {
|
||||
toast.error(errors.astFailed);
|
||||
} else {
|
||||
setSyntaxTree(parse.ast);
|
||||
setExpression(getDefinitionPrefix(activeCst) + value);
|
||||
setShowAST(true);
|
||||
showAST({ syntaxTree: parse.ast, expression: getDefinitionPrefix(activeCst) + value });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -149,10 +143,6 @@ function EditorRSExpression({
|
|||
|
||||
return (
|
||||
<div className='cc-fade-in'>
|
||||
{showAST ? (
|
||||
<DlgShowAST expression={expression} syntaxTree={syntaxTree} hideWindow={() => setShowAST(false)} />
|
||||
) : null}
|
||||
|
||||
<ToolbarRSExpression disabled={disabled} showAST={handleShowAST} showTypeGraph={onShowTypeGraph} />
|
||||
|
||||
<Overlay
|
||||
|
|
|
@ -24,10 +24,10 @@ import SelectedCounter from '@/components/info/SelectedCounter';
|
|||
import { CProps } from '@/components/props';
|
||||
import ToolbarGraphSelection from '@/components/select/ToolbarGraphSelection';
|
||||
import Overlay from '@/components/ui/Overlay';
|
||||
import DlgGraphParams from '@/dialogs/DlgGraphParams';
|
||||
import { ConstituentaID, CstType, IConstituenta } from '@/models/rsform';
|
||||
import { isBasicConcept } from '@/models/rsformAPI';
|
||||
import { useMainHeight } from '@/stores/appLayout';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { useTermGraphStore } from '@/stores/termGraph';
|
||||
import { APP_COLORS, colorBgGraphNode } from '@/styling/color';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
|
@ -60,7 +60,7 @@ function TGFlow({ onOpenEdit }: TGFlowProps) {
|
|||
const store = useStoreApi();
|
||||
const { addSelectedNodes } = store.getState();
|
||||
|
||||
const [showParamsDialog, setShowParamsDialog] = useState(false);
|
||||
const showParams = useDialogsStore(state => state.showGraphParams);
|
||||
|
||||
const filter = useTermGraphStore(state => state.filter);
|
||||
const setFilter = useTermGraphStore(state => state.setFilter);
|
||||
|
@ -295,15 +295,11 @@ function TGFlow({ onOpenEdit }: TGFlowProps) {
|
|||
|
||||
return (
|
||||
<>
|
||||
{showParamsDialog ? (
|
||||
<DlgGraphParams hideWindow={() => setShowParamsDialog(false)} initial={filter} onConfirm={setFilter} />
|
||||
) : null}
|
||||
|
||||
<Overlay position='cc-tab-tools' className='flex flex-col items-center rounded-b-2xl cc-blur'>
|
||||
<ToolbarTermGraph
|
||||
noText={filter.noText}
|
||||
foldDerived={filter.foldDerived}
|
||||
showParamsDialog={() => setShowParamsDialog(true)}
|
||||
showParamsDialog={() => showParams({ initial: filter, onConfirm: setFilter })}
|
||||
onCreate={handleCreateCst}
|
||||
onDelete={handleDeleteCst}
|
||||
onFitView={() => setToggleResetView(prev => !prev)}
|
||||
|
|
|
@ -8,21 +8,6 @@ import { urls } from '@/app/urls';
|
|||
import { useAuth } from '@/context/AuthContext';
|
||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
import DlgChangeLocation from '@/dialogs/DlgChangeLocation';
|
||||
import DlgCloneLibraryItem from '@/dialogs/DlgCloneLibraryItem';
|
||||
import DlgConstituentaTemplate from '@/dialogs/DlgConstituentaTemplate';
|
||||
import DlgCreateCst from '@/dialogs/DlgCreateCst';
|
||||
import DlgCreateVersion from '@/dialogs/DlgCreateVersion';
|
||||
import DlgDeleteCst from '@/dialogs/DlgDeleteCst';
|
||||
import DlgEditEditors from '@/dialogs/DlgEditEditors';
|
||||
import DlgEditVersions from '@/dialogs/DlgEditVersions';
|
||||
import DlgEditWordForms from '@/dialogs/DlgEditWordForms';
|
||||
import DlgInlineSynthesis from '@/dialogs/DlgInlineSynthesis';
|
||||
import DlgRenameCst from '@/dialogs/DlgRenameCst';
|
||||
import DlgShowQR from '@/dialogs/DlgShowQR';
|
||||
import DlgShowTypeGraph from '@/dialogs/DlgShowTypeGraph';
|
||||
import DlgSubstituteCst from '@/dialogs/DlgSubstituteCst';
|
||||
import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm';
|
||||
import {
|
||||
AccessPolicy,
|
||||
ILibraryItemEditor,
|
||||
|
@ -49,6 +34,7 @@ import {
|
|||
} from '@/models/rsform';
|
||||
import { generateAlias } from '@/models/rsformAPI';
|
||||
import { UserID, UserRole } from '@/models/user';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { usePreferencesStore } from '@/stores/preferences';
|
||||
import { useRoleStore } from '@/stores/role';
|
||||
import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
||||
|
@ -161,27 +147,26 @@ export const RSEditState = ({
|
|||
[model.schema]
|
||||
);
|
||||
|
||||
const [showUpload, setShowUpload] = useState(false);
|
||||
const [showClone, setShowClone] = useState(false);
|
||||
const [showDeleteCst, setShowDeleteCst] = useState(false);
|
||||
const [showEditEditors, setShowEditEditors] = useState(false);
|
||||
const [showEditLocation, setShowEditLocation] = useState(false);
|
||||
const [showEditTerm, setShowEditTerm] = useState(false);
|
||||
const [showSubstitute, setShowSubstitute] = useState(false);
|
||||
const [showCreateVersion, setShowCreateVersion] = useState(false);
|
||||
const [showEditVersions, setShowEditVersions] = useState(false);
|
||||
const [showInlineSynthesis, setShowInlineSynthesis] = useState(false);
|
||||
const [showTypeGraph, setShowTypeGraph] = useState(false);
|
||||
const [showQR, setShowQR] = useState(false);
|
||||
|
||||
const [createInitialData, setCreateInitialData] = useState<ICstCreateData>();
|
||||
const [showCreateCst, setShowCreateCst] = useState(false);
|
||||
|
||||
const [renameInitialData, setRenameInitialData] = useState<ICstRenameData>();
|
||||
const [showRenameCst, setShowRenameCst] = useState(false);
|
||||
|
||||
const [insertCstID, setInsertCstID] = useState<ConstituentaID | undefined>(undefined);
|
||||
const [showTemplates, setShowTemplates] = useState(false);
|
||||
const showClone = useDialogsStore(state => state.showCloneLibraryItem);
|
||||
const showCreateVersion = useDialogsStore(state => state.showCreateVersion);
|
||||
const showEditVersions = useDialogsStore(state => state.showEditVersions);
|
||||
const showEditEditors = useDialogsStore(state => state.showEditEditors);
|
||||
const showEditLocation = useDialogsStore(state => state.showChangeLocation);
|
||||
|
||||
const showCreateCst = useDialogsStore(state => state.showCreateCst);
|
||||
const showDeleteCst = useDialogsStore(state => state.showDeleteCst);
|
||||
|
||||
const showRenameCst = useDialogsStore(state => state.showRenameCst);
|
||||
const showEditTerm = useDialogsStore(state => state.showEditWordForms);
|
||||
|
||||
const showSubstituteCst = useDialogsStore(state => state.showSubstituteCst);
|
||||
const showCstTemplate = useDialogsStore(state => state.showCstTemplate);
|
||||
const showInlineSynthesis = useDialogsStore(state => state.showInlineSynthesis);
|
||||
const showTypeGraph = useDialogsStore(state => state.showShowTypeGraph);
|
||||
const showUpload = useDialogsStore(state => state.showUploadRSForm);
|
||||
const showQR = useDialogsStore(state => state.showQR);
|
||||
|
||||
const typeInfo = useMemo(
|
||||
() =>
|
||||
|
@ -235,13 +220,6 @@ export const RSEditState = ({
|
|||
[router]
|
||||
);
|
||||
|
||||
const createVersion = useCallback(() => {
|
||||
if (isModified && !promptUnsaved()) {
|
||||
return;
|
||||
}
|
||||
setShowCreateVersion(true);
|
||||
}, [isModified]);
|
||||
|
||||
const restoreVersion = useCallback(() => {
|
||||
if (!model.versionID || !window.confirm(prompts.restoreArchive)) {
|
||||
return;
|
||||
|
@ -252,7 +230,7 @@ export const RSEditState = ({
|
|||
});
|
||||
}, [model, viewVersion]);
|
||||
|
||||
function calculateCloneLocation(): string {
|
||||
const calculateCloneLocation = useCallback(() => {
|
||||
if (!model.schema) {
|
||||
return LocationHead.USER;
|
||||
}
|
||||
|
@ -265,7 +243,7 @@ export const RSEditState = ({
|
|||
return location;
|
||||
}
|
||||
return head === LocationHead.USER ? LocationHead.USER : location;
|
||||
}
|
||||
}, [model.schema, user]);
|
||||
|
||||
const handleCreateCst = useCallback(
|
||||
(data: ICstCreateData) => {
|
||||
|
@ -397,6 +375,29 @@ export const RSEditState = ({
|
|||
[model, setSelected]
|
||||
);
|
||||
|
||||
const createVersion = useCallback(() => {
|
||||
if (!model.schema || (isModified && !promptUnsaved())) {
|
||||
return;
|
||||
}
|
||||
showCreateVersion({
|
||||
versions: model.schema.versions,
|
||||
onCreate: handleCreateVersion,
|
||||
selected: selected,
|
||||
totalCount: model.schema.items.length
|
||||
});
|
||||
}, [isModified, model.schema, selected, handleCreateVersion, showCreateVersion]);
|
||||
|
||||
const promptEditVersions = useCallback(() => {
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
showEditVersions({
|
||||
versions: model.schema.versions,
|
||||
onDelete: handleDeleteVersion,
|
||||
onUpdate: handleUpdateVersion
|
||||
});
|
||||
}, [model.schema, handleDeleteVersion, handleUpdateVersion, showEditVersions]);
|
||||
|
||||
const moveUp = useCallback(() => {
|
||||
if (!model.schema?.items || selected.length === 0) {
|
||||
return;
|
||||
|
@ -460,11 +461,10 @@ export const RSEditState = ({
|
|||
if (skipDialog) {
|
||||
handleCreateCst(data);
|
||||
} else {
|
||||
setCreateInitialData(data);
|
||||
setShowCreateCst(true);
|
||||
showCreateCst({ schema: model.schema, onCreate: handleCreateCst, initial: data });
|
||||
}
|
||||
},
|
||||
[activeCst, handleCreateCst, model.schema]
|
||||
[activeCst, handleCreateCst, model.schema, showCreateCst]
|
||||
);
|
||||
|
||||
const cloneCst = useCallback(() => {
|
||||
|
@ -485,7 +485,7 @@ export const RSEditState = ({
|
|||
}, [activeCst, handleCreateCst, model.schema]);
|
||||
|
||||
const renameCst = useCallback(() => {
|
||||
if (!activeCst) {
|
||||
if (!activeCst || !model.schema) {
|
||||
return;
|
||||
}
|
||||
const data: ICstRenameData = {
|
||||
|
@ -494,22 +494,34 @@ export const RSEditState = ({
|
|||
cst_type: activeCst.cst_type
|
||||
};
|
||||
setRenameInitialData(data);
|
||||
setShowRenameCst(true);
|
||||
}, [activeCst]);
|
||||
showRenameCst({
|
||||
schema: model.schema,
|
||||
initial: data,
|
||||
allowChangeType: !activeCst.is_inherited,
|
||||
onRename: handleRenameCst
|
||||
});
|
||||
}, [activeCst, model.schema, handleRenameCst, showRenameCst]);
|
||||
|
||||
const substitute = useCallback(() => {
|
||||
if (isModified && !promptUnsaved()) {
|
||||
if (!model.schema || (isModified && !promptUnsaved())) {
|
||||
return;
|
||||
}
|
||||
setShowSubstitute(true);
|
||||
}, [isModified]);
|
||||
showSubstituteCst({ schema: model.schema, onSubstitute: handleSubstituteCst });
|
||||
}, [isModified, model.schema, handleSubstituteCst, showSubstituteCst]);
|
||||
|
||||
const inlineSynthesis = useCallback(() => {
|
||||
if (isModified && !promptUnsaved()) {
|
||||
if (!model.schema || (isModified && !promptUnsaved())) {
|
||||
return;
|
||||
}
|
||||
setShowInlineSynthesis(true);
|
||||
}, [isModified]);
|
||||
showInlineSynthesis({ receiver: model.schema, onInlineSynthesis: handleInlineSynthesis });
|
||||
}, [isModified, model.schema, handleInlineSynthesis, showInlineSynthesis]);
|
||||
|
||||
const promptDeleteCst = useCallback(() => {
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
showDeleteCst({ schema: model.schema, selected: selected, onDelete: handleDeleteCst });
|
||||
}, [model.schema, selected, handleDeleteCst, showDeleteCst]);
|
||||
|
||||
const editTermForms = useCallback(() => {
|
||||
if (!activeCst) {
|
||||
|
@ -518,8 +530,8 @@ export const RSEditState = ({
|
|||
if (isModified && !promptUnsaved()) {
|
||||
return;
|
||||
}
|
||||
setShowEditTerm(true);
|
||||
}, [isModified, activeCst]);
|
||||
showEditTerm({ target: activeCst, onSave: handleSaveWordforms });
|
||||
}, [isModified, activeCst, handleSaveWordforms, showEditTerm]);
|
||||
|
||||
const reindex = useCallback(() => model.resetAliases(() => toast.success(information.reindexComplete)), [model]);
|
||||
const reorder = useCallback(() => model.restoreOrder(() => toast.success(information.reorderComplete)), [model]);
|
||||
|
@ -551,28 +563,45 @@ export const RSEditState = ({
|
|||
});
|
||||
}, [activeCst, setSelected, model, isModified]);
|
||||
|
||||
const setEditors = useCallback(
|
||||
(newEditors: UserID[]) => {
|
||||
model.setEditors(newEditors, () => toast.success(information.changesSaved));
|
||||
},
|
||||
[model]
|
||||
);
|
||||
|
||||
const promptTemplate = useCallback(() => {
|
||||
if (isModified && !promptUnsaved()) {
|
||||
if ((isModified && !promptUnsaved()) || !model.schema) {
|
||||
return;
|
||||
}
|
||||
setInsertCstID(activeCst?.id);
|
||||
setShowTemplates(true);
|
||||
}, [activeCst, isModified]);
|
||||
showCstTemplate({ schema: model.schema, onCreate: handleCreateCst, insertAfter: activeCst?.id });
|
||||
}, [activeCst, isModified, handleCreateCst, model.schema, showCstTemplate]);
|
||||
|
||||
const promptClone = useCallback(() => {
|
||||
if (isModified && !promptUnsaved()) {
|
||||
if (!model.schema || (isModified && !promptUnsaved())) {
|
||||
return;
|
||||
}
|
||||
setShowClone(true);
|
||||
}, [isModified]);
|
||||
showClone({
|
||||
base: model.schema,
|
||||
initialLocation: calculateCloneLocation(),
|
||||
selected: selected,
|
||||
totalCount: model.schema.items.length
|
||||
});
|
||||
}, [isModified, model.schema, selected, showClone, calculateCloneLocation]);
|
||||
|
||||
const promptEditors = useCallback(() => {
|
||||
setShowEditEditors(true);
|
||||
}, []);
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
showEditEditors({ editors: model.schema.editors, setEditors: setEditors });
|
||||
}, [model.schema, showEditEditors, setEditors]);
|
||||
|
||||
const promptLocation = useCallback(() => {
|
||||
setShowEditLocation(true);
|
||||
}, []);
|
||||
if (!model.schema) {
|
||||
return;
|
||||
}
|
||||
showEditLocation({ initial: model.schema.location, onChangeLocation: handleSetLocation });
|
||||
}, [model.schema, showEditLocation, handleSetLocation]);
|
||||
|
||||
const download = useCallback(() => {
|
||||
if (isModified && !promptUnsaved()) {
|
||||
|
@ -611,13 +640,6 @@ export const RSEditState = ({
|
|||
[model]
|
||||
);
|
||||
|
||||
const setEditors = useCallback(
|
||||
(newEditors: UserID[]) => {
|
||||
model.setEditors(newEditors, () => toast.success(information.changesSaved));
|
||||
},
|
||||
[model]
|
||||
);
|
||||
|
||||
function generateQR(): string {
|
||||
const currentRef = window.location.href;
|
||||
return currentRef.includes('?') ? currentRef + '&qr' : currentRef + '?qr';
|
||||
|
@ -653,19 +675,19 @@ export const RSEditState = ({
|
|||
viewPredecessor,
|
||||
createVersion,
|
||||
restoreVersion,
|
||||
promptEditVersions: () => setShowEditVersions(true),
|
||||
promptEditVersions,
|
||||
|
||||
moveUp,
|
||||
moveDown,
|
||||
createCst,
|
||||
cloneCst,
|
||||
renameCst,
|
||||
promptDeleteCst: () => setShowDeleteCst(true),
|
||||
promptDeleteCst,
|
||||
editTermForms,
|
||||
|
||||
promptTemplate,
|
||||
promptClone,
|
||||
promptUpload: () => setShowUpload(true),
|
||||
promptUpload: () => showUpload({ upload: model.upload }),
|
||||
download,
|
||||
share,
|
||||
|
||||
|
@ -675,113 +697,10 @@ export const RSEditState = ({
|
|||
produceStructure,
|
||||
substitute,
|
||||
|
||||
showTypeGraph: () => setShowTypeGraph(true),
|
||||
showQR: () => setShowQR(true)
|
||||
showTypeGraph: () => showTypeGraph({ items: typeInfo }),
|
||||
showQR: () => showQR({ target: generateQR() })
|
||||
}}
|
||||
>
|
||||
{model.schema ? (
|
||||
<>
|
||||
{showQR ? <DlgShowQR hideWindow={() => setShowQR(false)} target={generateQR()} /> : null}
|
||||
{showUpload ? <DlgUploadRSForm hideWindow={() => setShowUpload(false)} /> : null}
|
||||
{showClone ? (
|
||||
<DlgCloneLibraryItem
|
||||
base={model.schema}
|
||||
initialLocation={calculateCloneLocation()}
|
||||
hideWindow={() => setShowClone(false)}
|
||||
selected={selected}
|
||||
totalCount={model.schema.items.length}
|
||||
/>
|
||||
) : null}
|
||||
{showCreateCst ? (
|
||||
<DlgCreateCst
|
||||
hideWindow={() => setShowCreateCst(false)}
|
||||
onCreate={handleCreateCst}
|
||||
schema={model.schema}
|
||||
initial={createInitialData}
|
||||
/>
|
||||
) : null}
|
||||
{activeCst && showRenameCst && renameInitialData ? (
|
||||
<DlgRenameCst
|
||||
hideWindow={() => setShowRenameCst(false)}
|
||||
onRename={handleRenameCst}
|
||||
allowChangeType={!activeCst.is_inherited}
|
||||
initial={renameInitialData}
|
||||
/>
|
||||
) : null}
|
||||
{showSubstitute ? (
|
||||
<DlgSubstituteCst
|
||||
schema={model.schema}
|
||||
hideWindow={() => setShowSubstitute(false)} // prettier: split lines
|
||||
onSubstitute={handleSubstituteCst}
|
||||
/>
|
||||
) : null}
|
||||
{showDeleteCst ? (
|
||||
<DlgDeleteCst
|
||||
schema={model.schema}
|
||||
hideWindow={() => setShowDeleteCst(false)}
|
||||
onDelete={handleDeleteCst}
|
||||
selected={selected}
|
||||
/>
|
||||
) : null}
|
||||
{showEditTerm && activeCst ? (
|
||||
<DlgEditWordForms
|
||||
hideWindow={() => setShowEditTerm(false)}
|
||||
onSave={handleSaveWordforms}
|
||||
target={activeCst}
|
||||
/>
|
||||
) : null}
|
||||
{showTemplates ? (
|
||||
<DlgConstituentaTemplate
|
||||
schema={model.schema}
|
||||
hideWindow={() => setShowTemplates(false)}
|
||||
insertAfter={insertCstID}
|
||||
onCreate={handleCreateCst}
|
||||
/>
|
||||
) : null}
|
||||
{showCreateVersion ? (
|
||||
<DlgCreateVersion
|
||||
versions={model.schema.versions}
|
||||
hideWindow={() => setShowCreateVersion(false)}
|
||||
onCreate={handleCreateVersion}
|
||||
selected={selected}
|
||||
totalCount={model.schema.items.length}
|
||||
/>
|
||||
) : null}
|
||||
{showEditVersions ? (
|
||||
<DlgEditVersions
|
||||
versions={model.schema.versions}
|
||||
hideWindow={() => setShowEditVersions(false)}
|
||||
onDelete={handleDeleteVersion}
|
||||
onUpdate={handleUpdateVersion}
|
||||
/>
|
||||
) : null}
|
||||
{showEditEditors ? (
|
||||
<DlgEditEditors
|
||||
hideWindow={() => setShowEditEditors(false)}
|
||||
editors={model.schema.editors}
|
||||
setEditors={setEditors}
|
||||
/>
|
||||
) : null}
|
||||
{showEditLocation ? (
|
||||
<DlgChangeLocation
|
||||
hideWindow={() => setShowEditLocation(false)}
|
||||
initial={model.schema.location}
|
||||
onChangeLocation={handleSetLocation}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{showInlineSynthesis ? (
|
||||
<DlgInlineSynthesis
|
||||
receiver={model.schema}
|
||||
hideWindow={() => setShowInlineSynthesis(false)}
|
||||
onInlineSynthesis={handleInlineSynthesis}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{showTypeGraph ? <DlgShowTypeGraph items={typeInfo} hideWindow={() => setShowTypeGraph(false)} /> : null}
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{children}
|
||||
</RSEditContext>
|
||||
);
|
||||
|
|
86
rsconcept/frontend/src/stores/dialogs.ts
Normal file
86
rsconcept/frontend/src/stores/dialogs.ts
Normal file
|
@ -0,0 +1,86 @@
|
|||
import { create } from 'zustand';
|
||||
|
||||
import { DlgChangeInputSchemaProps } from '@/dialogs/DlgChangeInputSchema';
|
||||
import { DlgChangeLocationProps } from '@/dialogs/DlgChangeLocation';
|
||||
import { DlgCloneLibraryItemProps } from '@/dialogs/DlgCloneLibraryItem';
|
||||
import { DlgCreateCstProps } from '@/dialogs/DlgCreateCst/DlgCreateCst';
|
||||
import { DlgCreateOperationProps } from '@/dialogs/DlgCreateOperation/DlgCreateOperation';
|
||||
import { DlgCreateVersionProps } from '@/dialogs/DlgCreateVersion';
|
||||
import { DlgCstTemplateProps } from '@/dialogs/DlgCstTemplate/DlgCstTemplate';
|
||||
import { DlgDeleteCstProps } from '@/dialogs/DlgDeleteCst/DlgDeleteCst';
|
||||
import { DlgDeleteOperationProps } from '@/dialogs/DlgDeleteOperation';
|
||||
import { DlgEditEditorsProps } from '@/dialogs/DlgEditEditors/DlgEditEditors';
|
||||
import { DlgEditOperationProps } from '@/dialogs/DlgEditOperation/DlgEditOperation';
|
||||
import { DlgEditReferenceProps } from '@/dialogs/DlgEditReference/DlgEditReference';
|
||||
import { DlgEditVersionsProps } from '@/dialogs/DlgEditVersions/DlgEditVersions';
|
||||
import { DlgEditWordFormsProps } from '@/dialogs/DlgEditWordForms/DlgEditWordForms';
|
||||
import { DlgGraphParamsProps } from '@/dialogs/DlgGraphParams';
|
||||
import { DlgInlineSynthesisProps } from '@/dialogs/DlgInlineSynthesis/DlgInlineSynthesis';
|
||||
import { DlgRelocateConstituentsProps } from '@/dialogs/DlgRelocateConstituents';
|
||||
import { DlgRenameCstProps } from '@/dialogs/DlgRenameCst';
|
||||
import { DlgShowASTProps } from '@/dialogs/DlgShowAST/DlgShowAST';
|
||||
import { DlgShowQRProps } from '@/dialogs/DlgShowQR';
|
||||
import { DlgShowTypeGraphProps } from '@/dialogs/DlgShowTypeGraph/DlgShowTypeGraph';
|
||||
import { DlgSubstituteCstProps } from '@/dialogs/DlgSubstituteCst';
|
||||
import { DlgUploadRSFormProps } from '@/dialogs/DlgUploadRSForm';
|
||||
import { DialogType } from '@/models/miscellaneous';
|
||||
|
||||
interface DialogsStore {
|
||||
active: DialogType | undefined;
|
||||
props: unknown;
|
||||
hideDialog: () => void;
|
||||
|
||||
showCstTemplate: (props: DlgCstTemplateProps) => void;
|
||||
showCreateCst: (props: DlgCreateCstProps) => void;
|
||||
showCreateOperation: (props: DlgCreateOperationProps) => void;
|
||||
showDeleteCst: (props: DlgDeleteCstProps) => void;
|
||||
showEditEditors: (props: DlgEditEditorsProps) => void;
|
||||
showEditOperation: (props: DlgEditOperationProps) => void;
|
||||
showEditReference: (props: DlgEditReferenceProps) => void;
|
||||
showEditVersions: (props: DlgEditVersionsProps) => void;
|
||||
showEditWordForms: (props: DlgEditWordFormsProps) => void;
|
||||
showInlineSynthesis: (props: DlgInlineSynthesisProps) => void;
|
||||
showShowAST: (props: DlgShowASTProps) => void;
|
||||
showShowTypeGraph: (props: DlgShowTypeGraphProps) => void;
|
||||
showChangeInputSchema: (props: DlgChangeInputSchemaProps) => void;
|
||||
showChangeLocation: (props: DlgChangeLocationProps) => void;
|
||||
showCloneLibraryItem: (props: DlgCloneLibraryItemProps) => void;
|
||||
showCreateVersion: (props: DlgCreateVersionProps) => void;
|
||||
showDeleteOperation: (props: DlgDeleteOperationProps) => void;
|
||||
showGraphParams: (props: DlgGraphParamsProps) => void;
|
||||
showRelocateConstituents: (props: DlgRelocateConstituentsProps) => void;
|
||||
showRenameCst: (props: DlgRenameCstProps) => void;
|
||||
showQR: (props: DlgShowQRProps) => void;
|
||||
showSubstituteCst: (props: DlgSubstituteCstProps) => void;
|
||||
showUploadRSForm: (props: DlgUploadRSFormProps) => void;
|
||||
}
|
||||
|
||||
export const useDialogsStore = create<DialogsStore>()(set => ({
|
||||
active: undefined,
|
||||
props: undefined,
|
||||
hideDialog: () => set({ active: undefined, props: undefined }),
|
||||
|
||||
showCstTemplate: props => set({ active: DialogType.CONSTITUENTA_TEMPLATE, props: props }),
|
||||
showCreateCst: props => set({ active: DialogType.CREATE_CONSTITUENTA, props: props }),
|
||||
showCreateOperation: props => set({ active: DialogType.CREATE_OPERATION, props: props }),
|
||||
showDeleteCst: props => set({ active: DialogType.DELETE_CONSTITUENTA, props: props }),
|
||||
showEditEditors: props => set({ active: DialogType.EDIT_EDITORS, props: props }),
|
||||
showEditOperation: props => set({ active: DialogType.EDIT_OPERATION, props: props }),
|
||||
showEditReference: props => set({ active: DialogType.EDIT_REFERENCE, props: props }),
|
||||
showEditVersions: props => set({ active: DialogType.EDIT_VERSIONS, props: props }),
|
||||
showEditWordForms: props => set({ active: DialogType.EDIT_WORD_FORMS, props: props }),
|
||||
showInlineSynthesis: props => set({ active: DialogType.INLINE_SYNTHESIS, props: props }),
|
||||
showShowAST: props => set({ active: DialogType.SHOW_AST, props: props }),
|
||||
showShowTypeGraph: props => set({ active: DialogType.SHOW_TYPE_GRAPH, props: props }),
|
||||
showChangeInputSchema: props => set({ active: DialogType.CHANGE_INPUT_SCHEMA, props: props }),
|
||||
showChangeLocation: props => set({ active: DialogType.CHANGE_LOCATION, props: props }),
|
||||
showCloneLibraryItem: props => set({ active: DialogType.CLONE_LIBRARY_ITEM, props: props }),
|
||||
showCreateVersion: props => set({ active: DialogType.CREATE_VERSION, props: props }),
|
||||
showDeleteOperation: props => set({ active: DialogType.DELETE_OPERATION, props: props }),
|
||||
showGraphParams: props => set({ active: DialogType.GRAPH_PARAMETERS, props: props }),
|
||||
showRelocateConstituents: props => set({ active: DialogType.RELOCATE_CONSTITUENTS, props: props }),
|
||||
showRenameCst: props => set({ active: DialogType.RENAME_CONSTITUENTA, props: props }),
|
||||
showQR: props => set({ active: DialogType.SHOW_QR_CODE, props: props }),
|
||||
showSubstituteCst: props => set({ active: DialogType.SUBSTITUTE_CONSTITUENTS, props: props }),
|
||||
showUploadRSForm: props => set({ active: DialogType.UPLOAD_RSFORM, props: props })
|
||||
}));
|
Loading…
Reference in New Issue
Block a user