ConceptPortal-public/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx
2023-11-06 18:44:14 +03:00

177 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { createColumnHelper } from '@tanstack/react-table';
import { Dispatch, useCallback, useMemo, useState } from 'react';
import MiniButton from '../../components/Common/MiniButton';
import DataTable, { IConditionalStyle } from '../../components/DataTable';
import { CheckIcon, CrossIcon } from '../../components/Icons';
import RSInput from '../../components/RSInput';
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
import { useConceptTheme } from '../../context/ThemeContext';
import { IConstituenta, IRSForm } from '../../models/rsform';
import { IArgumentValue } from '../../models/rslang';
import { prefixes } from '../../utils/constants';
interface ArgumentsTabProps {
state: IArgumentsState
schema: IRSForm
partialUpdate: Dispatch<Partial<IArgumentsState>>
}
export interface IArgumentsState {
arguments: IArgumentValue[]
definition: string
}
const argumentsHelper = createColumnHelper<IArgumentValue>();
function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
const { colors } = useConceptTheme();
const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined);
const [selectedArgument, setSelectedArgument] = useState<IArgumentValue | undefined>(undefined);
const [argumentValue, setArgumentValue] = useState('');
const handleSelectArgument = useCallback(
(arg: IArgumentValue) => {
setSelectedArgument(arg);
}, []);
const handleSelectConstituenta = useCallback(
(cst: IConstituenta) => {
setSelectedCst(cst);
setArgumentValue(cst.alias);
}, []);
const handleClearArgument = useCallback(
(target: IArgumentValue) => {
target.value = '';
partialUpdate({
arguments: [
target,
...state.arguments.filter(arg => arg.alias !== target.alias)
]
});
}, [partialUpdate, state.arguments]);
const handleAssignArgument = useCallback(
(target: IArgumentValue, value: string) => {
target.value = value;
partialUpdate({
arguments: [
target,
...state.arguments.filter(arg => arg.alias !== target.alias)
]
});
}, [partialUpdate, state.arguments]);
const columns = useMemo(
() => [
argumentsHelper.accessor('alias', {
id: 'alias',
header: 'Имя',
size: 40,
minSize: 40,
maxSize: 40,
cell: props => <div className='w-full text-center'>{props.getValue()}</div>
}),
argumentsHelper.accessor(arg => arg.value || 'свободный аргумент', {
id: 'value',
header: 'Значение',
size: 200,
minSize: 200,
maxSize: 200,
}),
argumentsHelper.accessor(arg => arg.typification, {
id: 'type',
header: 'Типизация',
size: 150,
minSize: 150,
maxSize: 150,
enableHiding: true,
cell: props => <div className='text-sm min-w-[9.3rem] max-w-[9.3rem] break-words'>{props.getValue()}</div>
}),
argumentsHelper.display({
id: 'actions',
size: 50,
minSize: 50,
maxSize: 50,
cell: props =>
<div className='max-h-[1.2rem]'>
{props.row.original.value &&
<MiniButton
tooltip='Очистить значение'
icon={<CrossIcon size={3} color='text-warning'/>}
noHover
onClick={() => handleClearArgument(props.row.original)}
/>}
</div>
})
], [handleClearArgument]);
const conditionalRowStyles = useMemo(
(): IConditionalStyle<IArgumentValue>[] => [{
when: (arg: IArgumentValue) => arg.alias === selectedArgument?.alias,
style: { backgroundColor: colors.bgSelected },
}], [selectedArgument, colors]);
return (
<div className='flex flex-col gap-3'>
<div className='overflow-y-auto text-sm border select-none max-h-[7.5rem] min-h-[7.5rem]'>
<DataTable dense
data={state.arguments}
columns={columns}
conditionalRowStyles={conditionalRowStyles}
noDataComponent={
<span className='flex flex-col justify-center p-2 text-center min-h-[5rem]'>
<p>Аргументы отсутствуют</p>
</span>
}
onRowClicked={handleSelectArgument}
/>
</div>
<div className='flex items-center justify-center w-full gap-2 select-none'>
<span title='Выберите аргумент из списка сверху и значение из списка снизу'
className='font-semibold text-center'
>
{selectedArgument?.alias || 'ARG'}
</span>
<span>=</span>
<RSInput
dimensions='max-w-[12rem] w-full'
value={argumentValue}
noTooltip
onChange={newValue => setArgumentValue(newValue)}
/>
<MiniButton
tooltip='Подставить значение аргумента'
icon={<CheckIcon
size={6}
color={!argumentValue || !selectedArgument ? 'text-disabled' : 'text-success'}
/>}
disabled={!argumentValue || !selectedArgument}
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
/>
</div>
<ConstituentaPicker
value={selectedCst}
data={schema?.items}
onSelectValue={handleSelectConstituenta}
prefixID={prefixes.cst_modal_list}
rows={5}
/>
<RSInput id='result'
placeholder='Итоговое определение'
height='4.8rem'
value={state.definition}
disabled
/>
</div>);
}
export default ArgumentsTab;