diff --git a/frontend/packages/core/public/locales/en/common.json b/frontend/packages/core/public/locales/en/common.json index 9a2b00d90f116fe0386d9085304f01135ea68c17..bc203e1e181df758301218c889bae5f14bd60e4b 100644 --- a/frontend/packages/core/public/locales/en/common.json +++ b/frontend/packages/core/public/locales/en/common.json @@ -11,7 +11,7 @@ "error": "Error occurred", "graph": "Graphs", "dynamic_graph": "dynamic", - "ToggleGraph": "X2Paddle", + "x2paddle": "Model Convertion", "static_graph": "static", "high-dimensional": "High Dimensional", "profiler": "performance analysis", diff --git a/frontend/packages/core/public/locales/en/togglegraph.json b/frontend/packages/core/public/locales/en/togglegraph.json index 2e55806ff0b2ce47d66cfc103987a876f492e8c4..180df4ae0a4ce76d7fee82683edf8a1c613d2e96 100644 --- a/frontend/packages/core/public/locales/en/togglegraph.json +++ b/frontend/packages/core/public/locales/en/togglegraph.json @@ -8,5 +8,26 @@ "warin-info4": "The model has been converted, please do not click again", "warin-info5": "Please upload the model file and convert it", "warin-info6": "Model file has been converted, please do not click again", - "warin-info7": "Please upload the model file" + "warin-info7": "Please upload the model file", + "Conversion": "Conversion", + "pdmodels": "pdmodels", + "pdiparams": "pdiparams", + "model": "model", + "opset_version": "opset_version", + "deploy_backend": "deploy_backend", + "lite_valid_places": "lite_valid_places", + "lite_model_type": "lite_model_type", + "convert_to_lite": "convert_to_lite", + "onnx_model": "onnx model", + "Download": "Download", + "Reload": "Reload", + "View": "View", + "Please": "Please select the file", + "isRequire": "This item is required", + "isYes": "Yes", + "isNo": "No", + "Paddle2OnnxTitle": "Paddle2Onnx model conversion configuration", + "Onnx2PaddleTitle": "Onnx2Paddle model conversion configuration", + "converting": "Converting now, please wait", + "downloading": "Downloading now, please wait" } diff --git a/frontend/packages/core/public/locales/zh/common.json b/frontend/packages/core/public/locales/zh/common.json index 1537d77f0f549085c049b0d66cbfb2158f837b1b..25fa1660136fdf169fbbe8f189de6466ce243e45 100644 --- a/frontend/packages/core/public/locales/zh/common.json +++ b/frontend/packages/core/public/locales/zh/common.json @@ -11,7 +11,7 @@ "error": "发生错误", "graph": "网络结构", "dynamic_graph": "动态", - "ToggleGraph": "X2Paddle", + "x2paddle": "模型转换", "static_graph": "静态", "high-dimensional": "数据降维", "profiler": "性能分析", diff --git a/frontend/packages/core/public/locales/zh/togglegraph.json b/frontend/packages/core/public/locales/zh/togglegraph.json index 53785da767f22f04a89e55cf8c08210026712be7..1748dc4fdd044ed85cca8458e230b6b65cbb6a7b 100644 --- a/frontend/packages/core/public/locales/zh/togglegraph.json +++ b/frontend/packages/core/public/locales/zh/togglegraph.json @@ -8,5 +8,26 @@ "warin-info4": "模型已转换,请勿再次点击", "warin-info5": "请上传模型文件并转换", "warin-info6": "模型文件已转换,请勿再次点击", - "warin-info7": "请上传模型文件" + "warin-info7": "请上传模型文件", + "Conversion": "转换", + "pdmodels": "模型结构文件", + "pdiparams": "模型参数文件", + "model": "模型", + "opset_version": "op集合版本", + "deploy_backend": "部署后端类型", + "lite_valid_places": "Lite后端类型", + "lite_model_type": "Lite模型类型", + "convert_to_lite": "是否转成Paddle-Lite支持格式", + "onnx_model": "onnx模型", + "Download": "下载", + "Reload": "重新载入", + "View": "视图", + "Please": "请上传模型文件", + "isRequire": "该项为必填项", + "isYes": "是", + "isNo": "否", + "Paddle2OnnxTitle": "Paddle2Onnx模型转换配置", + "Onnx2PaddleTitle": "Onnx2Paddle模型转换配置", + "converting": "转换中,请稍等片刻", + "downloading": "文件下载中,请稍等片刻" } diff --git a/frontend/packages/core/src/components/ContentXpaddle.tsx b/frontend/packages/core/src/components/ContentXpaddle.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bb9ee21dd8ba01ca613eb9de3eca1599624703ee --- /dev/null +++ b/frontend/packages/core/src/components/ContentXpaddle.tsx @@ -0,0 +1,118 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, {FunctionComponent} from 'react'; +import {WithStyled, contentHeight, contentMargin, headerHeight, position, transitionProps} from '~/utils/style'; + +import BodyLoading from '~/components/BodyLoading'; +import styled from 'styled-components'; + +const Section = styled.section` + display: flex; + font-family: PingFangSC-Regular; + aside { + position: static; + height: auto; + } +`; + +const Article = styled.article` + flex: auto; + min-width: 0; + margin: ${contentMargin}; + min-height: ${contentHeight}; +`; + +const Aside = styled.aside` + flex: none; + background-color: var(--background-color); + height: ${`calc(100vh - ${headerHeight})`}; + ${position('sticky', headerHeight, 0, null, null)} + width:18.571428571428573rem; + overflow-x: hidden; + overflow-y: auto; + ${transitionProps('background-color')} +`; +const ProfilerAside = styled.aside` + flex: none; + background-color: var(--background-color); + height: auto; + position: static; + overflow-x: hidden; + overflow-y: auto; + ${transitionProps('background-color')} +`; + +type ContentProps = { + aside?: React.ReactNode; + leftAside?: React.ReactNode; + loading?: boolean; + isProfiler?: boolean; + show?: boolean; + nodeShow?: boolean; +}; + +const Content: FunctionComponent = ({ + children, + aside, + leftAside, + loading, + className, + isProfiler, + show, + nodeShow +}) => ( +
+ {leftAside && } +
{children}
+ {aside && isProfiler ? ( + {aside} + ) : ( + // `${`calc(100vh - ${headerHeight})`}` + + + )} + {loading && } +
+); + +export default Content; diff --git a/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx b/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx index 7f9d88be439ad1b0494f1a6611db7b62881fa871..1ca56923faf0fd00d0e5bbf77623a5e0ff4c5861 100644 --- a/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx +++ b/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx @@ -71,6 +71,7 @@ const Content = styled.div` > iframe { ${size('100%', '100%')} + // ${size('50%', '100%')} border: none; } diff --git a/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx b/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx index 8c58cc04bfaca0cd5a04274e003152fb30075a99..66980f12af21c9e293cf78c6130d1bb979946d10 100644 --- a/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx +++ b/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx @@ -23,6 +23,8 @@ import ChartToolbox from '~/components/ChartToolbox'; import HashLoader from 'react-spinners/HashLoader'; import logo from '~/assets/images/netron.png'; import netron2 from '@visualdl/netron2'; +import netron from '@visualdl/netron'; + import styled from 'styled-components'; import {toast} from 'react-toastify'; import useTheme from '~/hooks/useTheme'; @@ -72,6 +74,7 @@ const Content = styled.div` height: calc(100% - ${toolboxHeight}); > iframe { + // ${size('50%', '100%')} ${size('100%', '100%')} border: none; } @@ -300,9 +303,17 @@ const Graph = React.forwardRef( tooltipPlacement="bottom" /> + {/* */} */} + + + Powered by netron + + + + + ); + } +); + +Graph.displayName = 'Graph'; + +export default Graph; diff --git a/frontend/packages/core/src/components/Onnx2PaddleUpload.tsx b/frontend/packages/core/src/components/Onnx2PaddleUpload.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4436ffe2f6e4ec09724c0f4c4d192b8397cc08a1 --- /dev/null +++ b/frontend/packages/core/src/components/Onnx2PaddleUpload.tsx @@ -0,0 +1,194 @@ +/* eslint-disable react-hooks/rules-of-hooks */ + +import React, {useState} from 'react'; +import {Form, Input, Radio, Select} from 'antd'; +import type {UploadProps} from 'antd'; +import Buttons from '~/components/Button'; +import {axios_fetcher} from '~/utils/fetch'; +import {message} from 'antd'; +import {useTranslation} from 'react-i18next'; +import {Progress} from 'antd'; + +const {Option} = Select; +export default function xpaddleUploader(props: any) { + const [form] = Form.useForm(); + const {t} = useTranslation(['togglegraph', 'common']); + const formLayout: any = {labelCol: {span: 4}, wrapperCol: {span: 14}}; + const [convertProcess, setConvertProgress] = useState(0); + const [convertProcessFlag, setconvertProcessFlag] = useState(false); + const Uploadprops: UploadProps = { + name: 'file', + action: '', + headers: { + authorization: 'authorization-text' + }, + onChange(info) { + // debugger; + if (info.file.status !== 'uploading') { + console.log(info.file, info.fileList); + } + if (info.file.status === 'done') { + message.success(`${info.file.name} file uploaded successfully`); + } else if (info.file.status === 'error') { + message.error(`${info.file.name} file upload failed.`); + } + } + }; + const LiteBackend = [ + 'arm', + 'opencl', + 'x86', + 'metal', + 'xpu', + 'bm', + 'mlu', + 'intel_fpga', + 'huawei_ascend_npu', + 'imagination_nna', + 'rockchip_npu', + 'mediatek_apu', + 'huawei_kirin_npu', + 'amlogic_npu' + ]; + + const lite_model_type = ['protobuf', 'naive_buffer']; + const base64UrlToFile = (base64Url: any, filename: any) => { + // const arr = base64Url.split(','); + // const mime = arr[0].match(/:(.*?);/)[1]; + const bstr = atob(base64Url); + let n = bstr.length; + const u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], filename); + }; + const submodel = async () => { + props.changeLoading(true); + const values = await form.validateFields(); + const formData = new FormData(); + const onnx_file_component = document.getElementById('upload_onnx_model_file') as HTMLInputElement; + const onnx_file = onnx_file_component!.files![0]; + formData.append('convert_to_lite', values.convertToLite); + formData.append('model', onnx_file); + formData.append('lite_valid_places', values.liteValidPlaces); + formData.append('lite_model_type:', values.liteModelType); + + axios_fetcher( + `/inference/onnx2paddle/convert`, + { + method: 'POST', + body: formData + }, + { + onDownloadProgress: function (axiosProgressEvent: any) { + setConvertProgress(Math.round(axiosProgressEvent.progress! * 100)); + setconvertProcessFlag(true); + } + } + ) + .then( + (res: any) => { + const files2 = base64UrlToFile(res.model, 'model.pdmodel'); + props.setFiles([onnx_file]); + props.changeFiles2([files2]); + + const current_date = new Date(); + const filename = `${current_date.getFullYear()}_${current_date.getMonth()}_${current_date.getDay()}_${current_date.getHours()}_${current_date.getMinutes()}_${current_date.getSeconds()}_paddlemodel.tar`; + props.downloadEvent(res['request_id'], filename); + }, + res => { + props.changeLoading(false); + console.log(res); + } + ) + .finally(() => { + setconvertProcessFlag(false); + }); + }; + return ( +
+
+ {t('togglegraph:Onnx2PaddleTitle')} +
+
+ + + + + + {t('togglegraph:isYes')} + {t('togglegraph:isNo')} + + + + + + + + + {/* + + */} +
+
+ { + setConvertProgress(0); + setconvertProcessFlag(true); + submodel(); + }} + > + {t('Conversion')} + + {convertProcessFlag ? : null} + {convertProcessFlag ?

{t('togglegraph:converting')}

: null} +
+
+ ); +} diff --git a/frontend/packages/core/src/components/Paddle2OnnxUpload.tsx b/frontend/packages/core/src/components/Paddle2OnnxUpload.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ae40685a51b3046d29a85acd75e26b63ef6211db --- /dev/null +++ b/frontend/packages/core/src/components/Paddle2OnnxUpload.tsx @@ -0,0 +1,187 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +/* eslint-disable prettier/prettier */ +import React, {useState} from 'react'; +import {Form, Input, Radio, Select} from 'antd'; +import {UploadOutlined} from '@ant-design/icons'; +import type {UploadProps} from 'antd'; +import Buttons from '~/components/Button'; +import {message, Upload, Button} from 'antd'; +import {fetcher, axios_fetcher} from '~/utils/fetch'; +import {useTranslation} from 'react-i18next'; +import {Progress, Space} from 'antd'; + +const {Option} = Select; +export default function xpaddleUploader(props: any) { + const [form] = Form.useForm(); + const formLayout: any = {labelCol: {span: 4}, wrapperCol: {span: 14}}; + const {t} = useTranslation(['togglegraph', 'common']); + const [convertProcess, setConvertProgress] = useState(0); + const [convertProcessFlag, setconvertProcessFlag] = useState(false); + const Uploadprops: UploadProps = { + name: 'file', + action: '', + headers: { + authorization: 'authorization-text' + }, + onChange(info) { + // debugger; + if (info.file.status !== 'uploading') { + console.log(info.file, info.fileList); + } + if (info.file.status === 'done') { + message.success(`${info.file.name} file uploaded successfully`); + } else if (info.file.status === 'error') { + message.error(`${info.file.name} file upload failed.`); + } + } + }; + const LiteBackend = [7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + const lite_model_type = ['onnxruntime', 'tensorrt', 'others']; + + const base64UrlToFile = (base64Url: any, filename: any) => { + // const arr = base64Url.split(','); + // const mime = arr[0].match(/:(.*?);/)[1]; + const bstr = atob(base64Url); + let n = bstr.length; + const u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], filename); + }; + const submodel = async () => { + props.changeLoading(true); + const values = await form.validateFields(); + // debugger; + const formData = new FormData(); + + const model_file_component = document.getElementById('upload_pd_model_file') as HTMLInputElement; + const model_file = model_file_component!.files![0]; + const param_file_component = document.getElementById('upload_pd_param_file') as HTMLInputElement; + const param_file = param_file_component!.files![0]; + + formData.append('model', model_file); + formData.append('param', param_file); + formData.append('opset_version', values['opset_version']); + formData.append('deploy_backend:', values['deployBackend']); + + axios_fetcher( + `/inference/paddle2onnx/convert`, + { + method: 'POST', + body: formData + }, + { + onDownloadProgress: function (axiosProgressEvent: any) { + setConvertProgress(Math.round(axiosProgressEvent.progress! * 100)); + setconvertProcessFlag(true); + } + } + ) + .then( + (res: any) => { + const files2 = base64UrlToFile(res.model, 'model.onnx'); + props.setFiles([model_file]); + props.changeFiles2([files2]); + const current_date = new Date(); + const filename = `${current_date.getFullYear()}_${current_date.getMonth()}_${current_date.getDay()}_${current_date.getHours()}_${current_date.getMinutes()}_${current_date.getSeconds()}_onnxmodel.onnx`; + props.downloadEvent(res['request_id'], filename); + }, + res => { + // debugger; + props.changeLoading(false); + console.log(res); + } + ) + .finally(() => { + setconvertProcessFlag(false); + }); + }; + return ( +
+
+ {t('togglegraph:Paddle2OnnxTitle')} +
+
+ + + + + + + + + + + + + +
+
+ { + setConvertProgress(0); + setconvertProcessFlag(true); + submodel(); + }} + > + {t('togglegraph:Conversion')} + + {convertProcessFlag ? ( + + ) : null} + {convertProcessFlag ?

{t('togglegraph:converting')}

: null} +
+
+ ); +} diff --git a/frontend/packages/core/src/components/styles.css b/frontend/packages/core/src/components/styles.css new file mode 100644 index 0000000000000000000000000000000000000000..fe9d6b9366045b10c99fd055012a97d16b653f52 --- /dev/null +++ b/frontend/packages/core/src/components/styles.css @@ -0,0 +1,3 @@ +.progressCircle{ + align-items: center; +} \ No newline at end of file diff --git a/frontend/packages/core/src/pages/graphStatic2.tsx b/frontend/packages/core/src/pages/graphStatic2.tsx index 6fecdb95762d68fd781192b5cc4416f9a8ebd400..b7ff98a57397d6952dc3d667df315fe987fc529b 100644 --- a/frontend/packages/core/src/pages/graphStatic2.tsx +++ b/frontend/packages/core/src/pages/graphStatic2.tsx @@ -27,7 +27,7 @@ import {useDispatch} from 'react-redux'; import type {BlobResponse} from '~/utils/fetch'; import Button from '~/components/Button'; import Checkbox from '~/components/Checkbox'; -import Content from '~/components/Content'; +import Content from '~/components/ContentXpaddle'; import Field from '~/components/Field'; import HashLoader from 'react-spinners/HashLoader'; import ModelPropertiesDialog from '~/components/GraphPage/ModelPropertiesDialog'; @@ -110,6 +110,7 @@ const Graph = React.forwardRef(({changeRendered, show = tru const {loading} = useRequest(files ? null : '/graph/graph'); const setModelFile = useCallback( (f: FileList | File[]) => { + // debugger; storeDispatch(actions.graph.setModel(f)); setFiles(f); }, @@ -224,7 +225,6 @@ const Graph = React.forwardRef(({changeRendered, show = tru ); } - console.log('nodeData && renderedflag3', nodeData, renderedflag3); if (nodeData && renderedflag3) { return ( @@ -290,6 +290,7 @@ const Graph = React.forwardRef(({changeRendered, show = tru + @@ -332,12 +333,13 @@ const Graph = React.forwardRef(({changeRendered, show = tru () => , [onClickFile, setModelFile] ); - + // const flags = false; + const flags = files && show; return ( <> {t('common:graph')} setModelData(null)} /> - + {loading ? ( diff --git a/frontend/packages/core/src/pages/graphStatic3.tsx b/frontend/packages/core/src/pages/graphStatic3.tsx index ede65550d727862890517383e88af81696523b5f..100345d34b361dbc0eebcb78355b3af06e567912 100644 --- a/frontend/packages/core/src/pages/graphStatic3.tsx +++ b/frontend/packages/core/src/pages/graphStatic3.tsx @@ -17,17 +17,19 @@ import Aside, {AsideSection} from '~/components/Aside'; import type {Documentation, OpenedResult, Properties, SearchItem, SearchResult} from '~/resource/graph/types'; -import GraphComponent, {GraphRef} from '~/components/GraphPage/GraphStatic'; +import GraphComponent, {GraphRef} from '~/components/GraphPage/GraphStatic3'; import React, {useImperativeHandle, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import Select, {SelectProps} from '~/components/Select'; import {actions} from '~/store'; import {primaryColor, rem, size} from '~/utils/style'; import {useDispatch} from 'react-redux'; +import XpaddleUploader from '~/components/Onnx2PaddleUpload'; +import Paddle2OnnxUpload from '~/components/Paddle2OnnxUpload'; import type {BlobResponse} from '~/utils/fetch'; -import Button from '~/components/Button'; +import Buttons from '~/components/Button'; import Checkbox from '~/components/Checkbox'; -import Content from '~/components/Content'; +import Content from '~/components/ContentXpaddle'; import Field from '~/components/Field'; import HashLoader from 'react-spinners/HashLoader'; import ModelPropertiesDialog from '~/components/GraphPage/ModelPropertiesDialog'; @@ -42,7 +44,7 @@ import styled from 'styled-components'; import useRequest from '~/hooks/useRequest'; import {useTranslation} from 'react-i18next'; -const FullWidthButton = styled(Button)` +const FullWidthButton = styled(Buttons)` width: 100%; `; @@ -87,280 +89,368 @@ const Loading = styled.div` `; type GraphProps = { changeName: (name: string) => void; + changeFlags: (flag: boolean) => void; + changeFiles2?: (file: any) => void; show?: boolean; changeshowdata?: () => void; + downloadEvent?: (baseId: number, fileName: string) => void; + changeLoading?: (value: any) => void; Xpaddlae?: boolean; + ModelValue?: number; }; type pageRef = { files: FileList | File[] | null; + setnewfiles: () => void; setNodeDocumentations: () => void; }; -const Graph = React.forwardRef(({changeName, changeshowdata, Xpaddlae, show = true}, ref) => { - const {t} = useTranslation(['graph', 'common']); +const Graph = React.forwardRef( + ( + { + changeName, + changeshowdata, + Xpaddlae, + show = true, + changeFlags, + changeLoading, + changeFiles2, + downloadEvent, + ModelValue + }, + ref + ) => { + const {t} = useTranslation(['graph', 'common']); - const storeDispatch = useDispatch(); - // const storeModel = useSelector(selectors.graph.model); + const storeDispatch = useDispatch(); + // const storeModel = useSelector(selectors.graph.model); - const graph = useRef(null); - const file = useRef(null); - const [files, setFiles] = useState(); - const setModelFile = useCallback( - (f: FileList | File[]) => { - storeDispatch(actions.graph.setModel(f)); - const name = f[0].name.substring(f[0].name.lastIndexOf('.') + 1); - changeName && changeName(name); + const graph = useRef(null); + const file = useRef(null); + const [files, setFiles] = useState(); + const setModelFile = useCallback( + (f: FileList | File[]) => { + storeDispatch(actions.graph.setModel(f)); + const name = f[0].name.substring(f[0].name.lastIndexOf('.') + 1); + changeName && changeName(name); + setFiles(f); + changeFlags(true); + changeshowdata && changeshowdata(); + }, + [storeDispatch] + ); + const newsetfiles = (f: FileList | File[]) => { + // changeFlags(false); + setRendered(false); setFiles(f); - changeshowdata && changeshowdata(); - }, - [storeDispatch] - ); - const onClickFile = useCallback(() => { - if (file.current) { - file.current.value = ''; - file.current.click(); - } - }, []); - const onChangeFile = useCallback( - (e: React.ChangeEvent) => { - const target = e.target; - if (target && target.files && target.files.length) { - setModelFile(target.files); + }; + const onClickFile = useCallback(() => { + if (file.current) { + file.current.value = ''; + file.current.click(); } - }, - [setModelFile] - ); - - // const {data, loading} = useRequest(files ? null : '/graph/static_graph'); + }, []); + const onChangeFile = useCallback( + (e: React.ChangeEvent) => { + const target = e.target; + if (target && target.files && target.files.length) { + setModelFile(target.files); + } + }, + [setModelFile] + ); - // useEffect(() => { - // if (data?.data?.size) { - // setFiles([new File([data.data], data.filename || 'unknown_model')]); - // } - // }, [data]); - const {loading} = useRequest(files ? null : '/graph/graph'); + // const {data, loading} = useRequest(files ? null : '/graph/static_graph'); - const [modelGraphs, setModelGraphs] = useState([]); - const [selectedGraph, setSelectedGraph] = useState>(''); - const setOpenedModel = useCallback((data: OpenedResult) => { - setModelGraphs(data.graphs); - setSelectedGraph(data.selected || ''); - }, []); - const changeGraph = useCallback((name: string) => { - setSelectedGraph(name); - graph.current?.changeGraph(name); - }, []); + // useEffect(() => { + // if (data?.data?.size) { + // setFiles([new File([data.data], data.filename || 'unknown_model')]); + // } + // }, [data]); + const {loading} = useRequest(files ? null : '/graph/graph'); - const [search, setSearch] = useState(''); - const [searching, setSearching] = useState(false); - const [searchResult, setSearchResult] = useState({text: '', result: []}); - const onSearch = useCallback((value: string) => { - setSearch(value); - graph.current?.search(value); - }, []); - const onSelect = useCallback((item: SearchItem) => { - setSearch(item.name); - graph.current?.select(item); - }, []); + const [modelGraphs, setModelGraphs] = useState([]); + const [selectedGraph, setSelectedGraph] = useState>(''); + const setOpenedModel = useCallback((data: OpenedResult) => { + setModelGraphs(data.graphs); + setSelectedGraph(data.selected || ''); + }, []); + const changeGraph = useCallback((name: string) => { + setSelectedGraph(name); + graph.current?.changeGraph(name); + }, []); - const [showAttributes, setShowAttributes] = useState(false); - const [showInitializers, setShowInitializers] = useState(true); - const [showNames, setShowNames] = useState(false); - const [horizontal, setHorizontal] = useState(false); + const [search, setSearch] = useState(''); + const [searching, setSearching] = useState(false); + const [searchResult, setSearchResult] = useState({text: '', result: []}); + const onSearch = useCallback((value: string) => { + setSearch(value); + graph.current?.search(value); + }, []); + const onSelect = useCallback((item: SearchItem) => { + setSearch(item.name); + graph.current?.select(item); + }, []); - const [modelData, setModelData] = useState(null); - const [nodeData, setNodeData] = useState(null); - const [nodeDocumentation, setNodeDocumentation] = useState(null); - const [renderedflag3, setRenderedflag3] = useState(true); + const [showAttributes, setShowAttributes] = useState(false); + const [showInitializers, setShowInitializers] = useState(true); + const [showNames, setShowNames] = useState(false); + const [horizontal, setHorizontal] = useState(false); - useEffect(() => { - setSearch(''); - setSearchResult({text: '', result: []}); - }, [files, showAttributes, showInitializers, showNames]); - useEffect(() => { - if (!show) { - setRenderedflag3(false); - } else { - setRenderedflag3(true); - setNodeData(null); - } - }, [show]); - const bottom = useMemo( - () => - searching ? null : ( - - {t('graph:change-model')} - - ), - [t, onClickFile, searching] - ); + const [modelData, setModelData] = useState(null); + const [nodeData, setNodeData] = useState(null); + const [nodeDocumentation, setNodeDocumentation] = useState(null); + const [renderedflag3, setRenderedflag3] = useState(true); + const [rendered, setRendered] = useState(false); + useEffect(() => { + setSearch(''); + setSearchResult({text: '', result: []}); + }, [files, showAttributes, showInitializers, showNames]); + useEffect(() => { + if (!show) { + setRenderedflag3(false); + } else { + setRenderedflag3(true); + setNodeData(null); + } + }, [show]); + useEffect(() => { + setFiles(undefined); + }, [ModelValue]); + // useEffect(() => { + // if (nodeData && renderedflag3) { + // debugger; + // changeFlags(false); + // } + // }, [nodeData, renderedflag3]); + useEffect(() => { + if (rendered) { + // debugger; + // if () + changeFlags(true); + changeLoading && changeLoading(false); + } + }, [rendered]); + const bottom = useMemo( + () => + searching ? null : ( + + {t('graph:change-model')} + + ), + [t, onClickFile, searching] + ); - const [rendered, setRendered] = useState(false); - useImperativeHandle(ref, () => ({ - files, - setNodeDocumentations: () => { - setRenderedflag3(false); - } - })); - const aside = useMemo(() => { - if (!rendered || loading) { - return null; - } - if (nodeDocumentation) { - return ( - - ); - } - console.log('nodeData && renderedflag3', nodeData, renderedflag3); - if (nodeData && renderedflag3) { + useImperativeHandle(ref, () => ({ + files, + setnewfiles: () => { + // debugger; + setFiles(undefined); + }, + setNodeDocumentations: () => { + setRenderedflag3(false); + } + })); + const aside = useMemo(() => { + if (!rendered || loading) { + return null; + } + if (nodeDocumentation) { + return ( + + ); + } + console.log('nodeData && renderedflag3', nodeData, renderedflag3); + if (nodeData && renderedflag3) { + return ( + + ); + } return ( - - ); - } - return ( -