From b680b59532f61246eb47568cc5a02b3c2f66f17e Mon Sep 17 00:00:00 2001
From: Shahriar <31452340+ShahriarKh@users.noreply.github.com>
Date: Fri, 19 Jan 2024 20:07:50 +0330
Subject: [PATCH] refactor state to zustand
---
admin/src/components/OptionsBar.js | 4 +-
admin/src/pages/HomePage/index.js | 112 ++++++++++++++---------------
admin/src/store/index.js | 76 ++++++++++++++++++++
package-lock.json | 5 +-
package.json | 3 +-
5 files changed, 137 insertions(+), 63 deletions(-)
create mode 100644 admin/src/store/index.js
diff --git a/admin/src/components/OptionsBar.js b/admin/src/components/OptionsBar.js
index 27c9d41..e19aa80 100644
--- a/admin/src/components/OptionsBar.js
+++ b/admin/src/components/OptionsBar.js
@@ -4,8 +4,10 @@ import {
SingleSelectOption,
} from "@strapi/design-system";
import React from "react";
+import { useDigramStore } from "../store";
-export default function OptionsBar({ options, toggleOption }) {
+export default function OptionsBar() {
+ const { options, toggleOption } = useDigramStore();
return (
{
const theme = useTheme();
const { get } = useFetchClient();
- const [contentTypesData, setContentTypesData] = useState([]);
+ // const { setViewport } = useReactFlow();
+ const [diagram, setDiagram] = useState(null);
- const [options, setOptions] = usePersistentState(
- "content-type-explorer-options",
- {
- snapToGrid: false,
- showTypes: true,
- showIcons: true,
- showRelationsOnly: false,
- showAdminTypes: false,
- showDefaultFields: false,
- showPluginTypes: false,
- showEdges: false,
- scrollMode: true,
- edgeType: "smartbezier",
- backgroundPattern: "dots",
- }
- );
-
- function toggleOption(optionName, optionValue = null) {
- setOptions({
- ...options,
- [optionName]: optionValue || !options[optionName],
- });
- }
+ const {
+ nodes,
+ redrawEdges,
+ edges,
+ onNodesChange,
+ onEdgesChange,
+ onConnect,
+ redrawNodes,
+ drawDiagram,
+ toggleOption,
+ options,
+ } = useDigramStore();
const nodeTypes = useMemo(() => ({ special: CustomNode }), []);
const edgeTypes = useMemo(
@@ -68,13 +52,32 @@ const HomePage = () => {
[]
);
- const [nodes, setNodes, onNodesChange] = useNodesState([]);
- const [edges, setEdges, onEdgesChange] = useEdgesState([]);
+ // const saveDiagram = useCallback(() => {
+ // if (diagram) {
+ // const flow = diagram.toObject();
+ // localStorage.setItem(
+ // "content-type-explorer-diagram",
+ // JSON.stringify(flow)
+ // );
+ // }
+ // }, [diagram]);
- const onConnect = useCallback(
- (params) => setEdges((eds) => addEdge(params, eds)),
- [setEdges]
- );
+ // const restoreDiagram = useCallback(() => {
+ // const restoreFlow = async () => {
+ // const flow = JSON.parse(
+ // localStorage.getItem("content-type-explorer-diagram")
+ // );
+
+ // if (flow) {
+ // const { x = 0, y = 0, zoom = 1 } = flow.viewport;
+ // setNodes(flow.nodes || []);
+ // setEdges(flow.edges || []);
+ // setViewport({ x, y, zoom });
+ // }
+ // };
+
+ // restoreFlow();
+ // }, [setNodes, setViewport]);
// get (and filter) content-types
useEffect(() => {
@@ -87,32 +90,20 @@ const HomePage = () => {
if (!options.showPluginTypes) {
allTypes = allTypes.filter((x) => !x.name.startsWith("plugin::"));
}
- setContentTypesData(allTypes);
+
+ drawDiagram(allTypes);
};
fetchData();
}, [options.showAdminTypes, options.showPluginTypes]);
- // create nodes & edges
useEffect(() => {
- if (contentTypesData.length > 0) {
- let newNodes = createNodes(contentTypesData, options);
- setNodes(newNodes);
- let newEdges = createEdegs(contentTypesData, options);
- setEdges(newEdges);
- }
- }, [contentTypesData]);
+ redrawEdges();
+ }, [options.edgeType, options.showEdges]);
useEffect(() => {
- let newEdges = updateEdges(edges, options);
- setEdges(newEdges);
- }, [setEdges, options.edgeType, options.showEdges]);
-
- useEffect(() => {
- let newNodes = updateNodes(nodes, options);
- setNodes(newNodes);
+ redrawNodes();
}, [
- setNodes,
options.showTypes,
options.showIcons,
options.showRelationsOnly,
@@ -134,7 +125,7 @@ const HomePage = () => {
}
/>
-
+
{
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
+ onInit={setDiagram}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
fitView
@@ -168,6 +160,8 @@ const HomePage = () => {
"--button-hover": theme.colors.buttonPrimary500,
}}
>
+ {/*
+ */}
toggleOption("scrollMode")}
title="Toggle Mouse Wheel Behavior (Zoom/Scroll)"
diff --git a/admin/src/store/index.js b/admin/src/store/index.js
new file mode 100644
index 0000000..ec10d06
--- /dev/null
+++ b/admin/src/store/index.js
@@ -0,0 +1,76 @@
+import { create } from "zustand";
+import { persist } from "zustand/middleware";
+import { addEdge, applyNodeChanges, applyEdgeChanges } from "reactflow";
+import {
+ createEdegs,
+ createNodes,
+ updateEdges,
+ updateNodes,
+} from "../utils/dataUtils";
+
+export const useDigramStore = create(
+ persist((set, get) => ({
+ nodes: [],
+ edges: [],
+ options: {
+ snapToGrid: false,
+ showTypes: true,
+ showIcons: true,
+ showRelationsOnly: false,
+ showAdminTypes: false,
+ showDefaultFields: false,
+ showPluginTypes: false,
+ showEdges: false,
+ scrollMode: true,
+ edgeType: "smartbezier",
+ backgroundPattern: "dots",
+ },
+ toggleOption: (optionName, optionValue = null) => {
+ let newOptions = {
+ ...get().options,
+ [optionName]: optionValue || !get().options[optionName],
+ };
+ set({
+ options: newOptions,
+ });
+ },
+ onNodesChange: (changes) => {
+ set({
+ nodes: applyNodeChanges(changes, get().nodes),
+ });
+ },
+ onEdgesChange: (changes) => {
+ set({
+ edges: applyEdgeChanges(changes, get().edges),
+ });
+ },
+ onConnect: (connection) => {
+ set({
+ edges: addEdge(connection, get().edges),
+ });
+ },
+ drawDiagram: (contentTypesData) => {
+ let newNodes = createNodes(contentTypesData, get().options);
+ let newEdges = createEdegs(contentTypesData, get().options);
+ set({
+ nodes: newNodes,
+ edges: newEdges,
+ });
+ },
+ redrawNodes: () => {
+ let newNodes = updateNodes(get().nodes, get().options);
+ set({
+ nodes: newNodes,
+ });
+ },
+ redrawEdges: () => {
+ let newEdges = updateEdges(get().edges, get().options);
+ set({
+ edges: newEdges,
+ });
+ },
+ })),
+ {
+ name: "strapi-content-type-explorer",
+ }
+);
diff --git a/package-lock.json b/package-lock.json
index d7640cd..646ab0d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,10 +10,11 @@
"license": "MIT",
"dependencies": {
"@tisoap/react-flow-smart-edge": "^3.0.0",
- "reactflow": "^11.10.2"
+ "reactflow": "^11.10.2",
+ "zustand": "^4.4.7"
},
"engines": {
- "node": ">=14.19.1 <=20.x.x",
+ "node": ">=14.19.1 <=18.x.x",
"npm": ">=6.0.0"
},
"peerDependencies": {
diff --git a/package.json b/package.json
index 2304ea0..a1dd0a3 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
},
"dependencies": {
"@tisoap/react-flow-smart-edge": "^3.0.0",
- "reactflow": "^11.10.2"
+ "reactflow": "^11.10.2",
+ "zustand": "^4.4.7"
},
"peerDependencies": {
"@strapi/strapi": "^4.0.0"