import './index.less'; import DetailSide from '@/component/detail-side'; import Sidebar from '@/component/sidebar'; import { useExecutionDump } from '@/component/store'; import type { GroupedActionDump } from '@midscene/core'; import { Helmet } from '@modern-js/runtime/head'; import { Button, ConfigProvider, Upload, message } from 'antd'; import type { UploadProps } from 'antd'; import { useEffect, useRef, useState } from 'react'; import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; import Logo from './component/assets/logo-plain.svg'; import DetailPanel from './component/detail-panel'; import GlobalHoverPreview from './component/global-hover-preview'; import Timeline from './component/timeline'; import demoDump from './demo-dump.json'; const { Dragger } = Upload; let globalRenderCount = 1; export function Visualizer(props: { hideLogo?: boolean; logoAction?: () => void; dump?: GroupedActionDump[]; }): JSX.Element { const { dump } = props; const executionDump = useExecutionDump((store) => store.dump); const setGroupedDump = useExecutionDump((store) => store.setGroupedDump); const reset = useExecutionDump((store) => store.reset); const [mainLayoutChangeFlag, setMainLayoutChangeFlag] = useState(0); const mainLayoutChangedRef = useRef(false); useEffect(() => { if (dump) { setGroupedDump(dump); } return () => { reset(); }; }, []); useEffect(() => { const onResize = () => { setMainLayoutChangeFlag((prev) => prev + 1); }; window.addEventListener('resize', onResize); return () => { window.removeEventListener('resize', onResize); }; }, []); const uploadProps: UploadProps = { name: 'file', multiple: false, capture: false, customRequest: () => { // noop }, beforeUpload(file) { const ifValidFile = file.name.endsWith('web-dump.json'); // || file.name.endsWith('.insight.json'); // const ifActionFile = // file.name.endsWith('.actions.json') || /_force_regard_as_action_file/.test(location.href); if (!ifValidFile) { message.error('invalid file extension'); return false; } const reader = new FileReader(); reader.readAsText(file); reader.onload = (e) => { const result = e.target?.result; if (typeof result === 'string') { try { const data = JSON.parse(result); // setMainLayoutChangeFlag((prev) => prev + 1); setGroupedDump(data); // if (ifActionFile) { // } else { // loadInsightDump(data); // } } catch (e: any) { console.error(e); message.error('failed to parse dump data', e.message); } } else { message.error('Invalid dump file'); } }; return false; }, }; const loadDemoDump = () => { setGroupedDump(demoDump as any); }; let mainContent: JSX.Element; if (!executionDump) { mainContent = (
Click or drag the{' '} .web-dump.json {' '} {/* or{' '} .actions.json {' '} */} file into this area.
The latest dump file is usually placed in{' '} ./midscene_run/report
All data will be processed locally by the browser. No data will be sent to the server.