mirror of
https://github.com/FranP-code/ChatGPT.git
synced 2025-10-13 00:13:25 +00:00
feat: chatgpt prompts
This commit is contained in:
@@ -147,6 +147,7 @@ yarn build
|
|||||||
## ❤️ Thanks
|
## ❤️ Thanks
|
||||||
|
|
||||||
- The core implementation of the share button code was copied from the [@liady](https://github.com/liady) extension with some modifications.
|
- The core implementation of the share button code was copied from the [@liady](https://github.com/liady) extension with some modifications.
|
||||||
|
<!-- - [Awesome ChatGPT Prompts](https://github.com/f/awesome-chatgpt-prompts) -->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
3
chat.model.md
Normal file
3
chat.model.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# ChatGPT Model
|
||||||
|
|
||||||
|
- [Awesome ChatGPT Prompts](https://github.com/f/awesome-chatgpt-prompts)
|
||||||
@@ -36,7 +36,8 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router-dom": "^6.4.5"
|
"react-router-dom": "^6.4.5",
|
||||||
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
"@tauri-apps/cli": "^1.2.2",
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
"@types/react": "^18.0.15",
|
"@types/react": "^18.0.15",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
|
"@types/uuid": "^9.0.0",
|
||||||
"@vitejs/plugin-react": "^3.0.0",
|
"@vitejs/plugin-react": "^3.0.0",
|
||||||
"sass": "^1.56.2",
|
"sass": "^1.56.2",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^4.9.4",
|
||||||
|
|||||||
@@ -11,7 +11,11 @@
|
|||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
"all": true
|
"all": true,
|
||||||
|
"fs": {
|
||||||
|
"all": true,
|
||||||
|
"scope": ["$HOME/.chatgpt/*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"systemTray": {
|
"systemTray": {
|
||||||
"iconPath": "icons/tray-icon.png",
|
"iconPath": "icons/tray-icon.png",
|
||||||
|
|||||||
94
src/components/Tags/index.tsx
vendored
Normal file
94
src/components/Tags/index.tsx
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { FC, useEffect, useRef, useState } from 'react';
|
||||||
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
|
import { Input, Tag } from 'antd';
|
||||||
|
import type { InputRef } from 'antd';
|
||||||
|
|
||||||
|
import { DISABLE_AUTO_COMPLETE } from '@/utils';
|
||||||
|
|
||||||
|
interface TagsProps {
|
||||||
|
value?: string[];
|
||||||
|
onChange?: (v: string[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tags: FC<TagsProps> = ({ value = [], onChange }) => {
|
||||||
|
const [tags, setTags] = useState<string[]>(value);
|
||||||
|
const [inputVisible, setInputVisible] = useState<boolean>(false);
|
||||||
|
const [inputValue, setInputValue] = useState('');
|
||||||
|
const inputRef = useRef<InputRef>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (inputVisible) {
|
||||||
|
inputRef.current?.focus();
|
||||||
|
}
|
||||||
|
}, [inputVisible]);
|
||||||
|
|
||||||
|
const handleClose = (removedTag: string) => {
|
||||||
|
const newTags = tags.filter((tag) => tag !== removedTag);
|
||||||
|
setTags(newTags);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showInput = () => {
|
||||||
|
setInputVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setInputValue(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputConfirm = () => {
|
||||||
|
if (inputValue && tags.indexOf(inputValue) === -1) {
|
||||||
|
const val = [...tags, inputValue];
|
||||||
|
setTags(val);
|
||||||
|
onChange && onChange(val);
|
||||||
|
}
|
||||||
|
setInputVisible(false);
|
||||||
|
setInputValue('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const forMap = (tag: string) => {
|
||||||
|
const tagElem = (
|
||||||
|
<Tag
|
||||||
|
closable
|
||||||
|
onClose={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleClose(tag);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<span key={tag} style={{ display: 'inline-block' }}>
|
||||||
|
{tagElem}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const tagChild = tags.map(forMap);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span style={{ marginBottom: 16 }}>{tagChild}</span>
|
||||||
|
{inputVisible && (
|
||||||
|
<Input
|
||||||
|
ref={inputRef}
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
style={{ width: 78 }}
|
||||||
|
value={inputValue}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
onBlur={handleInputConfirm}
|
||||||
|
onPressEnter={handleInputConfirm}
|
||||||
|
{...DISABLE_AUTO_COMPLETE}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!inputVisible && (
|
||||||
|
<Tag onClick={showInput} className="chat-tag-new">
|
||||||
|
<PlusOutlined /> New Tag
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tags;
|
||||||
23
src/hooks/useChatModel.ts
vendored
Normal file
23
src/hooks/useChatModel.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { clone } from 'lodash';
|
||||||
|
|
||||||
|
import { CHAT_MODEL_JSON, readJSON, writeJSON } from '@/utils';
|
||||||
|
import useInit from '@/hooks/useInit';
|
||||||
|
|
||||||
|
export default function useChatModel() {
|
||||||
|
const [modelJson, setModelJson] = useState<Record<string, any>>({});
|
||||||
|
|
||||||
|
useInit(async () => {
|
||||||
|
const data = await readJSON(CHAT_MODEL_JSON, { name: 'ChatGPT Model', data: [] });
|
||||||
|
setModelJson(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
const modelSet = async (data: Record<string, any>[]) => {
|
||||||
|
const oData = clone(modelJson);
|
||||||
|
oData.data = data;
|
||||||
|
await writeJSON(CHAT_MODEL_JSON, oData);
|
||||||
|
setModelJson(oData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { modelJson, modelSet, modelData: modelJson?.data || [] }
|
||||||
|
}
|
||||||
44
src/hooks/useColumns.ts
vendored
Normal file
44
src/hooks/useColumns.ts
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { useState, useCallback } from 'react';
|
||||||
|
|
||||||
|
export default function useColumns(columns: any[] = []) {
|
||||||
|
const [opType, setOpType] = useState('');
|
||||||
|
const [opRecord, setRecord] = useState<Record<string|symbol, any> | null>(null);
|
||||||
|
const [opTime, setNow] = useState<number | null>(null);
|
||||||
|
const [opExtra, setExtra] = useState<any>(null);
|
||||||
|
|
||||||
|
const handleRecord = useCallback((row: Record<string, any> | null, type: string) => {
|
||||||
|
setOpType(type);
|
||||||
|
setRecord(row);
|
||||||
|
setNow(Date.now());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const resetRecord = useCallback(() => {
|
||||||
|
setRecord(null);
|
||||||
|
setOpType('');
|
||||||
|
setNow(Date.now());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const opNew = useCallback(() => handleRecord(null, 'new'), [handleRecord]);
|
||||||
|
|
||||||
|
const cols = columns.map((i: any) => {
|
||||||
|
if (i.render) {
|
||||||
|
const opRender = i.render;
|
||||||
|
i.render = (text: string, row: Record<string, any>) => {
|
||||||
|
return opRender(text, row, { setRecord: handleRecord, setExtra });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
opTime,
|
||||||
|
opType,
|
||||||
|
opNew,
|
||||||
|
columns: cols,
|
||||||
|
opRecord,
|
||||||
|
setRecord: handleRecord,
|
||||||
|
resetRecord,
|
||||||
|
setExtra,
|
||||||
|
opExtra,
|
||||||
|
};
|
||||||
|
}
|
||||||
35
src/hooks/useData.ts
vendored
Normal file
35
src/hooks/useData.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
const safeKey = Symbol('chat-id');
|
||||||
|
|
||||||
|
export default function useData(oData: any[]) {
|
||||||
|
const [opData, setData] = useState<any[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const nData = oData.map(i => ({ [safeKey]: v4(), ...i }));
|
||||||
|
setData(nData);
|
||||||
|
}, [oData])
|
||||||
|
|
||||||
|
const opAdd = (val: any) => {
|
||||||
|
const v = [val, ...opData];
|
||||||
|
setData(v);
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
|
const opRemove = (id: string) => {
|
||||||
|
const nData = opData.filter(i => i[safeKey] !== id);
|
||||||
|
setData(nData);
|
||||||
|
return nData;
|
||||||
|
};
|
||||||
|
|
||||||
|
const opReplace = (id: string, data: any) => {
|
||||||
|
const nData = [...opData];
|
||||||
|
const idx = opData.findIndex(v => v[safeKey] === id);
|
||||||
|
nData[idx] = data;
|
||||||
|
setData(nData);
|
||||||
|
return nData;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { opSafeKey: safeKey, opReplace, opAdd, opRemove, opData };
|
||||||
|
}
|
||||||
12
src/hooks/useInit.ts
vendored
Normal file
12
src/hooks/useInit.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { useRef, useEffect } from 'react';
|
||||||
|
|
||||||
|
// fix: Two interface requests will be made in development mode
|
||||||
|
export default function useInit(callback: () => void) {
|
||||||
|
const isInit = useRef(true);
|
||||||
|
useEffect(() => {
|
||||||
|
if (isInit.current) {
|
||||||
|
callback();
|
||||||
|
isInit.current = false;
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
10
src/routes.tsx
vendored
10
src/routes.tsx
vendored
@@ -1,13 +1,13 @@
|
|||||||
import { useRoutes } from 'react-router-dom';
|
import { useRoutes } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
DesktopOutlined,
|
DesktopOutlined,
|
||||||
BulbOutlined
|
BulbOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import type { RouteObject } from 'react-router-dom';
|
import type { RouteObject } from 'react-router-dom';
|
||||||
import type { MenuProps } from 'antd';
|
import type { MenuProps } from 'antd';
|
||||||
|
|
||||||
import General from '@view/General';
|
import General from '@view/General';
|
||||||
import ChatGPTPrompts from '@/view/ChatGPTPrompts';
|
import LanguageModel from '@/view/LanguageModel';
|
||||||
|
|
||||||
export type ChatRouteObject = {
|
export type ChatRouteObject = {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -24,10 +24,10 @@ export const routes: Array<RouteObject & { meta: ChatRouteObject }> = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/chatgpt-prompts',
|
path: '/language-model',
|
||||||
element: <ChatGPTPrompts />,
|
element: <LanguageModel />,
|
||||||
meta: {
|
meta: {
|
||||||
label: 'ChatGPT Prompts',
|
label: 'Language Model',
|
||||||
icon: <BulbOutlined />,
|
icon: <BulbOutlined />,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
39
src/utils.ts
vendored
Normal file
39
src/utils.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { readTextFile, writeTextFile, exists } from '@tauri-apps/api/fs';
|
||||||
|
import { homeDir, join } from '@tauri-apps/api/path';
|
||||||
|
|
||||||
|
export const CHAT_MODEL_JSON = 'chat.model.json';
|
||||||
|
export const DISABLE_AUTO_COMPLETE = {
|
||||||
|
autoCapitalize: 'off',
|
||||||
|
autoComplete: 'off',
|
||||||
|
spellCheck: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const chatRoot = async () => {
|
||||||
|
return join(await homeDir(), '.chatgpt')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const readJSON = async (path: string, defaultVal = {}) => {
|
||||||
|
const root = await chatRoot();
|
||||||
|
const file = await join(root, path);
|
||||||
|
|
||||||
|
if (!await exists(file)) {
|
||||||
|
writeTextFile(file, JSON.stringify({
|
||||||
|
name: 'ChatGPT',
|
||||||
|
link: 'https://github.com/lencx/ChatGPT/blob/main/chat.model.md',
|
||||||
|
data: null,
|
||||||
|
...defaultVal,
|
||||||
|
}, null, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.parse(await readTextFile(file));
|
||||||
|
} catch(e) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const writeJSON = async (path: string, data: Record<string, any>) => {
|
||||||
|
const root = await chatRoot();
|
||||||
|
const file = await join(root, path);
|
||||||
|
await writeTextFile(file, JSON.stringify(data, null, 2));
|
||||||
|
}
|
||||||
23
src/view/ChatGPTPrompts/config.tsx
vendored
23
src/view/ChatGPTPrompts/config.tsx
vendored
@@ -1,23 +0,0 @@
|
|||||||
import { Tag, Tooltip } from 'antd';
|
|
||||||
|
|
||||||
export const columns = [
|
|
||||||
{
|
|
||||||
title: 'Command',
|
|
||||||
dataIndex: 'cmd',
|
|
||||||
key: 'cmd',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Type',
|
|
||||||
dataIndex: 'type',
|
|
||||||
key: 'type',
|
|
||||||
render: (v: string) => <Tag>{v}</Tag>
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Content',
|
|
||||||
dataIndex: 'content',
|
|
||||||
key: 'content',
|
|
||||||
render: (v: string) => (
|
|
||||||
<Tooltip overlayInnerStyle={{ width: 350 }} title={v}><span className="chat-prompts-val">{v}</span></Tooltip>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
34
src/view/ChatGPTPrompts/index.tsx
vendored
34
src/view/ChatGPTPrompts/index.tsx
vendored
@@ -1,34 +0,0 @@
|
|||||||
import { Table, Button } from 'antd';
|
|
||||||
|
|
||||||
import { columns } from './config';
|
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
const dataSource = [
|
|
||||||
{
|
|
||||||
cmd: 'terminal',
|
|
||||||
type: 'dev',
|
|
||||||
content: 'i want you to act as a linux terminal. I will type commands and you will reply with what the terminal should show. I want you to only reply with the terminal output inside one unique code block, and nothing else. do not write explanations. do not type commands unless I instruct you to do so. when i need to tell you something in english, i will do so by putting text inside curly brackets {like this}. my first command is pwd',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmd: 'translator',
|
|
||||||
type: 'tools',
|
|
||||||
content: 'I want you to act as an English translator, spelling corrector and improver. I will speak to you in any language and you will detect the language, translate it and answer in the corrected and improved version of my text, in English. I want you to replace my simplified A0-level words and sentences with more beautiful and elegant, upper level English words and sentences. Keep the meaning same, but make them more literary. I want you to only reply the correction, the improvements and nothing else, do not write explanations. My first sentence is "istanbulu cok seviyom burada olmak cok guzel"',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function ChatGPTPrompts() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Button className="add-btn" type="primary">Add Command</Button>
|
|
||||||
<Table
|
|
||||||
rowKey="content"
|
|
||||||
columns={columns}
|
|
||||||
dataSource={dataSource}
|
|
||||||
pagination={{
|
|
||||||
hideOnSinglePage: true,
|
|
||||||
pageSize: 10,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
14
src/view/General.tsx
vendored
14
src/view/General.tsx
vendored
@@ -7,6 +7,8 @@ import { ask } from '@tauri-apps/api/dialog';
|
|||||||
import { relaunch } from '@tauri-apps/api/process';
|
import { relaunch } from '@tauri-apps/api/process';
|
||||||
import { clone, omit, isEqual } from 'lodash';
|
import { clone, omit, isEqual } from 'lodash';
|
||||||
|
|
||||||
|
import { DISABLE_AUTO_COMPLETE } from '@/utils';
|
||||||
|
|
||||||
const OriginLabel = ({ url }: { url: string }) => {
|
const OriginLabel = ({ url }: { url: string }) => {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
@@ -15,12 +17,6 @@ const OriginLabel = ({ url }: { url: string }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const disableAuto = {
|
|
||||||
autoCapitalize: 'off',
|
|
||||||
autoComplete: 'off',
|
|
||||||
spellCheck: false
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function General() {
|
export default function General() {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [platformInfo, setPlatform] = useState<string>('');
|
const [platformInfo, setPlatform] = useState<string>('');
|
||||||
@@ -81,13 +77,13 @@ export default function General() {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
<Form.Item label={<OriginLabel url={chatConf?.default_origin} />} name="origin">
|
<Form.Item label={<OriginLabel url={chatConf?.default_origin} />} name="origin">
|
||||||
<Input placeholder="https://chat.openai.com" {...disableAuto} />
|
<Input placeholder="https://chat.openai.com" {...DISABLE_AUTO_COMPLETE} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="User Agent (Window)" name="ua_window">
|
<Form.Item label="User Agent (Window)" name="ua_window">
|
||||||
<Input.TextArea autoSize={{ minRows: 4, maxRows: 4 }} {...disableAuto} placeholder="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" />
|
<Input.TextArea autoSize={{ minRows: 4, maxRows: 4 }} {...DISABLE_AUTO_COMPLETE} placeholder="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="User Agent (SystemTray)" name="ua_tray">
|
<Form.Item label="User Agent (SystemTray)" name="ua_tray">
|
||||||
<Input.TextArea autoSize={{ minRows: 4, maxRows: 4 }} {...disableAuto} placeholder="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" />
|
<Input.TextArea autoSize={{ minRows: 4, maxRows: 4 }} {...DISABLE_AUTO_COMPLETE} placeholder="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Space size={20}>
|
<Space size={20}>
|
||||||
|
|||||||
59
src/view/LanguageModel/Form.tsx
vendored
Normal file
59
src/view/LanguageModel/Form.tsx
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { useEffect, ForwardRefRenderFunction, useImperativeHandle, forwardRef } from 'react';
|
||||||
|
import { Form, Input, Switch } from 'antd';
|
||||||
|
import type { FormProps } from 'antd';
|
||||||
|
|
||||||
|
import Tags from '@comps/Tags';
|
||||||
|
import { DISABLE_AUTO_COMPLETE } from '@/utils';
|
||||||
|
|
||||||
|
interface LanguageModelProps {
|
||||||
|
record?: Record<string|symbol, any> | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initFormValue = {
|
||||||
|
act: '',
|
||||||
|
enable: true,
|
||||||
|
tags: [],
|
||||||
|
prompt: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const LanguageModel: ForwardRefRenderFunction<FormProps, LanguageModelProps> = ({ record }, ref) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
useImperativeHandle(ref, () => ({ form }));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (record) {
|
||||||
|
form.setFieldsValue(record);
|
||||||
|
}
|
||||||
|
}, [record]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
labelCol={{ span: 4 }}
|
||||||
|
initialValues={initFormValue}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="Act"
|
||||||
|
name="act"
|
||||||
|
rules={[{ required: true, message: 'Please input act!' }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="Please input act" {...DISABLE_AUTO_COMPLETE} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="Tags" name="tags">
|
||||||
|
<Tags />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="Enable" name="enable" valuePropName="checked">
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="Prompt"
|
||||||
|
name="prompt"
|
||||||
|
rules={[{ required: true, message: 'Please input prompt!' }]}
|
||||||
|
>
|
||||||
|
<Input.TextArea rows={4} placeholder="Please input prompt" {...DISABLE_AUTO_COMPLETE} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default forwardRef(LanguageModel);
|
||||||
39
src/view/LanguageModel/config.tsx
vendored
Normal file
39
src/view/LanguageModel/config.tsx
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { Tag, Switch, Tooltip, Space } from 'antd';
|
||||||
|
|
||||||
|
export const modelColumns = () => [
|
||||||
|
{
|
||||||
|
title: 'Act',
|
||||||
|
dataIndex: 'act',
|
||||||
|
key: 'act',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Tags',
|
||||||
|
dataIndex: 'tags',
|
||||||
|
key: 'tags',
|
||||||
|
render: (v: string[]) => v?.map(i => <Tag key={i}>{i}</Tag>),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Enable',
|
||||||
|
dataIndex: 'enable',
|
||||||
|
key: 'enable',
|
||||||
|
render: (v: boolean = false) => <Switch checked={v} disabled />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Prompt',
|
||||||
|
dataIndex: 'prompt',
|
||||||
|
key: 'prompt',
|
||||||
|
render: (v: string) => (
|
||||||
|
<Tooltip overlayInnerStyle={{ width: 350 }} title={v}><span className="chat-prompts-val">{v}</span></Tooltip>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Action',
|
||||||
|
key: 'action',
|
||||||
|
render: (_: any, row: any, actions: any) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<a onClick={() => actions.setRecord(row, 'edit')}>Edit</a>
|
||||||
|
<a onClick={() => actions.setRecord(row, 'delete')}>Delete</a>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
];
|
||||||
79
src/view/LanguageModel/index.tsx
vendored
Normal file
79
src/view/LanguageModel/index.tsx
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { useState, useRef, useEffect } from 'react';
|
||||||
|
import { Table, Button, Modal } from 'antd';
|
||||||
|
|
||||||
|
import useChatModel from '@/hooks/useChatModel';
|
||||||
|
import useColumns from '@/hooks/useColumns';
|
||||||
|
import useData from '@/hooks/useData';
|
||||||
|
import { modelColumns } from './config';
|
||||||
|
import LanguageModelForm from './Form';
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
export default function LanguageModel() {
|
||||||
|
const [isVisible, setVisible] = useState(false);
|
||||||
|
const { modelData, modelSet } = useChatModel();
|
||||||
|
const { opData, opAdd, opRemove, opReplace, opSafeKey } = useData(modelData);
|
||||||
|
const { columns, ...opInfo } = useColumns(modelColumns());
|
||||||
|
const formRef = useRef<any>(null);
|
||||||
|
|
||||||
|
const hide = () => {
|
||||||
|
setVisible(false);
|
||||||
|
opInfo.resetRecord();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOk = () => {
|
||||||
|
formRef.current?.form?.validateFields()
|
||||||
|
.then((vals: Record<string, any>) => {
|
||||||
|
let data = [];
|
||||||
|
switch (opInfo.opType) {
|
||||||
|
case 'new': data = opAdd(vals); break;
|
||||||
|
case 'edit': data = opReplace(opInfo?.opRecord?.[opSafeKey], vals); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
modelSet(data)
|
||||||
|
hide();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!opInfo.opType) return;
|
||||||
|
if (['edit', 'new'].includes(opInfo.opType)) {
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
if (['delete'].includes(opInfo.opType)) {
|
||||||
|
const data = opRemove(opInfo?.opRecord?.[opSafeKey]);
|
||||||
|
modelSet(data);
|
||||||
|
opInfo.resetRecord();
|
||||||
|
}
|
||||||
|
}, [opInfo.opType, formRef]);
|
||||||
|
|
||||||
|
const modalTitle = `${({ new: 'Create', edit: 'Edit' })[opInfo.opType]} Language Model`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Button className="add-btn" type="primary" onClick={opInfo.opNew}>Add Model</Button>
|
||||||
|
<Table
|
||||||
|
rowKey="act"
|
||||||
|
columns={columns}
|
||||||
|
dataSource={opData}
|
||||||
|
pagination={{
|
||||||
|
hideOnSinglePage: true,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
defaultPageSize: 5,
|
||||||
|
pageSizeOptions: [5, 10, 15, 20],
|
||||||
|
showTotal: (total) => <span>Total {total} items</span>,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Modal
|
||||||
|
open={isVisible}
|
||||||
|
onCancel={hide}
|
||||||
|
title={modalTitle}
|
||||||
|
onOk={handleOk}
|
||||||
|
destroyOnClose
|
||||||
|
maskClosable={false}
|
||||||
|
>
|
||||||
|
<LanguageModelForm record={opInfo?.opRecord} ref={formRef} />
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user