diff --git a/plugins/flex.js b/plugins/flex.js
index ad53cd5..168657a 100644
--- a/plugins/flex.js
+++ b/plugins/flex.js
@@ -19,6 +19,7 @@ const flexCenter = plugin(function ({ addUtilities }) {
'.card-subtitle': {},
'.card-body': {},
'.card-footer': {},
+ '.card-key': {},
});
});
diff --git a/src/App.tsx b/src/App.tsx
index 1e929a3..ac2b3a3 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -6,7 +6,7 @@ import { App as PublishApp } from './pages/publish';
import { App as CodeEditorApp } from './pages/code-editor';
import { App as MapApp } from './pages/map';
import { App as PromptApp } from './pages/prompt';
-
+import { App as AiAgentApp } from './pages/ai-agent';
import '@abearxiong/container/dist/container.css';
export const App = () => {
@@ -25,6 +25,7 @@ export const App = () => {
} />
} />
} />
+ } />
404} />
404} />
diff --git a/src/globals.css b/src/globals.css
index 51fd0b6..8e73f15 100644
--- a/src/globals.css
+++ b/src/globals.css
@@ -42,6 +42,9 @@
.card-body {
@apply text-gray-700;
}
+ .card-key {
+ @apply text-xs text-gray-400;
+ }
.card-footer {
@apply text-sm text-gray-500;
}
diff --git a/src/pages/ai-agent/edit/List.tsx b/src/pages/ai-agent/edit/List.tsx
new file mode 100644
index 0000000..674a3bb
--- /dev/null
+++ b/src/pages/ai-agent/edit/List.tsx
@@ -0,0 +1,156 @@
+import { useShallow } from 'zustand/react/shallow';
+import { useAgentStore } from '../store';
+import { useEffect } from 'react';
+import { CardBlank } from '@/components/card/CardBlank';
+import { Button, Form, Input, message, Modal, Tooltip } from 'antd';
+import copy from 'copy-to-clipboard';
+import { useNavigate } from 'react-router';
+import { EditOutlined, SettingOutlined, LinkOutlined, SaveOutlined, DeleteOutlined, LeftOutlined, CaretRightOutlined } from '@ant-design/icons';
+import clsx from 'clsx';
+import { isObjectNull } from '@/utils/is-null';
+const FormModal = () => {
+ const [form] = Form.useForm();
+ const containerStore = useAgentStore(
+ useShallow((state) => {
+ return {
+ showEdit: state.showEdit,
+ setShowEdit: state.setShowEdit,
+ formData: state.formData,
+ updateData: state.updateData,
+ };
+ }),
+ );
+ useEffect(() => {
+ const open = containerStore.showEdit;
+ if (open) {
+ const isNull = isObjectNull(containerStore.formData);
+ if (isNull) {
+ form.setFieldsValue({});
+ } else form.setFieldsValue(containerStore.formData);
+ }
+ }, [containerStore.showEdit]);
+ const onFinish = async (values: any) => {
+ if (!values.id) {
+ message.error('Cant add data');
+ return;
+ }
+ containerStore.updateData(values);
+ };
+ const onClose = () => {
+ containerStore.setShowEdit(false);
+ form.resetFields();
+ };
+ const isEdit = containerStore.formData.id;
+ return (
+ containerStore.setShowEdit(false)}
+ destroyOnClose
+ footer={false}
+ width={800}
+ onCancel={onClose}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+export const List = () => {
+ const agentStore = useAgentStore(
+ useShallow((state) => {
+ return {
+ setFormData: state.setFormData,
+ setShowEdit: state.setShowEdit,
+ list: state.list,
+ deleteData: state.deleteData,
+ getList: state.getList,
+ loading: state.loading,
+ publishData: state.publishData,
+ updateData: state.updateData,
+ formData: state.formData,
+ };
+ }),
+ );
+ useEffect(() => {
+ agentStore.getList();
+ }, []);
+ return (
+
+
+
+ {agentStore.list.map((item) => {
+ return (
+
+
+ {item.model}
{item.key}
+
+
+
+
+
+
+
+
+ }
+ onClick={() => {
+ // aiStore.setData(item);
+ // aiStore.setOpen(true);
+ message.error('Not implemented');
+ }}
+ />
+
+
+
+
+
+
+
+
+ );
+ })}
+ {agentStore.list.length === 0 &&
No data
}
+
+
+
+
+
+ );
+};
diff --git a/src/pages/ai-agent/index.tsx b/src/pages/ai-agent/index.tsx
new file mode 100644
index 0000000..54c7e20
--- /dev/null
+++ b/src/pages/ai-agent/index.tsx
@@ -0,0 +1,14 @@
+import { Navigate, Route, Routes } from 'react-router-dom';
+import { List } from './edit/List';
+import { Main } from './layouts';
+export const App = () => {
+ return (
+
+ }>
+ }>
+ } />
+
+
+
+ );
+};
diff --git a/src/pages/ai-agent/layouts/index.tsx b/src/pages/ai-agent/layouts/index.tsx
new file mode 100644
index 0000000..b8b230d
--- /dev/null
+++ b/src/pages/ai-agent/layouts/index.tsx
@@ -0,0 +1,14 @@
+import { Outlet } from 'react-router';
+
+export const Main = () => {
+ return (
+
+ );
+};
diff --git a/src/pages/ai-agent/store/index.ts b/src/pages/ai-agent/store/index.ts
new file mode 100644
index 0000000..ee46b0c
--- /dev/null
+++ b/src/pages/ai-agent/store/index.ts
@@ -0,0 +1,94 @@
+import { create } from 'zustand';
+import { query } from '@/modules';
+import { message } from 'antd';
+type AgentStore = {
+ showEdit: boolean;
+ setShowEdit: (showEdit: boolean) => void;
+ formData: any;
+ setFormData: (formData: any) => void;
+ loading: boolean;
+ setLoading: (loading: boolean) => void;
+ list: any[];
+ getList: () => Promise;
+ updateData: (data: any) => Promise;
+ deleteData: (id: string) => Promise;
+ publishData: (data: any) => Promise;
+};
+export const useAgentStore = create((set, get) => {
+ return {
+ showEdit: false,
+ setShowEdit: (showEdit) => set({ showEdit }),
+ formData: {},
+ setFormData: (formData) => set({ formData }),
+ loading: false,
+ setLoading: (loading) => set({ loading }),
+ list: [],
+ getList: async () => {
+ set({ loading: true });
+
+ const res = await query.post({
+ path: 'agent',
+ key: 'list',
+ });
+ set({ loading: false });
+ if (res.code === 200) {
+ set({ list: res.data });
+ } else {
+ message.error(res.msg || 'Request failed');
+ }
+ },
+ updateData: async (data) => {
+ const { getList } = get();
+ const res = await query.post({
+ path: 'agent',
+ key: 'update',
+ data,
+ });
+ if (res.code === 200) {
+ message.success('Success');
+ set({ showEdit: false, formData: [] });
+ getList();
+ } else {
+ message.error(res.msg || 'Request failed');
+ }
+ },
+ deleteData: async (id) => {
+ const { getList } = get();
+ const res = await query.post({
+ path: 'agent',
+ key: 'delete',
+ id,
+ });
+ if (res.code === 200) {
+ getList();
+ message.success('Success');
+ } else {
+ message.error(res.msg || 'Request failed');
+ }
+ },
+ publishData: async (data) => {
+ const hasPublish = !!data.publish?.name;
+ const publish = {
+ name: 'test-import',
+ };
+ if (!hasPublish) {
+ console.error('need publish.name');
+ return;
+ }
+ const res = await query.post({
+ path: 'agent',
+ key: 'publish',
+ data: {
+ id: data.id,
+ publish: publish,
+ type: 'patch',
+ },
+ });
+ if (res.code === 200) {
+ message.success('Success');
+ } else {
+ message.error(res.msg || 'Request failed');
+ }
+ },
+ };
+});
diff --git a/src/pages/code-editor/store.ts b/src/pages/code-editor/store.ts
index 3cf4100..cc22d22 100644
--- a/src/pages/code-editor/store.ts
+++ b/src/pages/code-editor/store.ts
@@ -1,6 +1,7 @@
import { create } from 'zustand';
import { produce } from 'immer';
import { query } from '@/modules';
+import { message } from 'antd';
type QueryPath = {
key?: string;
@@ -50,8 +51,12 @@ export const useCodeEditorStore = create((set, get) => ({
_newData = data;
}
if (path && key) {
+ const load = message.loading('loading...', 0);
+
const res = await query.post({ path, key, data: _newData });
+ load();
if (res.code === 200) {
+ message.success('success');
set(
produce((state) => {
state.data = res.data;
diff --git a/src/pages/container/edit/List.tsx b/src/pages/container/edit/List.tsx
index d3118b9..a4f12d1 100644
--- a/src/pages/container/edit/List.tsx
+++ b/src/pages/container/edit/List.tsx
@@ -8,6 +8,7 @@ import copy from 'copy-to-clipboard';
import { useNavigate } from 'react-router';
import { EditOutlined, SettingOutlined, LinkOutlined, SaveOutlined, DeleteOutlined, LeftOutlined } from '@ant-design/icons';
import clsx from 'clsx';
+import { isObjectNull } from '@/utils/is-null';
const FormModal = () => {
const [form] = Form.useForm();
const containerStore = useContainerStore(
@@ -23,7 +24,12 @@ const FormModal = () => {
useEffect(() => {
const open = containerStore.showEdit;
if (open) {
- form.setFieldsValue(containerStore.formData || {});
+ if (open) {
+ const isNull = isObjectNull(containerStore.formData);
+ if (isNull) {
+ form.setFieldsValue({});
+ } else form.setFieldsValue(containerStore.formData);
+ }
}
}, [containerStore.showEdit]);
const onFinish = async (values: any) => {
diff --git a/src/pages/map/index.tsx b/src/pages/map/index.tsx
index 205fcad..d68b8a7 100644
--- a/src/pages/map/index.tsx
+++ b/src/pages/map/index.tsx
@@ -19,9 +19,13 @@ const serverPath = [
links: ['/'],
},
{
- path: 'ai-chat',
+ path: 'prompt',
links: ['/'],
},
+ {
+ path: 'agent',
+ links: ['edit/list'],
+ },
];
const ServerPath = () => {
const navigate = useNavigate();
@@ -41,6 +45,11 @@ const ServerPath = () => {
if (hasId) {
return;
}
+ console.log('link', link);
+ if (link === '/') {
+ navigate(`/${item.path}`);
+ return;
+ }
if (link) {
navigate(`/${item.path}/${link}`);
} else {
diff --git a/src/pages/panel/deck/Model.tsx b/src/pages/panel/deck/Model.tsx
new file mode 100644
index 0000000..65b863e
--- /dev/null
+++ b/src/pages/panel/deck/Model.tsx
@@ -0,0 +1,127 @@
+import { isObjectNull } from '@/utils/is-null';
+import { Button, Form, Input, message, Modal, Select } from 'antd';
+import { useEffect, useState } from 'react';
+import { useShallow } from 'zustand/react/shallow';
+import { useDeckPageStore } from './deck-store';
+export const FormModal = () => {
+ const [form] = Form.useForm();
+ const [options, setOptions] = useState<{ label: string; value: any }[]>([]);
+ const deckPageStore = useDeckPageStore(
+ useShallow((state) => {
+ return {
+ showEdit: state.showEdit,
+ setShowEdit: state.setShowEdit,
+ pageData: state.pageData,
+ getPageData: state.getPageData,
+ formData: state.formData,
+ setFormData: state.setFormData,
+ id: state.id,
+ setSelected: state.setSelected,
+ getSeleted: state.getSeleted,
+ };
+ }),
+ );
+ useEffect(() => {
+ if (!deckPageStore.showEdit) return;
+ const pageData = deckPageStore.getPageData() || [];
+ const data = pageData.map((item) => {
+ const { container } = item?.data || {};
+ const label = container?.title;
+ return {
+ label: label || item.id,
+ value: item.id,
+ };
+ });
+ setOptions(data);
+ const selected = deckPageStore.getSeleted();
+ const { cid } = selected?.data || {};
+ if (cid) {
+ form.setFieldsValue({ cid });
+ return;
+ }
+ const isNull = isObjectNull(deckPageStore.formData);
+ if (isNull) {
+ form.setFieldsValue({});
+ form.resetFields();
+ } else {
+ form.setFieldsValue(deckPageStore.formData);
+ }
+ }, [deckPageStore.showEdit, deckPageStore.pageData]);
+ const onFinish = async (values: any) => {
+ const pageData = deckPageStore.getPageData() || [];
+ const page = pageData.find((item) => item.id === values.cid);
+ if (!page) {
+ message.error('Page not found');
+ return;
+ }
+ const cid = values.cid;
+ if (!cid) {
+ return;
+ }
+ const el = document.querySelector(`[data-cid="${values.cid}"]`);
+ if (el) {
+ const data = (el as HTMLDivElement).dataset;
+ const { cid, pid } = data;
+ document.querySelectorAll('.active').forEach((item) => {
+ item.classList.remove('active');
+ });
+ el.classList.add('active');
+ // el.scrollIntoView({ behavior: 'smooth', });
+ deckPageStore.setSelected({ type: 'active', data: { cid, pid, rid: deckPageStore.id } });
+ }
+ onClose();
+ };
+ const onClose = () => {
+ deckPageStore.setShowEdit(false);
+ deckPageStore.setFormData({});
+ form.setFieldsValue({});
+ };
+ return (
+ deckPageStore.setShowEdit(false)}
+ destroyOnClose
+ footer={false}
+ width={800}
+ onCancel={onClose}>
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/pages/panel/deck/deck-store.ts b/src/pages/panel/deck/deck-store.ts
new file mode 100644
index 0000000..7101cb8
--- /dev/null
+++ b/src/pages/panel/deck/deck-store.ts
@@ -0,0 +1,60 @@
+import { create } from 'zustand';
+
+type DeckPageStore = {
+ id: string;
+ setId: (id: string) => void;
+ showEdit: boolean;
+ setShowEdit: (showEdit: boolean) => void;
+ formData: any;
+ setFormData: (formData: any) => void;
+ loading: boolean;
+ setLoading: (loading: boolean) => void;
+ pageData: any[];
+ setPageData: (data: any[]) => void;
+ getPageData: () => any[];
+ selected: any;
+ setSelected: (data: any) => void;
+ getSeleted: () => any;
+ code: string;
+ setCode: (data: string) => void;
+ getCode: () => string;
+};
+export const useDeckPageStore = create((set, get) => ({
+ id: '',
+ setId: (id) => {
+ set({ id });
+ },
+ showEdit: false,
+ setShowEdit: (showEdit) => {
+ set({ showEdit });
+ },
+ formData: {},
+ setFormData: (formData) => {
+ set({ formData });
+ },
+ loading: false,
+ setLoading: (loading) => {
+ set({ loading });
+ },
+ pageData: [],
+ setPageData: (data) => {
+ set({ pageData: data });
+ },
+ getPageData: () => {
+ return get().pageData;
+ },
+ selected: null,
+ setSelected: (data) => {
+ set({ selected: data });
+ },
+ getSeleted: () => {
+ return get().selected;
+ },
+ code: '',
+ setCode: (data) => {
+ set({ code: data });
+ },
+ getCode: () => {
+ return get().code;
+ },
+}));
diff --git a/src/pages/panel/deck/index.tsx b/src/pages/panel/deck/index.tsx
index 9737df4..d68e10e 100644
--- a/src/pages/panel/deck/index.tsx
+++ b/src/pages/panel/deck/index.tsx
@@ -1,11 +1,15 @@
import { Container, ContainerEdit } from '@abearxiong/container';
-import { useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router';
import { query, useStore, ws } from '@/modules';
-import { message } from 'antd';
+import { Button, message, Tooltip } from 'antd';
import { getContainerData } from '@/modules/deck-to-flow/deck';
import { usePanelStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
+import { TextArea } from '@/pages/container/components/TextArea';
+import { CloseOutlined, SaveOutlined, SelectOutlined } from '@ant-design/icons';
+import { useDeckPageStore } from './deck-store';
+import { FormModal } from './Model.tsx';
export const useListener = (id?: string, opts?: any) => {
const { refresh } = opts || {};
const connected = useStore((state) => state.connected);
@@ -62,13 +66,15 @@ const getParent = (data: { children?: string[]; [key: string]: any }[], id: stri
}
return;
};
+
export const Deck = () => {
const params = useParams<{ id: string }>();
const id = params.id;
const ref = useRef(null);
const containerRef = useRef(null);
- const [pageData, setPageData] = useState({});
- const [selected, setSelected] = useState(null);
+ const deckPageStore = useDeckPageStore();
+ const { code, setCode } = deckPageStore;
+ const { selected, setSelected } = deckPageStore;
const panelStore = usePanelStore(
useShallow((state) => {
return {
@@ -78,12 +84,17 @@ export const Deck = () => {
);
useEffect(() => {
if (!id) return;
+ deckPageStore.setId(id);
fetch();
}, []);
useEffect(() => {
ref.current?.addEventListener('onContainer', onContainer);
return () => {
ref.current?.removeEventListener('onContainer', onContainer);
+ if (ref.current) {
+ const children = ref.current;
+ children.innerHTML = '';
+ }
};
}, []);
const fetch = async () => {
@@ -97,23 +108,9 @@ export const Deck = () => {
console.log('data', data);
const { page, containerList } = data;
const result = getContainerData({ page, containerList });
- setPageData(result);
+ deckPageStore.setPageData(result);
init(result);
}
- // if (res.code === 200) {
- // const data = res.data;
- // // setData([data]);
- // console.log('data', data);
- // const code = {
- // id: data.id,
- // title: data.title,
- // code: data.code,
- // data: data.data,
- // };
- // init([code]);
- // } else {
- // message.error(res.msg || 'Failed to fetch data');
- // }
};
const refresh = async (data: any) => {
console.log('refresh', data);
@@ -144,8 +141,6 @@ export const Deck = () => {
const types = ['position', 'resize'];
if (types.includes(data.type)) {
const { type, data: containerData } = data;
- console.log('containerData', containerData);
-
if (type === 'position') {
const { cid, left, top, rid } = containerData;
const newData = {
@@ -154,6 +149,7 @@ export const Deck = () => {
id: cid,
data: {
style: {
+ // position: 'absolute',
left,
top,
},
@@ -163,6 +159,10 @@ export const Deck = () => {
if (left && top) {
panelStore.updateNodeDataStyle(newData);
}
+ updateStyle(cid, { left, top });
+ setTimeout(() => {
+ setCodeStyle(cid);
+ }, 1000);
} else if (type === 'resize') {
const { cid, rid, width, height } = containerData;
const newData = {
@@ -180,19 +180,85 @@ export const Deck = () => {
if (width && height) {
panelStore.updateNodeDataStyle(newData);
}
+ updateStyle(cid, { width, height });
+ setTimeout(() => {
+ setCodeStyle(cid);
+ }, 1000);
}
} else if (data.type === 'active') {
if (!data?.data?.cid) {
setSelected(null);
return;
}
- const { cid, rid } = data;
- console.log('getParent', cid, pageData);
+ const { cid, rid } = data?.data || {};
setSelected(data);
+ setCodeStyle(cid);
} else {
console.log('onContainer', data);
}
};
+ const onSave = () => {
+ const { cid, rid } = selected?.data || {};
+ let data: any;
+ try {
+ data = JSON.parse(code);
+ } catch (error) {
+ message.error('JSON format error');
+ return;
+ }
+ const newData = {
+ id: rid,
+ nodeData: {
+ id: cid,
+ data: {
+ style: data,
+ },
+ },
+ };
+ panelStore.updateNodeDataStyle(newData);
+ };
+ const setCodeStyle = (cid: string) => {
+ const pageData = deckPageStore.getPageData();
+ const selected = deckPageStore.getSeleted();
+ const _data = pageData.find((item) => item.id === cid);
+ const node = _data?.data?.node || {};
+ if (selected?.data?.cid === cid) {
+ setCode('');
+ setCode(JSON.stringify(node?.data?.style || {}, null, 2));
+ }
+ };
+ useEffect(() => {
+ if (selected) {
+ const { cid } = selected?.data || {};
+ cid && setCodeStyle(cid);
+ }
+ }, [deckPageStore.selected]);
+
+ const updateStyle = (rid: string, style: any) => {
+ const pageData = deckPageStore.getPageData();
+ const _pageData = pageData.map((item) => {
+ if (item.id === rid) {
+ return {
+ ...item,
+ data: {
+ ...item.data,
+ node: {
+ ...item.data.node,
+ data: {
+ ...item.data.node.data,
+ style: {
+ ...item.data.node.data.style,
+ ...style,
+ },
+ },
+ },
+ },
+ };
+ }
+ return item;
+ });
+ deckPageStore.setPageData([..._pageData]);
+ };
const init = async (data: any[]) => {
console.log(
'init',
@@ -215,22 +281,54 @@ export const Deck = () => {
return (
-
Deck
+
+ Deck
+
+ }
+ onClick={() => {
+ deckPageStore.setShowEdit(true);
+ }}>
+
+
{selected && (
-
-
{JSON.stringify(selected, null, 2)}
+
+ {/*
{JSON.stringify(selected, null, 2)}
*/}
+
+
+
+
+
+
+
+
+
+
+
+
+
)}
+
);
};
diff --git a/src/pages/prompt/edit/List.tsx b/src/pages/prompt/edit/List.tsx
index 9392971..77b99eb 100644
--- a/src/pages/prompt/edit/List.tsx
+++ b/src/pages/prompt/edit/List.tsx
@@ -12,6 +12,7 @@ import { TextArea } from '@/pages/container/components/TextArea';
import { marked } from 'marked';
import { extractKeysFromBraces } from '@/utils/extra';
import { useAiStore } from '@/pages/ai-chat';
+import { CardBlank } from '@/components/card/CardBlank';
const FormModal = () => {
const [form] = Form.useForm();
@@ -256,9 +257,7 @@ export const List = () => {
);
})}
- {new Array(4).fill(0).map((_, index) => {
- return
;
- })}
+
{promptStore.list.length == 0 && (
No Data