feat: 暂存,添加app-manager
This commit is contained in:
parent
969243cbbb
commit
272ceaa6a6
@ -20,6 +20,7 @@
|
|||||||
"@kevisual/codemirror": "^0.0.2",
|
"@kevisual/codemirror": "^0.0.2",
|
||||||
"@kevisual/query": "^0.0.6",
|
"@kevisual/query": "^0.0.6",
|
||||||
"@kevisual/ui": "^0.0.2",
|
"@kevisual/ui": "^0.0.2",
|
||||||
|
"@monaco-editor/react": "^4.6.0",
|
||||||
"@uiw/react-textarea-code-editor": "^3.0.2",
|
"@uiw/react-textarea-code-editor": "^3.0.2",
|
||||||
"@xyflow/react": "^12.3.1",
|
"@xyflow/react": "^12.3.1",
|
||||||
"antd": "^5.21.1",
|
"antd": "^5.21.1",
|
||||||
@ -34,6 +35,7 @@
|
|||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.7",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-resizable-panels": "^2.1.4",
|
||||||
"react-router": "^6.26.2",
|
"react-router": "^6.26.2",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
"react-toastify": "^10.0.5",
|
"react-toastify": "^10.0.5",
|
||||||
|
51
pnpm-lock.yaml
generated
51
pnpm-lock.yaml
generated
@ -32,6 +32,9 @@ importers:
|
|||||||
'@kevisual/ui':
|
'@kevisual/ui':
|
||||||
specifier: ^0.0.2
|
specifier: ^0.0.2
|
||||||
version: 0.0.2
|
version: 0.0.2
|
||||||
|
'@monaco-editor/react':
|
||||||
|
specifier: ^4.6.0
|
||||||
|
version: 4.6.0(monaco-editor@0.52.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@uiw/react-textarea-code-editor':
|
'@uiw/react-textarea-code-editor':
|
||||||
specifier: ^3.0.2
|
specifier: ^3.0.2
|
||||||
version: 3.0.2(@babel/runtime@7.25.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 3.0.2(@babel/runtime@7.25.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@ -74,6 +77,9 @@ importers:
|
|||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^18.3.1
|
specifier: ^18.3.1
|
||||||
version: 18.3.1(react@18.3.1)
|
version: 18.3.1(react@18.3.1)
|
||||||
|
react-resizable-panels:
|
||||||
|
specifier: ^2.1.4
|
||||||
|
version: 2.1.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
react-router:
|
react-router:
|
||||||
specifier: ^6.26.2
|
specifier: ^6.26.2
|
||||||
version: 6.26.2(react@18.3.1)
|
version: 6.26.2(react@18.3.1)
|
||||||
@ -577,6 +583,18 @@ packages:
|
|||||||
'@kevisual/ui@0.0.2':
|
'@kevisual/ui@0.0.2':
|
||||||
resolution: {integrity: sha512-MDZDQTrYToLyj3WhiVJQLJ0PUHiN4D0Z5yJIyGzzPewPGpP2xwNgKO1BFX37J95cGZckzCdZwTKP0XKAOq0QtA==}
|
resolution: {integrity: sha512-MDZDQTrYToLyj3WhiVJQLJ0PUHiN4D0Z5yJIyGzzPewPGpP2xwNgKO1BFX37J95cGZckzCdZwTKP0XKAOq0QtA==}
|
||||||
|
|
||||||
|
'@monaco-editor/loader@1.4.0':
|
||||||
|
resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==}
|
||||||
|
peerDependencies:
|
||||||
|
monaco-editor: '>= 0.21.0 < 1'
|
||||||
|
|
||||||
|
'@monaco-editor/react@4.6.0':
|
||||||
|
resolution: {integrity: sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==}
|
||||||
|
peerDependencies:
|
||||||
|
monaco-editor: '>= 0.25.0 < 1'
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@ -1773,6 +1791,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
|
|
||||||
|
monaco-editor@0.52.0:
|
||||||
|
resolution: {integrity: sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==}
|
||||||
|
|
||||||
ms@2.1.3:
|
ms@2.1.3:
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
|
|
||||||
@ -2185,6 +2206,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
react-resizable-panels@2.1.4:
|
||||||
|
resolution: {integrity: sha512-kzue8lsoSBdyyd2IfXLQMMhNujOxRoGVus+63K95fQqleGxTfvgYLTzbwYMOODeAHqnkjb3WV/Ks7f5+gDYZuQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.14.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0
|
||||||
|
|
||||||
react-router-dom@6.26.2:
|
react-router-dom@6.26.2:
|
||||||
resolution: {integrity: sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==}
|
resolution: {integrity: sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -2312,6 +2339,9 @@ packages:
|
|||||||
space-separated-tokens@2.0.2:
|
space-separated-tokens@2.0.2:
|
||||||
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
||||||
|
|
||||||
|
state-local@1.0.7:
|
||||||
|
resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==}
|
||||||
|
|
||||||
string-convert@0.2.1:
|
string-convert@0.2.1:
|
||||||
resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==}
|
resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==}
|
||||||
|
|
||||||
@ -3037,6 +3067,18 @@ snapshots:
|
|||||||
lodash-es: 4.17.21
|
lodash-es: 4.17.21
|
||||||
style-to-object: 1.0.8
|
style-to-object: 1.0.8
|
||||||
|
|
||||||
|
'@monaco-editor/loader@1.4.0(monaco-editor@0.52.0)':
|
||||||
|
dependencies:
|
||||||
|
monaco-editor: 0.52.0
|
||||||
|
state-local: 1.0.7
|
||||||
|
|
||||||
|
'@monaco-editor/react@4.6.0(monaco-editor@0.52.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@monaco-editor/loader': 1.4.0(monaco-editor@0.52.0)
|
||||||
|
monaco-editor: 0.52.0
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nodelib/fs.stat': 2.0.5
|
'@nodelib/fs.stat': 2.0.5
|
||||||
@ -4373,6 +4415,8 @@ snapshots:
|
|||||||
|
|
||||||
minipass@7.1.2: {}
|
minipass@7.1.2: {}
|
||||||
|
|
||||||
|
monaco-editor@0.52.0: {}
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
|
||||||
mz@2.7.0:
|
mz@2.7.0:
|
||||||
@ -4853,6 +4897,11 @@ snapshots:
|
|||||||
|
|
||||||
react-refresh@0.14.2: {}
|
react-refresh@0.14.2: {}
|
||||||
|
|
||||||
|
react-resizable-panels@2.1.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
react-router-dom@6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
react-router-dom@6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@remix-run/router': 1.19.2
|
'@remix-run/router': 1.19.2
|
||||||
@ -5004,6 +5053,8 @@ snapshots:
|
|||||||
|
|
||||||
space-separated-tokens@2.0.2: {}
|
space-separated-tokens@2.0.2: {}
|
||||||
|
|
||||||
|
state-local@1.0.7: {}
|
||||||
|
|
||||||
string-convert@0.2.1: {}
|
string-convert@0.2.1: {}
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
|
@ -2,7 +2,7 @@ import { useShallow } from 'zustand/react/shallow';
|
|||||||
import { useAiStore } from './store/ai-store';
|
import { useAiStore } from './store/ai-store';
|
||||||
import { CloseOutlined, HistoryOutlined, PlusOutlined } from '@ant-design/icons';
|
import { CloseOutlined, HistoryOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
import { Button, Dropdown, Form, Input, message, Modal, Tooltip } from 'antd';
|
import { Button, Dropdown, Form, Input, message, Modal, Tooltip } from 'antd';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { TextArea } from '../container/components/TextArea';
|
import { TextArea } from '../container/components/TextArea';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { query } from '@/modules';
|
import { query } from '@/modules';
|
||||||
@ -221,7 +221,11 @@ export const AiMoudle = () => {
|
|||||||
const onSendNoPrompt = (value) => {
|
const onSendNoPrompt = (value) => {
|
||||||
send({ type: 'messages', data: { message: value, root: true } });
|
send({ type: 'messages', data: { message: value, root: true } });
|
||||||
};
|
};
|
||||||
const inputs = form.getFieldValue('inputs');
|
const inputs = useMemo(() => {
|
||||||
|
if (!aiStore.open) return [];
|
||||||
|
const inputs = form.getFieldValue('inputs');
|
||||||
|
return inputs;
|
||||||
|
}, [aiStore.open]);
|
||||||
const isNotShow = inputs?.length === 0 || !inputs;
|
const isNotShow = inputs?.length === 0 || !inputs;
|
||||||
const OnlyNormalMessage = (
|
const OnlyNormalMessage = (
|
||||||
<Tooltip title='不需要任何预设prompt'>
|
<Tooltip title='不需要任何预设prompt'>
|
||||||
|
26
src/pages/panel/app/edit/Editor.tsx
Normal file
26
src/pages/panel/app/edit/Editor.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import Editor from '@monaco-editor/react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
export const AppEditor = () => {
|
||||||
|
const [code, setCode] = useState('');
|
||||||
|
const [language, setLanguage] = useState('javascript');
|
||||||
|
return (
|
||||||
|
<div className='w-full h-full'>
|
||||||
|
<Editor
|
||||||
|
height={'100%'}
|
||||||
|
value={code}
|
||||||
|
language={language}
|
||||||
|
onChange={(value) => {
|
||||||
|
setCode(value || '');
|
||||||
|
}}
|
||||||
|
options={{
|
||||||
|
minimap: { enabled: false },
|
||||||
|
}}
|
||||||
|
defaultLanguage='javascript'
|
||||||
|
defaultValue='// some comment'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppEditor;
|
36
src/pages/panel/app/index.tsx
Normal file
36
src/pages/panel/app/index.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { useParams } from 'react-router';
|
||||||
|
import { useAppStore } from './store';
|
||||||
|
import { lazy, useEffect } from 'react';
|
||||||
|
import { Left } from './panel/Left';
|
||||||
|
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
|
||||||
|
import { EditorHeader } from './panel/EditorHeader';
|
||||||
|
|
||||||
|
// import AppEditor from './edit/Editor';
|
||||||
|
const AppEditor = lazy(() => import('./edit/Editor'));
|
||||||
|
|
||||||
|
export const App = () => {
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const param = useParams();
|
||||||
|
const id = param.id as string;
|
||||||
|
useEffect(() => {
|
||||||
|
if (!id) return;
|
||||||
|
appStore.getData(id);
|
||||||
|
}, []);
|
||||||
|
if (!id) return <div>Not Found</div>;
|
||||||
|
return (
|
||||||
|
<div className='w-full h-full flex bg-slate-200'>
|
||||||
|
<PanelGroup autoSaveId='editor' direction='horizontal'>
|
||||||
|
<Panel defaultSize={25}>
|
||||||
|
<Left />
|
||||||
|
</Panel>
|
||||||
|
<PanelResizeHandle />
|
||||||
|
<Panel defaultSize={75}>
|
||||||
|
<div className='w-full h-full'>
|
||||||
|
<EditorHeader />
|
||||||
|
<AppEditor />
|
||||||
|
</div>
|
||||||
|
</Panel>
|
||||||
|
</PanelGroup>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
22
src/pages/panel/app/panel/EditorHeader.tsx
Normal file
22
src/pages/panel/app/panel/EditorHeader.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { useAppStore } from '../store';
|
||||||
|
|
||||||
|
export const EditorHeader = () => {
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const [headerList, setHeaderList] = useState([]);
|
||||||
|
return (
|
||||||
|
<div className=''>
|
||||||
|
<div className='px-2 border bg-[#f8f8f8]'>
|
||||||
|
<div className='flex justify-between items-center'>
|
||||||
|
<div className='flex items-center'>
|
||||||
|
<div className='text-lg font-semibold'>Header</div>
|
||||||
|
<div className='ml-2 text-xs text-gray-500'>({headerList.length})</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center'>
|
||||||
|
<button className='btn btn-sm btn-primary'>Add</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
36
src/pages/panel/app/panel/Left.tsx
Normal file
36
src/pages/panel/app/panel/Left.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { useAppStore } from '../store';
|
||||||
|
|
||||||
|
type LabelProps = {
|
||||||
|
title: string;
|
||||||
|
children?: any;
|
||||||
|
};
|
||||||
|
export const Label = (props: LabelProps) => {
|
||||||
|
const { title } = props;
|
||||||
|
return (
|
||||||
|
<div className='flex'>
|
||||||
|
<div className='font-medium'>{title}:</div>
|
||||||
|
<div className='ml-2 line-clamp-3'>{props.children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export const Left = () => {
|
||||||
|
const appStore = useAppStore();
|
||||||
|
return (
|
||||||
|
<div className='flex-shrink-0'>
|
||||||
|
<div className='px-4 py-2 max-h-[300px] overflow-auto scrollbar'>
|
||||||
|
<Label title='Title'>{appStore.data?.title}</Label>
|
||||||
|
<Label title='Description'>{appStore.data?.description}</Label>
|
||||||
|
</div>
|
||||||
|
<div className='h-0.5 bg-gray-500'></div>
|
||||||
|
<div className='mt-4 px-2 text-xs'>
|
||||||
|
{appStore.nodes?.map?.((node, index) => {
|
||||||
|
return (
|
||||||
|
<div className='hover:bg-gray-300 p-2 cursor-pointer' key={node.id}>
|
||||||
|
{node.id}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
45
src/pages/panel/app/store/index.ts
Normal file
45
src/pages/panel/app/store/index.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { query } from '@/modules';
|
||||||
|
import { message } from 'antd';
|
||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
type Node = {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
data: {
|
||||||
|
cid: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
type AppStore = {
|
||||||
|
id: string;
|
||||||
|
setId: (id: string) => void;
|
||||||
|
getData: (id: string) => Promise<any>;
|
||||||
|
nodes: Node[];
|
||||||
|
data: any;
|
||||||
|
};
|
||||||
|
export const useAppStore = create<AppStore>((set, get) => ({
|
||||||
|
id: '',
|
||||||
|
setId: (id: string) => set({ id }),
|
||||||
|
data: {},
|
||||||
|
nodes: [],
|
||||||
|
getData: async (id: string) => {
|
||||||
|
console.log('getData');
|
||||||
|
if (!id) {
|
||||||
|
message.error('Invalid id');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set({ id });
|
||||||
|
const loaded = message.loading('Loading...', 0);
|
||||||
|
const res = await query.post({
|
||||||
|
path: 'page',
|
||||||
|
key: 'get',
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
loaded();
|
||||||
|
if (res.code === 200) {
|
||||||
|
console.log(res.data);
|
||||||
|
const data = res.data;
|
||||||
|
const nodes = data?.data?.nodes;
|
||||||
|
set({ data: data, nodes });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
@ -3,6 +3,8 @@ import { List } from './edit/List';
|
|||||||
import { Main } from './layouts';
|
import { Main } from './layouts';
|
||||||
import { App as FlowApp } from './flow';
|
import { App as FlowApp } from './flow';
|
||||||
import { Deck } from './deck';
|
import { Deck } from './deck';
|
||||||
|
import { App as PanelApp } from './app';
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
@ -11,6 +13,7 @@ export const App = () => {
|
|||||||
<Route path='edit/list' element={<List />} />
|
<Route path='edit/list' element={<List />} />
|
||||||
<Route path='flow/:id' element={<FlowApp />} />
|
<Route path='flow/:id' element={<FlowApp />} />
|
||||||
<Route path='deck/:id' element={<Deck />} />
|
<Route path='deck/:id' element={<Deck />} />
|
||||||
|
<Route path='app/:id' element={<PanelApp />} />
|
||||||
<Route path='*' element={'Not Found'}></Route>
|
<Route path='*' element={'Not Found'}></Route>
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user