mirror of
https://github.com/FranP-code/ChatGPT.git
synced 2025-10-13 00:13:25 +00:00
chore: sync
This commit is contained in:
@@ -13,8 +13,10 @@
|
|||||||
"allowlist": {
|
"allowlist": {
|
||||||
"all": true,
|
"all": true,
|
||||||
"http": {
|
"http": {
|
||||||
|
"all": true,
|
||||||
"scope": [
|
"scope": [
|
||||||
"https://raw.githubusercontent.com/*"
|
"https://**",
|
||||||
|
"http://**"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"fs": {
|
"fs": {
|
||||||
|
|||||||
19
src/hooks/useData.ts
vendored
19
src/hooks/useData.ts
vendored
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
const safeKey = Symbol('chat-id');
|
export const safeKey = Symbol('chat-id');
|
||||||
|
|
||||||
export default function useData(oData: any[]) {
|
export default function useData(oData: any[]) {
|
||||||
const [opData, setData] = useState<any[]>([]);
|
const [opData, setData] = useState<any[]>([]);
|
||||||
@@ -35,5 +35,20 @@ export default function useData(oData: any[]) {
|
|||||||
return nData;
|
return nData;
|
||||||
};
|
};
|
||||||
|
|
||||||
return { opSafeKey: safeKey, opInit, opReplace, opAdd, opRemove, opData };
|
const opReplaceItems = (ids: string[], data: any) => {
|
||||||
|
const nData = [...opData];
|
||||||
|
let count = 0;
|
||||||
|
for (let i = 0; i < nData.length; i++) {
|
||||||
|
const v = nData[i];
|
||||||
|
if (ids.includes(v[safeKey])) {
|
||||||
|
count++;
|
||||||
|
nData[i] = { ...v, ...data };
|
||||||
|
}
|
||||||
|
if (count === ids.length) break;
|
||||||
|
}
|
||||||
|
setData(nData);
|
||||||
|
return nData;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { opSafeKey: safeKey, opInit, opReplace, opAdd, opRemove, opData, opReplaceItems };
|
||||||
}
|
}
|
||||||
37
src/hooks/useTable.tsx
vendored
Normal file
37
src/hooks/useTable.tsx
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Table } from 'antd';
|
||||||
|
import type { TableRowSelection } from 'antd/es/table/interface';
|
||||||
|
|
||||||
|
import { safeKey } from '@/hooks/useData';
|
||||||
|
|
||||||
|
export default function useTableRowSelection() {
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||||
|
const [selectedRowIDs, setSelectedRowIDs] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: Record<string|symbol, any>) => {
|
||||||
|
const keys = selectedRows.map((i: any) => i[safeKey]);
|
||||||
|
setSelectedRowIDs(keys);
|
||||||
|
setSelectedRowKeys(newSelectedRowKeys);
|
||||||
|
};
|
||||||
|
|
||||||
|
const rowSelection: TableRowSelection<Record<string, any>> = {
|
||||||
|
selectedRowKeys,
|
||||||
|
onChange: onSelectChange,
|
||||||
|
selections: [
|
||||||
|
Table.SELECTION_ALL,
|
||||||
|
Table.SELECTION_INVERT,
|
||||||
|
Table.SELECTION_NONE,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
return { rowSelection, selectedRowIDs };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TABLE_PAGINATION = {
|
||||||
|
hideOnSinglePage: true,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
defaultPageSize: 5,
|
||||||
|
pageSizeOptions: [5, 10, 15, 20],
|
||||||
|
showTotal: (total: number) => <span>Total {total} items</span>,
|
||||||
|
};
|
||||||
5
src/main.scss
vendored
5
src/main.scss
vendored
@@ -17,4 +17,9 @@
|
|||||||
html, body {
|
html, body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-selection-column {
|
||||||
|
width: 50px !important;
|
||||||
|
min-width: 50px !important;
|
||||||
}
|
}
|
||||||
10
src/routes.tsx
vendored
10
src/routes.tsx
vendored
@@ -3,6 +3,7 @@ import {
|
|||||||
DesktopOutlined,
|
DesktopOutlined,
|
||||||
BulbOutlined,
|
BulbOutlined,
|
||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
|
FileSyncOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import type { MenuProps } from 'antd';
|
import type { MenuProps } from 'antd';
|
||||||
@@ -10,6 +11,7 @@ import type { MenuProps } from 'antd';
|
|||||||
import General from '@view/General';
|
import General from '@view/General';
|
||||||
import LanguageModel from '@/view/LanguageModel';
|
import LanguageModel from '@/view/LanguageModel';
|
||||||
import SyncPrompts from '@/view/SyncPrompts';
|
import SyncPrompts from '@/view/SyncPrompts';
|
||||||
|
import SyncMore from '@/view/SyncMore';
|
||||||
|
|
||||||
export type ChatRouteMetaObject = {
|
export type ChatRouteMetaObject = {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -55,6 +57,14 @@ export const routes: Array<ChatRouteObject> = [
|
|||||||
icon: <SyncOutlined />,
|
icon: <SyncOutlined />,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'sync-more',
|
||||||
|
element: <SyncMore />,
|
||||||
|
meta: {
|
||||||
|
label: 'Sync More',
|
||||||
|
icon: <FileSyncOutlined />,
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
10
src/view/LanguageModel/index.tsx
vendored
10
src/view/LanguageModel/index.tsx
vendored
@@ -6,6 +6,7 @@ import useInit from '@/hooks/useInit';
|
|||||||
import useData from '@/hooks/useData';
|
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 { chatModelPath } from '@/utils';
|
import { chatModelPath } from '@/utils';
|
||||||
import { modelColumns } from './config';
|
import { modelColumns } from './config';
|
||||||
import LanguageModelForm from './Form';
|
import LanguageModelForm from './Form';
|
||||||
@@ -87,14 +88,7 @@ export default function LanguageModel() {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
scroll={{ x: 'auto' }}
|
scroll={{ x: 'auto' }}
|
||||||
dataSource={opData}
|
dataSource={opData}
|
||||||
pagination={{
|
pagination={TABLE_PAGINATION}
|
||||||
hideOnSinglePage: true,
|
|
||||||
showSizeChanger: true,
|
|
||||||
showQuickJumper: true,
|
|
||||||
defaultPageSize: 5,
|
|
||||||
pageSizeOptions: [5, 10, 15, 20],
|
|
||||||
showTotal: (total) => <span>Total {total} items</span>,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Modal
|
<Modal
|
||||||
open={isVisible}
|
open={isVisible}
|
||||||
|
|||||||
22
src/view/SyncMore/config.tsx
vendored
Normal file
22
src/view/SyncMore/config.tsx
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// import { Switch, Tag, Tooltip } from 'antd';
|
||||||
|
|
||||||
|
export const genCmd = (act: string) => act.replace(/\s+|\/+/g, '_').replace(/[^\d\w]/g, '').toLocaleLowerCase();
|
||||||
|
|
||||||
|
export const recordColumns = () => [
|
||||||
|
{
|
||||||
|
title: 'URL',
|
||||||
|
dataIndex: 'url',
|
||||||
|
// fixed: 'left',
|
||||||
|
// width: 120,
|
||||||
|
key: 'url',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'File Type',
|
||||||
|
dataIndex: 'file_type',
|
||||||
|
key: 'file_type',
|
||||||
|
// width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Action',
|
||||||
|
}
|
||||||
|
];
|
||||||
28
src/view/SyncMore/index.scss
vendored
Normal file
28
src/view/SyncMore/index.scss
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
.chat-prompts-tags {
|
||||||
|
.ant-tag {
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-model-path {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #888;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/view/SyncMore/index.tsx
vendored
Normal file
20
src/view/SyncMore/index.tsx
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { Table, Button } from 'antd';
|
||||||
|
|
||||||
|
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
export default function SyncMore() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Button className="add-btn" type="primary">Add URL</Button>
|
||||||
|
<Table
|
||||||
|
key="id"
|
||||||
|
rowKey="act"
|
||||||
|
columns={[]}
|
||||||
|
scroll={{ x: 'auto' }}
|
||||||
|
dataSource={[]}
|
||||||
|
pagination={TABLE_PAGINATION}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
13
src/view/SyncPrompts/index.scss
vendored
13
src/view/SyncPrompts/index.scss
vendored
@@ -8,6 +8,19 @@
|
|||||||
margin-bottom: 5px;
|
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-model-path {
|
.chat-model-path {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|||||||
41
src/view/SyncPrompts/index.tsx
vendored
41
src/view/SyncPrompts/index.tsx
vendored
@@ -7,6 +7,7 @@ import { writeTextFile } from '@tauri-apps/api/fs';
|
|||||||
import useColumns from '@/hooks/useColumns';
|
import useColumns from '@/hooks/useColumns';
|
||||||
import useData from '@/hooks/useData';
|
import useData from '@/hooks/useData';
|
||||||
import useChatModel from '@/hooks/useChatModel';
|
import useChatModel from '@/hooks/useChatModel';
|
||||||
|
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||||
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL } from '@/utils';
|
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL } from '@/utils';
|
||||||
import { modelColumns, genCmd } from './config';
|
import { modelColumns, genCmd } from './config';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
@@ -14,15 +15,19 @@ import './index.scss';
|
|||||||
const promptsURL = 'https://github.com/f/awesome-chatgpt-prompts/blob/main/prompts.csv';
|
const promptsURL = 'https://github.com/f/awesome-chatgpt-prompts/blob/main/prompts.csv';
|
||||||
|
|
||||||
export default function LanguageModel() {
|
export default function LanguageModel() {
|
||||||
|
const { rowSelection, selectedRowIDs } = useTable();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [lastUpdated, setLastUpdated] = useState();
|
const [lastUpdated, setLastUpdated] = useState();
|
||||||
const { modelJson, modelSet } = useChatModel('sys_sync_prompts');
|
const { modelJson, modelSet } = useChatModel('sys_sync_prompts');
|
||||||
const { opData, opInit, opReplace, opSafeKey } = useData([]);
|
const { opData, opInit, opReplace, opReplaceItems, opSafeKey } = useData([]);
|
||||||
const { columns, ...opInfo } = useColumns(modelColumns());
|
const { columns, ...opInfo } = useColumns(modelColumns());
|
||||||
|
|
||||||
|
const selectedItems = rowSelection.selectedRowKeys || [];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!modelJson?.sys_sync_prompts) return;
|
if (!modelJson?.sys_sync_prompts) return;
|
||||||
opInit(modelJson?.sys_sync_prompts);
|
opInit(modelJson?.sys_sync_prompts);
|
||||||
|
if (lastUpdated) return;
|
||||||
(async () => {
|
(async () => {
|
||||||
const fileData: Record<string, any> = await invoke('metadata', { path: await chatPromptsPath() });
|
const fileData: Record<string, any> = await invoke('metadata', { path: await chatPromptsPath() });
|
||||||
setLastUpdated(fileData.accessedAtMs);
|
setLastUpdated(fileData.accessedAtMs);
|
||||||
@@ -57,25 +62,37 @@ export default function LanguageModel() {
|
|||||||
}
|
}
|
||||||
}, [opInfo.opTime]);
|
}, [opInfo.opTime]);
|
||||||
|
|
||||||
|
const handleEnable = (isEnable: boolean) => {
|
||||||
|
const data = opReplaceItems(selectedRowIDs, { enable: isEnable })
|
||||||
|
modelSet(data);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button type="primary" loading={loading} onClick={handleSync}>Sync</Button>
|
<div className="chat-table-btns">
|
||||||
{lastUpdated && <span style={{ marginLeft: 10, color: '#999' }}>Last updated on {fmtDate(lastUpdated)}</span>}
|
<div>
|
||||||
<div className="chat-model-path">URL: <a href={promptsURL} target="_blank">{promptsURL}</a></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>
|
||||||
|
<Button type="primary" loading={loading} onClick={handleSync}>Sync</Button>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
{lastUpdated && <span style={{ marginLeft: 10, color: '#999' }}>Last updated on {fmtDate(lastUpdated)}</span>}
|
||||||
|
</div>
|
||||||
<Table
|
<Table
|
||||||
key={lastUpdated}
|
key={lastUpdated}
|
||||||
rowKey="act"
|
rowKey="act"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
scroll={{ x: 'auto' }}
|
scroll={{ x: 'auto' }}
|
||||||
dataSource={opData}
|
dataSource={opData}
|
||||||
pagination={{
|
rowSelection={rowSelection}
|
||||||
hideOnSinglePage: true,
|
pagination={TABLE_PAGINATION}
|
||||||
showSizeChanger: true,
|
|
||||||
showQuickJumper: true,
|
|
||||||
defaultPageSize: 5,
|
|
||||||
pageSizeOptions: [5, 10, 15, 20],
|
|
||||||
showTotal: (total) => <span>Total {total} items</span>,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user