mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 12:50:37 +03:00
F: Implement TermGraph view
This commit is contained in:
parent
bc7195d617
commit
aeebbc6d5b
|
@ -131,6 +131,9 @@ const DlgOssSettings = React.lazy(() =>
|
||||||
const DlgEditCst = React.lazy(() =>
|
const DlgEditCst = React.lazy(() =>
|
||||||
import('@/features/rsform/dialogs/dlg-edit-cst').then(module => ({ default: module.DlgEditCst }))
|
import('@/features/rsform/dialogs/dlg-edit-cst').then(module => ({ default: module.DlgEditCst }))
|
||||||
);
|
);
|
||||||
|
const DlgShowTermGraph = React.lazy(() =>
|
||||||
|
import('@/features/oss/dialogs/dlg-show-term-graph').then(module => ({ default: module.DlgShowTermGraph }))
|
||||||
|
);
|
||||||
|
|
||||||
export const GlobalDialogs = () => {
|
export const GlobalDialogs = () => {
|
||||||
const active = useDialogsStore(state => state.active);
|
const active = useDialogsStore(state => state.active);
|
||||||
|
@ -193,5 +196,7 @@ export const GlobalDialogs = () => {
|
||||||
return <DlgUploadRSForm />;
|
return <DlgUploadRSForm />;
|
||||||
case DialogType.EDIT_CONSTITUENTA:
|
case DialogType.EDIT_CONSTITUENTA:
|
||||||
return <DlgEditCst />;
|
return <DlgEditCst />;
|
||||||
|
case DialogType.SHOW_TERM_GRAPH:
|
||||||
|
return <DlgShowTermGraph />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { ReactFlowProvider } from 'reactflow';
|
||||||
import { urls, useConceptNavigation } from '@/app';
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
// import { useDialogsStore } from '@/stores/dialogs';
|
// import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { type IRSForm } from '@/features/rsform';
|
import { type IRSForm } from '@/features/rsform';
|
||||||
import { TGFlow } from '@/features/rsform/pages/rsform-page/editor-term-graph/tg-flow';
|
|
||||||
import { RSTabID } from '@/features/rsform/pages/rsform-page/rsedit-context';
|
import { RSTabID } from '@/features/rsform/pages/rsform-page/rsedit-context';
|
||||||
|
|
||||||
import { MiniButton } from '@/components/control';
|
import { MiniButton } from '@/components/control';
|
||||||
|
@ -12,6 +11,8 @@ import { IconRSForm } from '@/components/icons';
|
||||||
import { ModalView } from '@/components/modal';
|
import { ModalView } from '@/components/modal';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
|
import { TGReadonlyFlow } from './tg-readonly-flow';
|
||||||
|
|
||||||
export interface DlgShowTermGraphProps {
|
export interface DlgShowTermGraphProps {
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
}
|
}
|
||||||
|
@ -32,20 +33,16 @@ export function DlgShowTermGraph() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalView
|
<ModalView className='relative w-[calc(100dvw-3rem)] h-[calc(100dvh-3rem)]' fullScreen header='Граф термов'>
|
||||||
className='relative w-[calc(100dvw-3rem)] h-[calc(100dvh-3rem)] cc-mask-sides'
|
|
||||||
fullScreen
|
|
||||||
header='Граф термов'
|
|
||||||
>
|
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Открыть концептуальную схему'
|
title='Открыть концептуальную схему'
|
||||||
noPadding
|
noPadding
|
||||||
|
className='absolute z-pop top-2 left-2'
|
||||||
icon={<IconRSForm size='1.25rem' className='text-primary' />}
|
icon={<IconRSForm size='1.25rem' className='text-primary' />}
|
||||||
onClick={navigateToSchema}
|
onClick={navigateToSchema}
|
||||||
/>
|
/>
|
||||||
<ReactFlowProvider>
|
<ReactFlowProvider>
|
||||||
{/* TGFlow expects schema from context, so you may need to refactor TGFlow to accept schema as prop if needed */}
|
<TGReadonlyFlow schema={schema} />
|
||||||
<TGFlow />
|
|
||||||
</ReactFlowProvider>
|
</ReactFlowProvider>
|
||||||
</ModalView>
|
</ModalView>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { type Edge, MarkerType, type Node, useEdgesState, useNodesState } from 'reactflow';
|
||||||
|
|
||||||
|
import { TGEdgeTypes } from '@/features/rsform/components/term-graph/graph/tg-edge-types';
|
||||||
|
import { TGNodeTypes } from '@/features/rsform/components/term-graph/graph/tg-node-types';
|
||||||
|
import { SelectColoring } from '@/features/rsform/components/term-graph/select-coloring';
|
||||||
|
import { ToolbarFocusedCst } from '@/features/rsform/components/term-graph/toolbar-focused-cst';
|
||||||
|
import { applyLayout, produceFilteredGraph, type TGNodeData } from '@/features/rsform/models/graph-api';
|
||||||
|
import { type IConstituenta, type IRSForm } from '@/features/rsform/models/rsform';
|
||||||
|
import { flowOptions } from '@/features/rsform/pages/rsform-page/editor-term-graph/tg-flow';
|
||||||
|
import { useTermGraphStore } from '@/features/rsform/stores/term-graph';
|
||||||
|
|
||||||
|
import { DiagramFlow, useReactFlow } from '@/components/flow/diagram-flow';
|
||||||
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
|
import ToolbarGraphFilter from './toolbar-graph-filter';
|
||||||
|
|
||||||
|
export interface TGReadonlyFlowProps {
|
||||||
|
schema: IRSForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TGReadonlyFlow({ schema }: TGReadonlyFlowProps) {
|
||||||
|
const [focusCst, setFocusCst] = useState<IConstituenta | null>(null);
|
||||||
|
|
||||||
|
const filter = useTermGraphStore(state => state.filter);
|
||||||
|
const filteredGraph = produceFilteredGraph(schema, filter, focusCst);
|
||||||
|
|
||||||
|
const [nodes, setNodes, onNodesChange] = useNodesState<Node>([]);
|
||||||
|
const [edges, setEdges] = useEdgesState<Edge>([]);
|
||||||
|
const { fitView, viewportInitialized } = useReactFlow();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!viewportInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newNodes: Node[] = [];
|
||||||
|
filteredGraph.nodes.forEach(node => {
|
||||||
|
const cst = schema.cstByID.get(node.id);
|
||||||
|
if (cst) {
|
||||||
|
newNodes.push({
|
||||||
|
id: String(node.id),
|
||||||
|
type: 'concept',
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
data: { cst: cst, focused: focusCst?.id === cst.id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const newEdges: Edge[] = [];
|
||||||
|
let edgeID = 1;
|
||||||
|
filteredGraph.nodes.forEach(source => {
|
||||||
|
source.outputs.forEach(target => {
|
||||||
|
if (newNodes.find(node => node.id === String(target))) {
|
||||||
|
newEdges.push({
|
||||||
|
id: String(edgeID),
|
||||||
|
source: String(source.id),
|
||||||
|
target: String(target),
|
||||||
|
type: 'termEdge',
|
||||||
|
focusable: false,
|
||||||
|
markerEnd: {
|
||||||
|
type: MarkerType.ArrowClosed,
|
||||||
|
width: 20,
|
||||||
|
height: 20
|
||||||
|
}
|
||||||
|
});
|
||||||
|
edgeID += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
applyLayout(newNodes, newEdges, !filter.noText);
|
||||||
|
|
||||||
|
setNodes(newNodes);
|
||||||
|
setEdges(newEdges);
|
||||||
|
|
||||||
|
setTimeout(() => fitView(flowOptions.fitViewOptions), PARAMETER.minimalTimeout);
|
||||||
|
}, [schema, filteredGraph, setNodes, setEdges, filter.noText, fitView, viewportInitialized, focusCst]);
|
||||||
|
|
||||||
|
function handleNodeContextMenu(event: React.MouseEvent<Element>, node: TGNodeData) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
setFocusCst(focusCst?.id === node.data.cst.id ? null : node.data.cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='relative w-full h-full flex flex-col'>
|
||||||
|
<div className='cc-tab-tools flex flex-col mt-2 items-center rounded-b-2xl backdrop-blur-xs'>
|
||||||
|
<ToolbarGraphFilter />
|
||||||
|
<ToolbarFocusedCst className='-translate-x-9' focus={focusCst} resetFocus={() => setFocusCst(null)} />
|
||||||
|
</div>
|
||||||
|
<div className='absolute z-pop top-24 sm:top-16 left-2 sm:left-3 w-54 flex flex-col pointer-events-none'>
|
||||||
|
<SelectColoring schema={schema} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DiagramFlow
|
||||||
|
{...flowOptions}
|
||||||
|
height='100%'
|
||||||
|
className='cc-mask-sides w-full h-full'
|
||||||
|
nodes={nodes}
|
||||||
|
onNodesChange={onNodesChange}
|
||||||
|
edges={edges}
|
||||||
|
nodeTypes={TGNodeTypes}
|
||||||
|
edgeTypes={TGEdgeTypes}
|
||||||
|
onContextMenu={event => event.preventDefault()}
|
||||||
|
onNodeContextMenu={handleNodeContextMenu}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { useReactFlow } from 'reactflow';
|
||||||
|
|
||||||
|
import { useTermGraphStore } from '@/features/rsform/stores/term-graph';
|
||||||
|
|
||||||
|
import { MiniButton } from '@/components/control';
|
||||||
|
import { IconClustering, IconClusteringOff, IconFitImage, IconText, IconTextOff } from '@/components/icons';
|
||||||
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
|
import { flowOptions } from '../../pages/oss-page/editor-oss-graph/oss-flow';
|
||||||
|
|
||||||
|
export default function ToolbarGraphFilter() {
|
||||||
|
const filter = useTermGraphStore(state => state.filter);
|
||||||
|
const toggleText = useTermGraphStore(state => state.toggleText);
|
||||||
|
const toggleClustering = useTermGraphStore(state => state.toggleClustering);
|
||||||
|
const { fitView } = useReactFlow();
|
||||||
|
|
||||||
|
function handleFitView() {
|
||||||
|
setTimeout(() => {
|
||||||
|
fitView(flowOptions.fitViewOptions);
|
||||||
|
}, PARAMETER.minimalTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex flex-row gap-2'>
|
||||||
|
<MiniButton
|
||||||
|
title='Граф целиком'
|
||||||
|
icon={<IconFitImage size='1.25rem' className='icon-primary' />}
|
||||||
|
onClick={handleFitView}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
title={!filter.noText ? 'Скрыть текст' : 'Отобразить текст'}
|
||||||
|
icon={
|
||||||
|
!filter.noText ? (
|
||||||
|
<IconText size='1.25rem' className='icon-green' />
|
||||||
|
) : (
|
||||||
|
<IconTextOff size='1.25rem' className='icon-primary' />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onClick={toggleText}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
title={!filter.foldDerived ? 'Скрыть порожденные' : 'Отобразить порожденные'}
|
||||||
|
icon={
|
||||||
|
!filter.foldDerived ? (
|
||||||
|
<IconClustering size='1.25rem' className='icon-green' />
|
||||||
|
) : (
|
||||||
|
<IconClusteringOff size='1.25rem' className='icon-primary' />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onClick={toggleClustering}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { PARAMETER, prefixes } from '@/utils/constants';
|
import { PARAMETER, prefixes } from '@/utils/constants';
|
||||||
import { type RO } from '@/utils/meta';
|
import { type RO } from '@/utils/meta';
|
||||||
|
|
||||||
interface ToolbarConstituentsProps {
|
interface ToolbarSchemaProps {
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
isMutable: boolean;
|
isMutable: boolean;
|
||||||
activeCst: IConstituenta | null;
|
activeCst: IConstituenta | null;
|
||||||
|
@ -34,7 +34,7 @@ interface ToolbarConstituentsProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolbarConstituents({
|
export function ToolbarSchema({
|
||||||
schema,
|
schema,
|
||||||
activeCst,
|
activeCst,
|
||||||
setActive,
|
setActive,
|
||||||
|
@ -42,7 +42,7 @@ export function ToolbarConstituents({
|
||||||
onEditActive,
|
onEditActive,
|
||||||
isMutable,
|
isMutable,
|
||||||
className
|
className
|
||||||
}: ToolbarConstituentsProps) {
|
}: ToolbarSchemaProps) {
|
||||||
const router = useConceptNavigation();
|
const router = useConceptNavigation();
|
||||||
const isProcessing = useMutatingRSForm();
|
const isProcessing = useMutatingRSForm();
|
||||||
const searchText = useCstSearchStore(state => state.query);
|
const searchText = useCstSearchStore(state => state.query);
|
||||||
|
@ -175,6 +175,10 @@ export function ToolbarConstituents({
|
||||||
showTypeGraph({ items: typeInfo });
|
showTypeGraph({ items: typeInfo });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleShowTermGraph() {
|
||||||
|
showTermGraph({ schema: schema });
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn('flex gap-0.5', className)}>
|
<div className={cn('flex gap-0.5', className)}>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
@ -225,7 +229,7 @@ export function ToolbarConstituents({
|
||||||
<MiniButton
|
<MiniButton
|
||||||
icon={<IconTree size='1rem' className='hover:text-primary' />}
|
icon={<IconTree size='1rem' className='hover:text-primary' />}
|
||||||
title='Граф термов'
|
title='Граф термов'
|
||||||
onClick={() => showTermGraph({ schema })}
|
onClick={handleShowTermGraph}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
icon={<IconTypeGraph size='1rem' className='hover:text-primary' />}
|
icon={<IconTypeGraph size='1rem' className='hover:text-primary' />}
|
|
@ -8,7 +8,7 @@ import { ViewConstituents } from '@/features/rsform/components/view-constituents
|
||||||
import { useFitHeight } from '@/stores/app-layout';
|
import { useFitHeight } from '@/stores/app-layout';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
import { ToolbarConstituents } from './toolbar-constituents';
|
import { ToolbarSchema } from './toolbar-schema';
|
||||||
|
|
||||||
interface ViewSchemaProps {
|
interface ViewSchemaProps {
|
||||||
schemaID: number;
|
schemaID: number;
|
||||||
|
@ -29,7 +29,7 @@ export function ViewSchema({ schemaID, isMutable }: ViewSchemaProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='grid h-full relative cc-fade-in mt-5' style={{ gridTemplateRows: '1fr auto' }}>
|
<div className='grid h-full relative cc-fade-in mt-5' style={{ gridTemplateRows: '1fr auto' }}>
|
||||||
<ToolbarConstituents
|
<ToolbarSchema
|
||||||
className='absolute -top-6.5 left-1'
|
className='absolute -top-6.5 left-1'
|
||||||
schema={schema}
|
schema={schema}
|
||||||
activeCst={activeCst}
|
activeCst={activeCst}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import { Handle, Position } from 'reactflow';
|
import { Handle, Position } from 'reactflow';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
import { isBasicConcept } from '@/features/rsform/models/rsform-api';
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
|
@ -67,5 +69,9 @@ export function TGNode(node: TGNodeInternal) {
|
||||||
|
|
||||||
// ====== INTERNAL ======
|
// ====== INTERNAL ======
|
||||||
function describeCstNode(cst: IConstituenta) {
|
function describeCstNode(cst: IConstituenta) {
|
||||||
return `${cst.alias}: ${cst.term_resolved}</br>Типизация: ${labelCstTypification(cst)}`;
|
return `${cst.alias}: ${cst.term_resolved}</br><b>Типизация:</b> ${labelCstTypification(
|
||||||
|
cst
|
||||||
|
)}</br><b>Содержание:</b> ${
|
||||||
|
isBasicConcept(cst.cst_type) ? cst.convention : cst.definition_resolved || cst.definition_formal || cst.convention
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,27 +4,19 @@ import { MiniButton } from '@/components/control';
|
||||||
import { IconGraphInputs, IconGraphOutputs, IconReset } from '@/components/icons';
|
import { IconGraphInputs, IconGraphOutputs, IconReset } from '@/components/icons';
|
||||||
import { cn } from '@/components/utils';
|
import { cn } from '@/components/utils';
|
||||||
|
|
||||||
|
import { useTermGraphStore } from '../../stores/term-graph';
|
||||||
|
|
||||||
interface ToolbarFocusedCstProps {
|
interface ToolbarFocusedCstProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
focus: IConstituenta | null;
|
focus: IConstituenta | null;
|
||||||
resetFocus: () => void;
|
resetFocus: () => void;
|
||||||
|
|
||||||
showInputs: boolean;
|
|
||||||
toggleShowInputs: () => void;
|
|
||||||
|
|
||||||
showOutputs: boolean;
|
|
||||||
toggleShowOutputs: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolbarFocusedCst({
|
export function ToolbarFocusedCst({ focus, resetFocus, className }: ToolbarFocusedCstProps) {
|
||||||
focus,
|
const filter = useTermGraphStore(state => state.filter);
|
||||||
resetFocus,
|
const toggleFocusInputs = useTermGraphStore(state => state.toggleFocusInputs);
|
||||||
className,
|
const toggleFocusOutputs = useTermGraphStore(state => state.toggleFocusOutputs);
|
||||||
showInputs,
|
|
||||||
toggleShowInputs,
|
|
||||||
showOutputs,
|
|
||||||
toggleShowOutputs
|
|
||||||
}: ToolbarFocusedCstProps) {
|
|
||||||
if (!focus) {
|
if (!focus) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -44,14 +36,14 @@ export function ToolbarFocusedCst({
|
||||||
onClick={resetFocus}
|
onClick={resetFocus}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={showInputs ? 'Скрыть поставщиков' : 'Отобразить поставщиков'}
|
title={filter.focusShowInputs ? 'Скрыть поставщиков' : 'Отобразить поставщиков'}
|
||||||
icon={<IconGraphInputs size='1.25rem' className={showInputs ? 'icon-green' : 'icon-primary'} />}
|
icon={<IconGraphInputs size='1.25rem' className={filter.focusShowInputs ? 'icon-green' : 'icon-primary'} />}
|
||||||
onClick={toggleShowInputs}
|
onClick={toggleFocusInputs}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={showOutputs ? 'Скрыть потребителей' : 'Отобразить потребителей'}
|
title={filter.focusShowOutputs ? 'Скрыть потребителей' : 'Отобразить потребителей'}
|
||||||
icon={<IconGraphOutputs size='1.25rem' className={showOutputs ? 'icon-green' : 'icon-primary'} />}
|
icon={<IconGraphOutputs size='1.25rem' className={filter.focusShowOutputs ? 'icon-green' : 'icon-primary'} />}
|
||||||
onClick={toggleShowOutputs}
|
onClick={toggleFocusOutputs}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -55,8 +55,6 @@ export function TGFlow() {
|
||||||
const [edges, setEdges] = useEdgesState<Edge>([]);
|
const [edges, setEdges] = useEdgesState<Edge>([]);
|
||||||
|
|
||||||
const filter = useTermGraphStore(state => state.filter);
|
const filter = useTermGraphStore(state => state.filter);
|
||||||
const toggleFocusInputs = useTermGraphStore(state => state.toggleFocusInputs);
|
|
||||||
const toggleFocusOutputs = useTermGraphStore(state => state.toggleFocusOutputs);
|
|
||||||
const { filteredGraph, hidden } = useFilteredGraph();
|
const { filteredGraph, hidden } = useFilteredGraph();
|
||||||
|
|
||||||
function onSelectionChange({ nodes }: { nodes: Node[] }) {
|
function onSelectionChange({ nodes }: { nodes: Node[] }) {
|
||||||
|
@ -170,14 +168,7 @@ export function TGFlow() {
|
||||||
<div className='relative' tabIndex={-1} onKeyDown={handleKeyDown}>
|
<div className='relative' tabIndex={-1} onKeyDown={handleKeyDown}>
|
||||||
<div className='cc-tab-tools flex flex-col items-center rounded-b-2xl backdrop-blur-xs'>
|
<div className='cc-tab-tools flex flex-col items-center rounded-b-2xl backdrop-blur-xs'>
|
||||||
<ToolbarTermGraph />
|
<ToolbarTermGraph />
|
||||||
<ToolbarFocusedCst
|
<ToolbarFocusedCst focus={focusCst} resetFocus={() => setFocus(null)} />
|
||||||
focus={focusCst}
|
|
||||||
resetFocus={() => setFocus(null)}
|
|
||||||
showInputs={filter.focusShowInputs}
|
|
||||||
toggleShowInputs={toggleFocusInputs}
|
|
||||||
showOutputs={filter.focusShowOutputs}
|
|
||||||
toggleShowOutputs={toggleFocusOutputs}
|
|
||||||
/>
|
|
||||||
{!focusCst ? (
|
{!focusCst ? (
|
||||||
<ToolbarGraphSelection
|
<ToolbarGraphSelection
|
||||||
graph={schema.graph}
|
graph={schema.graph}
|
||||||
|
|
|
@ -43,7 +43,8 @@ export function ToolbarTermGraph() {
|
||||||
const showTypeGraph = useDialogsStore(state => state.showShowTypeGraph);
|
const showTypeGraph = useDialogsStore(state => state.showShowTypeGraph);
|
||||||
const showParams = useDialogsStore(state => state.showGraphParams);
|
const showParams = useDialogsStore(state => state.showGraphParams);
|
||||||
const filter = useTermGraphStore(state => state.filter);
|
const filter = useTermGraphStore(state => state.filter);
|
||||||
const setFilter = useTermGraphStore(state => state.setFilter);
|
const toggleText = useTermGraphStore(state => state.toggleText);
|
||||||
|
const toggleClustering = useTermGraphStore(state => state.toggleClustering);
|
||||||
|
|
||||||
const { fitView } = useReactFlow();
|
const { fitView } = useReactFlow();
|
||||||
|
|
||||||
|
@ -68,13 +69,6 @@ export function ToolbarTermGraph() {
|
||||||
promptDeleteCst();
|
promptDeleteCst();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleToggleNoText() {
|
|
||||||
setFilter({
|
|
||||||
...filter,
|
|
||||||
noText: !filter.noText
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleFitView() {
|
function handleFitView() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
fitView(flowOptions.fitViewOptions);
|
fitView(flowOptions.fitViewOptions);
|
||||||
|
@ -88,13 +82,6 @@ export function ToolbarTermGraph() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFoldDerived() {
|
|
||||||
setFilter({
|
|
||||||
...filter,
|
|
||||||
foldDerived: !filter.foldDerived
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSelectOss(event: React.MouseEvent<HTMLElement>, newValue: ILibraryItemReference) {
|
function handleSelectOss(event: React.MouseEvent<HTMLElement>, newValue: ILibraryItemReference) {
|
||||||
navigateOss(newValue.id, event.ctrlKey || event.metaKey);
|
navigateOss(newValue.id, event.ctrlKey || event.metaKey);
|
||||||
}
|
}
|
||||||
|
@ -127,7 +114,7 @@ export function ToolbarTermGraph() {
|
||||||
<IconTextOff size='1.25rem' className='icon-primary' />
|
<IconTextOff size='1.25rem' className='icon-primary' />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onClick={handleToggleNoText}
|
onClick={toggleText}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={!filter.foldDerived ? 'Скрыть порожденные' : 'Отобразить порожденные'}
|
title={!filter.foldDerived ? 'Скрыть порожденные' : 'Отобразить порожденные'}
|
||||||
|
@ -138,7 +125,7 @@ export function ToolbarTermGraph() {
|
||||||
<IconClusteringOff size='1.25rem' className='icon-primary' />
|
<IconClusteringOff size='1.25rem' className='icon-primary' />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onClick={handleFoldDerived}
|
onClick={toggleClustering}
|
||||||
/>
|
/>
|
||||||
{isContentEditable ? (
|
{isContentEditable ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
|
|
@ -34,6 +34,8 @@ interface TermGraphStore {
|
||||||
setFilter: (value: GraphFilterParams) => void;
|
setFilter: (value: GraphFilterParams) => void;
|
||||||
toggleFocusInputs: () => void;
|
toggleFocusInputs: () => void;
|
||||||
toggleFocusOutputs: () => void;
|
toggleFocusOutputs: () => void;
|
||||||
|
toggleText: () => void;
|
||||||
|
toggleClustering: () => void;
|
||||||
|
|
||||||
foldHidden: boolean;
|
foldHidden: boolean;
|
||||||
toggleFoldHidden: () => void;
|
toggleFoldHidden: () => void;
|
||||||
|
@ -69,6 +71,8 @@ export const useTermGraphStore = create<TermGraphStore>()(
|
||||||
set(state => ({ filter: { ...state.filter, focusShowInputs: !state.filter.focusShowInputs } })),
|
set(state => ({ filter: { ...state.filter, focusShowInputs: !state.filter.focusShowInputs } })),
|
||||||
toggleFocusOutputs: () =>
|
toggleFocusOutputs: () =>
|
||||||
set(state => ({ filter: { ...state.filter, focusShowOutputs: !state.filter.focusShowOutputs } })),
|
set(state => ({ filter: { ...state.filter, focusShowOutputs: !state.filter.focusShowOutputs } })),
|
||||||
|
toggleText: () => set(state => ({ filter: { ...state.filter, noText: !state.filter.noText } })),
|
||||||
|
toggleClustering: () => set(state => ({ filter: { ...state.filter, foldDerived: !state.filter.foldDerived } })),
|
||||||
|
|
||||||
foldHidden: false,
|
foldHidden: false,
|
||||||
toggleFoldHidden: () => set(state => ({ foldHidden: !state.foldHidden })),
|
toggleFoldHidden: () => set(state => ({ foldHidden: !state.foldHidden })),
|
||||||
|
|
|
@ -39,31 +39,31 @@ export const DialogType = {
|
||||||
RENAME_CONSTITUENTA: 6,
|
RENAME_CONSTITUENTA: 6,
|
||||||
|
|
||||||
CREATE_BLOCK: 7,
|
CREATE_BLOCK: 7,
|
||||||
EDIT_BLOCK: 25,
|
EDIT_BLOCK: 8,
|
||||||
|
|
||||||
CREATE_OPERATION: 8,
|
CREATE_OPERATION: 9,
|
||||||
EDIT_OPERATION: 9,
|
EDIT_OPERATION: 10,
|
||||||
DELETE_OPERATION: 10,
|
DELETE_OPERATION: 11,
|
||||||
CHANGE_INPUT_SCHEMA: 11,
|
CHANGE_INPUT_SCHEMA: 12,
|
||||||
RELOCATE_CONSTITUENTS: 12,
|
RELOCATE_CONSTITUENTS: 13,
|
||||||
OSS_SETTINGS: 26,
|
OSS_SETTINGS: 14,
|
||||||
EDIT_CONSTITUENTA: 27,
|
EDIT_CONSTITUENTA: 15,
|
||||||
|
|
||||||
CLONE_LIBRARY_ITEM: 13,
|
CLONE_LIBRARY_ITEM: 16,
|
||||||
UPLOAD_RSFORM: 14,
|
UPLOAD_RSFORM: 17,
|
||||||
EDIT_EDITORS: 15,
|
EDIT_EDITORS: 18,
|
||||||
EDIT_VERSIONS: 16,
|
EDIT_VERSIONS: 19,
|
||||||
CHANGE_LOCATION: 17,
|
CHANGE_LOCATION: 20,
|
||||||
|
|
||||||
EDIT_REFERENCE: 18,
|
EDIT_REFERENCE: 21,
|
||||||
EDIT_WORD_FORMS: 19,
|
EDIT_WORD_FORMS: 22,
|
||||||
INLINE_SYNTHESIS: 20,
|
INLINE_SYNTHESIS: 23,
|
||||||
|
|
||||||
SHOW_QR_CODE: 21,
|
SHOW_QR_CODE: 24,
|
||||||
SHOW_AST: 22,
|
SHOW_AST: 25,
|
||||||
SHOW_TYPE_GRAPH: 23,
|
SHOW_TYPE_GRAPH: 26,
|
||||||
GRAPH_PARAMETERS: 24,
|
GRAPH_PARAMETERS: 27,
|
||||||
SHOW_TERM_GRAPH: 25
|
SHOW_TERM_GRAPH: 28
|
||||||
} as const;
|
} as const;
|
||||||
export type DialogType = (typeof DialogType)[keyof typeof DialogType];
|
export type DialogType = (typeof DialogType)[keyof typeof DialogType];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user