Implemented tabs storage, only working if current tab is empty

This commit is contained in:
Lucas Oliveira 2023-02-23 01:28:24 -03:00
commit 45d6f8e569
8 changed files with 119 additions and 48 deletions

View file

@ -23,6 +23,7 @@
"@types/react-dom": "^18.0.10",
"axios": "^1.3.2",
"react": "^18.2.0",
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
"react-laag": "^2.0.5",
@ -4212,6 +4213,11 @@
"@types/node": "*"
}
},
"node_modules/@types/cookie": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
"integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
},
"node_modules/@types/d3": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.0.tgz",
@ -4491,6 +4497,15 @@
"@types/node": "*"
}
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@ -14802,6 +14817,19 @@
"node": ">=14"
}
},
"node_modules/react-cookie": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz",
"integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==",
"dependencies": {
"@types/hoist-non-react-statics": "^3.0.1",
"hoist-non-react-statics": "^3.0.0",
"universal-cookie": "^4.0.0"
},
"peerDependencies": {
"react": ">= 16.3.0"
}
},
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@ -16832,6 +16860,23 @@
"node": ">=8"
}
},
"node_modules/universal-cookie": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz",
"integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==",
"dependencies": {
"@types/cookie": "^0.3.3",
"cookie": "^0.4.0"
}
},
"node_modules/universal-cookie/node_modules/cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",

View file

@ -18,6 +18,7 @@
"@types/react-dom": "^18.0.10",
"axios": "^1.3.2",
"react": "^18.2.0",
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
"react-laag": "^2.0.5",

View file

