Commit 024d8d6e authored by tanapon yotanak's avatar tanapon yotanak

update

parent f14f4530
Pipeline #508 canceled with stages
This diff is collapsed.
......@@ -3,12 +3,16 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/material": "^5.15.17",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"reactflow": "^11.11.3",
"web-vitals": "^2.1.4"
},
"scripts": {
......
import logo from './logo.svg';
import './App.css';
import Main from './components/Main';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<Main />
</div>
);
}
......
import React, { useCallback, useState } from 'react';
import ReactFlow, {
MiniMap,
Controls,
Background,
useNodesState,
useEdgesState,
addEdge,
Panel,
useReactFlow,
} from 'reactflow';
import 'reactflow/dist/style.css';
const flowKey = 'example-flow';
const getNodeId = () => `randomnode_${+new Date()}`;
const initialNodes = [
{ id: '1', data: { label: 'Node 1' }, position: { x: 100, y: 100 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 200 } },
];
const initialEdges = [{ id: 'e1-2', source: '1', target: '2' }];
const DesignManagement = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const [rfInstance, setRfInstance] = useState(null);
const { setViewport } = useReactFlow();
const [selectedFile, setSelectedFile] = useState(null);
const [selectedJsonFile, setSelectedJsonFile] = useState(null);
const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);
const onSave = useCallback(() => {
if (rfInstance) {
const flow = rfInstance.toObject();
console.log('flowKey: ' + flowKey)
console.log('flow: ' + flow)
localStorage.setItem(flowKey, JSON.stringify(flow));
}
}, [rfInstance]);
const onRestore = useCallback(() => {
const restoreFlow = async () => {
const flow = JSON.parse(localStorage.getItem(flowKey));
if (flow) {
const { x = 0, y = 0, zoom = 1 } = flow.viewport;
setNodes(flow.nodes || []);
setEdges(flow.edges || []);
setViewport({ x, y, zoom });
}
};
restoreFlow();
}, [setNodes, setViewport]);
const onAdd = useCallback(() => {
const newNode = {
id: getNodeId(),
data: { label: 'Added node' },
position: {
x: Math.random() * window.innerWidth - 100,
y: Math.random() * window.innerHeight,
},
};
setNodes((nds) => nds.concat(newNode));
}, [setNodes]);
const onExport = useCallback(() => {
if (rfInstance) {
const flow = rfInstance.toObject();
// console.log("flow:", JSON.stringify(flow, null, 2));
// สร้าง Blob จาก JSON string
const jsonString = JSON.stringify(flow, null, 2);
const blob = new Blob([jsonString], { type: 'application/json' });
// สร้าง URL จาก Blob
const url = URL.createObjectURL(blob);
// สร้างลิงก์ดาวน์โหลดชั่วคราว
const link = document.createElement('a');
link.href = url;
link.download = 'data-react-flow.json';
// เพิ่มลิงก์ไปยัง DOM และคลิกมันโปรแกรมมิ่ง
document.body.appendChild(link);
link.click();
// ลบลิงก์ออกจาก DOM
document.body.removeChild(link);
// ปลดปล่อยหน่วยความจำ URL ที่สร้างขึ้น
URL.revokeObjectURL(url);
}
}, [rfInstance]);
const handleFileChange = (event) => {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = (event) => {
try {
const json = JSON.parse(event.target.result);
console.log("json file:", json);
setSelectedJsonFile(json)
} catch (error) {
console.error("Error parsing JSON: ", error);
}
};
if (file) {
reader.readAsText(file);
}
setSelectedFile(file);
};
const handleUploadClick = () => {
document.getElementById('fileInput').click();
};
const handleSubmit = () => {
if (!selectedFile) {
alert('Please select a file first!');
return;
}
// console.log("selectedFile:", selectedFile);
// console.log("file:", JSON.stringify(selectedFile, null, 2));
// สามารถเพิ่มการประมวลผลไฟล์ที่เลือกได้ที่นี่
// เช่น อัปโหลดไฟล์ไปยังเซิร์ฟเวอร์
const renderFlow = async () => {
console.log("selectedJsonFile:", selectedJsonFile);
if (selectedJsonFile) {
const { x = 0, y = 0, zoom = 1 } = selectedJsonFile.viewport;
setNodes(selectedJsonFile.nodes || []);
setEdges(selectedJsonFile.edges || []);
setViewport({ x, y, zoom });
}
};
renderFlow();
};
const handleCancel = () => {
setSelectedFile(null)
};
return (
<div style={{ width: '100%', height: '100%' }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
onInit={setRfInstance}
>
<Panel position="top-left">
<div style={{ display: 'flex', flexDirection: 'row', maxHeight: 20 }}>
<button onClick={handleUploadClick}>import</button>
<input
type="file"
id="fileInput"
style={{ display: 'none' }}
onChange={handleFileChange}
/>
{selectedFile && <div style={{ marginLeft: 10, marginRight: 10 }}>file: {selectedFile?.name}</div>}
<button onClick={handleSubmit}>upload</button>
<button onClick={handleCancel}>cancel</button>
</div>
</Panel>
<Panel position="top-right">
<button onClick={onSave}>save</button>
<button onClick={onRestore}>restore</button>
<button onClick={onAdd}>add node</button>
<button onClick={onExport}>export</button>
</Panel>
<Controls />
<MiniMap />
<Background variant="dots" gap={12} size={1} />
</ReactFlow>
</div>
);
}
export default DesignManagement;
\ No newline at end of file
import React, { useState } from 'react';
import DesignManagement from './DesignManagement';
import { styled } from '@mui/material/styles';
import MenuEditor from './MenuEditor';
import { Collapse } from '@mui/material';
import ToolEdit from './ToolEdit';
import { ReactFlowProvider } from 'reactflow';
const StyledContainer = styled('div')`
display: flex;
min-height: 100vh;
`;
const StyledLeftComponent = styled('div')`
// width: '20%';
`;
const StyledRightComponent = styled('div')`
flex: 1;
// width: 100%;
`;
const LeftComponent = () => {
return (
<StyledLeftComponent>
<MenuEditor />
</StyledLeftComponent>
)
}
const RightComponent = () => {
return (
<StyledRightComponent>
<ReactFlowProvider>
<DesignManagement />
</ReactFlowProvider>
</StyledRightComponent>
)
}
const Main = () => {
const [open, setOpen] = useState(false);
return (
<StyledContainer>
<ToolEdit setOpen={setOpen} open={open} />
<Collapse in={open} timeout="auto" orientation='horizontal' collapsedSize='0px' unmountOnExit>
<LeftComponent />
</Collapse>
<RightComponent />
</StyledContainer>
);
}
export default Main;
\ No newline at end of file
import { Typography } from '@mui/material';
import { styled } from '@mui/material/styles';
const Container = styled('div')`
width: 300px;
min-height: 100vh;
background: #607d8b;
margin: 0;
padding: 0;
`;
const Text = styled(Typography)`
color: white;
padding-top: 15px;
`;
const MenuEditor = () => {
return (
<Container>
<Text>
Tool Editor
</Text>
</Container>
)
}
export default MenuEditor;
\ No newline at end of file
import { Button } from '@mui/material';
import { styled } from '@mui/material/styles';
const Container = styled('div')`
width: 60px;
min-height: 100vh;
background: #455a64;
`;
const ButtonMui = styled(Button)`
background: #455a64;
border: 1px solid #ffffff;
min-width: 10px;
min-height: 20px;
margin-top: 10px;
padding: 5px 10px;
`;
const ToolEdit = (props) => {
const { setOpen, open } = props;
const handleToggle = () => {
setOpen(!open);
};
return (
<Container>
<ButtonMui variant="contained" onClick={handleToggle}>{open ? '<<' : '>>'}</ButtonMui>
</Container>
);
}
export default ToolEdit;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment