mirror of
https://github.com/lencx/ChatGPT.git
synced 2024-10-01 01:06:13 -04:00
chore: sync
This commit is contained in:
parent
921d670f53
commit
8319eae519
@ -2,8 +2,13 @@
|
|||||||
|
|
||||||
## v0.5.2
|
## v0.5.2
|
||||||
|
|
||||||
|
fix:
|
||||||
|
- windows show Chinese when upgrading
|
||||||
|
|
||||||
feat:
|
feat:
|
||||||
- optimize the generated pdf file size
|
- optimize the generated pdf file size
|
||||||
|
- menu added `Sync Prompts`
|
||||||
|
- the slash command is triggered by the enter key
|
||||||
|
|
||||||
## v0.5.1
|
## v0.5.1
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ pub fn get_chat_model() -> serde_json::Value {
|
|||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct PromptRecord {
|
pub struct PromptRecord {
|
||||||
|
pub cmd: Option<String>,
|
||||||
pub act: String,
|
pub act: String,
|
||||||
pub prompt: String,
|
pub prompt: String,
|
||||||
}
|
}
|
||||||
|
8
src/hooks/useChatModel.ts
vendored
8
src/hooks/useChatModel.ts
vendored
@ -5,18 +5,20 @@ import { invoke } from '@tauri-apps/api';
|
|||||||
import { CHAT_MODEL_JSON, readJSON, writeJSON } from '@/utils';
|
import { CHAT_MODEL_JSON, readJSON, writeJSON } from '@/utils';
|
||||||
import useInit from '@/hooks/useInit';
|
import useInit from '@/hooks/useInit';
|
||||||
|
|
||||||
export default function useChatModel(key: string) {
|
export default function useChatModel(key: string, file = CHAT_MODEL_JSON) {
|
||||||
const [modelJson, setModelJson] = useState<Record<string, any>>({});
|
const [modelJson, setModelJson] = useState<Record<string, any>>({});
|
||||||
|
|
||||||
useInit(async () => {
|
useInit(async () => {
|
||||||
const data = await readJSON(CHAT_MODEL_JSON, { name: 'ChatGPT Model', [key]: [] });
|
const data = await readJSON(file, {
|
||||||
|
defaultVal: { name: 'ChatGPT Model', [key]: [] },
|
||||||
|
});
|
||||||
setModelJson(data);
|
setModelJson(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
const modelSet = async (data: Record<string, any>[]) => {
|
const modelSet = async (data: Record<string, any>[]) => {
|
||||||
const oData = clone(modelJson);
|
const oData = clone(modelJson);
|
||||||
oData[key] = data;
|
oData[key] = data;
|
||||||
await writeJSON(CHAT_MODEL_JSON, oData);
|
await writeJSON(file, oData);
|
||||||
await invoke('window_reload', { label: 'core' });
|
await invoke('window_reload', { label: 'core' });
|
||||||
setModelJson(oData);
|
setModelJson(oData);
|
||||||
}
|
}
|
||||||
|
28
src/utils.ts
vendored
28
src/utils.ts
vendored
@ -1,8 +1,9 @@
|
|||||||
import { readTextFile, writeTextFile, exists } from '@tauri-apps/api/fs';
|
import { readTextFile, writeTextFile, exists, createDir, BaseDirectory } from '@tauri-apps/api/fs';
|
||||||
import { homeDir, join } from '@tauri-apps/api/path';
|
import { homeDir, join, dirname } from '@tauri-apps/api/path';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
export const CHAT_MODEL_JSON = 'chat.model.json';
|
export const CHAT_MODEL_JSON = 'chat.model.json';
|
||||||
|
export const CHAT_MODEL_SYNC_JSON = 'chat.model.sync.json';
|
||||||
export const CHAT_PROMPTS_CSV = 'chat.prompts.csv';
|
export const CHAT_PROMPTS_CSV = 'chat.prompts.csv';
|
||||||
export const GITHUB_PROMPTS_CSV_URL = 'https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv';
|
export const GITHUB_PROMPTS_CSV_URL = 'https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv';
|
||||||
export const DISABLE_AUTO_COMPLETE = {
|
export const DISABLE_AUTO_COMPLETE = {
|
||||||
@ -19,18 +20,24 @@ export const chatModelPath = async (): Promise<string> => {
|
|||||||
return join(await chatRoot(), CHAT_MODEL_JSON);
|
return join(await chatRoot(), CHAT_MODEL_JSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const chatModelSyncPath = async (): Promise<string> => {
|
||||||
|
return join(await chatRoot(), CHAT_MODEL_SYNC_JSON);
|
||||||
|
}
|
||||||
|
|
||||||
export const chatPromptsPath = async (): Promise<string> => {
|
export const chatPromptsPath = async (): Promise<string> => {
|
||||||
return join(await chatRoot(), CHAT_PROMPTS_CSV);
|
return join(await chatRoot(), CHAT_PROMPTS_CSV);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const readJSON = async (path: string, defaultVal = {}) => {
|
type readJSONOpts = { defaultVal?: Record<string, any>, isRoot?: boolean };
|
||||||
|
export const readJSON = async (path: string, opts: readJSONOpts = {}) => {
|
||||||
|
const { defaultVal = {}, isRoot = false } = opts;
|
||||||
const root = await chatRoot();
|
const root = await chatRoot();
|
||||||
const file = await join(root, path);
|
const file = await join(isRoot ? '' : root, path);
|
||||||
|
|
||||||
if (!await exists(file)) {
|
if (!await exists(file)) {
|
||||||
writeTextFile(file, JSON.stringify({
|
writeTextFile(file, JSON.stringify({
|
||||||
name: 'ChatGPT',
|
name: 'ChatGPT',
|
||||||
link: 'https://github.com/lencx/ChatGPT/blob/main/chat.model.md',
|
link: 'https://github.com/lencx/ChatGPT',
|
||||||
...defaultVal,
|
...defaultVal,
|
||||||
}, null, 2))
|
}, null, 2))
|
||||||
}
|
}
|
||||||
@ -42,9 +49,16 @@ export const readJSON = async (path: string, defaultVal = {}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const writeJSON = async (path: string, data: Record<string, any>) => {
|
type writeJSONOpts = { dir?: string, isRoot?: boolean };
|
||||||
|
export const writeJSON = async (path: string, data: Record<string, any>, opts: writeJSONOpts = {}) => {
|
||||||
|
const { isRoot = false, dir = '' } = opts;
|
||||||
const root = await chatRoot();
|
const root = await chatRoot();
|
||||||
const file = await join(root, path);
|
const file = await join(isRoot ? '' : root, path);
|
||||||
|
|
||||||
|
if (isRoot && !await exists(await dirname(file))) {
|
||||||
|
await createDir(await join('.chatgpt', dir), { dir: BaseDirectory.Home });
|
||||||
|
}
|
||||||
|
|
||||||
await writeTextFile(file, JSON.stringify(data, null, 2));
|
await writeTextFile(file, JSON.stringify(data, null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
105
src/view/model/SyncMore/Form.tsx
vendored
Normal file
105
src/view/model/SyncMore/Form.tsx
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import { useEffect, useState, ForwardRefRenderFunction, useImperativeHandle, forwardRef } from 'react';
|
||||||
|
import { Form, Input, Select, Tooltip } from 'antd';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
import type { FormProps } from 'antd';
|
||||||
|
|
||||||
|
import { DISABLE_AUTO_COMPLETE, chatRoot } from '@/utils';
|
||||||
|
import useInit from '@/hooks/useInit';
|
||||||
|
|
||||||
|
interface SyncFormProps {
|
||||||
|
record?: Record<string|symbol, any> | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initFormValue = {
|
||||||
|
act: '',
|
||||||
|
enable: true,
|
||||||
|
tags: [],
|
||||||
|
prompt: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const SyncForm: ForwardRefRenderFunction<FormProps, SyncFormProps> = ({ record }, ref) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
useImperativeHandle(ref, () => ({ form }));
|
||||||
|
const [root, setRoot] = useState('');
|
||||||
|
|
||||||
|
useInit(async () => {
|
||||||
|
setRoot(await chatRoot());
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (record) {
|
||||||
|
form.setFieldsValue(record);
|
||||||
|
}
|
||||||
|
}, [record]);
|
||||||
|
|
||||||
|
const pathOptions = (
|
||||||
|
<Form.Item noStyle name="protocol" initialValue="https">
|
||||||
|
<Select>
|
||||||
|
<Select.Option value="local">{root}</Select.Option>
|
||||||
|
<Select.Option value="http">http://</Select.Option>
|
||||||
|
<Select.Option value="https">https://</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
const extOptions = (
|
||||||
|
<Form.Item noStyle name="ext" initialValue="json">
|
||||||
|
<Select>
|
||||||
|
<Select.Option value="csv">.csv</Select.Option>
|
||||||
|
<Select.Option value="json">.json</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
|
||||||
|
const jsonTip = (
|
||||||
|
<Tooltip
|
||||||
|
title={<pre>{JSON.stringify([
|
||||||
|
{ cmd: '', act: '', prompt: '' },
|
||||||
|
{ cmd: '', act: '', prompt: '' },
|
||||||
|
], null, 2)}</pre>}
|
||||||
|
>
|
||||||
|
<a>JSON</a>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
|
const csvTip = (
|
||||||
|
<Tooltip
|
||||||
|
title={<pre>{`"cmd","act","prompt"
|
||||||
|
"cmd","act","prompt"
|
||||||
|
"cmd","act","prompt"
|
||||||
|
"cmd","act","prompt"`}</pre>}
|
||||||
|
>
|
||||||
|
<a>CSV</a>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
labelCol={{ span: 4 }}
|
||||||
|
initialValues={initFormValue}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="Name"
|
||||||
|
name="name"
|
||||||
|
rules={[{ required: true, message: 'Please input name!' }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="Please input name" {...DISABLE_AUTO_COMPLETE} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="PATH"
|
||||||
|
name="path"
|
||||||
|
rules={[{ required: true, message: 'Please input path!' }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="YOUR_PATH" addonBefore={pathOptions} addonAfter={extOptions} {...DISABLE_AUTO_COMPLETE} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item style={{ display: 'none' }} name="id" initialValue={v4().replace(/-/g, '')}><input /></Form.Item>
|
||||||
|
</Form>
|
||||||
|
<div className="tip">
|
||||||
|
<p>The file supports only {csvTip} and {jsonTip} formats.</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default forwardRef(SyncForm);
|
72
src/view/model/SyncMore/config.tsx
vendored
72
src/view/model/SyncMore/config.tsx
vendored
@ -1,15 +1,73 @@
|
|||||||
export const recordColumns = () => [
|
import { useState } from 'react';
|
||||||
|
import { Tag, Space, Popconfirm } from 'antd';
|
||||||
|
import { shell, path } from '@tauri-apps/api';
|
||||||
|
|
||||||
|
import useInit from '@/hooks/useInit';
|
||||||
|
import { chatRoot, fmtDate } from '@/utils';
|
||||||
|
|
||||||
|
export const pathColumns = () => [
|
||||||
{
|
{
|
||||||
title: 'URL',
|
title: 'Name',
|
||||||
dataIndex: 'url',
|
dataIndex: 'name',
|
||||||
key: 'url',
|
key: 'name',
|
||||||
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'File Type',
|
title: 'Protocol',
|
||||||
dataIndex: 'file_type',
|
dataIndex: 'protocol',
|
||||||
key: 'file_type',
|
key: 'protocol',
|
||||||
|
width: 80,
|
||||||
|
render: (v: string) => <Tag>{v}</Tag>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'PATH',
|
||||||
|
dataIndex: 'path',
|
||||||
|
key: 'path',
|
||||||
|
width: 180,
|
||||||
|
render: (_: string, row: any) => <RenderPath row={row} />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Last updated',
|
||||||
|
dataIndex: 'last_updated',
|
||||||
|
key: 'last_updated',
|
||||||
|
width: 140,
|
||||||
|
render: fmtDate,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Action',
|
title: 'Action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 140,
|
||||||
|
render: (_: any, row: any, actions: any) => {
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<a onClick={() => actions.setRecord(row, 'sync')}>Sync</a>
|
||||||
|
<a onClick={() => actions.setRecord(row, 'edit')}>Edit</a>
|
||||||
|
<Popconfirm
|
||||||
|
title="Are you sure to delete this path?"
|
||||||
|
onConfirm={() => actions.setRecord(row, 'delete')}
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
>
|
||||||
|
<a>Delete</a>
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const RenderPath = ({ row }: any) => {
|
||||||
|
const [filePath, setFilePath] = useState('');
|
||||||
|
useInit(async () => {
|
||||||
|
setFilePath(await getPath(row));
|
||||||
|
})
|
||||||
|
return <a onClick={() => shell.open(filePath)}>{filePath}</a>
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPath = async (row: any) => {
|
||||||
|
if (!/^http/.test(row.protocol)) {
|
||||||
|
return await path.join(await chatRoot(), row.path) + `.${row.ext}`;
|
||||||
|
} else {
|
||||||
|
return `${row.protocol}://${row.path}.${row.ext}`;
|
||||||
|
}
|
||||||
|
}
|
136
src/view/model/SyncMore/index.tsx
vendored
136
src/view/model/SyncMore/index.tsx
vendored
@ -1,20 +1,144 @@
|
|||||||
import { Table, Button } from 'antd';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
|
import { Table, Modal, Button, message } from 'antd';
|
||||||
|
import { invoke, http, path, fs } from '@tauri-apps/api';
|
||||||
|
|
||||||
|
import useData from '@/hooks/useData';
|
||||||
|
import useChatModel from '@/hooks/useChatModel';
|
||||||
|
import useColumns from '@/hooks/useColumns';
|
||||||
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||||
|
import { CHAT_MODEL_SYNC_JSON, chatRoot, writeJSON, readJSON, genCmd } from '@/utils';
|
||||||
|
import { pathColumns, getPath } from './config';
|
||||||
|
import SyncForm from './Form';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
|
const setTag = (data: Record<string, any>[]) => data.map((i) => ({ ...i, tags: ['user-sync'], enable: true }))
|
||||||
|
|
||||||
export default function SyncMore() {
|
export default function SyncMore() {
|
||||||
|
const [isVisible, setVisible] = useState(false);
|
||||||
|
// const [modelPath, setChatModelPath] = useState('');
|
||||||
|
const { modelData, modelSet } = useChatModel('sync_url', CHAT_MODEL_SYNC_JSON);
|
||||||
|
const { opData, opInit, opAdd, opRemove, opReplace, opSafeKey } = useData([]);
|
||||||
|
const { columns, ...opInfo } = useColumns(pathColumns());
|
||||||
|
const formRef = useRef<any>(null);
|
||||||
|
|
||||||
|
const hide = () => {
|
||||||
|
setVisible(false);
|
||||||
|
opInfo.resetRecord();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (modelData.length <= 0) return;
|
||||||
|
opInit(modelData);
|
||||||
|
}, [modelData]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!opInfo.opType) return;
|
||||||
|
if (opInfo.opType === 'sync') {
|
||||||
|
const filename = `${opInfo?.opRecord?.id}.json`;
|
||||||
|
handleSync(filename).then(() => {
|
||||||
|
const data = opReplace(opInfo?.opRecord?.[opSafeKey], { ...opInfo?.opRecord, last_updated: Date.now() });
|
||||||
|
console.log('«38» /model/SyncMore/index.tsx ~> ', data);
|
||||||
|
|
||||||
|
modelSet(data);
|
||||||
|
opInfo.resetRecord();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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 handleSync = async (filename: string) => {
|
||||||
|
const record = opInfo?.opRecord;
|
||||||
|
const isJson = /json$/.test(record?.ext);
|
||||||
|
const file = await path.join(await chatRoot(), 'cache_sync', filename);
|
||||||
|
const filePath = await getPath(record);
|
||||||
|
|
||||||
|
// https or http
|
||||||
|
if (/^http/.test(record?.protocol)) {
|
||||||
|
const res = await http.fetch(filePath, {
|
||||||
|
method: 'GET',
|
||||||
|
responseType: isJson ? 1 : 2,
|
||||||
|
});
|
||||||
|
if (res.ok) {
|
||||||
|
if (isJson) {
|
||||||
|
// parse json
|
||||||
|
writeJSON(file, setTag(Array.isArray(res?.data) ? res?.data : []), { isRoot: true, dir: 'cache_sync' });
|
||||||
|
} else {
|
||||||
|
// parse csv
|
||||||
|
const list: Record<string, string>[] = await invoke('parse_prompt', { data: res?.data });
|
||||||
|
const fmtList = list.map(i => ({ ...i, cmd: i.cmd ? i.cmd : genCmd(i.act), enable: true, tags: ['user-sync'] }));
|
||||||
|
await writeJSON(file, fmtList, { isRoot: true, dir: 'cache_sync' });
|
||||||
|
}
|
||||||
|
message.success('ChatGPT Prompts data has been synchronized!');
|
||||||
|
} else {
|
||||||
|
message.error('ChatGPT Prompts data sync failed, please try again!');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// local
|
||||||
|
if (isJson) {
|
||||||
|
// parse json
|
||||||
|
const data = await readJSON(filePath, { isRoot: true });
|
||||||
|
await writeJSON(file, setTag(Array.isArray(data) ? data : []), { isRoot: true, dir: 'cache_sync' });
|
||||||
|
} else {
|
||||||
|
// parse csv
|
||||||
|
const data = await fs.readTextFile(filePath);
|
||||||
|
const list: Record<string, string>[] = await invoke('parse_prompt', { data });
|
||||||
|
const fmtList = list.map(i => ({ ...i, cmd: i.cmd ? i.cmd : genCmd(i.act), enable: true, tags: ['user-sync'] }));
|
||||||
|
await writeJSON(file, fmtList, { isRoot: true, dir: 'cache_sync' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
console.log('«95» /model/SyncMore/index.tsx ~> ', data);
|
||||||
|
|
||||||
|
modelSet(data);
|
||||||
|
opInfo.setExtra(Date.now());
|
||||||
|
hide();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button className="add-btn" type="primary">Add URL</Button>
|
<Button
|
||||||
|
className="add-btn"
|
||||||
|
type="primary"
|
||||||
|
onClick={opInfo.opNew}
|
||||||
|
>
|
||||||
|
Add PATH
|
||||||
|
</Button>
|
||||||
<Table
|
<Table
|
||||||
key="id"
|
key="id"
|
||||||
rowKey="url"
|
rowKey="name"
|
||||||
columns={[]}
|
columns={columns}
|
||||||
scroll={{ x: 'auto' }}
|
scroll={{ x: 800 }}
|
||||||
dataSource={[]}
|
dataSource={opData}
|
||||||
pagination={TABLE_PAGINATION}
|
pagination={TABLE_PAGINATION}
|
||||||
/>
|
/>
|
||||||
|
<Modal
|
||||||
|
open={isVisible}
|
||||||
|
onCancel={hide}
|
||||||
|
title="Model PATH"
|
||||||
|
onOk={handleOk}
|
||||||
|
destroyOnClose
|
||||||
|
maskClosable={false}
|
||||||
|
>
|
||||||
|
<SyncForm ref={formRef} record={opInfo?.opRecord} />
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
4
src/view/model/SyncPrompts/index.tsx
vendored
4
src/view/model/SyncPrompts/index.tsx
vendored
@ -44,7 +44,7 @@ export default function LanguageModel() {
|
|||||||
await writeTextFile(await chatPromptsPath(), data);
|
await writeTextFile(await chatPromptsPath(), data);
|
||||||
const list: Record<string, string>[] = await invoke('parse_prompt', { data });
|
const list: Record<string, string>[] = await invoke('parse_prompt', { data });
|
||||||
opInit(list);
|
opInit(list);
|
||||||
modelSet(list.map(i => ({ cmd: genCmd(i.act), enable: true, tags: ['chatgpt-prompts'], ...i })));
|
modelSet(list.map(i => ({ ...i, cmd: i.cmd ? i.cmd : genCmd(i.act), enable: true, tags: ['chatgpt-prompts'] })));
|
||||||
setLastUpdated(fmtDate(Date.now()) as any);
|
setLastUpdated(fmtDate(Date.now()) as any);
|
||||||
message.success('ChatGPT Prompts data has been synchronized!');
|
message.success('ChatGPT Prompts data has been synchronized!');
|
||||||
} else {
|
} else {
|
||||||
@ -88,7 +88,7 @@ export default function LanguageModel() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="chat-table-tip">
|
<div className="chat-table-tip">
|
||||||
<span className="chat-model-path">URL: <a href={promptsURL} target="_blank" title={promptsURL}>f/awesome-chatgpt-prompts/prompts.csv</a></span>
|
<span className="chat-model-path">URL: <a href={promptsURL} target="_blank" title={promptsURL}>f/awesome-chatgpt-prompts/prompts.csv</a></span>
|
||||||
{lastUpdated && <span style={{ marginLeft: 10, color: '#999' }}>Last updated on {fmtDate(lastUpdated)}</span>}
|
{lastUpdated && <span style={{ marginLeft: 10, color: '#888', fontSize: 12 }}>Last updated on {fmtDate(lastUpdated)}</span>}
|
||||||
</div>
|
</div>
|
||||||
<Table
|
<Table
|
||||||
key={lastUpdated}
|
key={lastUpdated}
|
||||||
|
6
src/view/model/UserCustom/Form.tsx
vendored
6
src/view/model/UserCustom/Form.tsx
vendored
@ -5,7 +5,7 @@ import type { FormProps } from 'antd';
|
|||||||
import Tags from '@comps/Tags';
|
import Tags from '@comps/Tags';
|
||||||
import { DISABLE_AUTO_COMPLETE } from '@/utils';
|
import { DISABLE_AUTO_COMPLETE } from '@/utils';
|
||||||
|
|
||||||
interface LanguageModelProps {
|
interface UserCustomFormProps {
|
||||||
record?: Record<string|symbol, any> | null;
|
record?: Record<string|symbol, any> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ const initFormValue = {
|
|||||||
prompt: '',
|
prompt: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const LanguageModel: ForwardRefRenderFunction<FormProps, LanguageModelProps> = ({ record }, ref) => {
|
const UserCustomForm: ForwardRefRenderFunction<FormProps, UserCustomFormProps> = ({ record }, ref) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
useImperativeHandle(ref, () => ({ form }));
|
useImperativeHandle(ref, () => ({ form }));
|
||||||
|
|
||||||
@ -63,4 +63,4 @@ const LanguageModel: ForwardRefRenderFunction<FormProps, LanguageModelProps> = (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default forwardRef(LanguageModel);
|
export default forwardRef(UserCustomForm);
|
||||||
|
15
src/view/model/UserCustom/index.tsx
vendored
15
src/view/model/UserCustom/index.tsx
vendored
@ -7,9 +7,9 @@ import useData from '@/hooks/useData';
|
|||||||
import useChatModel from '@/hooks/useChatModel';
|
import useChatModel from '@/hooks/useChatModel';
|
||||||
import useColumns from '@/hooks/useColumns';
|
import useColumns from '@/hooks/useColumns';
|
||||||
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||||
import { chatModelPath, genCmd } from '@/utils';
|
import { chatModelPath } from '@/utils';
|
||||||
import { modelColumns } from './config';
|
import { modelColumns } from './config';
|
||||||
import LanguageModelForm from './Form';
|
import UserCustomForm from './Form';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
export default function LanguageModel() {
|
export default function LanguageModel() {
|
||||||
@ -23,7 +23,7 @@ export default function LanguageModel() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (modelData.length <= 0) return;
|
if (modelData.length <= 0) return;
|
||||||
opInit(modelData);
|
opInit(modelData);
|
||||||
}, [modelData])
|
}, [modelData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!opInfo.opType) return;
|
if (!opInfo.opType) return;
|
||||||
@ -67,7 +67,8 @@ export default function LanguageModel() {
|
|||||||
case 'edit': data = opReplace(opInfo?.opRecord?.[opSafeKey], vals); break;
|
case 'edit': data = opReplace(opInfo?.opRecord?.[opSafeKey], vals); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
modelSet(data)
|
modelSet(data);
|
||||||
|
opInfo.setExtra(Date.now());
|
||||||
hide();
|
hide();
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@ -76,14 +77,14 @@ export default function LanguageModel() {
|
|||||||
invoke('open_file', { path: modelPath });
|
invoke('open_file', { path: modelPath });
|
||||||
};
|
};
|
||||||
|
|
||||||
const modalTitle = `${({ new: 'Create', edit: 'Edit' })[opInfo.opType]} Language Model`;
|
const modalTitle = `${({ new: 'Create', edit: 'Edit' })[opInfo.opType]} Model`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button className="add-btn" type="primary" onClick={opInfo.opNew}>Add Model</Button>
|
<Button className="add-btn" type="primary" onClick={opInfo.opNew}>Add Model</Button>
|
||||||
<div className="chat-model-path">PATH: <span onClick={handleOpenFile}>{modelPath}</span></div>
|
<div className="chat-model-path">PATH: <span onClick={handleOpenFile}>{modelPath}</span></div>
|
||||||
<Table
|
<Table
|
||||||
key={opInfo.opTime}
|
key={opInfo.opExtra}
|
||||||
rowKey="cmd"
|
rowKey="cmd"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
scroll={{ x: 'auto' }}
|
scroll={{ x: 'auto' }}
|
||||||
@ -98,7 +99,7 @@ export default function LanguageModel() {
|
|||||||
destroyOnClose
|
destroyOnClose
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
>
|
>
|
||||||
<LanguageModelForm record={opInfo?.opRecord} ref={formRef} />
|
<UserCustomForm record={opInfo?.opRecord} ref={formRef} />
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user