mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Minor UI improvements
This commit is contained in:
parent
6999e086d5
commit
b026a57fad
|
@ -35,17 +35,16 @@ function Modal({
|
|||
if (onSubmit) onSubmit();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
return (<>
|
||||
<div className='fixed top-0 left-0 w-full h-full z-navigation clr-modal-backdrop' />
|
||||
<div ref={ref}
|
||||
className='fixed bottom-1/2 left-1/2 translate-y-1/2 -translate-x-1/2 px-4 py-3 flex flex-col justify-start w-fit max-w-[calc(100vw-2rem)] overflow-x-auto h-fit z-modal clr-app border shadow-md'
|
||||
className='fixed bottom-1/2 left-1/2 translate-y-1/2 -translate-x-1/2 px-4 flex flex-col justify-start w-fit max-w-[calc(100vw-2rem)] overflow-x-auto h-fit z-modal clr-app border shadow-md'
|
||||
>
|
||||
{title ? <h1 className='pb-3 text-xl select-none'>{title}</h1> : null}
|
||||
{title ? <h1 className='py-2 text-lg select-none'>{title}</h1> : null}
|
||||
<div className='max-h-[calc(100vh-8rem)] overflow-auto px-2'>
|
||||
{children}
|
||||
</div>
|
||||
<div className='flex justify-center w-full gap-4 pt-3 mt-2 border-t-2 z-modal-controls'>
|
||||
<div className='flex justify-center w-full gap-6 py-3 z-modal-controls'>
|
||||
{!readonly ?
|
||||
<Button autoFocus
|
||||
text={submitText}
|
||||
|
@ -62,8 +61,7 @@ function Modal({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
</>);
|
||||
}
|
||||
|
||||
export default Modal;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
function HelpTerminologyControl() {
|
||||
return (
|
||||
<div>
|
||||
<div className='flex flex-col gap-1'>
|
||||
<h1>Терминологизация: Контроль терминологии</h1>
|
||||
<p>Портал позволяет контролировать употребление терминов, привязанных к сущностям в концептуальных схемах.</p>
|
||||
<p>Для этого используется механизм текстовых отсылок: <i>использование термина</i> и <i>связывание слов.</i></p>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Dispatch, useCallback, useEffect, useMemo, useState } from 'react';
|
|||
|
||||
import MiniButton from '../../components/Common/MiniButton';
|
||||
import DataTable, { IConditionalStyle } from '../../components/DataTable';
|
||||
import { CheckIcon, CrossIcon } from '../../components/Icons';
|
||||
import { ArrowsRotateIcon, CheckIcon, CrossIcon } from '../../components/Icons';
|
||||
import RSInput from '../../components/RSInput';
|
||||
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
|
@ -32,6 +32,15 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
|||
|
||||
const [argumentValue, setArgumentValue] = useState('');
|
||||
|
||||
const selectedClearable = useMemo(
|
||||
() => {
|
||||
return argumentValue && !!selectedArgument && !!selectedArgument.value;
|
||||
}, [argumentValue, selectedArgument]);
|
||||
|
||||
const isModified = useMemo(
|
||||
() => (selectedArgument && argumentValue !== selectedArgument.value),
|
||||
[selectedArgument, argumentValue]);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (!selectedArgument && state.arguments.length > 0) {
|
||||
|
@ -55,24 +64,25 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
|||
|
||||
const handleClearArgument = useCallback(
|
||||
(target: IArgumentValue) => {
|
||||
target.value = '';
|
||||
const newArg = { ...target, value: '' }
|
||||
partialUpdate({
|
||||
arguments: [
|
||||
target,
|
||||
...state.arguments.filter(arg => arg.alias !== target.alias)
|
||||
]
|
||||
arguments: state.arguments.map((arg) => (arg.alias !== target.alias ? arg : newArg))
|
||||
});
|
||||
setSelectedArgument(newArg);
|
||||
}, [partialUpdate, state.arguments]);
|
||||
|
||||
const handleReset = useCallback(
|
||||
() => {
|
||||
setArgumentValue(selectedArgument?.value ?? '');
|
||||
}, [selectedArgument]);
|
||||
|
||||
const handleAssignArgument = useCallback(
|
||||
(target: IArgumentValue, value: string) => {
|
||||
target.value = value;
|
||||
const newArg = { ...target, value: value }
|
||||
partialUpdate({
|
||||
arguments: [
|
||||
target,
|
||||
...state.arguments.filter(arg => arg.alias !== target.alias)
|
||||
]
|
||||
arguments: state.arguments.map((arg) => (arg.alias !== target.alias ? arg : newArg))
|
||||
});
|
||||
setSelectedArgument(newArg);
|
||||
}, [partialUpdate, state.arguments]);
|
||||
|
||||
const columns = useMemo(
|
||||
|
@ -148,21 +158,31 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
|||
{selectedArgument?.alias || 'ARG'}
|
||||
</span>
|
||||
<span>=</span>
|
||||
<RSInput
|
||||
<RSInput noTooltip
|
||||
dimensions='max-w-[12rem] w-full'
|
||||
value={argumentValue}
|
||||
noTooltip
|
||||
onChange={newValue => setArgumentValue(newValue)}
|
||||
/>
|
||||
<MiniButton
|
||||
tooltip='Подставить значение аргумента'
|
||||
icon={<CheckIcon
|
||||
size={5}
|
||||
color={!argumentValue || !selectedArgument ? 'text-disabled' : 'text-success'}
|
||||
/>}
|
||||
disabled={!argumentValue || !selectedArgument}
|
||||
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
|
||||
/>
|
||||
<div className='flex'>
|
||||
<MiniButton
|
||||
tooltip='Подставить значение аргумента'
|
||||
icon={<CheckIcon size={5} color={!argumentValue || !selectedArgument ? 'text-disabled' : 'text-success'} />}
|
||||
disabled={!argumentValue || !selectedArgument}
|
||||
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
|
||||
/>
|
||||
<MiniButton
|
||||
tooltip='Откатить значение'
|
||||
disabled={!isModified}
|
||||
onClick={handleReset}
|
||||
icon={<ArrowsRotateIcon size={5} color={isModified ? 'text-primary' : ''} />}
|
||||
/>
|
||||
<MiniButton
|
||||
tooltip='Очистить значение аргумента'
|
||||
disabled={!selectedClearable}
|
||||
icon={<CrossIcon size={5} color={!selectedClearable ? 'text-disabled' : 'text-warning'}/>}
|
||||
onClick={() => selectedArgument ? handleClearArgument(selectedArgument) : undefined}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ConstituentaPicker
|
||||
|
|
|
@ -218,8 +218,9 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
|
|||
</div>
|
||||
<ConceptTooltip
|
||||
anchorSelect='#terminology-help'
|
||||
className='max-w-[30rem] z-modal-tooltip'
|
||||
offset={4}
|
||||
className='max-w-[40rem]'
|
||||
layer='z-modal-tooltip'
|
||||
offset={1}
|
||||
>
|
||||
<HelpTerminologyControl />
|
||||
</ConceptTooltip>
|
||||
|
|
|
@ -27,7 +27,7 @@ function ConstituentaToolbar({
|
|||
return (
|
||||
<div className='relative w-full'>
|
||||
<div className='absolute right-0 flex items-start justify-center w-full top-1'>
|
||||
<div className=' flex justify-start w-fit select-auto z-pop'>
|
||||
<div className='flex justify-start select-auto w-fit z-tooltip'>
|
||||
<MiniButton
|
||||
tooltip='Сохранить изменения'
|
||||
disabled={!canSave}
|
||||
|
@ -35,7 +35,7 @@ function ConstituentaToolbar({
|
|||
onClick={onSubmit}
|
||||
/>
|
||||
<MiniButton
|
||||
tooltip='Сборсить несохраненные изменения'
|
||||
tooltip='Сбросить несохраненные изменения'
|
||||
disabled={!canSave}
|
||||
onClick={onReset}
|
||||
icon={<ArrowsRotateIcon size={5} color={canSave ? 'text-primary' : ''} />}
|
||||
|
@ -67,7 +67,10 @@ function ConstituentaToolbar({
|
|||
<div id='cst-help' className='px-1 py-1'>
|
||||
<HelpIcon color='text-primary' size={5} />
|
||||
</div>
|
||||
<ConceptTooltip anchorSelect='#cst-help' offset={4}>
|
||||
<ConceptTooltip
|
||||
anchorSelect='#cst-help'
|
||||
offset={4}
|
||||
>
|
||||
<HelpConstituenta />
|
||||
</ConceptTooltip>
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,11 @@
|
|||
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { useLayoutEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import DataTable, { createColumnHelper, type RowSelectionState,VisibilityState } from '../../../components/DataTable';
|
||||
import ConstituentaBadge from '../../../components/Shared/ConstituentaBadge';
|
||||
import { type RowSelectionState } from '../../../components/DataTable';
|
||||
import { useRSForm } from '../../../context/RSFormContext';
|
||||
import { useConceptTheme } from '../../../context/ThemeContext';
|
||||
import useWindowSize from '../../../hooks/useWindowSize';
|
||||
import { CstType, IConstituenta, ICstCreateData, ICstMovetoData } from '../../../models/rsform'
|
||||
import { prefixes } from '../../../utils/constants';
|
||||
import { labelCstTypification } from '../../../utils/labels';
|
||||
import { CstType, ICstCreateData, ICstMovetoData } from '../../../models/rsform'
|
||||
import RSListToolbar from './RSListToolbar';
|
||||
|
||||
// Window width cutoff for columns
|
||||
const COLUMN_DEFINITION_HIDE_THRESHOLD = 1000;
|
||||
const COLUMN_TYPE_HIDE_THRESHOLD = 1200;
|
||||
const COLUMN_CONVENTION_HIDE_THRESHOLD = 1800;
|
||||
|
||||
const columnHelper = createColumnHelper<IConstituenta>();
|
||||
import RSTable from './RSTable';
|
||||
|
||||
interface EditorRSListProps {
|
||||
onOpenEdit: (cstID: number) => void
|
||||
|
@ -26,13 +15,25 @@ interface EditorRSListProps {
|
|||
}
|
||||
|
||||
function EditorRSList({ onOpenEdit, onCreateCst, onDeleteCst, onTemplates }: EditorRSListProps) {
|
||||
const { colors, noNavigation } = useConceptTheme();
|
||||
const windowSize = useWindowSize();
|
||||
const { schema, editorMode: isEditable, cstMoveTo, resetAliases } = useRSForm();
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
|
||||
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
if (!schema || Object.keys(rowSelection).length === 0) {
|
||||
setSelected([]);
|
||||
} else {
|
||||
const selected: number[] = [];
|
||||
schema.items.forEach((cst, index) => {
|
||||
if (rowSelection[String(index)] === true) {
|
||||
selected.push(cst.id);
|
||||
}
|
||||
});
|
||||
setSelected(selected);
|
||||
}
|
||||
}, [rowSelection, schema]);
|
||||
|
||||
// Delete selected constituents
|
||||
function handleDelete() {
|
||||
|
@ -179,123 +180,19 @@ function EditorRSList({ onOpenEdit, onCreateCst, onDeleteCst, onTemplates }: Edi
|
|||
}
|
||||
}
|
||||
switch (code) {
|
||||
case 'Backquote': handleCreateCst(); return true;
|
||||
case 'Digit1': handleCreateCst(CstType.BASE); return true;
|
||||
case 'Digit2': handleCreateCst(CstType.STRUCTURED); return true;
|
||||
case 'Digit3': handleCreateCst(CstType.TERM); return true;
|
||||
case 'Digit4': handleCreateCst(CstType.AXIOM); return true;
|
||||
case 'KeyQ': handleCreateCst(CstType.FUNCTION); return true;
|
||||
case 'KeyW': handleCreateCst(CstType.PREDICATE); return true;
|
||||
case 'Digit5': handleCreateCst(CstType.CONSTANT); return true;
|
||||
case 'Digit6': handleCreateCst(CstType.THEOREM); return true;
|
||||
case 'Backquote': handleCreateCst(); return true;
|
||||
case 'Digit1': handleCreateCst(CstType.BASE); return true;
|
||||
case 'Digit2': handleCreateCst(CstType.STRUCTURED); return true;
|
||||
case 'Digit3': handleCreateCst(CstType.TERM); return true;
|
||||
case 'Digit4': handleCreateCst(CstType.AXIOM); return true;
|
||||
case 'KeyQ': handleCreateCst(CstType.FUNCTION); return true;
|
||||
case 'KeyW': handleCreateCst(CstType.PREDICATE); return true;
|
||||
case 'Digit5': handleCreateCst(CstType.CONSTANT); return true;
|
||||
case 'Digit6': handleCreateCst(CstType.THEOREM); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const handleRowClicked = useCallback(
|
||||
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
||||
if (event.altKey) {
|
||||
event.preventDefault();
|
||||
onOpenEdit(cst.id);
|
||||
}
|
||||
}, [onOpenEdit]);
|
||||
|
||||
const handleRowDoubleClicked = useCallback(
|
||||
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
||||
event.preventDefault();
|
||||
onOpenEdit(cst.id);
|
||||
}, [onOpenEdit]);
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
setColumnVisibility({
|
||||
'type': (windowSize.width ?? 0) >= COLUMN_TYPE_HIDE_THRESHOLD,
|
||||
'convention': (windowSize.width ?? 0) >= COLUMN_CONVENTION_HIDE_THRESHOLD,
|
||||
'definition': (windowSize.width ?? 0) >= COLUMN_DEFINITION_HIDE_THRESHOLD
|
||||
});
|
||||
}, [windowSize]);
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
if (!schema || Object.keys(rowSelection).length === 0) {
|
||||
setSelected([]);
|
||||
} else {
|
||||
const selected: number[] = [];
|
||||
schema.items.forEach((cst, index) => {
|
||||
if (rowSelection[String(index)] === true) {
|
||||
selected.push(cst.id);
|
||||
}
|
||||
});
|
||||
setSelected(selected);
|
||||
}
|
||||
}, [rowSelection, schema]);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
columnHelper.accessor('alias', {
|
||||
id: 'alias',
|
||||
header: 'Имя',
|
||||
size: 65,
|
||||
minSize: 65,
|
||||
maxSize: 65,
|
||||
cell: props =>
|
||||
<ConstituentaBadge
|
||||
theme={colors}
|
||||
value={props.row.original}
|
||||
prefixID={prefixes.cst_list}
|
||||
shortTooltip
|
||||
/>
|
||||
}),
|
||||
columnHelper.accessor(cst => labelCstTypification(cst), {
|
||||
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>
|
||||
}),
|
||||
columnHelper.accessor(cst => cst.term_resolved || cst.term_raw || '', {
|
||||
id: 'term',
|
||||
header: 'Термин',
|
||||
size: 500,
|
||||
minSize: 150,
|
||||
maxSize: 500
|
||||
}),
|
||||
columnHelper.accessor('definition_formal', {
|
||||
id: 'expression',
|
||||
header: 'Формальное определение',
|
||||
size: 1000,
|
||||
minSize: 300,
|
||||
maxSize: 1000,
|
||||
cell: props => <div className='break-words'>{props.getValue()}</div>
|
||||
}),
|
||||
columnHelper.accessor(cst => cst.definition_resolved || cst.definition_raw || '', {
|
||||
id: 'definition',
|
||||
header: 'Текстовое определение',
|
||||
size: 1000,
|
||||
minSize: 200,
|
||||
maxSize: 1000,
|
||||
cell: props => <div className='text-xs'>{props.getValue()}</div>
|
||||
}),
|
||||
columnHelper.accessor('convention', {
|
||||
id: 'convention',
|
||||
header: 'Конвенция / Комментарий',
|
||||
size: 500,
|
||||
minSize: 100,
|
||||
maxSize: 500,
|
||||
enableHiding: true,
|
||||
cell: props => <div className='text-xs'>{props.getValue()}</div>
|
||||
})
|
||||
], [colors]);
|
||||
|
||||
const tableHeight = useMemo(
|
||||
() => {
|
||||
return !noNavigation ?
|
||||
'calc(100vh - 7.2rem - 4px)'
|
||||
: 'calc(100vh - 4.4rem - 4px)';
|
||||
}, [noNavigation]);
|
||||
|
||||
return (
|
||||
<div tabIndex={-1}
|
||||
className='w-full outline-none'
|
||||
|
@ -317,37 +214,14 @@ function EditorRSList({ onOpenEdit, onCreateCst, onDeleteCst, onTemplates }: Edi
|
|||
onReindex={handleReindex}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='w-full h-full overflow-auto text-sm' style={{maxHeight: tableHeight}}>
|
||||
<DataTable dense noFooter
|
||||
data={schema?.items ?? []}
|
||||
columns={columns}
|
||||
headPosition='0rem'
|
||||
|
||||
onRowDoubleClicked={handleRowDoubleClicked}
|
||||
onRowClicked={handleRowClicked}
|
||||
|
||||
enableHiding
|
||||
columnVisibility={columnVisibility}
|
||||
onColumnVisibilityChange={setColumnVisibility}
|
||||
|
||||
enableRowSelection
|
||||
rowSelection={rowSelection}
|
||||
onRowSelectionChange={setRowSelection}
|
||||
|
||||
noDataComponent={
|
||||
<span className='flex flex-col justify-center p-2 text-center'>
|
||||
<p>Список пуст</p>
|
||||
<p
|
||||
className='cursor-pointer text-primary hover:underline'
|
||||
onClick={() => handleCreateCst()}
|
||||
>
|
||||
Создать новую конституенту
|
||||
</p>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<RSTable
|
||||
items={schema?.items}
|
||||
selected={rowSelection}
|
||||
setSelected={setRowSelection}
|
||||
onEdit={onOpenEdit}
|
||||
onCreateNew={() => handleCreateCst()}
|
||||
/>
|
||||
</div>);
|
||||
}
|
||||
|
||||
|
|
159
rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSTable.tsx
Normal file
159
rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSTable.tsx
Normal file
|
@ -0,0 +1,159 @@
|
|||
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||
|
||||
import DataTable, { createColumnHelper,RowSelectionState,VisibilityState } from '../../../components/DataTable';
|
||||
import ConstituentaBadge from '../../../components/Shared/ConstituentaBadge';
|
||||
import { useConceptTheme } from '../../../context/ThemeContext';
|
||||
import useWindowSize from '../../../hooks/useWindowSize';
|
||||
import { IConstituenta } from '../../../models/rsform';
|
||||
import { prefixes } from '../../../utils/constants';
|
||||
import { labelCstTypification } from '../../../utils/labels';
|
||||
|
||||
interface RSTableProps {
|
||||
items?: IConstituenta[]
|
||||
selected: RowSelectionState
|
||||
setSelected: React.Dispatch<React.SetStateAction<RowSelectionState>>
|
||||
|
||||
onEdit: (cstID: number) => void
|
||||
onCreateNew: () => void
|
||||
}
|
||||
|
||||
// Window width cutoff for columns
|
||||
const COLUMN_DEFINITION_HIDE_THRESHOLD = 1000;
|
||||
const COLUMN_TYPE_HIDE_THRESHOLD = 1200;
|
||||
const COLUMN_CONVENTION_HIDE_THRESHOLD = 1800;
|
||||
|
||||
const columnHelper = createColumnHelper<IConstituenta>();
|
||||
|
||||
function RSTable({
|
||||
items, selected, setSelected,
|
||||
onEdit, onCreateNew
|
||||
}: RSTableProps) {
|
||||
const { colors, noNavigation } = useConceptTheme();
|
||||
const windowSize = useWindowSize();
|
||||
|
||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
setColumnVisibility({
|
||||
'type': (windowSize.width ?? 0) >= COLUMN_TYPE_HIDE_THRESHOLD,
|
||||
'convention': (windowSize.width ?? 0) >= COLUMN_CONVENTION_HIDE_THRESHOLD,
|
||||
'definition': (windowSize.width ?? 0) >= COLUMN_DEFINITION_HIDE_THRESHOLD
|
||||
});
|
||||
}, [windowSize]);
|
||||
|
||||
const handleRowClicked = useCallback(
|
||||
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
||||
if (event.altKey) {
|
||||
event.preventDefault();
|
||||
onEdit(cst.id);
|
||||
}
|
||||
}, [onEdit]);
|
||||
|
||||
const handleRowDoubleClicked = useCallback(
|
||||
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
||||
event.preventDefault();
|
||||
onEdit(cst.id);
|
||||
}, [onEdit]);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
columnHelper.accessor('alias', {
|
||||
id: 'alias',
|
||||
header: 'Имя',
|
||||
size: 65,
|
||||
minSize: 65,
|
||||
maxSize: 65,
|
||||
cell: props =>
|
||||
<ConstituentaBadge
|
||||
theme={colors}
|
||||
value={props.row.original}
|
||||
prefixID={prefixes.cst_list}
|
||||
shortTooltip
|
||||
/>
|
||||
}),
|
||||
columnHelper.accessor(cst => labelCstTypification(cst), {
|
||||
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>
|
||||
}),
|
||||
columnHelper.accessor(cst => cst.term_resolved || cst.term_raw || '', {
|
||||
id: 'term',
|
||||
header: 'Термин',
|
||||
size: 500,
|
||||
minSize: 150,
|
||||
maxSize: 500
|
||||
}),
|
||||
columnHelper.accessor('definition_formal', {
|
||||
id: 'expression',
|
||||
header: 'Формальное определение',
|
||||
size: 1000,
|
||||
minSize: 300,
|
||||
maxSize: 1000,
|
||||
cell: props => <div className='break-words'>{props.getValue()}</div>
|
||||
}),
|
||||
columnHelper.accessor(cst => cst.definition_resolved || cst.definition_raw || '', {
|
||||
id: 'definition',
|
||||
header: 'Текстовое определение',
|
||||
size: 1000,
|
||||
minSize: 200,
|
||||
maxSize: 1000,
|
||||
cell: props => <div className='text-xs'>{props.getValue()}</div>
|
||||
}),
|
||||
columnHelper.accessor('convention', {
|
||||
id: 'convention',
|
||||
header: 'Конвенция / Комментарий',
|
||||
size: 500,
|
||||
minSize: 100,
|
||||
maxSize: 500,
|
||||
enableHiding: true,
|
||||
cell: props => <div className='text-xs'>{props.getValue()}</div>
|
||||
})
|
||||
], [colors]);
|
||||
|
||||
const tableHeight = useMemo(
|
||||
() => {
|
||||
return !noNavigation ?
|
||||
'calc(100vh - 7.2rem - 4px)'
|
||||
: 'calc(100vh - 4.4rem - 4px)';
|
||||
}, [noNavigation]);
|
||||
|
||||
return (
|
||||
<div className='w-full h-full overflow-auto text-sm min-h-[20rem]' style={{maxHeight: tableHeight}}>
|
||||
<DataTable dense noFooter
|
||||
data={items ?? []}
|
||||
columns={columns}
|
||||
headPosition='0rem'
|
||||
|
||||
onRowDoubleClicked={handleRowDoubleClicked}
|
||||
onRowClicked={handleRowClicked}
|
||||
|
||||
enableHiding
|
||||
columnVisibility={columnVisibility}
|
||||
onColumnVisibilityChange={setColumnVisibility}
|
||||
|
||||
enableRowSelection
|
||||
rowSelection={selected}
|
||||
onRowSelectionChange={setSelected}
|
||||
|
||||
noDataComponent={
|
||||
<span className='flex flex-col justify-center p-2 text-center'>
|
||||
<p>Список пуст</p>
|
||||
<p
|
||||
className='cursor-pointer text-primary hover:underline'
|
||||
onClick={() => onCreateNew()}
|
||||
>
|
||||
Создать новую конституенту
|
||||
</p>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default RSTable;
|
Loading…
Reference in New Issue
Block a user