Added a 'Collapse/Expand Graph' button

This commit is contained in:
VladCuciureanu 2022-10-05 20:25:59 +03:00
parent 50a553a022
commit a3e110a1ea
2 changed files with 72 additions and 7 deletions

View File

@ -11,7 +11,12 @@ import {
AiOutlineLink, AiOutlineLink,
AiOutlineEdit, AiOutlineEdit,
} from "react-icons/ai"; } from "react-icons/ai";
import { CgArrowsMergeAltH, CgArrowsShrinkH } from "react-icons/cg"; import {
CgArrowsMergeAltH,
CgArrowsMergeAltV,
CgArrowsShrinkH,
CgArrowsShrinkV,
} from "react-icons/cg";
import { FiDownload } from "react-icons/fi"; import { FiDownload } from "react-icons/fi";
import { HiHeart } from "react-icons/hi"; import { HiHeart } from "react-icons/hi";
import { MdCenterFocusWeak } from "react-icons/md"; import { MdCenterFocusWeak } from "react-icons/md";
@ -22,6 +27,7 @@ import { DownloadModal } from "src/containers/Modals/DownloadModal";
import { ImportModal } from "src/containers/Modals/ImportModal"; import { ImportModal } from "src/containers/Modals/ImportModal";
import { ShareModal } from "src/containers/Modals/ShareModal"; import { ShareModal } from "src/containers/Modals/ShareModal";
import useConfig from "src/hooks/store/useConfig"; import useConfig from "src/hooks/store/useConfig";
import useGraph from "src/hooks/store/useGraph";
import { getNextLayout } from "src/utils/getNextLayout"; import { getNextLayout } from "src/utils/getNextLayout";
import styled from "styled-components"; import styled from "styled-components";
import shallow from "zustand/shallow"; import shallow from "zustand/shallow";
@ -154,6 +160,8 @@ export const Sidebar: React.FC = () => {
shallow shallow
); );
const { collapseGraph, expandGraph, graphCollapsed } = useGraph();
const handleSave = () => { const handleSave = () => {
const a = document.createElement("a"); const a = document.createElement("a");
const file = new Blob([getJson()], { type: "text/plain" }); const file = new Blob([getJson()], { type: "text/plain" });
@ -163,9 +171,9 @@ export const Sidebar: React.FC = () => {
a.click(); a.click();
}; };
const toggleExpandCollapse = () => { const toggleExpandShrink = () => {
setConfig("expand", !expand); setConfig("expand", !expand);
toast(`${expand ? "Collapsed" : "Expanded"} nodes.`); toast(`${expand ? "Shrunk" : "Expanded"} nodes.`);
}; };
const toggleLayout = () => { const toggleLayout = () => {
@ -173,6 +181,15 @@ export const Sidebar: React.FC = () => {
setConfig("layout", nextLayout); setConfig("layout", nextLayout);
}; };
const toggleExpandCollapseGraph = () => {
if (graphCollapsed) {
expandGraph();
} else {
collapseGraph();
}
toast(`${graphCollapsed ? "Expanded" : "Collapsed"} graph.`);
};
return ( return (
<StyledSidebar> <StyledSidebar>
<StyledTopWrapper> <StyledTopWrapper>
@ -206,13 +223,21 @@ export const Sidebar: React.FC = () => {
className="desktop" className="desktop"
title={expand ? "Shrink Nodes" : "Expand Nodes"} title={expand ? "Shrink Nodes" : "Expand Nodes"}
> >
<StyledElement <StyledElement title="Toggle Expand/Shrink" onClick={toggleExpandShrink}>
title="Toggle Expand/Collapse"
onClick={toggleExpandCollapse}
>
{expand ? <CgArrowsMergeAltH /> : <CgArrowsShrinkH />} {expand ? <CgArrowsMergeAltH /> : <CgArrowsShrinkH />}
</StyledElement> </StyledElement>
</Tooltip> </Tooltip>
<Tooltip
className="desktop"
title={graphCollapsed ? "Expand Graph" : "Collapse Graph"}
>
<StyledElement
title="Expand/Collapse Graph"
onClick={toggleExpandCollapseGraph}
>
{graphCollapsed ? <CgArrowsShrinkV /> : <CgArrowsMergeAltV />}
</StyledElement>
</Tooltip>
<Tooltip className="desktop" title="Save JSON"> <Tooltip className="desktop" title="Save JSON">
<StyledElement onClick={handleSave}> <StyledElement onClick={handleSave}>
<AiOutlineSave /> <AiOutlineSave />

View File

@ -5,6 +5,7 @@ import create from "zustand";
const initialStates = { const initialStates = {
loading: false, loading: false,
graphCollapsed: false,
nodes: [] as NodeData[], nodes: [] as NodeData[],
edges: [] as EdgeData[], edges: [] as EdgeData[],
collapsedNodes: [] as string[], collapsedNodes: [] as string[],
@ -18,6 +19,8 @@ interface GraphActions {
setGraphValue: (key: keyof Graph, value: any) => void; setGraphValue: (key: keyof Graph, value: any) => void;
expandNodes: (nodeId: string) => void; expandNodes: (nodeId: string) => void;
collapseNodes: (nodeId: string) => void; collapseNodes: (nodeId: string) => void;
collapseGraph: () => void;
expandGraph: () => void;
} }
const useGraph = create<Graph & GraphActions>((set, get) => ({ const useGraph = create<Graph & GraphActions>((set, get) => ({
@ -53,6 +56,7 @@ const useGraph = create<Graph & GraphActions>((set, get) => ({
collapsedParents, collapsedParents,
collapsedNodes, collapsedNodes,
collapsedEdges, collapsedEdges,
graphCollapsed: false,
}); });
}, },
collapseNodes: nodeId => { collapseNodes: nodeId => {
@ -68,6 +72,42 @@ const useGraph = create<Graph & GraphActions>((set, get) => ({
collapsedEdges: get().collapsedEdges.concat(edgeIds), collapsedEdges: get().collapsedEdges.concat(edgeIds),
}); });
}, },
collapseGraph: () => {
const edges = get().edges;
const tos = edges.map(edge => edge.to);
const froms = edges.map(edge => edge.from);
const parentNodesIds = froms.filter(id => !tos.includes(id));
const secondDegreeNodesIds = edges
.filter(edge => parentNodesIds.includes(edge.from))
.map(edge => edge.to);
set({
collapsedParents: get()
.nodes.filter(
node => !parentNodesIds.includes(node.id) && node.data.isParent
)
.map(node => node.id),
collapsedNodes: get()
.nodes.filter(
node =>
!parentNodesIds.includes(node.id) &&
!secondDegreeNodesIds.includes(node.id)
)
.map(node => node.id),
collapsedEdges: get()
.edges.filter(edge => !parentNodesIds.includes(edge.from))
.map(edge => edge.id),
graphCollapsed: true,
});
},
expandGraph: () => {
set({
collapsedNodes: [],
collapsedEdges: [],
collapsedParents: [],
graphCollapsed: false,
});
},
})); }));
export default useGraph; export default useGraph;