import { useLayoutEffect, useMemo, useState } from 'react'; import { toast } from 'react-toastify'; import ConceptTooltip from '../../components/Common/ConceptTooltip'; import Divider from '../../components/Common/Divider'; import MiniButton from '../../components/Common/MiniButton'; import SubmitButton from '../../components/Common/SubmitButton'; import TextArea from '../../components/Common/TextArea'; import CstStatusInfo from '../../components/Help/CstStatusInfo'; import { DumpBinIcon, HelpIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons'; import { useRSForm } from '../../context/RSFormContext'; import { type CstType, EditMode, ICstUpdateData, SyntaxTree } from '../../utils/models'; import { getCstTypeLabel, getCstTypificationLabel } from '../../utils/staticUI'; import EditorRSExpression from './EditorRSExpression'; import ViewSideConstituents from './elements/ViewSideConstituents'; // Max height of content for left enditor pane const UNFOLDED_HEIGHT = '59.1rem'; interface EditorConstituentaProps { activeID?: number onOpenEdit: (cstID: number) => void onShowAST: (expression: string, ast: SyntaxTree) => void onCreateCst: (selectedID: number | undefined, type: CstType | undefined) => void onDeleteCst: (selected: number[], callback?: (items: number[]) => void) => void } function EditorConstituenta({ activeID, onShowAST, onCreateCst, onOpenEdit, onDeleteCst }: EditorConstituentaProps) { const { schema, processing, isEditable, cstUpdate } = useRSForm(); const activeCst = useMemo( () => { return schema?.items?.find((cst) => cst.id === activeID); }, [schema?.items, activeID]); const [isModified, setIsModified] = useState(false); const [editMode, setEditMode] = useState(EditMode.TEXT); const [alias, setAlias] = useState(''); const [type, setType] = useState(''); const [term, setTerm] = useState(''); const [textDefinition, setTextDefinition] = useState(''); const [expression, setExpression] = useState(''); const [convention, setConvention] = useState(''); const [typification, setTypification] = useState('N/A'); const isEnabled = useMemo(() => activeCst && isEditable, [activeCst, isEditable]); useLayoutEffect(() => { if (!activeCst) { setIsModified(false); return; } setIsModified( activeCst.term.raw !== term || activeCst.definition.text.raw !== textDefinition || activeCst.convention !== convention || activeCst.definition.formal !== expression ); }, [activeCst, activeCst?.term, activeCst?.definition.formal, activeCst?.definition.text.raw, activeCst?.convention, term, textDefinition, expression, convention]); useLayoutEffect(() => { if (activeCst) { setAlias(activeCst.alias); setType(getCstTypeLabel(activeCst.cstType)); setConvention(activeCst.convention ?? ''); setTerm(activeCst.term?.raw ?? ''); setTextDefinition(activeCst.definition?.text?.raw ?? ''); setExpression(activeCst.definition?.formal ?? ''); setTypification(activeCst ? getCstTypificationLabel(activeCst) : 'N/A'); } else if (schema && schema?.items.length > 0) { onOpenEdit(schema.items[0].id); } }, [activeCst, onOpenEdit, schema]); function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (!activeID || processing) { return; } const data: ICstUpdateData = { id: activeID, alias: alias, convention: convention, definition_formal: expression, definition_raw: textDefinition, term_raw: term }; cstUpdate(data, () => { toast.success('Изменения сохранены'); }); } function handleDelete() { if (!schema || !activeID) { return; } onDeleteCst([activeID]); } function handleCreateCst() { if (!activeID || !schema) { return; } onCreateCst(activeID, activeCst?.cstType); } function handleRename() { toast.info('Переименование в разработке'); } function handleChangeType() { toast.info('Изменение типа в разработке'); } return (
{alias} {type}
} /> } />

Подсказки

Изменения сохраняются ПОСЛЕ нажатия на кнопку снизу или слева вверху

Клик на формальное выражение - обратите внимание на кнопки снизу.
Для каждой есть горячая клавиша в подсказке

Список конституент справа - обратите внимание на настройки фильтрации

- слева от ввода текста настраивается набор атрибутов конституенты

- справа от ввода текста настраивается список конституент, которые фильтруются

- текущая конституента выделена цветом строки

- двойной клик / Alt + клик - выбор редактируемой конституенты

- при наведении на ID конституенты отображаются ее атрибуты

- столбец "Описание" содержит один из непустых текстовых атрибутов