From 4465cf9c49b541d893d3a8b71b60b7ea4ae1d43b Mon Sep 17 00:00:00 2001 From: Palt <8233942+Palt@users.noreply.github.com> Date: Thu, 14 Nov 2024 23:40:32 +0100 Subject: [PATCH] Toogle labels option (#814) * Added switch to toggle node lable names * Adding functionality to toggle label visibility * Fixed with some spacing, fixed global viewstate * Removed uneccesary List element * Formating * Total rewrite * fix: fix bug causing edge labels to re-appear after dragging a node even when edge labels have been hidden * feat: align menu buttons with BHE implementation * fix: update GraphButtons.test.tsx --------- Co-authored-by: Eli K Miller --- .../GraphButtons/GraphButtons.test.tsx | 40 +++++++++++++++++++ .../components/GraphButtons/GraphButtons.tsx | 18 +++++++++ cmd/ui/src/components/GraphEvents.tsx | 24 +++++++++-- cmd/ui/src/components/SigmaChart.tsx | 9 ++++- cmd/ui/src/views/Explore/GraphView.tsx | 23 +++++++++++ .../components/GraphButton/GraphButton.tsx | 4 +- .../src/components/GraphMenu/GraphMenu.tsx | 2 +- 7 files changed, 113 insertions(+), 7 deletions(-) diff --git a/cmd/ui/src/components/GraphButtons/GraphButtons.test.tsx b/cmd/ui/src/components/GraphButtons/GraphButtons.test.tsx index 58471d90d5..4283fa2cd6 100644 --- a/cmd/ui/src/components/GraphButtons/GraphButtons.test.tsx +++ b/cmd/ui/src/components/GraphButtons/GraphButtons.test.tsx @@ -28,6 +28,11 @@ describe('GraphLayoutButtons', () => { const testOnRunSequentialLayout = vi.fn(); const testOnExportJson = vi.fn(); const testOnSearchCurrentResults = vi.fn(); + const testOnToggleAllLabels = vi.fn(); + const testOnToggleNodeLabels = vi.fn(); + const testOnToggleEdgeLabels = vi.fn(); + const testShowNodeLabels = true; + const testShowEdgeLabels = true; const testIsCurrentSearchOpen = false; render( @@ -37,6 +42,11 @@ describe('GraphLayoutButtons', () => { onRunSequentialLayout={testOnRunSequentialLayout} onExportJson={testOnExportJson} onSearchCurrentResults={testOnSearchCurrentResults} + onToggleAllLabels={testOnToggleAllLabels} + onToggleNodeLabels={testOnToggleNodeLabels} + onToggleEdgeLabels={testOnToggleEdgeLabels} + showNodeLabels={testShowNodeLabels} + showEdgeLabels={testShowEdgeLabels} isCurrentSearchOpen={testIsCurrentSearchOpen} /> @@ -55,6 +65,11 @@ describe('GraphLayoutButtons', () => { const testOnRunSequentialLayout = vi.fn(); const testOnExportJson = vi.fn(); const testOnSearchCurrentResults = vi.fn(); + const testOnToggleAllLabels = vi.fn(); + const testOnToggleNodeLabels = vi.fn(); + const testOnToggleEdgeLabels = vi.fn(); + const testShowNodeLabels = true; + const testShowEdgeLabels = true; const testIsCurrentSearchOpen = false; render( @@ -64,6 +79,11 @@ describe('GraphLayoutButtons', () => { onRunSequentialLayout={testOnRunSequentialLayout} onExportJson={testOnExportJson} onSearchCurrentResults={testOnSearchCurrentResults} + onToggleAllLabels={testOnToggleAllLabels} + onToggleNodeLabels={testOnToggleNodeLabels} + onToggleEdgeLabels={testOnToggleEdgeLabels} + showNodeLabels={testShowNodeLabels} + showEdgeLabels={testShowEdgeLabels} isCurrentSearchOpen={testIsCurrentSearchOpen} /> @@ -87,6 +107,11 @@ describe('GraphLayoutButtons', () => { const testOnRunSequentialLayout = vi.fn(); const testOnExportJson = vi.fn(); const testOnSearchCurrentResults = vi.fn(); + const testOnToggleAllLabels = vi.fn(); + const testOnToggleNodeLabels = vi.fn(); + const testOnToggleEdgeLabels = vi.fn(); + const testShowNodeLabels = true; + const testShowEdgeLabels = true; const testIsCurrentSearchOpen = false; render( @@ -96,6 +121,11 @@ describe('GraphLayoutButtons', () => { onRunSequentialLayout={testOnRunSequentialLayout} onExportJson={testOnExportJson} onSearchCurrentResults={testOnSearchCurrentResults} + onToggleAllLabels={testOnToggleAllLabels} + onToggleNodeLabels={testOnToggleNodeLabels} + onToggleEdgeLabels={testOnToggleEdgeLabels} + showNodeLabels={testShowNodeLabels} + showEdgeLabels={testShowEdgeLabels} isCurrentSearchOpen={testIsCurrentSearchOpen} /> @@ -116,6 +146,11 @@ describe('GraphLayoutButtons', () => { const testOnRunSequentialLayout = vi.fn(); const testOnExportJson = vi.fn(); const testOnSearchCurrentResults = vi.fn(); + const testOnToggleAllLabels = vi.fn(); + const testOnToggleNodeLabels = vi.fn(); + const testOnToggleEdgeLabels = vi.fn(); + const testShowNodeLabels = true; + const testShowEdgeLabels = true; const testIsCurrentSearchOpen = false; render( @@ -125,6 +160,11 @@ describe('GraphLayoutButtons', () => { onRunSequentialLayout={testOnRunSequentialLayout} onExportJson={testOnExportJson} onSearchCurrentResults={testOnSearchCurrentResults} + onToggleAllLabels={testOnToggleAllLabels} + onToggleNodeLabels={testOnToggleNodeLabels} + onToggleEdgeLabels={testOnToggleEdgeLabels} + showNodeLabels={testShowNodeLabels} + showEdgeLabels={testShowEdgeLabels} isCurrentSearchOpen={testIsCurrentSearchOpen} /> , diff --git a/cmd/ui/src/components/GraphButtons/GraphButtons.tsx b/cmd/ui/src/components/GraphButtons/GraphButtons.tsx index 767269b337..844102f1c0 100644 --- a/cmd/ui/src/components/GraphButtons/GraphButtons.tsx +++ b/cmd/ui/src/components/GraphButtons/GraphButtons.tsx @@ -28,6 +28,11 @@ interface GraphButtonsProps { onRunSequentialLayout: () => void; onExportJson: () => void; onSearchCurrentResults: () => void; + onToggleAllLabels: () => void; + onToggleNodeLabels: () => void; + onToggleEdgeLabels: () => void; + showNodeLabels: boolean; + showEdgeLabels: boolean; isCurrentSearchOpen: boolean; } @@ -37,6 +42,11 @@ const GraphButtons: FC = ({ onRunSequentialLayout, onExportJson, onSearchCurrentResults, + onToggleAllLabels, + onToggleNodeLabels, + onToggleEdgeLabels, + showNodeLabels, + showEdgeLabels, isCurrentSearchOpen, }) => { const exportableGraphState = useAppSelector((state) => state.explore.export); @@ -45,6 +55,14 @@ const GraphButtons: FC = ({ } /> + + + {!showNodeLabels || !showEdgeLabels ? 'Show' : 'Hide'} All Labels + + {showNodeLabels ? 'Hide' : 'Show'} Node Labels + {showEdgeLabels ? 'Hide' : 'Show'} Edge Labels + + Sequential Standard diff --git a/cmd/ui/src/components/GraphEvents.tsx b/cmd/ui/src/components/GraphEvents.tsx index 4e82969e97..59a4255451 100644 --- a/cmd/ui/src/components/GraphEvents.tsx +++ b/cmd/ui/src/components/GraphEvents.tsx @@ -39,10 +39,21 @@ export interface GraphEventProps { onClickStage?: () => void; edgeReducer?: (edge: string, data: Attributes, graph: AbstractGraph) => Attributes; onRightClickNode?: (event: SigmaNodeEventPayload) => void; + showNodeLabels?: boolean; + showEdgeLabels?: boolean; } export const GraphEvents = forwardRef(function GraphEvents( - { onDoubleClickNode, onClickNode, onClickEdge, onClickStage, onRightClickNode, edgeReducer }: GraphEventProps, + { + onDoubleClickNode, + onClickNode, + onClickEdge, + onClickStage, + onRightClickNode, + edgeReducer, + showNodeLabels = true, + showEdgeLabels = true, + }: GraphEventProps, ref ) { const dispatch = useAppDispatch(); @@ -302,9 +313,9 @@ export const GraphEvents = forwardRef(function GraphEvents( if (draggedNode) { setSettings({ renderEdgeLabels: false }); } else { - setSettings({ renderEdgeLabels: true }); + setSettings({ renderEdgeLabels: showEdgeLabels }); } - }, [draggedNode, setSettings]); + }, [draggedNode, setSettings, showEdgeLabels]); useEffect(() => { resetCamera(sigma); @@ -321,5 +332,12 @@ export const GraphEvents = forwardRef(function GraphEvents( } }, [selectedNode]); + useEffect(() => { + setSettings({ + renderLabels: showNodeLabels, + renderEdgeLabels: showEdgeLabels, + }); + }, [setSettings, showNodeLabels, showEdgeLabels]); + return null; }); diff --git a/cmd/ui/src/components/SigmaChart.tsx b/cmd/ui/src/components/SigmaChart.tsx index 3f0459d09c..0133b798de 100644 --- a/cmd/ui/src/components/SigmaChart.tsx +++ b/cmd/ui/src/components/SigmaChart.tsx @@ -41,6 +41,8 @@ interface SigmaChartProps { onClickStage: () => void; edgeReducer: (edge: string, data: Attributes, graph: AbstractGraph) => Attributes; handleContextMenu: (event: SigmaNodeEventPayload) => void; + showNodeLabels?: boolean; + showEdgeLabels?: boolean; } const SigmaChart = forwardRef(function SigmaChart( @@ -52,6 +54,8 @@ const SigmaChart = forwardRef(function SigmaChart( onClickStage, edgeReducer, handleContextMenu, + showNodeLabels = true, + showEdgeLabels = true, }: Partial, ref ) { @@ -82,7 +86,8 @@ const SigmaChart = forwardRef(function SigmaChart( self: SelfEdgeArrowProgram, arrow: EdgeArrowProgram, }, - renderEdgeLabels: true, + renderEdgeLabels: showEdgeLabels, + renderLabels: showNodeLabels, hoverRenderer: drawHover, edgeLabelRenderer: drawEdgeLabel, edgeLabelSize: 12, @@ -100,6 +105,8 @@ const SigmaChart = forwardRef(function SigmaChart( onClickStage={onClickStage} edgeReducer={edgeReducer} onRightClickNode={handleContextMenu} + showNodeLabels={showNodeLabels} + showEdgeLabels={showEdgeLabels} ref={ref} /> diff --git a/cmd/ui/src/views/Explore/GraphView.tsx b/cmd/ui/src/views/Explore/GraphView.tsx index e6407246d3..468032a947 100644 --- a/cmd/ui/src/views/Explore/GraphView.tsx +++ b/cmd/ui/src/views/Explore/GraphView.tsx @@ -114,6 +114,10 @@ const GraphView: FC = () => { const [columns, setColumns] = useState(columnsDefault); + const [showNodeLabels, setShowNodeLabels] = useState(true); + + const [showEdgeLabels, setShowEdgeLabels] = useState(true); + useEffect(() => { let items: any = graphState.chartProps.items; if (!items) return; @@ -221,6 +225,8 @@ const GraphView: FC = () => { graph={graphologyGraph} onClickNode={handleClickNode} handleContextMenu={handleContextMenu} + showNodeLabels={showNodeLabels} + showEdgeLabels={showEdgeLabels} ref={sigmaChartRef} /> @@ -271,6 +277,23 @@ const GraphView: FC = () => { onSearchCurrentResults={() => { toggleCurrentSearch(); }} + onToggleAllLabels={() => { + if (!showNodeLabels || !showEdgeLabels) { + setShowNodeLabels(true); + setShowEdgeLabels(true); + } else { + setShowNodeLabels(false); + setShowEdgeLabels(false); + } + }} + onToggleNodeLabels={() => { + setShowNodeLabels((prev) => !prev); + }} + onToggleEdgeLabels={() => { + setShowEdgeLabels((prev) => !prev); + }} + showNodeLabels={showNodeLabels} + showEdgeLabels={showEdgeLabels} isCurrentSearchOpen={false} /> ({ button: { @@ -42,7 +42,7 @@ const useStyles = makeStyles((theme) => ({ export interface GraphButtonProps { onClick: (e?: any) => void; - displayText: string | JSX.Element; + displayText: string | ReactNode; disabled?: boolean; } diff --git a/packages/javascript/bh-shared-ui/src/components/GraphMenu/GraphMenu.tsx b/packages/javascript/bh-shared-ui/src/components/GraphMenu/GraphMenu.tsx index daf29ebef2..3d9b2298c2 100644 --- a/packages/javascript/bh-shared-ui/src/components/GraphMenu/GraphMenu.tsx +++ b/packages/javascript/bh-shared-ui/src/components/GraphMenu/GraphMenu.tsx @@ -18,7 +18,7 @@ import { Menu } from '@mui/material'; import GraphButton from '../GraphButton'; import { Children, FC, ReactNode, useState } from 'react'; -const GraphMenu: FC<{ label: string; children: ReactNode }> = ({ children, label }) => { +const GraphMenu: FC<{ label: ReactNode; children: ReactNode }> = ({ children, label }) => { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl);