LucaVivona's picture
update/refactor frontend
1e8b235
raw
history blame
5.88 kB
import CustomNodeIframe from "../Nodes/Custom.js";
import '../../css/dist/output.css'
import ReactFlow, { Background,
applyNodeChanges,
ReactFlowProvider,
} from 'react-flow-renderer';
import React ,{ useState, useCallback, useRef, useEffect } from 'react';
import Navbar from '../Navagation/navbar';
import { useThemeDetector } from '../../helper/visual'
import {CgMoreVerticalAlt} from 'react-icons/cg'
import {BsFillEraserFill} from 'react-icons/bs'
import {FaRegSave} from 'react-icons/fa'
const types = {
custom : CustomNodeIframe,
}
export default function ReactEnviorment() {
const [theme, setTheme] = useState(useThemeDetector)
const [nodes, setNodes] = useState([]);
const [reactFlowInstance, setReactFlowInstance] = useState(null);
const reactFlowWrapper = useRef(null);
const [tool, setTool] = useState(false)
useEffect(() => {
const restore = () => {
const flow = JSON.parse(localStorage.getItem('flowkey'));
if(flow){
flow.nodes.map((nds) => nds.data.delete = deleteNode)
setNodes(flow.nodes || [])
console.log(flow)
}
}
restore()
},[])
const onNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[setNodes]
);
const onDragOver = useCallback((event) => {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
}, []);
const deleteNodeContains = (id) =>{setNodes((nds) => nds.filter(n => !n.id.includes(`${id}-`) ))}
const deleteNode = (id) =>{setNodes((nds) => nds.filter(n => n.id !== id ))}
const onSave = useCallback(() => {
if (reactFlowInstance) {
const flow = reactFlowInstance.toObject();
alert("The current nodes have been saved into the localstorage ๐Ÿ’พ")
localStorage.setItem('flowkey', JSON.stringify(flow));
var labels = [];
var colour = [];
var emoji = [];
for(let i = 0; i < flow.nodes.length; i++){
if (!labels.includes(flow.nodes[i].data.label))
colour.push(flow.nodes[i].data.colour)
emoji.push(flow.nodes[i].data.emoji)
labels.push(flow.nodes[i].data.label)
}
localStorage.setItem('colour',JSON.stringify(colour))
localStorage.setItem('emoji', JSON.stringify(emoji))
}
}, [reactFlowInstance]);
const onErase = useCallback(() => {
const flow = localStorage.getItem("flowkey")
if (reactFlowInstance && flow){
alert("The current nodes have been erased from the localstorage")
localStorage.removeItem("flowkey")
localStorage.removeItem('colour')
localStorage.removeItem('emoji')
}
},[reactFlowInstance])
const onDrop = useCallback(
(event) => {
event.preventDefault();
if(event.dataTransfer.getData('application/reactflow') !== ""){
const reactFlowBounds = reactFlowWrapper.current.getBoundingClientRect();
const type = event.dataTransfer.getData('application/reactflow');
const item = JSON.parse(event.dataTransfer.getData('application/item'));
const style = JSON.parse(event.dataTransfer.getData('application/style'));
// check if the dropped element is valid
if (typeof type === 'undefined' || !type) {
return;
}
const position = reactFlowInstance.project({
x: event.clientX - reactFlowBounds.left,
y: event.clientY - reactFlowBounds.top,
});
const newNode = {
id: `${item.name}-${nodes.length+1}`,
type,
position,
dragHandle : `#draggable`,
data: { label: `${item.name}`, host : `${item.host}`, colour : `${style.colour}`, emoji : `${style.emoji}`, delete : deleteNode },
};
setNodes((nds) => nds.concat(newNode));
}
},
[reactFlowInstance, nodes]);
return (
<div className={`${theme ? "dark" : ""}`}>
<div className={` absolute text-center ${tool ? "h-[203.3333px]" : "h-[41px]"} overflow-hidden w-[41px] text-4xl top-4 right-5 z-50 cursor-default select-none bg-white dark:bg-stone-900 rounded-full border border-black dark:border-white duration-500`} >
<CgMoreVerticalAlt className={` text-black dark:text-white ${tool ? "-rotate-0 mr-auto ml-auto mt-1" : " rotate-180 mr-auto ml-auto mt-1"} duration-300`} onClick={() => setTool(!tool)}/>
<h1 title={theme ? 'Dark Mode' : 'Light Mode'} className={`p-4 px-1 pb-0 ${tool ? "visible" : "invisible"} text-3xl`} onClick={() => setTheme(!theme)} >{theme ? '๐ŸŒ™' : 'โ˜€๏ธ'}</h1>
<FaRegSave title="Save" className={`mt-6 text-black dark:text-white ${tool ? "visible" : " invisible"} ml-auto mr-auto `} onClick={() => onSave()}/>
<BsFillEraserFill title="Erase" className={`mt-6 text-black dark:text-white ml-auto mr-auto ${tool ? "visible" : " invisible"} `} onClick={() => onErase()}/>
</div>
<div className={`flex h-screen w-screen ${theme ? "dark" : ""} transition-all`}>
<Navbar onDelete={deleteNodeContains} colour={JSON.parse(localStorage.getItem('colour'))} emoji={JSON.parse(localStorage.getItem('emoji'))}/>
<ReactFlowProvider>
<div className="h-screen w-screen" ref={reactFlowWrapper}>
<ReactFlow nodes={nodes} nodeTypes={types} onNodesChange={onNodesChange} onNodesDelete={deleteNode} onDragOver={onDragOver} onDrop={onDrop} onInit={setReactFlowInstance} fitView>
<Background variant='dots' size={1} className=" bg-white dark:bg-neutral-800"/>
</ReactFlow>
</div>
</ReactFlowProvider>
</div>
</div>
);
}