mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactor dialogs using partialUpdate hook for states
This commit is contained in:
parent
e1d82d4b3a
commit
90c8303ee7
|
@ -5,9 +5,10 @@ import SelectSingle from '../components/Common/SelectSingle';
|
|||
import TextArea from '../components/Common/TextArea';
|
||||
import TextInput from '../components/Common/TextInput';
|
||||
import RSInput from '../components/RSInput';
|
||||
import usePartialUpdate from '../hooks/usePartialUpdate';
|
||||
import { CstType,ICstCreateData, IRSForm } from '../models/rsform';
|
||||
import { labelCstType } from '../utils/labels';
|
||||
import { createAliasFor, getCstTypePrefix } from '../utils/misc';
|
||||
import { createAliasFor, validateCstAlias } from '../utils/misc';
|
||||
import { SelectorCstType } from '../utils/selectors';
|
||||
|
||||
interface DlgCreateCstProps
|
||||
|
@ -19,53 +20,31 @@ extends Pick<ModalProps, 'hideWindow'> {
|
|||
|
||||
function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstProps) {
|
||||
const [validated, setValidated] = useState(false);
|
||||
const [selectedType, setSelectedType] = useState<CstType>(CstType.BASE);
|
||||
const [alias, setAlias] = useState('');
|
||||
|
||||
const [term, setTerm] = useState('');
|
||||
const [textDefinition, setTextDefinition] = useState('');
|
||||
const [expression, setExpression] = useState('');
|
||||
const [convention, setConvention] = useState('');
|
||||
|
||||
function getData(): ICstCreateData {
|
||||
return {
|
||||
cst_type: selectedType,
|
||||
insert_after: initial?.insert_after ?? null,
|
||||
alias: alias,
|
||||
convention: convention,
|
||||
definition_formal: expression,
|
||||
definition_raw: textDefinition,
|
||||
term_raw: term,
|
||||
const [cstData, updateCstData] = usePartialUpdate(
|
||||
initial || {
|
||||
cst_type: CstType.BASE,
|
||||
insert_after: null,
|
||||
alias: '',
|
||||
convention: '',
|
||||
definition_formal: '',
|
||||
definition_raw: '',
|
||||
term_raw: '',
|
||||
term_forms: []
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const handleSubmit = () => onCreate(getData());
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (initial) {
|
||||
setSelectedType(initial.cst_type);
|
||||
setTerm(initial.term_raw);
|
||||
setTextDefinition(initial.definition_raw);
|
||||
setExpression(initial.definition_formal);
|
||||
setConvention(initial.convention);
|
||||
setAlias(initial.alias);
|
||||
}
|
||||
}, [initial]);
|
||||
const handleSubmit = () => onCreate(cstData);
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
setAlias(createAliasFor(selectedType, schema));
|
||||
}, [selectedType, schema]);
|
||||
updateCstData({ alias: createAliasFor(cstData.cst_type, schema) });
|
||||
}, [cstData.cst_type, updateCstData, schema]);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if(alias.length < 2 || alias[0] !== getCstTypePrefix(selectedType)) {
|
||||
setValidated(false);
|
||||
} else {
|
||||
setValidated(!schema.items.find(cst => cst.alias === alias))
|
||||
}
|
||||
}, [alias, selectedType, schema]);
|
||||
setValidated(validateCstAlias(cstData.alias, cstData.cst_type, schema));
|
||||
}, [cstData.alias, cstData.cst_type, schema]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
@ -81,43 +60,43 @@ function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstPro
|
|||
className='my-2 min-w-[15rem] self-center'
|
||||
options={SelectorCstType}
|
||||
placeholder='Выберите тип'
|
||||
value={selectedType ? { value: selectedType, label: labelCstType(selectedType) } : null}
|
||||
onChange={data => setSelectedType(data?.value ?? CstType.BASE)}
|
||||
value={{ value: cstData.cst_type, label: labelCstType(cstData.cst_type) }}
|
||||
onChange={data => updateCstData({ cst_type: data?.value ?? CstType.BASE})}
|
||||
/>
|
||||
<TextInput id='alias' label='Имя'
|
||||
dense
|
||||
dimensions='w-[7rem]'
|
||||
value={alias}
|
||||
onChange={event => setAlias(event.target.value)}
|
||||
value={cstData.alias}
|
||||
onChange={event => updateCstData({ alias: event.target.value})}
|
||||
/>
|
||||
</div>
|
||||
<TextArea id='term' label='Термин'
|
||||
placeholder='Схемный или предметный термин, обозначающий данное понятие или утверждение'
|
||||
rows={2}
|
||||
value={term}
|
||||
value={cstData.term_raw}
|
||||
spellCheck
|
||||
onChange={event => setTerm(event.target.value)}
|
||||
onChange={event => updateCstData({ term_raw: event.target.value })}
|
||||
/>
|
||||
<RSInput id='expression' label='Формальное выражение'
|
||||
placeholder='Родоструктурное выражение, задающее формальное определение'
|
||||
editable
|
||||
height='4.8rem'
|
||||
value={expression}
|
||||
onChange={value => setExpression(value)}
|
||||
value={cstData.definition_formal}
|
||||
onChange={value => updateCstData({definition_formal: value})}
|
||||
/>
|
||||
<TextArea id='definition' label='Текстовое определение'
|
||||
placeholder='Лингвистическая интерпретация формального выражения'
|
||||
rows={2}
|
||||
value={textDefinition}
|
||||
value={cstData.definition_raw}
|
||||
spellCheck
|
||||
onChange={event => setTextDefinition(event.target.value)}
|
||||
onChange={event => updateCstData({ definition_raw: event.target.value })}
|
||||
/>
|
||||
<TextArea id='convention' label='Конвенция / Комментарий'
|
||||
placeholder='Договоренность об интерпретации неопределяемого понятия
Комментарий к производному понятию'
|
||||
rows={2}
|
||||
value={convention}
|
||||
value={cstData.convention}
|
||||
spellCheck
|
||||
onChange={event => setConvention(event.target.value)}
|
||||
onChange={event => updateCstData({ convention: event.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { useLayoutEffect, useState } from 'react';
|
||||
|
||||
import Checkbox from '../components/Common/Checkbox';
|
||||
import Modal, { ModalProps } from '../components/Common/Modal';
|
||||
import usePartialUpdate from '../hooks/usePartialUpdate';
|
||||
import { GraphEditorParams } from '../models/miscelanious';
|
||||
import { CstType } from '../models/rsform';
|
||||
import { labelCstType } from '../utils/labels';
|
||||
|
@ -13,59 +12,13 @@ extends Pick<ModalProps, 'hideWindow'> {
|
|||
}
|
||||
|
||||
function DlgGraphOptions({ hideWindow, initial, onConfirm } : DlgGraphOptionsProps) {
|
||||
const [ noHermits, setNoHermits ] = useState(true);
|
||||
const [ noTransitive, setNoTransitive ] = useState(false);
|
||||
const [ noTemplates, setNoTemplates ] = useState(true);
|
||||
const [ noTerms, setNoTerms ] = useState(true);
|
||||
|
||||
const [ allowBase, setAllowBase ] = useState(true);
|
||||
const [ allowStruct, setAllowStruct ] = useState(true);
|
||||
const [ allowTerm, setAllowTerm ] = useState(true);
|
||||
const [ allowAxiom, setAllowAxiom ] = useState(true);
|
||||
const [ allowFunction, setAllowFunction ] = useState(true);
|
||||
const [ allowPredicate, setAllowPredicate ] = useState(true);
|
||||
const [ allowConstant, setAllowConstant ] = useState(true);
|
||||
const [ allowTheorem, setAllowTheorem ] = useState(true);
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
noHermits: noHermits,
|
||||
noTransitive: noTransitive,
|
||||
noTemplates: noTemplates,
|
||||
noTerms: noTerms,
|
||||
|
||||
allowBase: allowBase,
|
||||
allowStruct: allowStruct,
|
||||
allowTerm: allowTerm,
|
||||
allowAxiom: allowAxiom,
|
||||
allowFunction: allowFunction,
|
||||
allowPredicate: allowPredicate,
|
||||
allowConstant: allowConstant,
|
||||
allowTheorem: allowTheorem
|
||||
}
|
||||
}
|
||||
const [params, updateParams] = usePartialUpdate(initial);
|
||||
|
||||
const handleSubmit = () => {
|
||||
hideWindow();
|
||||
onConfirm(getParams());
|
||||
onConfirm(params);
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setNoHermits(initial.noHermits);
|
||||
setNoTransitive(initial.noTransitive);
|
||||
setNoTemplates(initial.noTemplates);
|
||||
setNoTerms(initial.noTerms);
|
||||
|
||||
setAllowBase(initial.allowBase);
|
||||
setAllowStruct(initial.allowStruct);
|
||||
setAllowTerm(initial.allowTerm);
|
||||
setAllowAxiom(initial.allowAxiom);
|
||||
setAllowFunction(initial.allowFunction);
|
||||
setAllowPredicate(initial.allowPredicate);
|
||||
setAllowConstant(initial.allowConstant);
|
||||
setAllowTheorem(initial.allowTheorem);
|
||||
}, [initial]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
hideWindow={hideWindow}
|
||||
|
@ -80,69 +33,69 @@ function DlgGraphOptions({ hideWindow, initial, onConfirm }:DlgGraphOptionsProps
|
|||
<Checkbox
|
||||
label='Скрыть текст'
|
||||
tooltip='Не отображать термины'
|
||||
value={noTerms}
|
||||
setValue={ value => setNoTerms(value) }
|
||||
value={params.noTerms}
|
||||
setValue={ value => updateParams({noTerms: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label='Скрыть несвязанные'
|
||||
tooltip='Неиспользуемые конституенты'
|
||||
value={noHermits}
|
||||
setValue={ value => setNoHermits(value) }
|
||||
value={params.noHermits}
|
||||
setValue={ value => updateParams({ noHermits: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label='Скрыть шаблоны'
|
||||
tooltip='Терм-функции и предикат-функции с параметризованными аргументами'
|
||||
value={noTemplates}
|
||||
setValue={ value => setNoTemplates(value) }
|
||||
value={params.noTemplates}
|
||||
setValue={ value => updateParams({ noTemplates: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label='Транзитивная редукция'
|
||||
tooltip='Удалить связи, образующие транзитивные пути в графе'
|
||||
value={noTransitive}
|
||||
setValue={ value => setNoTransitive(value) }
|
||||
value={params.noTransitive}
|
||||
setValue={ value => updateParams({ noTransitive: value}) }
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-col gap-1'>
|
||||
<h1>Типы конституент</h1>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.BASE)}
|
||||
value={allowBase}
|
||||
setValue={ value => setAllowBase(value) }
|
||||
value={params.allowBase}
|
||||
setValue={ value => updateParams({ allowBase: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.STRUCTURED)}
|
||||
value={allowStruct}
|
||||
setValue={ value => setAllowStruct(value) }
|
||||
value={params.allowStruct}
|
||||
setValue={ value => updateParams({ allowStruct: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.TERM)}
|
||||
value={allowTerm}
|
||||
setValue={ value => setAllowTerm(value) }
|
||||
value={params.allowTerm}
|
||||
setValue={ value => updateParams({ allowTerm: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.AXIOM)}
|
||||
value={allowAxiom}
|
||||
setValue={ value => setAllowAxiom(value) }
|
||||
value={params.allowAxiom}
|
||||
setValue={ value => updateParams({ allowAxiom: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.FUNCTION)}
|
||||
value={allowFunction}
|
||||
setValue={ value => setAllowFunction(value) }
|
||||
value={params.allowFunction}
|
||||
setValue={ value => updateParams({ allowFunction: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.PREDICATE)}
|
||||
value={allowPredicate}
|
||||
setValue={ value => setAllowPredicate(value) }
|
||||
value={params.allowPredicate}
|
||||
setValue={ value => updateParams({ allowPredicate: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.CONSTANT)}
|
||||
value={allowConstant}
|
||||
setValue={ value => setAllowConstant(value) }
|
||||
value={params.allowConstant}
|
||||
setValue={ value => updateParams({ allowConstant: value}) }
|
||||
/>
|
||||
<Checkbox
|
||||
label={labelCstType(CstType.THEOREM)}
|
||||
value={allowTheorem}
|
||||
setValue ={ value => setAllowTheorem(value) }
|
||||
value={params.allowTheorem}
|
||||
setValue ={ value => updateParams({ allowTheorem: value}) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,60 +4,40 @@ import Modal, { ModalProps } from '../components/Common/Modal';
|
|||
import SelectSingle from '../components/Common/SelectSingle';
|
||||
import TextInput from '../components/Common/TextInput';
|
||||
import { useRSForm } from '../context/RSFormContext';
|
||||
import usePartialUpdate from '../hooks/usePartialUpdate';
|
||||
import { CstType, ICstRenameData } from '../models/rsform';
|
||||
import { labelCstType } from '../utils/labels';
|
||||
import { createAliasFor, getCstTypePrefix } from '../utils/misc';
|
||||
import { createAliasFor, validateCstAlias } from '../utils/misc';
|
||||
import { SelectorCstType } from '../utils/selectors';
|
||||
|
||||
interface DlgRenameCstProps
|
||||
extends Pick<ModalProps, 'hideWindow'> {
|
||||
initial?: ICstRenameData
|
||||
initial: ICstRenameData
|
||||
onRename: (data: ICstRenameData) => void
|
||||
}
|
||||
|
||||
function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
||||
const { schema } = useRSForm();
|
||||
const [validated, setValidated] = useState(false);
|
||||
const [cstType, setCstType] = useState<CstType>(CstType.BASE);
|
||||
const [cstID, setCstID] = useState(0)
|
||||
const [alias, setAlias] = useState('');
|
||||
const [cstData, updateData] = usePartialUpdate(initial);
|
||||
|
||||
function getData(): ICstRenameData {
|
||||
return {
|
||||
cst_type: cstType,
|
||||
alias: alias,
|
||||
id: cstID
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = () => onRename(getData());
|
||||
const handleSubmit = () => onRename(cstData);
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
if (schema && initial && cstType !== initial.cst_type) {
|
||||
setAlias(createAliasFor(cstType, schema));
|
||||
if (schema && initial && cstData.cst_type !== initial.cst_type) {
|
||||
updateData({ alias: createAliasFor(cstData.cst_type, schema)});
|
||||
}
|
||||
}, [initial, cstType, schema]);
|
||||
}, [initial, cstData.cst_type, updateData, schema]);
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
if (initial) {
|
||||
setCstType(initial.cst_type);
|
||||
setAlias(initial.alias);
|
||||
setCstID(initial.id);
|
||||
}
|
||||
}, [initial]);
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
if (!initial || !schema) {
|
||||
setValidated(false);
|
||||
} else if(alias === initial.alias || alias.length < 2 || alias[0] !== getCstTypePrefix(cstType)) {
|
||||
setValidated(false);
|
||||
} else {
|
||||
setValidated(!schema.items.find(cst => cst.alias === alias))
|
||||
}
|
||||
}, [cstType, alias, initial, schema]);
|
||||
setValidated(
|
||||
!!schema &&
|
||||
cstData.alias !== initial.alias &&
|
||||
validateCstAlias(cstData.alias, cstData.cst_type, schema)
|
||||
);
|
||||
}, [cstData.cst_type, cstData.alias, initial, schema]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
@ -73,15 +53,15 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
|||
className='min-w-[14rem] self-center z-modal-top'
|
||||
options={SelectorCstType}
|
||||
placeholder='Выберите тип'
|
||||
value={cstType ? { value: cstType, label: labelCstType(cstType) } : null}
|
||||
onChange={data => setCstType(data?.value ?? CstType.BASE)}
|
||||
value={{ value: cstData.cst_type, label: labelCstType(cstData.cst_type) }}
|
||||
onChange={data => updateData({cst_type: data?.value ?? CstType.BASE})}
|
||||
/>
|
||||
<div>
|
||||
<TextInput id='alias' label='Имя'
|
||||
dense
|
||||
dimensions='w-[7rem]'
|
||||
value={alias}
|
||||
onChange={event => setAlias(event.target.value)}
|
||||
value={cstData.alias}
|
||||
onChange={event => updateData({alias: event.target.value})}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import { useEffect, useLayoutEffect, useState } from 'react';
|
||||
|
||||
import ConceptTooltip from '../components/Common/ConceptTooltip';
|
||||
import Modal, { ModalProps } from '../components/Common/Modal';
|
||||
import SelectSingle from '../components/Common/SelectSingle';
|
||||
import SwitchButton from '../components/Common/SwitchButton';
|
||||
import TextArea from '../components/Common/TextArea';
|
||||
import TextInput from '../components/Common/TextInput';
|
||||
import HelpRSTemplates from '../components/Help/HelpRSTemplates';
|
||||
import { HelpIcon } from '../components/Icons';
|
||||
import RSInput from '../components/RSInput';
|
||||
import { CstType,ICstCreateData, IRSForm } from '../models/rsform';
|
||||
import { labelCstType } from '../utils/labels';
|
||||
import { createAliasFor, getCstTypePrefix } from '../utils/misc';
|
||||
import { SelectorCstType } from '../utils/selectors';
|
||||
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
||||
import Modal, { ModalProps } from '../../components/Common/Modal';
|
||||
import SelectSingle from '../../components/Common/SelectSingle';
|
||||
import SwitchButton from '../../components/Common/SwitchButton';
|
||||
import TextArea from '../../components/Common/TextArea';
|
||||
import TextInput from '../../components/Common/TextInput';
|
||||
import HelpRSTemplates from '../../components/Help/HelpRSTemplates';
|
||||
import { HelpIcon } from '../../components/Icons';
|
||||
import RSInput from '../../components/RSInput';
|
||||
import usePartialUpdate from '../../hooks/usePartialUpdate';
|
||||
import { CstType,ICstCreateData, IRSForm } from '../../models/rsform';
|
||||
import { labelCstType } from '../../utils/labels';
|
||||
import { createAliasFor, validateCstAlias } from '../../utils/misc';
|
||||
import { SelectorCstType } from '../../utils/selectors';
|
||||
|
||||
interface DlgTemplatesProps
|
||||
extends Pick<ModalProps, 'hideWindow'> {
|
||||
|
@ -22,44 +23,30 @@ extends Pick<ModalProps, 'hideWindow'> {
|
|||
|
||||
function DlgTemplates({ hideWindow, schema, onCreate }: DlgTemplatesProps) {
|
||||
const [validated, setValidated] = useState(false);
|
||||
const [selectedType, setSelectedType] = useState<CstType>(CstType.TERM);
|
||||
const [alias, setAlias] = useState('');
|
||||
|
||||
const [term, setTerm] = useState('');
|
||||
const [textDefinition, setTextDefinition] = useState('');
|
||||
const [expression, setExpression] = useState('');
|
||||
const [convention, setConvention] = useState('');
|
||||
const [cstData, updateCstData] = usePartialUpdate({
|
||||
cst_type: CstType.TERM,
|
||||
insert_after: null,
|
||||
alias: '',
|
||||
convention: '',
|
||||
definition_formal: '',
|
||||
definition_raw: '',
|
||||
term_raw: '',
|
||||
term_forms: []
|
||||
});
|
||||
|
||||
const [ showAttributes, setShowAttributes ] = useState(false);
|
||||
|
||||
function getData(): ICstCreateData {
|
||||
return {
|
||||
cst_type: selectedType,
|
||||
insert_after: null,
|
||||
alias: alias,
|
||||
convention: convention,
|
||||
definition_formal: expression,
|
||||
definition_raw: textDefinition,
|
||||
term_raw: term,
|
||||
term_forms: []
|
||||
};
|
||||
}
|
||||
|
||||
const handleSubmit = () => onCreate(getData());
|
||||
const handleSubmit = () => onCreate(cstData);
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
setAlias(createAliasFor(selectedType, schema));
|
||||
}, [selectedType, schema]);
|
||||
updateCstData({ alias: createAliasFor(cstData.cst_type, schema) });
|
||||
}, [cstData.cst_type, updateCstData, schema]);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if(alias.length < 2 || alias[0] !== getCstTypePrefix(selectedType)) {
|
||||
setValidated(false);
|
||||
} else {
|
||||
setValidated(!schema.items.find(cst => cst.alias === alias))
|
||||
}
|
||||
}, [alias, selectedType, schema]);
|
||||
setValidated(validateCstAlias(cstData.alias, cstData.cst_type, schema));
|
||||
}, [cstData.alias, cstData.cst_type, schema]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
@ -111,43 +98,43 @@ function DlgTemplates({ hideWindow, schema, onCreate }: DlgTemplatesProps) {
|
|||
className='my-2 min-w-[15rem] self-center'
|
||||
options={SelectorCstType}
|
||||
placeholder='Выберите тип'
|
||||
value={selectedType ? { value: selectedType, label: labelCstType(selectedType) } : null}
|
||||
onChange={data => setSelectedType(data?.value ?? CstType.BASE)}
|
||||
value={{ value: cstData.cst_type, label: labelCstType(cstData.cst_type) }}
|
||||
onChange={data => updateCstData({ cst_type: data?.value ?? CstType.TERM})}
|
||||
/>
|
||||
<TextInput id='alias' label='Имя'
|
||||
dense
|
||||
dimensions='w-[7rem]'
|
||||
value={alias}
|
||||
onChange={event => setAlias(event.target.value)}
|
||||
value={cstData.alias}
|
||||
onChange={event => updateCstData({ alias: event.target.value})}
|
||||
/>
|
||||
</div>
|
||||
<TextArea id='term' label='Термин'
|
||||
placeholder='Схемный или предметный термин, обозначающий данное понятие или утверждение'
|
||||
rows={2}
|
||||
value={term}
|
||||
value={cstData.term_raw}
|
||||
spellCheck
|
||||
onChange={event => setTerm(event.target.value)}
|
||||
onChange={event => updateCstData({ term_raw: event.target.value })}
|
||||
/>
|
||||
<RSInput id='expression' label='Формальное выражение'
|
||||
placeholder='Родоструктурное выражение, задающее формальное определение'
|
||||
editable
|
||||
height='4.8rem'
|
||||
value={expression}
|
||||
onChange={value => setExpression(value)}
|
||||
value={cstData.definition_formal}
|
||||
onChange={value => updateCstData({definition_formal: value})}
|
||||
/>
|
||||
<TextArea id='definition' label='Текстовое определение'
|
||||
placeholder='Лингвистическая интерпретация формального выражения'
|
||||
rows={2}
|
||||
value={textDefinition}
|
||||
value={cstData.definition_raw}
|
||||
spellCheck
|
||||
onChange={event => setTextDefinition(event.target.value)}
|
||||
onChange={event => updateCstData({ definition_raw: event.target.value })}
|
||||
/>
|
||||
<TextArea id='convention' label='Конвенция / Комментарий'
|
||||
placeholder='Договоренность об интерпретации неопределяемого понятия
Комментарий к производному понятию'
|
||||
rows={2}
|
||||
value={convention}
|
||||
value={cstData.convention}
|
||||
spellCheck
|
||||
onChange={event => setConvention(event.target.value)}
|
||||
onChange={event => updateCstData({ convention: event.target.value })}
|
||||
/>
|
||||
</div>}
|
||||
</div>
|
15
rsconcept/frontend/src/hooks/usePartialUpdate.tsx
Normal file
15
rsconcept/frontend/src/hooks/usePartialUpdate.tsx
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { useReducer } from 'react';
|
||||
|
||||
function usePartialUpdate<ValueType>(initialValue: ValueType) {
|
||||
const [value, updateValue] = useReducer(
|
||||
(data: ValueType, newData: Partial<ValueType>) => ({
|
||||
...data,
|
||||
...newData,
|
||||
}),
|
||||
initialValue
|
||||
);
|
||||
|
||||
return [value, updateValue] as [ValueType, typeof updateValue];
|
||||
}
|
||||
|
||||
export default usePartialUpdate;
|
|
@ -360,7 +360,7 @@ function RSTabs() {
|
|||
<DlgRenameCst
|
||||
hideWindow={() => setShowRenameCst(false)}
|
||||
onRename={handleRenameCst}
|
||||
initial={renameInitialData}
|
||||
initial={renameInitialData!}
|
||||
/>}
|
||||
{showDeleteCst &&
|
||||
<DlgDeleteCst
|
||||
|
|
|
@ -19,6 +19,14 @@ export function getCstTypePrefix(type: CstType) {
|
|||
}
|
||||
}
|
||||
|
||||
export function validateCstAlias(alias: string, type: CstType, schema: IRSForm): boolean {
|
||||
return (
|
||||
alias.length >= 2 &&
|
||||
alias[0] == getCstTypePrefix(type) &&
|
||||
!schema.items.find(cst => cst.alias === alias)
|
||||
);
|
||||
}
|
||||
|
||||
export function getCstExpressionPrefix(cst: IConstituenta): string {
|
||||
return cst.alias + (cst.cst_type === CstType.STRUCTURED ? '::=' : ':==');
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user