Implemented tabs storage, only working if current tab is empty
This commit is contained in:
parent
06a17c5eb9
commit
45d6f8e569
8 changed files with 119 additions and 48 deletions
45
space_flow/package-lock.json
generated
45
space_flow/package-lock.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue