import { createColumnHelper } from '@tanstack/react-table'; import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react'; import { useConceptTheme } from '../../context/ThemeContext'; import { getCompatibleGrams, Grammeme, parseEntityReference,parseGrammemes,parseSyntacticReference,ReferenceType } from '../../models/language'; import { CstMatchMode } from '../../models/miscelanious'; import { IConstituenta, matchConstituenta } from '../../models/rsform'; import ConstituentaTooltip from '../../pages/RSFormPage/elements/ConstituentaTooltip'; import { colorfgCstStatus } from '../../utils/color'; import { prefixes } from '../../utils/constants'; import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors'; import ConceptTooltip from '../Common/ConceptTooltip'; import Label from '../Common/Label'; import Modal from '../Common/Modal'; import SelectMulti from '../Common/SelectMulti'; import TextInput from '../Common/TextInput'; import DataTable, { IConditionalStyle } from '../DataTable'; import HelpTerminologyControl from '../Help/HelpTerminologyControl'; import { HelpIcon } from '../Icons'; 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 } const constituentaHelper = createColumnHelper(); function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferenceProps) { const { colors } = useConceptTheme(); const [type, setType] = useState(ReferenceType.ENTITY); const [nominal, setNominal] = useState(''); const [offset, setOffset] = useState(1); const [alias, setAlias] = useState(''); const [term, setTerm] = useState(''); const [filter, setFilter] = useState(''); const [filteredData, setFilteredData] = 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 ?? ''); setFilter(initial.text); } }, [initial, items]); // Filter constituents useEffect( () => { if (filter === '') { setFilteredData(items.filter( (cst) => cst.term_resolved !== '') ); } else { setFilteredData(items.filter( (cst) => matchConstituenta(filter, cst, CstMatchMode.TERM)) ); } }, [filter, 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); } 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]); const columnsConstituenta = useMemo( () => [ constituentaHelper.accessor('alias', { id: 'alias', header: 'Имя', size: 65, minSize: 65, cell: props => { const cst = props.row.original; return (<>
{cst.alias}
); } }), constituentaHelper.accessor('term_resolved', { id: 'term', header: 'Термин', size: 600, minSize: 350, maxSize: 600 }) ], [colors]); const conditionalRowStyles = useMemo( (): IConditionalStyle[] => [ { when: (cst: IConstituenta) => cst.alias === alias, style: { backgroundColor: colors.bgSelected }, } ], [alias, colors]); return (
{type === ReferenceType.SYNTACTIC &&
setOffset(event.target.valueAsNumber)} />
Основная ссылка:
setNominal(event.target.value)} />
} {type === ReferenceType.ENTITY &&
setFilter(event.target.value)} />

Список конституент пуст

Измените параметры фильтра

} onRowClicked={handleSelectConstituenta} />
setAlias(event.target.value)} />
Термин:
{FormButtons}
}
); } export default DlgEditReference;