useGraph.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { Graph } from "src/components/Graph";
  2. import { getChildrenEdges } from "src/utils/getChildrenEdges";
  3. import { getOutgoers } from "src/utils/getOutgoers";
  4. import create from "zustand";
  5. const initialStates = {
  6. loading: false,
  7. graphCollapsed: false,
  8. nodes: [] as NodeData[],
  9. edges: [] as EdgeData[],
  10. collapsedNodes: [] as string[],
  11. collapsedEdges: [] as string[],
  12. collapsedParents: [] as string[],
  13. };
  14. export type Graph = typeof initialStates;
  15. interface GraphActions {
  16. setGraphValue: (key: keyof Graph, value: any) => void;
  17. setLoading: (loading: boolean) => void;
  18. expandNodes: (nodeId: string) => void;
  19. collapseNodes: (nodeId: string) => void;
  20. collapseGraph: () => void;
  21. expandGraph: () => void;
  22. }
  23. const useGraph = create<Graph & GraphActions>((set, get) => ({
  24. ...initialStates,
  25. setGraphValue: (key, value) =>
  26. set({
  27. collapsedParents: [],
  28. collapsedNodes: [],
  29. collapsedEdges: [],
  30. [key]: value,
  31. }),
  32. setLoading: loading => set({ loading }),
  33. expandNodes: nodeId => {
  34. const [childrenNodes, matchingNodes] = getOutgoers(
  35. nodeId,
  36. get().nodes,
  37. get().edges,
  38. get().collapsedParents
  39. );
  40. const childrenEdges = getChildrenEdges(childrenNodes, get().edges);
  41. const nodeIds = childrenNodes.map(node => node.id).concat(matchingNodes);
  42. const edgeIds = childrenEdges.map(edge => edge.id);
  43. const collapsedParents = get().collapsedParents.filter(cp => cp !== nodeId);
  44. const collapsedNodes = get().collapsedNodes.filter(
  45. nodeId => !nodeIds.includes(nodeId)
  46. );
  47. const collapsedEdges = get().collapsedEdges.filter(
  48. edgeId => !edgeIds.includes(edgeId)
  49. );
  50. set({
  51. collapsedParents,
  52. collapsedNodes,
  53. collapsedEdges,
  54. graphCollapsed: false,
  55. });
  56. },
  57. collapseNodes: nodeId => {
  58. const [childrenNodes] = getOutgoers(nodeId, get().nodes, get().edges);
  59. const childrenEdges = getChildrenEdges(childrenNodes, get().edges);
  60. const nodeIds = childrenNodes.map(node => node.id);
  61. const edgeIds = childrenEdges.map(edge => edge.id);
  62. set({
  63. collapsedParents: get().collapsedParents.concat(nodeId),
  64. collapsedNodes: get().collapsedNodes.concat(nodeIds),
  65. collapsedEdges: get().collapsedEdges.concat(edgeIds),
  66. });
  67. },
  68. collapseGraph: () => {
  69. const edges = get().edges;
  70. const tos = edges.map(edge => edge.to);
  71. const froms = edges.map(edge => edge.from);
  72. const parentNodesIds = froms.filter(id => !tos.includes(id));
  73. const secondDegreeNodesIds = edges
  74. .filter(edge => parentNodesIds.includes(edge.from))
  75. .map(edge => edge.to);
  76. set({
  77. collapsedParents: get()
  78. .nodes.filter(
  79. node => !parentNodesIds.includes(node.id) && node.data.isParent
  80. )
  81. .map(node => node.id),
  82. collapsedNodes: get()
  83. .nodes.filter(
  84. node =>
  85. !parentNodesIds.includes(node.id) &&
  86. !secondDegreeNodesIds.includes(node.id)
  87. )
  88. .map(node => node.id),
  89. collapsedEdges: get()
  90. .edges.filter(edge => !parentNodesIds.includes(edge.from))
  91. .map(edge => edge.id),
  92. graphCollapsed: true,
  93. });
  94. },
  95. expandGraph: () => {
  96. set({
  97. collapsedNodes: [],
  98. collapsedEdges: [],
  99. collapsedParents: [],
  100. graphCollapsed: false,
  101. });
  102. },
  103. }));
  104. export default useGraph;