) {
+ if (!schema) {
setSelected([]);
} else {
- const selected: number[] = [];
- schema.items.forEach((cst, index) => {
- if (rowSelection[String(index)] === true) {
- selected.push(cst.id);
+ const newRowSelection = typeof updater === 'function' ? updater(rowSelection) : updater;
+ const newSelection: number[] = [];
+ schema?.items.forEach((cst, index) => {
+ if (newRowSelection[String(index)] === true) {
+ newSelection.push(cst.id);
}
});
- setSelected(selected);
+ setSelected(newSelection);
}
- }, [rowSelection, schema]);
-
- // Delete selected constituents
- function handleDelete() {
- if (!schema) {
- return;
- }
- onDeleteCst(selected, () => {
- setRowSelection({});
- });
}
// Move selected cst up
@@ -65,13 +78,7 @@ function EditorRSList({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Edito
items: selected,
move_to: target
};
- cstMoveTo(data, () => {
- const newSelection: RowSelectionState = {};
- selected.forEach((_, index) => {
- newSelection[String(target + index - 1)] = true;
- });
- setRowSelection(newSelection);
- });
+ cstMoveTo(data);
}
// Move selected cst down
@@ -96,57 +103,7 @@ function EditorRSList({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Edito
items: selected,
move_to: target
};
- cstMoveTo(data, () => {
- const newSelection: RowSelectionState = {};
- selected.forEach((_, index) => {
- newSelection[String(target + index - 1)] = true;
- });
- setRowSelection(newSelection);
- });
- }
-
- 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: '',
- term_forms: []
- };
- onCreateCst(data, type !== undefined);
- }
-
- // Clone selected
- function handleClone() {
- if (selected.length < 1 || !schema) {
- return;
- }
- const activeCst = schema.items.find(cst => cst.id === selected[0]);
- if (!activeCst) {
- return;
- }
- const data: ICstCreateData = {
- insert_after: activeCst.id,
- cst_type: activeCst.cst_type,
- alias: '',
- term_raw: activeCst.term_raw,
- definition_formal: activeCst.definition_formal,
- definition_raw: activeCst.definition_raw,
- convention: activeCst.convention,
- term_forms: activeCst.term_forms
- };
- onCreateCst(data, true);
+ cstMoveTo(data);
}
// Implement hotkeys for working with constituents table
@@ -156,7 +113,7 @@ function EditorRSList({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Edito
}
if (event.key === 'Delete' && selected.length > 0) {
event.preventDefault();
- handleDelete();
+ onDelete();
return;
}
if (!event.altKey || event.shiftKey) {
@@ -174,21 +131,21 @@ function EditorRSList({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Edito
switch (code) {
case 'ArrowUp': handleMoveUp(); return true;
case 'ArrowDown': handleMoveDown(); return true;
- case 'KeyV': handleClone(); return true;
+ case 'KeyV': onClone(); return true;
}
}
// prettier-ignore
switch (code) {
- case 'Backquote': handleCreateCst(); return true;
+ case 'Backquote': onCreate(); 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 'Digit1': onCreate(CstType.BASE); return true;
+ case 'Digit2': onCreate(CstType.STRUCTURED); return true;
+ case 'Digit3': onCreate(CstType.TERM); return true;
+ case 'Digit4': onCreate(CstType.AXIOM); return true;
+ case 'KeyQ': onCreate(CstType.FUNCTION); return true;
+ case 'KeyW': onCreate(CstType.PREDICATE); return true;
+ case 'Digit5': onCreate(CstType.CONSTANT); return true;
+ case 'Digit6': onCreate(CstType.THEOREM); return true;
}
return false;
}
@@ -196,8 +153,8 @@ function EditorRSList({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Edito
return (
@@ -206,9 +163,9 @@ function EditorRSList({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Edito
isMutable={isMutable}
onMoveUp={handleMoveUp}
onMoveDown={handleMoveDown}
- onClone={handleClone}
- onCreate={handleCreateCst}
- onDelete={handleDelete}
+ onClone={onClone}
+ onCreate={onCreate}
+ onDelete={onDelete}
/>
@@ -216,9 +173,9 @@ function EditorRSList({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Edito
handleCreateCst()}
+ onCreateNew={onCreate}
/>
);
diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx
index d781c53c..fcca1bdc 100644
--- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx
+++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx
@@ -67,6 +67,7 @@ function RSListToolbar({
}
disabled={!isMutable}
onClick={insertMenu.toggle}
diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx
index 273c15cf..87c74013 100644
--- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx
+++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx
@@ -8,12 +8,11 @@ import { GraphEdge, GraphNode, LayoutTypes } from 'reagraph';
import InfoConstituenta from '@/components/InfoConstituenta';
import SelectedCounter from '@/components/SelectedCounter';
import Overlay from '@/components/ui/Overlay';
-import { useRSForm } from '@/context/RSFormContext';
import { useConceptTheme } from '@/context/ThemeContext';
import DlgGraphParams from '@/dialogs/DlgGraphParams';
import useLocalStorage from '@/hooks/useLocalStorage';
import { GraphColoringScheme, GraphFilterParams } from '@/models/miscellaneous';
-import { CstType, ICstCreateData } from '@/models/rsform';
+import { CstType, IRSForm } from '@/models/rsform';
import { colorBgGraphNode } from '@/styling/color';
import { classnames, TIMEOUT_GRAPH_REFRESH } from '@/utils/constants';
@@ -25,16 +24,25 @@ import ViewHidden from './ViewHidden';
interface EditorTermGraphProps {
isMutable: boolean;
+ selected: number[];
+ schema?: IRSForm;
+ setSelected: React.Dispatch>;
onOpenEdit: (cstID: number) => void;
- onCreateCst: (initial: ICstCreateData, skipDialog?: boolean) => void;
- onDeleteCst: (selected: number[], callback: (items: number[]) => void) => void;
+ onCreate: (type: CstType, definition: string) => void;
+ onDelete: () => void;
}
-function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGraphProps) {
- const { schema } = useRSForm();
+function EditorTermGraph({
+ schema,
+ selected,
+ setSelected,
+ isMutable,
+ onOpenEdit,
+ onCreate,
+ onDelete
+}: EditorTermGraphProps) {
const { colors } = useConceptTheme();
- const [toggleDataUpdate, setToggleDataUpdate] = useState(false);
const [filterParams, setFilterParams] = useLocalStorage('graph_filter', {
noHermits: true,
noTemplates: false,
@@ -51,14 +59,10 @@ function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Ed
allowTheorem: true
});
const [showParamsDialog, setShowParamsDialog] = useState(false);
- const filtered = useGraphFilter(schema, filterParams, toggleDataUpdate);
+ const filtered = useGraphFilter(schema, filterParams);
- const [selectedGraph, setSelectedGraph] = useState([]);
const [hidden, setHidden] = useState([]);
- const [selectedHidden, setSelectedHidden] = useState([]);
- const selected: number[] = useMemo(() => {
- return [...selectedHidden, ...selectedGraph];
- }, [selectedHidden, selectedGraph]);
+
const nothingSelected = useMemo(() => selected.length === 0, [selected]);
const [layout, setLayout] = useLocalStorage('graph_layout', 'treeTd2d');
@@ -72,7 +76,6 @@ function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Ed
}, [schema?.items, hoverID]);
const [toggleResetView, setToggleResetView] = useState(false);
- const [toggleResetSelection, setToggleResetSelection] = useState(false);
useLayoutEffect(() => {
if (!schema) {
@@ -85,9 +88,8 @@ function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Ed
}
});
setHidden(newDismissed);
- setSelectedHidden([]);
setHoverID(undefined);
- }, [schema, filtered, toggleDataUpdate]);
+ }, [schema, filtered]);
const nodes: GraphNode[] = useMemo(() => {
const result: GraphNode[] = [];
@@ -123,15 +125,20 @@ function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Ed
return result;
}, [filtered.nodes]);
+ const handleGraphSelection = useCallback(
+ (newID: number) => {
+ setSelected(prev => [...prev, newID]);
+ },
+ [setSelected]
+ );
+
function toggleDismissed(cstID: number) {
- setSelectedHidden(prev => {
- const index = prev.findIndex(id => cstID === id);
- if (index !== -1) {
- prev.splice(index, 1);
+ setSelected(prev => {
+ if (prev.includes(cstID)) {
+ return [...prev.filter(id => id !== cstID)];
} else {
- prev.push(cstID);
+ return [...prev, cstID];
}
- return [...prev];
});
}
@@ -139,29 +146,15 @@ function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Ed
if (!schema) {
return;
}
- const data: ICstCreateData = {
- insert_after: null,
- cst_type: selected.length === 0 ? CstType.BASE : CstType.TERM,
- alias: '',
- term_raw: '',
- definition_formal: selected.map(id => schema.items.find(cst => cst.id === id)!.alias).join(' '),
- definition_raw: '',
- convention: '',
- term_forms: []
- };
- onCreateCst(data);
+ const definition = selected.map(id => schema.items.find(cst => cst.id === id)!.alias).join(' ');
+ onCreate(selected.length === 0 ? CstType.BASE : CstType.TERM, definition);
}
function handleDeleteCst() {
if (!schema || selected.length === 0) {
return;
}
- onDeleteCst(selected, () => {
- setHidden([]);
- setSelectedHidden([]);
- setToggleResetSelection(prev => !prev);
- setToggleDataUpdate(prev => !prev);
- });
+ onDelete();
}
function handleChangeLayout(newLayout: LayoutTypes) {
@@ -206,8 +199,8 @@ function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Ed
@@ -249,7 +242,7 @@ function EditorTermGraph({ isMutable, onOpenEdit, onCreateCst, onDeleteCst }: Ed
/>
setSelectedHidden([])}
+ onDeselectAll={() => setSelected([])}
toggleResetView={toggleResetView}
- toggleResetSelection={toggleResetSelection}
/>
);
diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx
index b75bc93a..50064c7b 100644
--- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx
+++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx
@@ -10,18 +10,18 @@ import { resources } from '@/utils/constants';
interface TermGraphProps {
nodes: GraphNode[];
edges: GraphEdge[];
+ selectedIDs: number[];
layout: LayoutTypes;
is3D: boolean;
orbit: boolean;
- setSelected: (selected: number[]) => void;
setHoverID: (newID: number | undefined) => void;
onEdit: (cstID: number) => void;
- onDeselect: () => void;
+ onSelect: (newID: number) => void;
+ onDeselectAll: () => void;
toggleResetView: boolean;
- toggleResetSelection: boolean;
}
const TREE_SIZE_MILESTONE = 50;
@@ -29,29 +29,28 @@ const TREE_SIZE_MILESTONE = 50;
function TermGraph({
nodes,
edges,
+ selectedIDs,
layout,
is3D,
orbit,
toggleResetView,
- toggleResetSelection,
setHoverID,
onEdit,
- setSelected,
- onDeselect
+ onSelect,
+ onDeselectAll
}: TermGraphProps) {
const { noNavigation, darkMode } = useConceptTheme();
const graphRef = useRef(null);
- const { selections, actives, onNodeClick, clearSelections, onCanvasClick, onNodePointerOver, onNodePointerOut } =
- useSelection({
- ref: graphRef,
- nodes,
- edges,
- type: 'multi', // 'single' | 'multi' | 'multiModifier'
- pathSelectionType: 'out',
- pathHoverType: 'all',
- focusOnSelect: false
- });
+ const { selections, actives, setSelections, onCanvasClick, onNodePointerOver, onNodePointerOut } = useSelection({
+ ref: graphRef,
+ nodes,
+ edges,
+ type: 'multi', // 'single' | 'multi' | 'multiModifier'
+ pathSelectionType: 'out',
+ pathHoverType: 'all',
+ focusOnSelect: false
+ });
const handleHoverIn = useCallback(
(node: GraphNode) => {
@@ -73,19 +72,19 @@ function TermGraph({
(node: GraphNode) => {
if (selections.includes(node.id)) {
onEdit(Number(node.id));
- return;
+ } else {
+ onSelect(Number(node.id));
}
- if (onNodeClick) onNodeClick(node);
},
- [onNodeClick, selections, onEdit]
+ [onSelect, selections, onEdit]
);
const handleCanvasClick = useCallback(
(event: MouseEvent) => {
- onDeselect();
+ onDeselectAll();
if (onCanvasClick) onCanvasClick(event);
},
- [onCanvasClick, onDeselect]
+ [onCanvasClick, onDeselectAll]
);
useLayoutEffect(() => {
@@ -94,12 +93,9 @@ function TermGraph({
}, [toggleResetView]);
useLayoutEffect(() => {
- clearSelections();
- }, [toggleResetSelection, clearSelections]);
-
- useLayoutEffect(() => {
- setSelected(selections.map(id => Number(id)));
- }, [selections, setSelected]);
+ const newSelections = nodes.filter(node => selectedIDs.includes(Number(node.id))).map(node => node.id);
+ setSelections(newSelections);
+ }, [selectedIDs, setSelections, nodes]);
const canvasWidth = useMemo(() => {
return 'calc(100vw - 1.1rem)';
diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts
index 74cb5a9c..797d4aef 100644
--- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts
+++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts
@@ -1,10 +1,10 @@
import { useLayoutEffect, useMemo, useState } from 'react';
+import { Graph } from '@/models/Graph';
import { GraphFilterParams } from '@/models/miscellaneous';
import { CstType, IRSForm } from '@/models/rsform';
-import { Graph } from '@/models/Graph';
-function useGraphFilter(schema: IRSForm | undefined, params: GraphFilterParams, toggleUpdate: boolean) {
+function useGraphFilter(schema: IRSForm | undefined, params: GraphFilterParams) {
const [filtered, setFiltered] = useState(new Graph());
const allowedTypes: CstType[] = useMemo(() => {
@@ -47,7 +47,7 @@ function useGraphFilter(schema: IRSForm | undefined, params: GraphFilterParams,
});
}
setFiltered(graph);
- }, [schema, params, allowedTypes, toggleUpdate]);
+ }, [schema, params, allowedTypes]);
return filtered;
}
diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx
index 207d4fed..e09e0287 100644
--- a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx
+++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx
@@ -28,7 +28,7 @@ import DlgRenameCst from '@/dialogs/DlgRenameCst';
import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm';
import useQueryStrings from '@/hooks/useQueryStrings';
import { UserAccessMode } from '@/models/miscellaneous';
-import { IConstituenta, ICstCreateData, ICstRenameData, ICstUpdateData, TermForm } from '@/models/rsform';
+import { CstType, IConstituenta, ICstCreateData, ICstRenameData, ICstUpdateData, TermForm } from '@/models/rsform';
import { generateAlias } from '@/models/rsformAPI';
import { EXTEOR_TRS_FILE, prefixes, TIMEOUT_UI_REFRESH } from '@/utils/constants';
@@ -85,14 +85,18 @@ function RSTabs() {
);
}, [user?.is_staff, mode, isOwned, loading, processing]);
- const [activeID, setActiveID] = useState(undefined);
- const activeCst = useMemo(() => schema?.items?.find(cst => cst.id === activeID), [schema?.items, activeID]);
+ const [selected, setSelected] = useState([]);
+ const activeCst: IConstituenta | undefined = useMemo(() => {
+ if (!schema || selected.length === 0) {
+ return undefined;
+ } else {
+ return schema.items.find(cst => cst.id === selected.at(-1));
+ }
+ }, [schema, selected]);
const [showUpload, setShowUpload] = useState(false);
const [showClone, setShowClone] = useState(false);
- const [afterDelete, setAfterDelete] = useState<((items: number[]) => void) | undefined>(undefined);
- const [toBeDeleted, setToBeDeleted] = useState([]);
const [showDeleteCst, setShowDeleteCst] = useState(false);
const [createInitialData, setCreateInitialData] = useState();
@@ -118,10 +122,19 @@ function RSTabs() {
useLayoutEffect(() => {
setNoFooter(activeTab === RSTabID.CST_EDIT || activeTab === RSTabID.CST_LIST);
- setActiveID(Number(cstQuery) ?? (schema && schema?.items.length > 0 ? schema.items[0].id : undefined));
setIsModified(false);
+ if (activeTab === RSTabID.CST_EDIT) {
+ const cstID = Number(cstQuery);
+ if (cstID && schema && schema.items.find(cst => cst.id === cstID)) {
+ setSelected([cstID]);
+ } else if (schema && schema?.items.length > 0) {
+ setSelected([schema.items[0].id]);
+ } else {
+ setSelected([]);
+ }
+ }
return () => setNoFooter(false);
- }, [activeTab, cstQuery, setActiveID, schema, setNoFooter, setIsModified]);
+ }, [activeTab, cstQuery, setSelected, schema, setNoFooter, setIsModified]);
useLayoutEffect(
() =>
@@ -137,10 +150,6 @@ function RSTabs() {
[schema, setMode, isOwned]
);
- function onSelectTab(index: number) {
- navigateTab(index, activeID);
- }
-
const navigateTab = useCallback(
(tab: RSTabID, activeID?: number) => {
if (!schema) {
@@ -162,6 +171,10 @@ function RSTabs() {
[router, schema, activeTab]
);
+ function onSelectTab(index: number) {
+ navigateTab(index, selected.length > 0 ? selected.at(-1) : undefined);
+ }
+
const handleCreateCst = useCallback(
(data: ICstCreateData) => {
if (!schema?.items) {
@@ -189,17 +202,44 @@ function RSTabs() {
);
const promptCreateCst = useCallback(
- (initialData: ICstCreateData, skipDialog?: boolean) => {
+ (type: CstType | undefined, skipDialog: boolean, definition?: string) => {
+ const data: ICstCreateData = {
+ insert_after: activeCst?.id ?? null,
+ cst_type: type ?? activeCst?.cst_type ?? CstType.BASE,
+ alias: '',
+ term_raw: '',
+ definition_formal: definition ?? '',
+ definition_raw: '',
+ convention: '',
+ term_forms: []
+ };
if (skipDialog) {
- handleCreateCst(initialData);
+ handleCreateCst(data);
} else {
- setCreateInitialData(initialData);
+ setCreateInitialData(data);
setShowCreateCst(true);
}
},
- [handleCreateCst]
+ [handleCreateCst, activeCst]
);
+ const handleCloneCst = useCallback(() => {
+ if (!activeCst) {
+ return;
+ }
+ const data: ICstCreateData = {
+ insert_after: activeCst.id,
+ cst_type: activeCst.cst_type,
+ alias: '',
+ term_raw: activeCst.term_raw,
+ definition_formal: activeCst.definition_formal,
+ definition_raw: activeCst.definition_raw,
+ convention: activeCst.convention,
+ term_forms: activeCst.term_forms
+ };
+ handleCreateCst(data);
+ }, [activeCst, handleCreateCst]);
+
const handleRenameCst = useCallback(
(data: ICstRenameData) => {
cstRename(data, () => toast.success(`Переименование: ${renameInitialData!.alias} -> ${data.alias}`));
@@ -207,10 +247,18 @@ function RSTabs() {
[cstRename, renameInitialData]
);
- const promptRenameCst = useCallback((initialData: ICstRenameData) => {
- setRenameInitialData(initialData);
+ const promptRenameCst = useCallback(() => {
+ if (!activeCst) {
+ return;
+ }
+ const data: ICstRenameData = {
+ id: activeCst.id,
+ alias: activeCst.alias,
+ cst_type: activeCst.cst_type
+ };
+ setRenameInitialData(data);
setShowRenameCst(true);
- }, []);
+ }, [activeCst]);
const onReindex = useCallback(() => resetAliases(() => toast.success('Имена конституент обновлены')), [resetAliases]);
@@ -225,33 +273,26 @@ function RSTabs() {
const deletedNames = deleted.map(id => schema.items.find(cst => cst.id === id)?.alias).join(', ');
const isEmpty = deleted.length === schema.items.length;
- const nextActive = isEmpty ? undefined : getNextActiveOnDelete(activeID, schema.items, deleted);
+ const nextActive = isEmpty ? undefined : getNextActiveOnDelete(activeCst?.id, schema.items, deleted);
cstDelete(data, () => {
toast.success(`Конституенты удалены: ${deletedNames}`);
if (isEmpty) {
navigateTab(RSTabID.CST_LIST);
- } else if (!nextActive) {
- navigateTab(activeTab);
- } else {
+ } else if (activeTab === RSTabID.CST_EDIT) {
navigateTab(activeTab, nextActive);
+ } else {
+ setSelected(nextActive ? [nextActive] : []);
+ navigateTab(activeTab);
}
- if (afterDelete) afterDelete(deleted);
});
},
- [afterDelete, cstDelete, schema, activeID, activeTab, navigateTab]
+ [cstDelete, schema, activeTab, activeCst, navigateTab]
);
- const promptDeleteCst = useCallback((selected: number[], callback?: (items: number[]) => void) => {
- setAfterDelete(() => (items: number[]) => {
- if (callback) callback(items);
- });
- setToBeDeleted(selected);
- setShowDeleteCst(true);
- }, []);
-
const onOpenCst = useCallback(
(cstID: number) => {
+ setSelected([cstID]);
navigateTab(RSTabID.CST_EDIT, cstID);
},
[navigateTab]
@@ -334,16 +375,16 @@ function RSTabs() {
const handleSaveWordforms = useCallback(
(forms: TermForm[]) => {
- if (!activeID) {
+ if (!activeCst) {
return;
}
const data: ICstUpdateData = {
- id: activeID,
+ id: activeCst.id,
term_forms: forms
};
cstUpdate(data, () => toast.success('Изменения сохранены'));
},
- [cstUpdate, activeID]
+ [cstUpdate, activeCst]
);
return (
@@ -371,7 +412,7 @@ function RSTabs() {
schema={schema!}
hideWindow={() => setShowDeleteCst(false)}
onDelete={handleDeleteCst}
- selected={toBeDeleted}
+ selected={selected}
/>
) : null}
{showEditTerm ? (
@@ -438,34 +479,41 @@ function RSTabs() {
promptCreateCst(type, type !== undefined)}
+ onDelete={() => setShowDeleteCst(true)}
/>
promptCreateCst(type, false)}
+ onDelete={() => setShowDeleteCst(true)}
+ onRename={promptRenameCst}
onEditTerm={promptShowEditTerm}
/>
promptCreateCst(type, false, definition)}
+ onDelete={() => setShowDeleteCst(true)}
/>
diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx
index bbb4b591..0de90e4d 100644
--- a/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx
+++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx
@@ -118,6 +118,7 @@ function RSTabsMenu({
dense
tabIndex={-1}
title='Меню'
+ hideTitle={schemaMenu.isOpen}
icon={}
className='h-full pl-2'
style={{ outlineColor: 'transparent' }}
@@ -172,6 +173,7 @@ function RSTabsMenu({
noBorder
tabIndex={-1}
title={'Редактирование'}
+ hideTitle={editMenu.isOpen}
className='h-full'
style={{ outlineColor: 'transparent' }}
icon={}
@@ -201,6 +203,7 @@ function RSTabsMenu({
noBorder
tabIndex={-1}
title={`Режим ${labelAccessMode(mode)}`}
+ hideTitle={accessMenu.isOpen}
className='h-full pr-2'
style={{ outlineColor: 'transparent' }}
icon={
diff --git a/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsSearch.tsx b/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsSearch.tsx
index bfc2d2de..f1c830fb 100644
--- a/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsSearch.tsx
+++ b/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsSearch.tsx
@@ -82,6 +82,7 @@ function ConstituentsSearch({ schema, activeID, activeExpression, setFiltered }:
transparent
tabIndex={-1}
title='Настройка атрибутов для фильтрации'
+ hideTitle={matchModeMenu.isOpen}
className='h-full'
icon={}
text={labelCstMatchMode(filterMatch)}
@@ -94,6 +95,7 @@ function ConstituentsSearch({ schema, activeID, activeExpression, setFiltered }:
const matchMode = value as CstMatchMode;
return (
handleMatchModeChange(matchMode)}
>
@@ -111,6 +113,7 @@ function ConstituentsSearch({ schema, activeID, activeExpression, setFiltered }:
transparent
tabIndex={-1}
title='Настройка фильтрации по графу термов'
+ hideTitle={sourceMenu.isOpen}
className='h-full pr-2'
icon={}
text={labelCstSource(filterSource)}
@@ -122,7 +125,11 @@ function ConstituentsSearch({ schema, activeID, activeExpression, setFiltered }:
.map((value, index) => {
const source = value as DependencyMode;
return (
- handleSourceChange(source)}>
+ handleSourceChange(source)}
+ >
{labelCstSource(source)}: {describeCstSource(source)}