chore: sync

This commit is contained in:
lencx
2022-12-21 14:00:42 +08:00
parent 878bb6c265
commit d513a50e27
11 changed files with 186 additions and 23 deletions

View File

@@ -13,8 +13,10 @@
"allowlist": {
"all": true,
"http": {
"all": true,
"scope": [
"https://raw.githubusercontent.com/*"
"https://**",
"http://**"
]
},
"fs": {

19
src/hooks/useData.ts vendored
View File

@@ -1,7 +1,7 @@
import { useState, useEffect } from 'react';
import { v4 } from 'uuid';
const safeKey = Symbol('chat-id');
export const safeKey = Symbol('chat-id');
export default function useData(oData: any[]) {
const [opData, setData] = useState<any[]>([]);
@@ -35,5 +35,20 @@ export default function useData(oData: any[]) {
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
View 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
View File

@@ -17,4 +17,9 @@
html, body {
padding: 0;
margin: 0;
}
.ant-table-selection-column {
width: 50px !important;
min-width: 50px !important;
}

10
src/routes.tsx vendored
View File

@@ -3,6 +3,7 @@ import {
DesktopOutlined,
BulbOutlined,
SyncOutlined,
FileSyncOutlined,
UserOutlined,
} from '@ant-design/icons';
import type { MenuProps } from 'antd';
@@ -10,6 +11,7 @@ import type { MenuProps } from 'antd';
import General from '@view/General';
import LanguageModel from '@/view/LanguageModel';
import SyncPrompts from '@/view/SyncPrompts';
import SyncMore from '@/view/SyncMore';
export type ChatRouteMetaObject = {
label: string;
@@ -55,6 +57,14 @@ export const routes: Array<ChatRouteObject> = [
icon: <SyncOutlined />,
},
},
{
path: 'sync-more',
element: <SyncMore />,
meta: {
label: 'Sync More',
icon: <FileSyncOutlined />,
},
},
]
},
];

View File

@@ -6,6 +6,7 @@ import useInit from '@/hooks/useInit';
import useData from '@/hooks/useData';
import useChatModel from '@/hooks/useChatModel';
import useColumns from '@/hooks/useColumns';
import { TABLE_PAGINATION } from '@/hooks/useTable';
import { chatModelPath } from '@/utils';
import { modelColumns } from './config';
import LanguageModelForm from './Form';
@@ -87,14 +88,7 @@ export default function LanguageModel() {
columns={columns}
scroll={{ x: 'auto' }}
dataSource={opData}
pagination={{
hideOnSinglePage: true,
showSizeChanger: true,
showQuickJumper: true,
defaultPageSize: 5,
pageSizeOptions: [5, 10, 15, 20],
showTotal: (total) => <span>Total {total} items</span>,
}}
pagination={TABLE_PAGINATION}
/>
<Modal
open={isVisible}

22
src/view/SyncMore/config.tsx vendored Normal file
View 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
View 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
View 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>
)
}

View File

@@ -8,6 +8,19 @@
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 {
font-size: 12px;
font-weight: bold;

View File

@@ -7,6 +7,7 @@ import { writeTextFile } from '@tauri-apps/api/fs';
import useColumns from '@/hooks/useColumns';
import useData from '@/hooks/useData';
import useChatModel from '@/hooks/useChatModel';
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL } from '@/utils';
import { modelColumns, genCmd } from './config';
import './index.scss';
@@ -14,15 +15,19 @@ import './index.scss';
const promptsURL = 'https://github.com/f/awesome-chatgpt-prompts/blob/main/prompts.csv';
export default function LanguageModel() {
const { rowSelection, selectedRowIDs } = useTable();
const [loading, setLoading] = useState(false);
const [lastUpdated, setLastUpdated] = useState();
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 selectedItems = rowSelection.selectedRowKeys || [];
useEffect(() => {
if (!modelJson?.sys_sync_prompts) return;
opInit(modelJson?.sys_sync_prompts);
if (lastUpdated) return;
(async () => {
const fileData: Record<string, any> = await invoke('metadata', { path: await chatPromptsPath() });
setLastUpdated(fileData.accessedAtMs);
@@ -57,25 +62,37 @@ export default function LanguageModel() {
}
}, [opInfo.opTime]);
const handleEnable = (isEnable: boolean) => {
const data = opReplaceItems(selectedRowIDs, { enable: isEnable })
modelSet(data);
};
return (
<div>
<Button type="primary" loading={loading} onClick={handleSync}>Sync</Button>
{lastUpdated && <span style={{ marginLeft: 10, color: '#999' }}>Last updated on {fmtDate(lastUpdated)}</span>}
<div className="chat-model-path">URL: <a href={promptsURL} target="_blank">{promptsURL}</a></div>
<div className="chat-table-btns">
<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
key={lastUpdated}
rowKey="act"
columns={columns}
scroll={{ x: 'auto' }}
dataSource={opData}
pagination={{
hideOnSinglePage: true,
showSizeChanger: true,
showQuickJumper: true,
defaultPageSize: 5,
pageSizeOptions: [5, 10, 15, 20],
showTotal: (total) => <span>Total {total} items</span>,
}}
rowSelection={rowSelection}
pagination={TABLE_PAGINATION}
/>
</div>
)