mirror of
https://github.com/lencx/ChatGPT.git
synced 2024-10-01 01:06:13 -04:00
chore: sync record
This commit is contained in:
parent
6abe7c783e
commit
2be560e69a
26
src/hooks/useChatModel.ts
vendored
26
src/hooks/useChatModel.ts
vendored
@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { clone } from 'lodash';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
|
||||
@ -6,7 +6,7 @@ import { CHAT_MODEL_JSON, readJSON, writeJSON } from '@/utils';
|
||||
import useInit from '@/hooks/useInit';
|
||||
|
||||
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 () => {
|
||||
const data = await readJSON(file, {
|
||||
@ -23,5 +23,25 @@ export default function useChatModel(key: string, file = CHAT_MODEL_JSON) {
|
||||
setModelJson(oData);
|
||||
}
|
||||
|
||||
return { modelJson, modelSet, modelData: modelJson?.[key] || [] }
|
||||
return { modelJson, modelSet, modelData: modelJson?.[key] || [] };
|
||||
}
|
||||
|
||||
export function useCacheModel(file: string) {
|
||||
const [modelJson, setModelJson] = useState<Record<string, any>[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!file) return;
|
||||
(async () => {
|
||||
const data = await readJSON(file, { isRoot: true });
|
||||
setModelJson(data);
|
||||
})();
|
||||
}, [file]);
|
||||
|
||||
const modelSet = async (data: Record<string, any>[]) => {
|
||||
await writeJSON(file, data, { isRoot: true });
|
||||
await invoke('window_reload', { label: 'core' });
|
||||
setModelJson(data);
|
||||
}
|
||||
|
||||
return { modelJson, modelSet };
|
||||
}
|
28
src/routes.tsx
vendored
28
src/routes.tsx
vendored
@ -11,7 +11,8 @@ import type { MenuProps } from 'antd';
|
||||
import General from '@view/General';
|
||||
import UserCustom from '@/view/model/UserCustom';
|
||||
import SyncPrompts from '@/view/model/SyncPrompts';
|
||||
import SyncMore from '@/view/model/SyncMore';
|
||||
import SyncCustom from '@/view/model/SyncCustom';
|
||||
import SyncRecord from '@/view/model/SyncRecord';
|
||||
|
||||
export type ChatRouteMetaObject = {
|
||||
label: string;
|
||||
@ -21,7 +22,8 @@ export type ChatRouteMetaObject = {
|
||||
type ChatRouteObject = {
|
||||
path: string;
|
||||
element?: JSX.Element;
|
||||
meta: ChatRouteMetaObject;
|
||||
hideMenu?: boolean;
|
||||
meta?: ChatRouteMetaObject;
|
||||
children?: ChatRouteObject[];
|
||||
}
|
||||
|
||||
@ -58,24 +60,32 @@ export const routes: Array<ChatRouteObject> = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'sync-more',
|
||||
element: <SyncMore />,
|
||||
path: 'sync-custom',
|
||||
element: <SyncCustom />,
|
||||
meta: {
|
||||
label: 'Sync More',
|
||||
label: 'Sync Custom',
|
||||
icon: <FileSyncOutlined />,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'sync-custom/:id',
|
||||
element: <SyncRecord />,
|
||||
hideMenu: true,
|
||||
},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
export const menuItems: MenuItem[] = routes.map(i => ({
|
||||
export const menuItems: MenuItem[] = routes
|
||||
.filter((j) => !j.hideMenu)
|
||||
.map(i => ({
|
||||
...i.meta,
|
||||
key: i.path || '',
|
||||
children: i?.children?.map((j) =>
|
||||
({ ...j.meta, key: `${i.path}/${j.path}` || ''})),
|
||||
}));
|
||||
children: i?.children
|
||||
?.filter((j) => !j.hideMenu)
|
||||
?.map((j) => ({ ...j.meta, key: `${i.path}/${j.path}` || ''})),
|
||||
}));
|
||||
|
||||
export default () => {
|
||||
return useRoutes(routes);
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { useState } from 'react';
|
||||
import { Tag, Space, Popconfirm } from 'antd';
|
||||
import { HistoryOutlined } from '@ant-design/icons';
|
||||
import { shell, path } from '@tauri-apps/api';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import useInit from '@/hooks/useInit';
|
||||
import { chatRoot, fmtDate } from '@/utils';
|
||||
|
||||
export const pathColumns = () => [
|
||||
export const syncColumns = () => [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
@ -31,16 +33,22 @@ export const pathColumns = () => [
|
||||
dataIndex: 'last_updated',
|
||||
key: 'last_updated',
|
||||
width: 140,
|
||||
render: fmtDate,
|
||||
render: (v: number) => (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<HistoryOutlined style={{ marginRight: 5, color: v ? '#52c41a' : '#ff4d4f' }} />
|
||||
{ v ? fmtDate(v) : ''}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
fixed: 'right',
|
||||
width: 140,
|
||||
width: 150,
|
||||
render: (_: any, row: any, actions: any) => {
|
||||
return (
|
||||
<Space>
|
||||
<a onClick={() => actions.setRecord(row, 'sync')}>Sync</a>
|
||||
{row.last_updated && <Link to={`${row.id}`} state={row}>View</Link>}
|
||||
<a onClick={() => actions.setRecord(row, 'edit')}>Edit</a>
|
||||
<Popconfirm
|
||||
title="Are you sure to delete this path?"
|
@ -7,17 +7,17 @@ import useChatModel from '@/hooks/useChatModel';
|
||||
import useColumns from '@/hooks/useColumns';
|
||||
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||
import { CHAT_MODEL_SYNC_JSON, chatRoot, writeJSON, readJSON, genCmd } from '@/utils';
|
||||
import { pathColumns, getPath } from './config';
|
||||
import { syncColumns, getPath } from './config';
|
||||
import SyncForm from './Form';
|
||||
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 SyncCustom() {
|
||||
const [isVisible, setVisible] = useState(false);
|
||||
const { modelData, modelSet } = useChatModel('sync_url', CHAT_MODEL_SYNC_JSON);
|
||||
const { opData, opInit, opAdd, opRemove, opReplace, opSafeKey } = useData([]);
|
||||
const { columns, ...opInfo } = useColumns(pathColumns());
|
||||
const { columns, ...opInfo } = useColumns(syncColumns());
|
||||
const formRef = useRef<any>(null);
|
||||
|
||||
const hide = () => {
|
||||
@ -36,8 +36,6 @@ export default function SyncMore() {
|
||||
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();
|
||||
});
|
||||
@ -103,10 +101,7 @@ export default function SyncMore() {
|
||||
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();
|
||||
})
|
||||
};
|
2
src/view/model/SyncPrompts/config.tsx
vendored
2
src/view/model/SyncPrompts/config.tsx
vendored
@ -2,7 +2,7 @@ import { Switch, Tag, Tooltip } from 'antd';
|
||||
|
||||
import { genCmd } from '@/utils';
|
||||
|
||||
export const modelColumns = () => [
|
||||
export const syncColumns = () => [
|
||||
{
|
||||
title: '/{cmd}',
|
||||
dataIndex: 'cmd',
|
||||
|
6
src/view/model/SyncPrompts/index.tsx
vendored
6
src/view/model/SyncPrompts/index.tsx
vendored
@ -9,17 +9,17 @@ import useData from '@/hooks/useData';
|
||||
import useChatModel from '@/hooks/useChatModel';
|
||||
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL, genCmd } from '@/utils';
|
||||
import { modelColumns } from './config';
|
||||
import { syncColumns } from './config';
|
||||
import './index.scss';
|
||||
|
||||
const promptsURL = 'https://github.com/f/awesome-chatgpt-prompts/blob/main/prompts.csv';
|
||||
|
||||
export default function LanguageModel() {
|
||||
export default function SyncPrompts() {
|
||||
const { rowSelection, selectedRowIDs } = useTable();
|
||||
const [lastUpdated, setLastUpdated] = useState();
|
||||
const { modelJson, modelSet } = useChatModel('sys_sync_prompts');
|
||||
const { opData, opInit, opReplace, opReplaceItems, opSafeKey } = useData([]);
|
||||
const { columns, ...opInfo } = useColumns(modelColumns());
|
||||
const { columns, ...opInfo } = useColumns(syncColumns());
|
||||
|
||||
const selectedItems = rowSelection.selectedRowKeys || [];
|
||||
|
||||
|
47
src/view/model/SyncRecord/config.tsx
vendored
Normal file
47
src/view/model/SyncRecord/config.tsx
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
import { Switch, Tag, Tooltip } from 'antd';
|
||||
|
||||
import { genCmd } from '@/utils';
|
||||
|
||||
export const syncColumns = () => [
|
||||
{
|
||||
title: '/{cmd}',
|
||||
dataIndex: 'cmd',
|
||||
fixed: 'left',
|
||||
// width: 120,
|
||||
key: 'cmd',
|
||||
render: (_: string, row: Record<string, string>) => (
|
||||
<Tag color="#2a2a2a">/{genCmd(row.act)}</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Act',
|
||||
dataIndex: 'act',
|
||||
key: 'act',
|
||||
// width: 200,
|
||||
},
|
||||
{
|
||||
title: 'Tags',
|
||||
dataIndex: 'tags',
|
||||
key: 'tags',
|
||||
// width: 150,
|
||||
render: () => <Tag>chatgpt-prompts</Tag>,
|
||||
},
|
||||
{
|
||||
title: 'Enable',
|
||||
dataIndex: 'enable',
|
||||
key: 'enable',
|
||||
// width: 80,
|
||||
render: (v: boolean = false, row: Record<string, any>, action: Record<string, any>) => (
|
||||
<Switch checked={v} onChange={(v) => action.setRecord({ ...row, enable: v }, 'enable')} />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Prompt',
|
||||
dataIndex: 'prompt',
|
||||
key: 'prompt',
|
||||
// width: 300,
|
||||
render: (v: string) => (
|
||||
<Tooltip overlayInnerStyle={{ width: 350 }} title={v}><span className="chat-prompts-val">{v}</span></Tooltip>
|
||||
),
|
||||
},
|
||||
];
|
42
src/view/model/SyncRecord/index.scss
vendored
Normal file
42
src/view/model/SyncRecord/index.scss
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
// .chat-prompts-tags {
|
||||
// .ant-tag {
|
||||
// margin: 2px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .add-btn {
|
||||
// margin-bottom: 5px;
|
||||
// }
|
||||
|
||||
// .chat-table-tip, .chat-table-btns {
|
||||
// display: flex;
|
||||
// justify-content: space-between;
|
||||
// }
|
||||
|
||||
// .chat-table-btns {
|
||||
// margin-bottom: 5px;
|
||||
|
||||
// .num {
|
||||
// margin-left: 10px;
|
||||
// }
|
||||
// }
|
||||
|
||||
.chat-sync-path {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #888;
|
||||
margin-bottom: 5px;
|
||||
line-height: 16px;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
// background-color: #d8d8d8;
|
||||
color: #4096ff;
|
||||
padding: 0 8px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
86
src/view/model/SyncRecord/index.tsx
vendored
Normal file
86
src/view/model/SyncRecord/index.tsx
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { Table, Button } from 'antd';
|
||||
import { shell, path } from '@tauri-apps/api';
|
||||
|
||||
import useColumns from '@/hooks/useColumns';
|
||||
import useData from '@/hooks/useData';
|
||||
import { useCacheModel } from '@/hooks/useChatModel';
|
||||
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||
import { fmtDate, chatRoot } from '@/utils';
|
||||
import { getPath } from '@/view/model/SyncCustom/config';
|
||||
import { syncColumns } from './config';
|
||||
import useInit from '@/hooks/useInit';
|
||||
import './index.scss';
|
||||
|
||||
export default function SyncRecord() {
|
||||
const location = useLocation();
|
||||
const [filePath, setFilePath] = useState('');
|
||||
const [jsonPath, setJsonPath] = useState('');
|
||||
const state = location?.state;
|
||||
|
||||
const { rowSelection, selectedRowIDs } = useTable();
|
||||
const { modelJson, modelSet } = useCacheModel(jsonPath);
|
||||
const { opData, opInit, opReplace, opReplaceItems, opSafeKey } = useData([]);
|
||||
const { columns, ...opInfo } = useColumns(syncColumns());
|
||||
|
||||
const selectedItems = rowSelection.selectedRowKeys || [];
|
||||
|
||||
useInit(async () => {
|
||||
setFilePath(await getPath(state));
|
||||
setJsonPath(await path.join(await chatRoot(), 'cache_sync', `${state?.id}.json`));
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (modelJson.length <= 0) return;
|
||||
opInit(modelJson);
|
||||
}, [modelJson.length]);
|
||||
|
||||
useEffect(() => {
|
||||
if (opInfo.opType === 'enable') {
|
||||
const data = opReplace(opInfo?.opRecord?.[opSafeKey], opInfo?.opRecord);
|
||||
modelSet(data);
|
||||
}
|
||||
}, [opInfo.opTime]);
|
||||
|
||||
const handleEnable = (isEnable: boolean) => {
|
||||
const data = opReplaceItems(selectedRowIDs, { enable: isEnable })
|
||||
modelSet(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="chat-table-btns">
|
||||
<div>
|
||||
<Button shape="round" icon={<ArrowLeftOutlined />} onClick={() => history.back()} />
|
||||
</div>
|
||||
<div>
|
||||
{selectedItems.length > 0 && (
|
||||
<>
|
||||
<Button type="primary" onClick={() => handleEnable(true)}>Enable</Button>
|
||||
<Button onClick={() => handleEnable(false)}>Disable</Button>
|
||||
<span className="num">Selected {selectedItems.length} items</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-table-tip">
|
||||
<div className="chat-sync-path">
|
||||
<div>PATH: <a onClick={() => shell.open(filePath)} target="_blank" title={filePath}>{filePath}</a></div>
|
||||
<div>CACHE: <a onClick={() => shell.open(jsonPath)} target="_blank" title={jsonPath}>{jsonPath}</a></div>
|
||||
</div>
|
||||
{state?.last_updated && <span style={{ marginLeft: 10, color: '#888', fontSize: 12 }}>Last updated on {fmtDate(state?.last_updated)}</span>}
|
||||
</div>
|
||||
<Table
|
||||
key="prompt"
|
||||
rowKey="act"
|
||||
columns={columns}
|
||||
scroll={{ x: 'auto' }}
|
||||
dataSource={opData}
|
||||
rowSelection={rowSelection}
|
||||
pagination={TABLE_PAGINATION}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user