import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react'; import ConceptTooltip from '../../components/common/ConceptTooltip'; import Label from '../../components/common/Label'; import Modal from '../../components/common/Modal'; import SelectMulti from '../../components/common/SelectMulti'; import TextInput from '../../components/common/TextInput'; import HelpTerminologyControl from '../../components/Help/HelpTerminologyControl'; import { HelpIcon } from '../../components/Icons'; import ConstituentaPicker from '../../components/shared/ConstituentaPicker'; import { Grammeme, ReferenceType } from '../../models/language'; import { getCompatibleGrams, parseEntityReference, parseGrammemes, parseSyntacticReference } from '../../models/languageAPI'; import { CstMatchMode } from '../../models/miscelanious'; import { IConstituenta } from '../../models/rsform'; import { matchConstituenta } from '../../models/rsformAPI'; import { prefixes } from '../../utils/constants'; import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors'; import ReferenceTypeButton from './ReferenceTypeButton'; import WordformButton from './WordformButton'; export interface IReferenceInputState { type: ReferenceType refRaw?: string text?: string mainRefs: string[] basePosition: number } interface DlgEditReferenceProps { hideWindow: () => void items: IConstituenta[] initial: IReferenceInputState onSave: (newRef: string) => void } function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferenceProps) { const [type, setType] = useState(ReferenceType.ENTITY); const [nominal, setNominal] = useState(''); const [offset, setOffset] = useState(1); const [selectedCst, setSelectedCst] = useState(undefined); const [alias, setAlias] = useState(''); const [term, setTerm] = useState(''); const [selectedGrams, setSelectedGrams] = useState([]); const [gramOptions, setGramOptions] = useState([]); const mainLink = useMemo( () => { const position = offset > 0 ? initial.basePosition + (offset - 1) : initial.basePosition + offset; if (offset === 0 || position < 0 || position >= initial.mainRefs.length) { return 'Некорректное значение смещения'; } else { return initial.mainRefs[position]; } }, [initial, offset]); const isValid = useMemo( () => { if (type === ReferenceType.ENTITY) { return alias !== '' && selectedGrams.length > 0; } else if (type === ReferenceType.SYNTACTIC) { return nominal !== '' && offset !== 0; } else { return false; } }, [type, alias, selectedGrams, nominal, offset]); function produceReference(): string { if (type === ReferenceType.ENTITY) { return `@{${alias}|${selectedGrams.map(gram => gram.value).join(',')}}`; } else if (type === ReferenceType.SYNTACTIC) { return `@{${offset}|${nominal}}`; } else { return ''; } } // Initialization useLayoutEffect( () => { setType(initial.type); if (initial.refRaw) { if (initial.type === ReferenceType.ENTITY) { const ref = parseEntityReference(initial.refRaw); setAlias(ref.entity); const grams = parseGrammemes(ref.form); setSelectedGrams(SelectorGrammems.filter(data => grams.includes(data.value))); } else if (initial.type === ReferenceType.SYNTACTIC) { const ref = parseSyntacticReference(initial.refRaw); setOffset(ref.offset); setNominal(ref.nominal); } } else if (initial.text) { setNominal(initial.text ?? ''); } }, [initial, items]); // Filter grammemes when input changes useEffect( () => { const compatible = getCompatibleGrams( selectedGrams .filter(data => Object.values(Grammeme).includes(data.value as Grammeme)) .map(data => data.value as Grammeme) ); setGramOptions(SelectorGrammems.filter(({value}) => compatible.includes(value as Grammeme))); }, [selectedGrams]); // Update term when alias changes useEffect( () => { const cst = items.find(item => item.alias === alias) setTerm(cst?.term_resolved ?? '') }, [alias, term, items]); const handleSubmit = () => onSave(produceReference()); function handleSelectConstituenta(cst: IConstituenta) { setAlias(cst.alias); setSelectedCst(cst); } const handleSelectGrams = useCallback( (grams: Grammeme[]) => { setSelectedGrams(SelectorGrammems.filter(({value}) => grams.includes(value as Grammeme))); }, []); const FormButtons = useMemo(() => { return (
{PremadeWordForms.slice(0, 6).map( (data, index) => selectedGrams.find(item => item.value as Grammeme === gram))} onSelectGrams={handleSelectGrams} /> )}
{PremadeWordForms.slice(6, 12).map( (data, index) => selectedGrams.find(item => item.value as Grammeme === gram))} onSelectGrams={handleSelectGrams} /> )}
); }, [handleSelectGrams, selectedGrams]); return (
{type === ReferenceType.SYNTACTIC &&
setOffset(event.target.valueAsNumber)} />
Основная ссылка:
setNominal(event.target.value)} />
} {type === ReferenceType.ENTITY &&
cst.term_resolved} matchFunc={(cst, filter) => matchConstituenta(cst, filter, CstMatchMode.TERM)} prefilterFunc={cst => cst.term_resolved !== ''} rows={8} />
setAlias(event.target.value)} />
Термин:
{FormButtons}
}
); } export default DlgEditReference;