F: Improve template dialog

This commit is contained in:
Ivan 2025-11-04 20:12:54 +03:00
parent 820e567557
commit d5ccf1b9a9
2 changed files with 48 additions and 51 deletions

View File

@ -6,13 +6,14 @@ import { createColumnHelper } from '@tanstack/react-table';
import { MiniButton } from '@/components/control'; import { MiniButton } from '@/components/control';
import { DataTable, type IConditionalStyle } from '@/components/data-table'; import { DataTable, type IConditionalStyle } from '@/components/data-table';
import { IconAccept, IconRemove, IconReset } from '@/components/icons'; import { IconReset } from '@/components/icons';
import { NoData } from '@/components/view'; import { NoData } from '@/components/view';
import { type ICreateConstituentaDTO } from '../../backend/types'; import { type ICreateConstituentaDTO } from '../../backend/types';
import { PickConstituenta } from '../../components/pick-constituenta'; import { PickConstituenta } from '../../components/pick-constituenta';
import { RSInput } from '../../components/rs-input'; import { RSInput } from '../../components/rs-input';
import { type IConstituenta, type IRSForm } from '../../models/rsform'; import { type IConstituenta, type IRSForm } from '../../models/rsform';
import { isFunctional, isLogical } from '../../models/rsform-api';
import { type IArgumentValue } from '../../models/rslang'; import { type IArgumentValue } from '../../models/rslang';
import { useTemplateContext } from './template-context'; import { useTemplateContext } from './template-context';
@ -31,18 +32,13 @@ export function TabArguments({ schema }: TabArgumentsProps) {
const [selectedCst, setSelectedCst] = useState<IConstituenta | null>(null); const [selectedCst, setSelectedCst] = useState<IConstituenta | null>(null);
const [selectedArgument, setSelectedArgument] = useState<IArgumentValue | null>(args.length > 0 ? args[0] : null); const [selectedArgument, setSelectedArgument] = useState<IArgumentValue | null>(args.length > 0 ? args[0] : null);
const [argumentValue, setArgumentValue] = useState('');
function handleSelectArgument(arg: IArgumentValue) { function handleSelectArgument(arg: IArgumentValue) {
setSelectedArgument(arg); setSelectedArgument(arg);
if (arg.value) {
setArgumentValue(arg.value);
}
} }
function handleSelectConstituenta(cst: IConstituenta) { function handleSelectConstituenta(cst: IConstituenta) {
setSelectedCst(cst); setSelectedCst(cst);
setArgumentValue(cst.alias); handleAssignArgument(selectedArgument!, cst.alias);
} }
function handleClearArgument(target: IArgumentValue) { function handleClearArgument(target: IArgumentValue) {
@ -51,48 +47,56 @@ export function TabArguments({ schema }: TabArgumentsProps) {
setSelectedArgument(newArg); setSelectedArgument(newArg);
} }
function handleReset() {
setArgumentValue(selectedArgument?.value ?? '');
}
function handleAssignArgument(target: IArgumentValue, argValue: string) { function handleAssignArgument(target: IArgumentValue, argValue: string) {
const newArg = { ...target, value: argValue }; const newArg = { ...target, value: argValue };
onChangeArguments(args.map(arg => (arg.alias !== target.alias ? arg : newArg))); onChangeArguments(args.map(arg => (arg.alias !== target.alias ? arg : newArg)));
setSelectedArgument(newArg); setSelectedArgument(newArg);
} }
function cstFilter(cst: IConstituenta) {
return cst.id === selectedCst?.id || (!isFunctional(cst.cst_type) && !isLogical(cst.cst_type));
}
const filteredItems = schema.items.filter(cstFilter);
const columns = [ const columns = [
argumentsHelper.accessor('alias', { argumentsHelper.accessor('alias', {
id: 'alias', id: 'alias',
header: 'Имя',
size: 40, size: 40,
minSize: 40, minSize: 40,
maxSize: 40, maxSize: 40,
cell: props => <div className='text-center'>{props.getValue()}</div> cell: props => <div className='text-center pr-2'>{props.getValue()}</div>
}), }),
argumentsHelper.accessor(arg => arg.value || 'свободный аргумент', { argumentsHelper.accessor(arg => arg.value || 'свободный аргумент', {
id: 'value', id: 'value',
header: 'Значение',
size: 200, size: 200,
minSize: 200, minSize: 200,
maxSize: 200 maxSize: 200
}), }),
argumentsHelper.accessor(arg => arg.typification, { argumentsHelper.accessor(arg => arg.typification, {
id: 'type', id: 'type',
header: 'Типизация',
enableHiding: true, enableHiding: true,
cell: props => <div className='w-36 text-sm wrap-break-word'>{props.getValue()}</div> cell: props => <div className='w-36 text-sm wrap-break-word'>{props.getValue()}</div>
}), }),
argumentsHelper.display({ argumentsHelper.display({
id: 'actions', id: 'actions',
size: 0, size: 0,
cell: props => cell: props => (
props.row.original.value ? ( <div className='w-6 flex justify-center'>
<MiniButton {props.row.original.value ? (
title='Очистить значение' <MiniButton
noPadding title='Очистить значение'
className='align-middle' noPadding
icon={<IconRemove size='1.25rem' className='cc-remove' />} className='align-middle'
onClick={() => handleClearArgument(props.row.original)} icon={<IconReset size='1rem' className='cc-remove' />}
/> onClick={() => handleClearArgument(props.row.original)}
) : null />
) : null}
</div>
)
}) })
]; ];
@ -108,8 +112,7 @@ export function TabArguments({ schema }: TabArgumentsProps) {
<DataTable <DataTable
dense dense
noFooter noFooter
noHeader className='h-31 cc-scroll-y text-sm border select-none'
className='h-23 cc-scroll-y text-sm border select-none'
data={args} data={args}
columns={columns} columns={columns}
conditionalRowStyles={conditionalRowStyles} conditionalRowStyles={conditionalRowStyles}
@ -117,36 +120,12 @@ export function TabArguments({ schema }: TabArgumentsProps) {
onRowClicked={handleSelectArgument} onRowClicked={handleSelectArgument}
/> />
<div className='my-3 flex gap-2 justify-center items-center select-none'> <h2>Конституенты</h2>
<span
title='Выберите аргумент из списка сверху и значение из списка снизу'
className='font-semibold text-center'
>
{selectedArgument?.alias || 'ARG'}
</span>
<span>=</span>
<RSInput noTooltip className='w-48' value={argumentValue} onChange={newValue => setArgumentValue(newValue)} />
<div className='flex'>
<MiniButton
title='Подставить значение аргумента'
className='py-0'
icon={<IconAccept size='1.5rem' className='icon-green' />}
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
disabled={!argumentValue || !selectedArgument}
/>
<MiniButton
title='Очистить поле'
className='py-0'
onClick={handleReset}
icon={<IconReset size='1.5rem' className='icon-primary' />}
/>
</div>
</div>
<PickConstituenta <PickConstituenta
id='dlg_argument_picker' id='dlg_argument_picker'
value={selectedCst} value={selectedCst}
items={schema.items} items={filteredItems}
onChange={handleSelectConstituenta} onChange={handleSelectConstituenta}
rows={7} rows={7}
/> />

View File

@ -200,7 +200,7 @@ export function isBaseSet(type: CstType): boolean {
} }
/** /**
* Evaluate if {@link CstType} is function. * Evaluate if {@link CstType} is a function.
*/ */
export function isFunctional(type: CstType): boolean { export function isFunctional(type: CstType): boolean {
// prettier-ignore // prettier-ignore
@ -217,6 +217,24 @@ export function isFunctional(type: CstType): boolean {
} }
} }
/**
* Evaluate if {@link CstType} is logical.
*/
export function isLogical(type: CstType): boolean {
// prettier-ignore
switch (type) {
case CstType.NOMINAL: return false;
case CstType.BASE: return false;
case CstType.CONSTANT: return false;
case CstType.STRUCTURED: return false;
case CstType.AXIOM: return true;
case CstType.TERM: return false;
case CstType.FUNCTION: return false;
case CstType.PREDICATE: return false;
case CstType.THEOREM: return true;
}
}
/** /**
* Evaluate if {@link IConstituenta} can be used produce structure. * Evaluate if {@link IConstituenta} can be used produce structure.
*/ */