From 74cbfb6be2f84c49d5bb88f6d9a36dfeb4c9a359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A8=E6=AC=A3?= Date: Tue, 20 Aug 2024 14:30:15 +0800 Subject: [PATCH] feat: add export/import functionality to flow canvas --- web/components/flow/node-param-handler.tsx | 26 ---------- web/pages/flow/canvas/index.tsx | 58 ++++++++++++++++++---- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/web/components/flow/node-param-handler.tsx b/web/components/flow/node-param-handler.tsx index f7d3abadf..ff2901aab 100644 --- a/web/components/flow/node-param-handler.tsx +++ b/web/components/flow/node-param-handler.tsx @@ -110,32 +110,6 @@ const NodeParamHandler: React.FC = ({ node, data, label, } } - // TODO: refresh flow node - async function refreshFlowNode() { - // setLoading(true); - const params = { - id: '', - type_name: '', - type_cls: '', - flow_type: 'operator' as const, - refresh: [ - { - name: '', - depends: [ - { - name: '', - value: '', - has_value: true, - }, - ], - }, - ], - }; - const [_, data] = await apiInterceptors(refreshFlowNodeById(params)); - // setLoading(false); - // setFlowList(data?.items ?? []); - } - function renderComponentByType(type: string, props?: any) { switch (type) { case 'select': diff --git a/web/pages/flow/canvas/index.tsx b/web/pages/flow/canvas/index.tsx index 072884f5c..e7ae601aa 100644 --- a/web/pages/flow/canvas/index.tsx +++ b/web/pages/flow/canvas/index.tsx @@ -5,8 +5,8 @@ import ButtonEdge from '@/components/flow/button-edge'; import CanvasNode from '@/components/flow/canvas-node'; import { IFlowData, IFlowUpdateParam } from '@/types/flow'; import { checkFlowDataRequied, getUniqueNodeId, mapHumpToUnderline, mapUnderlineToHump } from '@/utils/flow'; -import { FrownOutlined, SaveOutlined } from '@ant-design/icons'; -import { Button, Checkbox, Divider, Form, Input, Modal, Space, message, notification } from 'antd'; +import { ExportOutlined, FrownOutlined, ImportOutlined, SaveOutlined } from '@ant-design/icons'; +import { Button, Checkbox, Divider, Form, Input, Modal, Space, Tooltip, message, notification } from 'antd'; import { useSearchParams } from 'next/navigation'; import React, { DragEvent, useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -150,7 +150,7 @@ const Canvas: React.FC = () => { form.setFieldsValue({ name: result }); } - function clickSave() { + function onSave() { const flowData = reactFlow.toObject() as IFlowData; const [check, node, message] = checkFlowDataRequied(flowData); if (!check && message) { @@ -175,11 +175,40 @@ const Canvas: React.FC = () => { setIsModalVisible(true); } + // TODO: EXport flow data + function onExport() { + const flowData = reactFlow.toObject() as IFlowData; + const blob = new Blob([JSON.stringify(flowData)], { type: 'text/plain;charset=utf-8' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'flow.json'; + a.click(); + } + + // TODO: Import flow data + function onImport() { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.json'; + input.onchange = async (e: any) => { + const file = e.target.files[0]; + const reader = new FileReader(); + reader.onload = async (event) => { + const flowData = JSON.parse(event.target?.result as string) as IFlowData; + setNodes(flowData.nodes); + setEdges(flowData.edges); + }; + reader.readAsText(file); + }; + input.click; + } + async function handleSaveFlow() { const { name, label, description = '', editable = false, state = 'deployed' } = form.getFieldsValue(); console.log(form.getFieldsValue()); const reactFlowObject = mapHumpToUnderline(reactFlow.toObject() as IFlowData); - + if (id) { const [, , res] = await apiInterceptors(updateFlowById(id, { name, label, description, editable, uid: id, flow_data: reactFlowObject, state })); setIsModalVisible(false); @@ -202,11 +231,22 @@ const Canvas: React.FC = () => { return ( <> -
-
- -
-
+ + {[ + { title: 'import', icon: }, + { title: 'export', icon: }, + { title: 'save', icon: }, + ].map(({ title, icon }) => ( + + {icon} + + ))} + +