import { useCallback, useMemo, useState } from 'react'; import { toast } from 'react-toastify'; import Button from '../../components/Common/Button'; import ConceptDataTable from '../../components/Common/ConceptDataTable'; import ConceptTooltip from '../../components/Common/ConceptTooltip'; import Divider from '../../components/Common/Divider'; import CstStatusInfo from '../../components/Help/InfoCstStatus'; import { ArrowDownIcon, ArrowsRotateIcon, ArrowUpIcon, DumpBinIcon, HelpIcon, SmallPlusIcon } from '../../components/Icons'; import { useRSForm } from '../../context/RSFormContext'; import { useConceptTheme } from '../../context/ThemeContext'; import { prefixes } from '../../utils/constants'; import { CstType, IConstituenta, ICstCreateData, ICstMovetoData } from '../../utils/models' import { getCstTypePrefix, getCstTypeShortcut, getCstTypificationLabel, mapStatusInfo } from '../../utils/staticUI'; interface EditorItemsProps { onOpenEdit: (cstID: number) => void onCreateCst: (initial: ICstCreateData, skipDialog?: boolean) => void onDeleteCst: (selected: number[], callback: (items: number[]) => void) => void } function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps) { const { schema, isEditable, cstMoveTo, resetAliases } = useRSForm(); const { noNavigation } = useConceptTheme(); const [selected, setSelected] = useState([]); const nothingSelected = useMemo(() => selected.length === 0, [selected]); const [toggledClearRows, setToggledClearRows] = useState(false); // Delete selected constituents function handleDelete() { if (!schema) { return; } onDeleteCst(selected, () => { setToggledClearRows(prev => !prev); setSelected([]); }); } // Move selected cst up function handleMoveUp() { if (!schema?.items || selected.length === 0) { return; } const currentIndex = schema.items.reduce((prev, cst, index) => { if (!selected.includes(cst.id)) { return prev; } else if (prev === -1) { return index; } return Math.min(prev, index); }, -1); const target = Math.max(0, currentIndex - 1) + 1 const data = { items: selected.map(id => { return { id: id }; }), move_to: target } cstMoveTo(data); } // Move selected cst down function handleMoveDown() { if (!schema?.items || selected.length === 0) { return; } let count = 0; const currentIndex = schema.items.reduce((prev, cst, index) => { if (!selected.includes(cst.id)) { return prev; } else { count += 1; if (prev === -1) { return index; } return Math.max(prev, index); } }, -1); const target = Math.min(schema.items.length - 1, currentIndex - count + 2) + 1 const data: ICstMovetoData = { items: selected.map(id => { return { id: id }; }), move_to: target } cstMoveTo(data); } // Generate new names for all constituents function handleReindex() { resetAliases(() => toast.success('Переиндексация конституент успешна')); } // Add new constituenta function handleCreateCst(type?: CstType) { if (!schema) { return; } const selectedPosition = selected.reduce((prev, cstID) => { const position = schema.items.findIndex(cst => cst.id === cstID); return Math.max(position, prev); }, -1); const insert_where = selectedPosition >= 0 ? schema.items[selectedPosition].id : undefined; const data: ICstCreateData = { insert_after: insert_where ?? null, cst_type: type ?? CstType.BASE, alias: '', term_raw: '', definition_formal: '', definition_raw: '', convention: '', }; onCreateCst(data, type !== undefined); } // Implement hotkeys for working with constituents table function handleTableKey(event: React.KeyboardEvent) { if (!isEditable) { return; } if (event.key === 'Delete' && selected.length > 0) { event.preventDefault(); handleDelete(); return; } if (!event.altKey || event.shiftKey) { return; } if (processAltKey(event.key)) { event.preventDefault(); return; } } function processAltKey(key: string): boolean { if (selected.length > 0) { switch (key) { case 'ArrowUp': handleMoveUp(); return true; case 'ArrowDown': handleMoveDown(); return true; } } switch (key) { case '1': handleCreateCst(CstType.BASE); return true; case '2': handleCreateCst(CstType.STRUCTURED); return true; case '3': handleCreateCst(CstType.TERM); return true; case '4': handleCreateCst(CstType.AXIOM); return true; case 'q': handleCreateCst(CstType.FUNCTION); return true; case 'w': handleCreateCst(CstType.PREDICATE); return true; case '5': handleCreateCst(CstType.CONSTANT); return true; case '6': handleCreateCst(CstType.THEOREM); return true; } return false; } const handleRowClicked = useCallback( (cst: IConstituenta, event: React.MouseEvent) => { if (event.altKey) { onOpenEdit(cst.id); } }, [onOpenEdit]); const handleSelectionChange = useCallback( ({ selectedRows }: { allSelected: boolean selectedCount: number selectedRows: IConstituenta[] }) => { setSelected(selectedRows.map(cst => cst.id)); }, [setSelected]); const columns = useMemo( () => [ { name: 'ID', id: 'id', selector: (cst: IConstituenta) => cst.id, omit: true }, { name: 'Имя', id: 'alias', selector: (cst: IConstituenta) => cst.alias, cell: (cst: IConstituenta) => { const info = mapStatusInfo.get(cst.status)!; return (<>
{cst.alias}

Статус: {info.tooltip}

); }, width: '65px', maxWidth: '65px', reorder: true, }, { name: 'Тип', id: 'type', cell: (cst: IConstituenta) =>
{getCstTypificationLabel(cst)}
, width: '175px', maxWidth: '175px', 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 ?? '', minWidth: '300px', maxWidth: '500px', grow: 2, wrap: true, reorder: true }, { name: 'Текстовое определение', id: 'definition', cell: (cst: IConstituenta) => (
{cst.definition?.text.resolved ?? cst.definition?.text.raw ?? ''}
), minWidth: '200px', grow: 2, wrap: true, reorder: true }, { name: 'Конвенция / Комментарий', id: 'convention', cell: (cst: IConstituenta) =>
{cst.convention ?? ''}
, minWidth: '100px', wrap: true, reorder: true, hide: 1800 } ], []); return (
Выбраны {selected.length} из {schema?.stats?.count_all ?? 0}

Список пуст

Создайте новую конституенту

} striped highlightOnHover pointerOnHover selectableRows selectableRowsHighlight onSelectedRowsChange={handleSelectionChange} onRowDoubleClicked={cst => onOpenEdit(cst.id)} onRowClicked={handleRowClicked} clearSelectedRows={toggledClearRows} dense />
); } export default EditorItems;