2023-07-23 15:23:01 +03:00
|
|
|
|
import { CstType, IConstituenta, INewCstData, ParsingStatus, ValueClass, inferStatus } from '../../utils/models'
|
2023-07-15 17:46:19 +03:00
|
|
|
|
import { useCallback, useMemo, useState } from 'react';
|
2023-07-23 15:23:01 +03:00
|
|
|
|
import DataTableThemed from '../../components/Common/DataTableThemed';
|
2023-07-15 17:46:19 +03:00
|
|
|
|
import { useRSForm } from '../../context/RSFormContext';
|
2023-07-20 17:11:03 +03:00
|
|
|
|
import Button from '../../components/Common/Button';
|
|
|
|
|
import { ArrowDownIcon, ArrowUpIcon, ArrowsRotateIcon, DumpBinIcon, SmallPlusIcon } from '../../components/Icons';
|
|
|
|
|
import { toast } from 'react-toastify';
|
|
|
|
|
import Divider from '../../components/Common/Divider';
|
2023-07-23 15:23:01 +03:00
|
|
|
|
import { createAliasFor, getCstTypeLabel, getCstTypePrefix, getStatusInfo, getTypeLabel } from '../../utils/staticUI';
|
2023-07-22 12:24:14 +03:00
|
|
|
|
import CreateCstModal from './CreateCstModal';
|
2023-07-23 15:23:01 +03:00
|
|
|
|
import { AxiosResponse } from 'axios';
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
|
|
|
|
interface ConstituentsTableProps {
|
|
|
|
|
onOpenEdit: (cst: IConstituenta) => void
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ConstituentsTable({onOpenEdit}: ConstituentsTableProps) {
|
2023-07-23 15:23:01 +03:00
|
|
|
|
const { schema, isEditable, cstCreate, reload } = useRSForm();
|
2023-07-15 17:46:19 +03:00
|
|
|
|
const [selectedRows, setSelectedRows] = useState<IConstituenta[]>([]);
|
2023-07-20 17:11:03 +03:00
|
|
|
|
const nothingSelected = useMemo(() => selectedRows.length === 0, [selectedRows]);
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
2023-07-23 15:23:01 +03:00
|
|
|
|
const [showCstModal, setShowCstModal] = useState(false);
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
2023-07-20 17:11:03 +03:00
|
|
|
|
const handleRowClicked = useCallback(
|
|
|
|
|
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
2023-07-22 03:18:48 +03:00
|
|
|
|
if (event.altKey) {
|
2023-07-21 01:50:57 +03:00
|
|
|
|
onOpenEdit(cst);
|
2023-07-20 17:11:03 +03:00
|
|
|
|
}
|
2023-07-21 01:50:57 +03:00
|
|
|
|
}, [onOpenEdit]);
|
2023-07-20 17:11:03 +03:00
|
|
|
|
|
|
|
|
|
const handleDelete = useCallback(() => {
|
|
|
|
|
toast.info('Удаление конституент');
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleMoveUp = useCallback(() => {
|
|
|
|
|
toast.info('Перемещение вверх');
|
|
|
|
|
}, []);
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
2023-07-20 17:11:03 +03:00
|
|
|
|
const handleMoveDown = useCallback(() => {
|
|
|
|
|
toast.info('Перемещение вниз');
|
|
|
|
|
}, []);
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
2023-07-20 17:11:03 +03:00
|
|
|
|
const handleReindex = useCallback(() => {
|
|
|
|
|
toast.info('Переиндексация');
|
|
|
|
|
}, []);
|
|
|
|
|
|
2023-07-23 15:23:01 +03:00
|
|
|
|
const handleAddNew = useCallback((csttype?: CstType) => {
|
|
|
|
|
if (!csttype) {
|
2023-07-22 12:24:14 +03:00
|
|
|
|
setShowCstModal(true);
|
|
|
|
|
} else {
|
2023-07-23 15:23:01 +03:00
|
|
|
|
let data: INewCstData = {
|
|
|
|
|
csttype: csttype,
|
|
|
|
|
alias: createAliasFor(csttype, schema!)
|
|
|
|
|
}
|
|
|
|
|
if (selectedRows.length > 0) {
|
|
|
|
|
data['insert_after'] = selectedRows[selectedRows.length - 1].entityUID
|
|
|
|
|
}
|
|
|
|
|
cstCreate(data, (response: AxiosResponse) => {
|
|
|
|
|
reload();
|
|
|
|
|
toast.info(`Добавлена конституента ${response.data['alias']}`);
|
|
|
|
|
});
|
2023-07-22 12:24:14 +03:00
|
|
|
|
}
|
2023-07-23 15:23:01 +03:00
|
|
|
|
}, [schema, selectedRows, reload, cstCreate]);
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
|
|
|
|
const columns = useMemo(() =>
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
name: 'ID',
|
|
|
|
|
id: 'id',
|
|
|
|
|
selector: (cst: IConstituenta) => cst.entityUID,
|
|
|
|
|
omit: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Статус',
|
|
|
|
|
id: 'status',
|
2023-07-20 17:11:03 +03:00
|
|
|
|
cell: (cst: IConstituenta) =>
|
|
|
|
|
<div style={{fontSize: 12}}>
|
|
|
|
|
{getStatusInfo(inferStatus(cst.parse?.status, cst.parse?.valueClass)).text}
|
|
|
|
|
</div>,
|
2023-07-15 17:46:19 +03:00
|
|
|
|
width: '80px',
|
|
|
|
|
maxWidth: '80px',
|
|
|
|
|
reorder: true,
|
|
|
|
|
hide: 1280,
|
|
|
|
|
conditionalCellStyles: [
|
|
|
|
|
{
|
|
|
|
|
when: (cst: IConstituenta) => cst.parse?.status !== ParsingStatus.VERIFIED,
|
|
|
|
|
classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]']
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
when: (cst: IConstituenta) => cst.parse?.status === ParsingStatus.VERIFIED && cst.parse?.valueClass === ValueClass.INVALID,
|
|
|
|
|
classNames: ['bg-[#beeefa]', 'dark:bg-[#286675]']
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
when: (cst: IConstituenta) => cst.parse?.status === ParsingStatus.VERIFIED && cst.parse?.valueClass === ValueClass.PROPERTY,
|
|
|
|
|
classNames: ['bg-[#a5e9fa]', 'dark:bg-[#36899e]']
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Имя',
|
|
|
|
|
id: 'alias',
|
|
|
|
|
selector: (cst: IConstituenta) => cst.alias,
|
|
|
|
|
width: '65px',
|
|
|
|
|
maxWidth: '65px',
|
|
|
|
|
reorder: true,
|
|
|
|
|
conditionalCellStyles: [
|
|
|
|
|
{
|
|
|
|
|
when: (cst: IConstituenta) => cst.parse?.status !== ParsingStatus.VERIFIED,
|
2023-07-20 17:11:03 +03:00
|
|
|
|
classNames: ['bg-[#ff8080]', 'dark:bg-[#800000]']
|
2023-07-15 17:46:19 +03:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
when: (cst: IConstituenta) => cst.parse?.status === ParsingStatus.VERIFIED && cst.parse?.valueClass === ValueClass.INVALID,
|
2023-07-20 17:11:03 +03:00
|
|
|
|
classNames: ['bg-[#ffbb80]', 'dark:bg-[#964600]']
|
2023-07-15 17:46:19 +03:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
when: (cst: IConstituenta) => cst.parse?.status === ParsingStatus.VERIFIED && cst.parse?.valueClass === ValueClass.PROPERTY,
|
|
|
|
|
classNames: ['bg-[#a5e9fa]', 'dark:bg-[#36899e]']
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Тип',
|
|
|
|
|
id: 'type',
|
2023-07-20 17:11:03 +03:00
|
|
|
|
cell: (cst: IConstituenta) => <div style={{fontSize: 12}}>{getTypeLabel(cst)}</div>,
|
2023-07-15 17:46:19 +03:00
|
|
|
|
width: '140px',
|
|
|
|
|
minWidth: '100px',
|
|
|
|
|
maxWidth: '140px',
|
|
|
|
|
wrap: true,
|
|
|
|
|
reorder: true,
|
|
|
|
|
hide: 1600,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Термин',
|
|
|
|
|
id: 'term',
|
|
|
|
|
selector: (cst: IConstituenta) => cst.term?.resolved || cst.term?.raw || '',
|
|
|
|
|
width: '350px',
|
|
|
|
|
minWidth: '150px',
|
|
|
|
|
maxWidth: '350px',
|
|
|
|
|
wrap: true,
|
|
|
|
|
reorder: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Формальное определение',
|
|
|
|
|
id: 'expression',
|
|
|
|
|
selector: (cst: IConstituenta) => cst.definition?.formal || '',
|
2023-07-20 17:11:03 +03:00
|
|
|
|
minWidth: '300px',
|
2023-07-15 17:46:19 +03:00
|
|
|
|
maxWidth: '500px',
|
2023-07-20 17:11:03 +03:00
|
|
|
|
grow: 2,
|
2023-07-15 17:46:19 +03:00
|
|
|
|
wrap: true,
|
|
|
|
|
reorder: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Текстовое определение',
|
|
|
|
|
id: 'definition',
|
|
|
|
|
cell: (cst: IConstituenta) => (
|
|
|
|
|
<div style={{fontSize: 12}}>
|
|
|
|
|
{cst.definition?.text.resolved || cst.definition?.text.raw || ''}
|
|
|
|
|
</div>
|
|
|
|
|
),
|
|
|
|
|
minWidth: '200px',
|
2023-07-20 17:11:03 +03:00
|
|
|
|
grow: 2,
|
2023-07-15 17:46:19 +03:00
|
|
|
|
wrap: true,
|
|
|
|
|
reorder: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Конвенция / Комментарий',
|
|
|
|
|
id: 'convention',
|
|
|
|
|
cell: (cst: IConstituenta) => <div style={{fontSize: 12}}>{cst.convention || ''}</div>,
|
2023-07-20 17:11:03 +03:00
|
|
|
|
minWidth: '100px',
|
2023-07-15 17:46:19 +03:00
|
|
|
|
wrap: true,
|
|
|
|
|
reorder: true,
|
|
|
|
|
hide: 1800,
|
|
|
|
|
},
|
|
|
|
|
], []
|
|
|
|
|
);
|
|
|
|
|
|
2023-07-22 12:24:14 +03:00
|
|
|
|
return (<>
|
|
|
|
|
<CreateCstModal
|
|
|
|
|
show={showCstModal}
|
|
|
|
|
toggle={() => setShowCstModal(!showCstModal)}
|
|
|
|
|
onCreate={handleAddNew}
|
|
|
|
|
/>
|
2023-07-20 17:11:03 +03:00
|
|
|
|
<div className='w-full'>
|
2023-07-22 12:24:14 +03:00
|
|
|
|
<div className='sticky top-[4rem] z-10 flex justify-start w-full gap-1 px-2 py-1 border-y items-center h-[2.2rem] clr-app'>
|
2023-07-21 18:44:14 +03:00
|
|
|
|
<div className='mr-3 whitespace-nowrap'>Выбраны <span className='ml-2'><b>{selectedRows.length}</b> из {schema?.stats?.count_all || 0}</span></div>
|
|
|
|
|
{isEditable && <div className='flex justify-start w-full gap-1'>
|
|
|
|
|
<Button
|
|
|
|
|
tooltip='Переместить вверх'
|
|
|
|
|
icon={<ArrowUpIcon size={6}/>}
|
|
|
|
|
disabled={nothingSelected}
|
|
|
|
|
dense
|
|
|
|
|
onClick={handleMoveUp}
|
|
|
|
|
/>
|
|
|
|
|
<Button
|
|
|
|
|
tooltip='Переместить вниз'
|
|
|
|
|
icon={<ArrowDownIcon size={6}/>}
|
|
|
|
|
disabled={nothingSelected}
|
|
|
|
|
dense
|
|
|
|
|
onClick={handleMoveDown}
|
|
|
|
|
/>
|
|
|
|
|
<Button
|
|
|
|
|
tooltip='Удалить выбранные'
|
|
|
|
|
icon={<DumpBinIcon color={!nothingSelected ? 'text-red': ''} size={6}/>}
|
|
|
|
|
disabled={nothingSelected}
|
|
|
|
|
dense
|
|
|
|
|
onClick={handleDelete}
|
|
|
|
|
/>
|
|
|
|
|
<Divider vertical margins='1' />
|
|
|
|
|
<Button
|
|
|
|
|
tooltip='Переиндексировать имена'
|
|
|
|
|
icon={<ArrowsRotateIcon color='text-primary' size={6}/>}
|
|
|
|
|
dense
|
|
|
|
|
onClick={handleReindex}
|
|
|
|
|
/>
|
|
|
|
|
<Button
|
|
|
|
|
tooltip='Новая конституента'
|
|
|
|
|
icon={<SmallPlusIcon color='text-green' size={6}/>}
|
|
|
|
|
dense
|
|
|
|
|
onClick={() => handleAddNew()}
|
|
|
|
|
/>
|
|
|
|
|
{(Object.values(CstType)).map(
|
|
|
|
|
(typeStr) => {
|
|
|
|
|
const type = typeStr as CstType;
|
|
|
|
|
return <Button
|
|
|
|
|
text={`${getCstTypePrefix(type)}`}
|
|
|
|
|
tooltip={getCstTypeLabel(type)}
|
|
|
|
|
dense
|
|
|
|
|
onClick={() =>handleAddNew(type)}
|
|
|
|
|
/>;
|
|
|
|
|
})}
|
|
|
|
|
</div>}
|
2023-07-20 17:11:03 +03:00
|
|
|
|
</div>
|
|
|
|
|
<DataTableThemed
|
|
|
|
|
data={schema!.items!}
|
|
|
|
|
columns={columns}
|
|
|
|
|
keyField='id'
|
2023-07-23 15:23:01 +03:00
|
|
|
|
noDataComponent={
|
|
|
|
|
<span className='flex flex-col justify-center p-2 text-center'>
|
|
|
|
|
<p>Список пуст</p>
|
|
|
|
|
<p>Создайте новую конституенту</p>
|
|
|
|
|
</span>
|
|
|
|
|
}
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
2023-07-20 17:11:03 +03:00
|
|
|
|
striped
|
|
|
|
|
highlightOnHover
|
|
|
|
|
pointerOnHover
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
2023-07-20 17:11:03 +03:00
|
|
|
|
selectableRows
|
|
|
|
|
selectableRowsHighlight
|
2023-07-23 15:23:01 +03:00
|
|
|
|
onSelectedRowsChange={({selectedRows}) => setSelectedRows(selectedRows)}
|
2023-07-20 17:11:03 +03:00
|
|
|
|
onRowDoubleClicked={onOpenEdit}
|
|
|
|
|
onRowClicked={handleRowClicked}
|
|
|
|
|
dense
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2023-07-22 12:24:14 +03:00
|
|
|
|
</>);
|
2023-07-15 17:46:19 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default ConstituentsTable;
|