@ -5,10 +5,11 @@ import {
nodeColors,
snakeToNormalCase,
} from "../../../../utils";
import { useEffect, useRef, useState } from "react";
import { useContext, useEffect, useRef, useState } from "react";
import InputComponent from "../../../../components/inputComponent";
import ToggleComponent from "../../../../components/toggleComponent";
import InputListComponent from "../../../../components/inputListComponent";
import { typesContext } from "../../../../contexts/typesContext";
export default function ParameterComponent({
left,
@ -37,7 +38,8 @@ export default function ParameterComponent({
}, [data.id, position, updateNodeInternals]);
const [enabled, setEnabled] = useState(data.node.template[name]?.value ?? false);
let disabled = data.reactFlowInstance.getEdges().some((e) => (e.sourceHandle === id));
const {reactFlowInstance} = useContext(typesContext);
let disabled = reactFlowInstance?.getEdges().some((e) => (e.sourceHandle === id)) ?? false;
return (
<div ref={ref} className="w-full flex flex-wrap justify-between items-center bg-gray-50 mt-1 px-5 py-2">

View file

@ -1,3 +1,4 @@
import { CookiesProvider } from "react-cookie";
import { AlertProvider } from "./alertContext";
import { LocationProvider } from "./locationContext";
import PopUpProvider from "./popUpContext";
@ -7,15 +8,17 @@ import { TypesProvider } from "./typesContext";
export default function ContextWrapper({ children }) {
return (
<>
<LocationProvider>
<PopUpProvider>
<TypesProvider>
<TabsProvider>
<AlertProvider>{children}</AlertProvider>
</TabsProvider>
</TypesProvider>
</PopUpProvider>
</LocationProvider>
<CookiesProvider>
<LocationProvider>
<PopUpProvider>
<TypesProvider>
<TabsProvider>
<AlertProvider>{children}</AlertProvider>
</TabsProvider>
</TypesProvider>
</PopUpProvider>
</LocationProvider>
</CookiesProvider>
</>
);
}

View file

@ -1,4 +1,4 @@
import { createContext, useState } from "react";
import { createContext, useEffect, useState } from "react";
type flow={name:string,id:string,data:any}
@ -7,8 +7,8 @@ type TabsContextType={
setTabIndex:(index:number)=>void;
flows:Array<flow>
removeFlow:(id:string)=>void;
addFlow:(newFlow:flow)=>void;
updateFlow:(newFLow:flow)=>void;
addFlow:()=>void;
updateFlow:(newFlow:flow)=>void;
}
const TabsContextInitialValue = {
@ -16,8 +16,8 @@ const TabsContextInitialValue = {
setTabIndex:(index:number)=>{},
flows:[],
removeFlow:(id:string)=>{},
addFlow:(newFlow:flow)=>{},
updateFlow:(newFLow:flow)=>{}
addFlow:()=>{},
updateFlow:(newFlow:flow)=>{}
}
@ -27,6 +27,22 @@ export const TabsContext = createContext<TabsContextType>(TabsContextInitialValu
export function TabsProvider({children}){
const [tabIndex,setTabIndex] = useState(0)
const [flows,setFlows] = useState<Array<flow>>([])
const [id, setId] = useState(0);
useEffect(() => {
if(flows.length !== 0)
window.localStorage.setItem('tabsData', JSON.stringify({tabIndex, flows, id}));
}, [flows, id, tabIndex]);
useEffect(() => {
let cookie = window.localStorage.getItem('tabsData');
if(cookie){
let cookieObject = JSON.parse(cookie);
setTabIndex(cookieObject.tabIndex);
setFlows(cookieObject.flows)
setId(cookieObject.id)
}
}, [])
function removeFlow(id:string){
setFlows(prevState=>{
const newFlows = [...prevState];
@ -42,14 +58,14 @@ export function TabsProvider({children}){
}
}
window.sessionStorage.setItem('tabs', JSON.stringify(newFlows));
return newFlows;
})
});
}
function addFlow(newFlow: flow) {
function addFlow() {
let newFlow: flow = {name: "flow"+id, id: id.toString(), data:null}
setId((old) => old+1);
setFlows(prevState => {
const newFlows = [...prevState, newFlow];
window.sessionStorage.setItem('tabs', JSON.stringify(newFlows));
return newFlows;
});
setTabIndex(flows.length);
@ -62,7 +78,6 @@ export function TabsProvider({children}){
newFlows[index].data = newFlow.data
newFlows[index].name = newFlow.name
}
window.sessionStorage.setItem('tabs', JSON.stringify(newFlows));
return newFlows;
});
}

View file

@ -1,12 +1,17 @@
import { createContext, useState } from "react";
import { ReactEventHandler, createContext, useState } from "react";
import { ReactFlowInstance } from "reactflow";
type typesContextType=
{
reactFlowInstance: ReactFlowInstance;
setReactFlowInstance: any;
types: {};
setTypes:(newState:{})=>void;
}
const initialValue= {
reactFlowInstance: null,
setReactFlowInstance: ()=>{},
types: {},
setTypes:()=>{},
}
@ -15,8 +20,9 @@ export const typesContext = createContext<typesContextType>(initialValue);
export function TypesProvider({children}){
const [types, setTypes] = useState({});
const [reactFlowInstance, setReactFlowInstance] = useState(null);
return (
<typesContext.Provider value={{ types, setTypes}}>
<typesContext.Provider value={{ types, setTypes, reactFlowInstance, setReactFlowInstance}}>
{children}
</typesContext.Provider>
)

View file

@ -9,14 +9,13 @@ export function TabsManager() {
const { flows, addFlow, tabIndex, setTabIndex } = useContext(TabsContext);
useEffect(() => {
if (flows.length === 0) {
const id = _.uniqueId();
addFlow({ name: "flow " + id, data: null, id });
addFlow();
}
}, []);
}, [addFlow, flows.length]);
return (
<div className="h-full w-full flex flex-col">
<div className="w-full flex pr-2 flex-row text-center items-center bg-gray-100">
<div className="w-full flex pr-2 flex-row text-center items-center bg-gray-100 px-2">
{flows.map((flow, index) => {
return (
<TabComponent
@ -29,17 +28,19 @@ export function TabsManager() {
})}
<TabComponent
onClick={() => {
const id = _.uniqueId();
addFlow({ name: "flow" + id, data: null, id });
addFlow();
}}
selected={false}
key={0}
flow={null}
/>
</div>
<div className="w-full h-full">
<ReactFlowProvider>
<FlowPage flow={flows[tabIndex]}></FlowPage>
{flows[tabIndex] ? (
<FlowPage flow={flows[tabIndex]}></FlowPage>
) : (
<></>
)}
</ReactFlowProvider>
</div>
</div>

View file

@ -19,6 +19,7 @@ import InputNode from "../../CustomNodes/InputNode";
import BooleanNode from "../../CustomNodes/BooleanNode";
import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext";
import { typesContext } from "../../contexts/typesContext";
const nodeTypes = {
genericNode: GenericNode,
@ -31,9 +32,9 @@ const nodeTypes = {
var _ = require("lodash");
export default function FlowPage({flow}) {
console.log(flow?.data)
const {updateFlow} = useContext(TabsContext)
const {reactFlowInstance, setReactFlowInstance} = useContext(typesContext);
const reactFlowWrapper = useRef(null);
const getId = () => `dndnode_${_.uniqueId()}`;
@ -41,30 +42,27 @@ export default function FlowPage({flow}) {
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
const { setErrorData } = useContext(alertContext);
const [nodes, setNodes, onNodesChange] = useNodesState(flow?.data?.nodes || []);
const [edges, setEdges, onEdgesChange] = useEdgesState(flow?.data?.edges || []);
const [reactFlowInstance, setReactFlowInstance] = useState(null);
const { setViewport} = useReactFlow();
useEffect(()=>{
if(flow?.data && reactFlowInstance){
setViewport(flow.data.viewport)
}
},[nodes, edges, flow, reactFlowInstance, setViewport])
const [nodes, setNodes, onNodesChange] = useNodesState(flow.data?.nodes ?? []);
const [edges, setEdges, onEdgesChange] = useEdgesState(flow.data?.edges ?? []);
useEffect(()=>{
if(reactFlowInstance && flow){
flow.data =reactFlowInstance.toObject()
updateFlow(flow)
flow.data = reactFlowInstance.toObject();
updateFlow(flow);
}
},[nodes,edges])
useEffect(()=>{
setNodes(flow?.data?.nodes || [])
setEdges(flow?.data?.edges || [])
console.log(flow);
setNodes(flow?.data?.nodes ?? [])
setEdges(flow?.data?.edges ?? [])
},[flow])
useEffect(() => {
console.log(nodes);
console.log(edges);
}, [edges, nodes])
useEffect(() => {
setExtraComponent(<ExtraSidebar />);
setExtraNavigation({ title: "Nodes" });
@ -133,7 +131,6 @@ export default function FlowPage({flow}) {
...data,
id: newId,
value: null,
reactFlowInstance,
onDelete: () => {
setNodes(
reactFlowInstance.getNodes().filter((n) => n.id !== newId)
@ -156,6 +153,7 @@ export default function FlowPage({flow}) {
<div className="w-full h-full" ref={reactFlowWrapper}>
<ReactFlow
nodes={nodes}
defaultViewport={flow?.data?.viewport ?? {x: 1, y: 0, zoom: 1}}
onMove={()=>updateFlow({...flow,data:reactFlowInstance.toObject()})}
edges={edges}
onNodesChange={onNodesChange}