mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
F: Simplify termgraph tooltip
This commit is contained in:
parent
0d899f6258
commit
4352ba93b6
|
@ -15,7 +15,6 @@ import {
|
||||||
|
|
||||||
import { Overlay } from '@/components/Container';
|
import { Overlay } from '@/components/Container';
|
||||||
import { useMainHeight } from '@/stores/appLayout';
|
import { useMainHeight } from '@/stores/appLayout';
|
||||||
import { useTooltipsStore } from '@/stores/tooltips';
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ export const ZOOM_MIN = 0.25;
|
||||||
|
|
||||||
export function TGFlow() {
|
export function TGFlow() {
|
||||||
const mainHeight = useMainHeight();
|
const mainHeight = useMainHeight();
|
||||||
const flow = useReactFlow();
|
const { fitView, viewportInitialized } = useReactFlow();
|
||||||
const store = useStoreApi();
|
const store = useStoreApi();
|
||||||
const { addSelectedNodes } = store.getState();
|
const { addSelectedNodes } = store.getState();
|
||||||
const isProcessing = useMutatingRSForm();
|
const isProcessing = useMutatingRSForm();
|
||||||
|
@ -62,8 +61,6 @@ export function TGFlow() {
|
||||||
const coloring = useTermGraphStore(state => state.coloring);
|
const coloring = useTermGraphStore(state => state.coloring);
|
||||||
const setColoring = useTermGraphStore(state => state.setColoring);
|
const setColoring = useTermGraphStore(state => state.setColoring);
|
||||||
|
|
||||||
const setActiveCst = useTooltipsStore(state => state.setActiveCst);
|
|
||||||
|
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
||||||
const [edges, setEdges] = useEdgesState([]);
|
const [edges, setEdges] = useEdgesState([]);
|
||||||
|
|
||||||
|
@ -108,8 +105,7 @@ export function TGFlow() {
|
||||||
position: { x: 0, y: 0 },
|
position: { x: 0, y: 0 },
|
||||||
data: {
|
data: {
|
||||||
fill: focusCst === cst ? APP_COLORS.bgPurple : colorBgGraphNode(cst, coloring),
|
fill: focusCst === cst ? APP_COLORS.bgPurple : colorBgGraphNode(cst, coloring),
|
||||||
label: cst.alias,
|
cst: cst
|
||||||
description: !filter.noText ? cst.term_resolved : ''
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -148,12 +144,12 @@ export function TGFlow() {
|
||||||
}, [schema, focusCst, coloring, filter]);
|
}, [schema, focusCst, coloring, filter]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!needReset || !flow.viewportInitialized) {
|
if (!needReset || !viewportInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setNeedReset(false);
|
setNeedReset(false);
|
||||||
resetNodes();
|
resetNodes();
|
||||||
}, [needReset, schema, resetNodes, flow.viewportInitialized]);
|
}, [needReset, schema, resetNodes, viewportInitialized]);
|
||||||
|
|
||||||
function handleSetSelected(newSelection: number[]) {
|
function handleSetSelected(newSelection: number[]) {
|
||||||
setSelected(newSelection);
|
setSelected(newSelection);
|
||||||
|
@ -193,7 +189,7 @@ export function TGFlow() {
|
||||||
}
|
}
|
||||||
setSelected([]);
|
setSelected([]);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
flow.fitView({ duration: PARAMETER.zoomDuration });
|
fitView({ duration: PARAMETER.zoomDuration });
|
||||||
}, PARAMETER.minimalTimeout);
|
}, PARAMETER.minimalTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,13 +205,6 @@ export function TGFlow() {
|
||||||
navigateCst(cstID);
|
navigateCst(cstID);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleNodeEnter(cstID: number) {
|
|
||||||
const cst = schema.cstByID.get(cstID);
|
|
||||||
if (cst) {
|
|
||||||
setActiveCst(cst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Overlay position='cc-tab-tools' className='flex flex-col items-center rounded-b-2xl cc-blur'>
|
<Overlay position='cc-tab-tools' className='flex flex-col items-center rounded-b-2xl cc-blur'>
|
||||||
|
@ -269,7 +258,6 @@ export function TGFlow() {
|
||||||
edgeTypes={TGEdgeTypes}
|
edgeTypes={TGEdgeTypes}
|
||||||
maxZoom={ZOOM_MAX}
|
maxZoom={ZOOM_MAX}
|
||||||
minZoom={ZOOM_MIN}
|
minZoom={ZOOM_MIN}
|
||||||
onNodeMouseEnter={(_, node) => handleNodeEnter(Number(node.id))}
|
|
||||||
onNodeDoubleClick={(event, node) => handleNodeDoubleClick(event, Number(node.id))}
|
onNodeDoubleClick={(event, node) => handleNodeDoubleClick(event, Number(node.id))}
|
||||||
onNodeContextMenu={(event, node) => handleNodeContextMenu(event, Number(node.id))}
|
onNodeContextMenu={(event, node) => handleNodeContextMenu(event, Number(node.id))}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
import { Handle, Position } from 'reactflow';
|
import { Handle, Position } from 'reactflow';
|
||||||
|
|
||||||
|
import { type IConstituenta } from '@/features/rsform/models/rsform';
|
||||||
|
import { useTermGraphStore } from '@/features/rsform/stores/termGraph';
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
|
@ -14,8 +17,7 @@ const FONT_SIZE_MIN = 10;
|
||||||
|
|
||||||
export interface TGNodeData {
|
export interface TGNodeData {
|
||||||
fill: string;
|
fill: string;
|
||||||
label: string;
|
cst: IConstituenta;
|
||||||
description: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +33,10 @@ interface TGNodeInternal {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TGNode(node: TGNodeInternal) {
|
export function TGNode(node: TGNodeInternal) {
|
||||||
|
const filter = useTermGraphStore(state => state.filter);
|
||||||
|
const label = node.data.cst.alias;
|
||||||
|
const description = !filter.noText ? node.data.cst.term_resolved : '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Handle type='target' position={Position.Top} style={{ opacity: 0 }} />
|
<Handle type='target' position={Position.Top} style={{ opacity: 0 }} />
|
||||||
|
@ -38,9 +44,10 @@ export function TGNode(node: TGNodeInternal) {
|
||||||
className='w-full h-full cursor-default flex items-center justify-center rounded-full'
|
className='w-full h-full cursor-default flex items-center justify-center rounded-full'
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: !node.selected ? node.data.fill : APP_COLORS.bgActiveSelection,
|
backgroundColor: !node.selected ? node.data.fill : APP_COLORS.bgActiveSelection,
|
||||||
fontSize: node.data.label.length > LABEL_THRESHOLD ? FONT_SIZE_MED : FONT_SIZE_MAX
|
fontSize: label.length > LABEL_THRESHOLD ? FONT_SIZE_MED : FONT_SIZE_MAX
|
||||||
}}
|
}}
|
||||||
data-tooltip-id={globalIDs.constituenta_tooltip}
|
data-tooltip-id={globalIDs.tooltip}
|
||||||
|
data-tooltip-html={describeCstNode(node.data.cst)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@ -49,19 +56,19 @@ export function TGNode(node: TGNodeInternal) {
|
||||||
WebkitTextStrokeColor: APP_COLORS.bgDefault
|
WebkitTextStrokeColor: APP_COLORS.bgDefault
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{node.data.label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Handle type='source' position={Position.Bottom} style={{ opacity: 0 }} />
|
<Handle type='source' position={Position.Bottom} style={{ opacity: 0 }} />
|
||||||
{node.data.description ? (
|
{description ? (
|
||||||
<div
|
<div
|
||||||
className='mt-1 w-[150px] px-1 text-center translate-x-[calc(-50%+20px)]'
|
className='mt-1 w-[150px] px-1 text-center translate-x-[calc(-50%+20px)]'
|
||||||
style={{
|
style={{
|
||||||
fontSize: node.data.description.length > DESCRIPTION_THRESHOLD ? FONT_SIZE_MIN : FONT_SIZE_MED
|
fontSize: description.length > DESCRIPTION_THRESHOLD ? FONT_SIZE_MIN : FONT_SIZE_MED
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='absolute top-0 px-1 left-0 text-center w-full line-clamp-3 hover:line-clamp-none'>
|
<div className='absolute top-0 px-1 left-0 text-center w-full line-clamp-3 hover:line-clamp-none'>
|
||||||
{node.data.description}
|
{description}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-hidden='true'
|
aria-hidden='true'
|
||||||
|
@ -71,10 +78,15 @@ export function TGNode(node: TGNodeInternal) {
|
||||||
WebkitTextStrokeColor: APP_COLORS.bgDefault
|
WebkitTextStrokeColor: APP_COLORS.bgDefault
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{node.data.description}
|
{description}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====== INTERNAL ======
|
||||||
|
function describeCstNode(cst: IConstituenta) {
|
||||||
|
return `${cst.alias}: ${cst.term_resolved}</br>Типизация: ${cst.parse.typification}`;
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
/** Semantic colors for application. */
|
/** Semantic colors for application. */
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
export const APP_COLORS = {
|
export const APP_COLORS = {
|
||||||
|
bgDefaultLight: '#fafafa',
|
||||||
|
bgDefaultDark: '#171717',
|
||||||
bgDefault: 'var(--clr-prim-100)',
|
bgDefault: 'var(--clr-prim-100)',
|
||||||
bgInput: 'var(--clr-prim-0)',
|
bgInput: 'var(--clr-prim-0)',
|
||||||
bgControls: 'var(--clr-prim-200)',
|
bgControls: 'var(--clr-prim-200)',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user