ConceptPortal-public/rsconcept/frontend/src/pages/RSFormPage/DlgEditTerm.tsx

247 lines
7.1 KiB
TypeScript
Raw Normal View History

2023-09-21 14:58:01 +03:00
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
2023-09-11 20:31:54 +03:00
2023-09-14 16:53:38 +03:00
import Divider from '../../components/Common/Divider';
2023-09-19 17:55:17 +03:00
import MiniButton from '../../components/Common/MiniButton';
2023-09-11 20:31:54 +03:00
import Modal from '../../components/Common/Modal';
2023-09-14 16:53:38 +03:00
import SelectMulti from '../../components/Common/SelectMulti';
2023-09-11 20:31:54 +03:00
import TextArea from '../../components/Common/TextArea';
2023-09-21 14:58:01 +03:00
import DataTable, { createColumnHelper } from '../../components/DataTable';
2023-09-19 17:55:17 +03:00
import { CheckIcon, ChevronDoubleUpIcon, ChevronUpIcon, CrossIcon } from '../../components/Icons';
2023-09-21 14:58:01 +03:00
import { Grammeme, GrammemeGroups, IWordForm, NounGrams, parseGrammemes,VerbGrams } from '../../models/language';
import { IConstituenta, TermForm } from '../../models/rsform';
import { labelGrammeme } from '../../utils/labels';
import { IGrammemeOption, SelectorGrammems } from '../../utils/selectors';
2023-09-11 20:31:54 +03:00
interface DlgEditTermProps {
hideWindow: () => void
target: IConstituenta
2023-09-21 14:58:01 +03:00
onSave: (data: TermForm[]) => void
2023-09-11 20:31:54 +03:00
}
2023-09-21 14:58:01 +03:00
const columnHelper = createColumnHelper<IWordForm>();
2023-09-11 20:31:54 +03:00
function DlgEditTerm({ hideWindow, target, onSave }: DlgEditTermProps) {
const [term, setTerm] = useState('');
2023-09-19 17:55:17 +03:00
const [inputText, setInputText] = useState('');
2023-09-21 14:58:01 +03:00
const [inputGrams, setInputGrams] = useState<IGrammemeOption[]>([]);
const [options, setOptions] = useState<IGrammemeOption[]>([]);
2023-09-19 17:55:17 +03:00
2023-09-21 14:58:01 +03:00
const [forms, setForms] = useState<IWordForm[]>([]);
2023-09-19 17:55:17 +03:00
2023-09-21 14:58:01 +03:00
function getData(): TermForm[] {
const result: TermForm[] = [];
forms.forEach(
({text, grams}) => result.push({
text: text,
tags: grams.join(',')
}));
return result;
}
2023-09-11 20:31:54 +03:00
2023-09-21 14:58:01 +03:00
// Initialization
useLayoutEffect(
() => {
const initForms: IWordForm[] = [];
target.term_forms.forEach(
term => initForms.push({
text: term.text,
grams: parseGrammemes(term.tags),
}));
setForms(initForms);
setTerm(target.term_resolved);
}, [target]);
2023-09-11 20:31:54 +03:00
2023-09-21 14:58:01 +03:00
// Filter grammemes when input changes
useEffect(
() => {
let newFilter: Grammeme[] = [];
inputGrams.forEach(({value: gram}) => {
if (!newFilter.includes(gram)) {
if (NounGrams.includes(gram)) {
newFilter.push(...NounGrams);
}
if (VerbGrams.includes(gram)) {
newFilter.push(...NounGrams);
}
}
});
inputGrams.forEach(({value: gram}) =>
GrammemeGroups.forEach(group => {
if (group.includes(gram)) {
newFilter = newFilter.filter(item => !group.includes(item) || item === gram);
}
}));
newFilter.push(...inputGrams.map(({value: gram}) => gram));
if (newFilter.length === 0) {
newFilter = [...VerbGrams, ...NounGrams];
}
newFilter = [... new Set(newFilter)];
setOptions(SelectorGrammems.filter(({value: gram}) => newFilter.includes(gram)));
}, [inputGrams]);
const handleSubmit = () => onSave(getData());
2023-09-11 20:31:54 +03:00
2023-09-19 17:55:17 +03:00
function handleAddForm() {
2023-09-21 14:58:01 +03:00
setForms(forms => [
...forms,
{
text: inputText,
grams: inputGrams.map(item => ({
type: item.value, data: item.value as string
}))
}
]);
2023-09-19 17:55:17 +03:00
}
function handleResetForm() {
}
function handleGenerateSelected() {
}
function handleGenerateBasics() {
}
2023-09-21 14:58:01 +03:00
const columns = useMemo(
() => [
columnHelper.accessor('text', {
id: 'text',
header: 'Текст',
size: 350,
minSize: 350,
maxSize: 350
}),
columnHelper.accessor('grams', {
id: 'grams',
header: 'Граммемы',
size: 250,
minSize: 250,
maxSize: 250,
cell: props => {
return (
<div className='flex justify-start gap-1 select-none'>
{ props.getValue().map(
data => (<>
<div
className='min-w-[3rem] px-1 text-center rounded-md whitespace-nowrap border clr-border clr-input'
title=''
// style={{
// borderWidth: '1px',
// borderColor: getCstStatusFgColor(cst.status, colors),
// color: getCstStatusFgColor(cst.status, colors),
// fontWeight: 600,
// backgroundColor: isMockCst(cst) ? colors.bgWarning : colors.bgInput
// }}
>
{labelGrammeme(data)}
</div>
{/* <ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_list}${cst.alias}`} /> */}
</>))}
</div>);
}
// cell: props =>
// <div style={{
// fontSize: 12,
// color: isMockCst(props.row.original) ? colors.fgWarning : undefined
// }}>
// {props.getValue()}
// </div>
}),
// columnHelper.accessor(, {
// })
], []);
2023-09-11 20:31:54 +03:00
return (
2023-09-19 17:55:17 +03:00
<Modal
title='Редактирование словоформ'
hideWindow={hideWindow}
submitText='Сохранить данные'
canSubmit
onSubmit={handleSubmit}
>
<div className='min-w-[40rem]'>
<TextArea id='nominal' label='Начальная форма'
placeholder='Начальная форма'
rows={1}
value={term}
disabled={true}
spellCheck
/>
<Divider margins='my-4'/>
<div className='flex items-start gap-2 justify-stretch min-h-[6.3rem]'>
<div className='flex flex-col gap-1'>
<TextArea
placeholder='Введите текст'
rows={2}
dimensions='min-w-[20rem]'
2023-09-14 16:53:38 +03:00
2023-09-19 17:55:17 +03:00
value={inputText}
onChange={event => setInputText(event.target.value)}
2023-09-14 16:53:38 +03:00
/>
2023-09-19 17:55:17 +03:00
<div className='flex items-center justify-start'>
<MiniButton
tooltip='Добавить словоформу'
icon={<CheckIcon size={6} color='text-success'/>}
onClick={handleAddForm}
/>
<MiniButton
tooltip='Сбросить словоформу'
icon={<CrossIcon size={6} color='text-warning'/>}
onClick={handleResetForm}
/>
<MiniButton
tooltip='Генерировать словоформу'
icon={<ChevronUpIcon size={6} color='text-primary'/>}
onClick={handleGenerateSelected}
/>
<MiniButton
tooltip='Генерировать базовые словоформы'
icon={<ChevronDoubleUpIcon size={6} color='text-primary'/>}
onClick={handleGenerateBasics}
/>
</div>
2023-09-14 16:53:38 +03:00
</div>
2023-09-19 17:55:17 +03:00
<SelectMulti
className='z-modal-top min-w-[20rem] max-w-[20rem] h-full flex-grow'
2023-09-21 14:58:01 +03:00
options={options}
2023-09-19 17:55:17 +03:00
placeholder='Выберите граммемы'
2023-09-21 14:58:01 +03:00
value={inputGrams}
onChange={data => setInputGrams(data.map(value => value))}
2023-09-19 17:55:17 +03:00
/>
</div>
2023-09-21 14:58:01 +03:00
<div className='border overflow-y-auto max-h-[20rem]'>
<DataTable
data={forms}
columns={columns}
dense
noDataComponent={
<span className='flex flex-col justify-center p-2 text-center min-h-[2rem]'>
<p>Список пуст</p>
</span>
}
// onRowDoubleClicked={handleDoubleClick}
// onRowClicked={handleRowClicked}
/>
2023-09-14 16:53:38 +03:00
</div>
2023-09-19 17:55:17 +03:00
</div>
</Modal>);
2023-09-11 20:31:54 +03:00
}
export default DlgEditTerm;