From 9bd6dedd908647a56124bed8f47ae2a20a78b4e7 Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 28 Aug 2024 14:45:11 +0800 Subject: [PATCH] chore: add english comment --- package.json | 2 + pnpm-lock.yaml | 50 ++++++++++- src/app.tsx | 2 +- src/components/markdown-viewer/index.tsx | 28 +++++++ src/components/short-cuts/index.tsx | 84 ++++--------------- src/components/short-cuts/keymap.ts | 60 +++++++++++++ src/config/hotkeys.ts | 67 ++++++++++++--- src/global.tsx | 2 +- src/layouts/Layout.css | 19 ++++- src/layouts/Logo.tsx | 2 - src/layouts/index.tsx | 9 +- src/layouts/runtime.tsx | 3 - src/layouts/runtimeConfig.d.ts | 2 - src/layouts/types.d.ts | 9 +- src/locales/en-US.ts | 4 +- src/locales/en-US/shortcuts.ts | 13 +++ src/locales/zh-CN.ts | 4 +- src/locales/zh-CN/shortcuts.ts | 14 ++++ src/pages/access/index.tsx | 4 +- src/pages/api-keys/index.tsx | 12 +++ .../llmodels/components/search-input.tsx | 2 - src/pages/llmodels/components/separator.tsx | 1 - src/pages/llmodels/style/separator.less | 12 +-- .../playground/components/ground-left.tsx | 24 ++++++ src/pages/playground/index.tsx | 14 ++++ src/pages/resources/components/workers.tsx | 6 ++ src/pages/users/index.tsx | 12 +++ src/utils/index.ts | 37 ++++---- 28 files changed, 353 insertions(+), 145 deletions(-) create mode 100644 src/components/markdown-viewer/index.tsx create mode 100644 src/components/short-cuts/keymap.ts create mode 100644 src/locales/en-US/shortcuts.ts create mode 100644 src/locales/zh-CN/shortcuts.ts diff --git a/package.json b/package.json index c84612b5..e24004ff 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "jotai": "^2.8.4", "localforage": "^1.10.0", "lodash": "^4.17.21", + "marked": "^14.1.0", "numeral": "^2.0.6", "query-string": "^9.0.0", "react": "^18.2.0", @@ -42,6 +43,7 @@ "umi-presets-pro": "^2.0.3" }, "devDependencies": { + "@types/marked": "^6.0.0", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.0", "@umijs/case-sensitive-paths-webpack-plugin": "^1.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3da3f9f2..67c2b89c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -71,6 +71,9 @@ dependencies: lodash: specifier: ^4.17.21 version: 4.17.21 + marked: + specifier: ^14.1.0 + version: 14.1.0 numeral: specifier: ^2.0.6 version: 2.0.6 @@ -94,6 +97,9 @@ dependencies: version: 2.0.3(@babel/core@7.24.9)(@types/react-dom@18.3.0)(@types/react@18.3.1)(antd@5.18.3)(dva@2.5.0-beta.2)(rc-field-form@1.44.0)(react-dom@18.2.0)(react@18.2.0)(umi@4.3.6) devDependencies: + '@types/marked': + specifier: ^6.0.0 + version: 6.0.0 '@types/react': specifier: ^18.3.1 version: 18.3.1 @@ -4459,7 +4465,7 @@ packages: dependencies: '@babel/core': 7.24.5 postcss: 7.0.39 - postcss-syntax: 0.36.2(postcss@8.4.38) + postcss-syntax: 0.36.2(postcss@7.0.39) transitivePeerDependencies: - supports-color dev: false @@ -4500,7 +4506,7 @@ packages: postcss-syntax: '>=0.36.2' dependencies: postcss: 7.0.39 - postcss-syntax: 0.36.2(postcss@8.4.38) + postcss-syntax: 0.36.2(postcss@7.0.39) remark: 13.0.0 unist-util-find-all-after: 3.0.2 transitivePeerDependencies: @@ -4833,6 +4839,13 @@ packages: resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==} dev: false + /@types/marked@6.0.0: + resolution: {integrity: sha512-jmjpa4BwUsmhxcfsgUit/7A9KbrC48Q0q8KvnY107ogcjGgTFDlIL3RpihNpx2Mu1hM4mdFQjoVc4O6JoGKHsA==, tarball: https://registry.npmjs.org/@types/marked/-/marked-6.0.0.tgz} + deprecated: This is a stub types definition. marked provides its own type definitions, so you do not need this installed. + dependencies: + marked: 14.1.0 + dev: true + /@types/mdast@3.0.15: resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==, tarball: https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz} dependencies: @@ -11806,6 +11819,11 @@ packages: engines: {node: '>=8'} dev: false + /marked@14.1.0: + resolution: {integrity: sha512-P93GikH/Pde0hM5TAXEd8I4JAYi8IB03n8qzW8Bh1BIEFpEyBoYxi/XWZA53LSpTeLBiMQOoSMj0u5E/tiVYTA==, tarball: https://registry.npmjs.org/marked/-/marked-14.1.0.tgz} + engines: {node: '>= 18'} + hasBin: true + /mathml-tag-names@2.1.3: resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} dev: false @@ -13125,7 +13143,7 @@ packages: dependencies: htmlparser2: 3.10.1 postcss: 7.0.39 - postcss-syntax: 0.36.2(postcss@8.4.38) + postcss-syntax: 0.36.2(postcss@7.0.39) dev: false /postcss-image-set-function@4.0.7(postcss@8.4.38): @@ -13599,6 +13617,30 @@ packages: lodash: 4.17.21 postcss: 8.4.38 + /postcss-syntax@0.36.2(postcss@7.0.39): + resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==} + peerDependencies: + postcss: '>=5.0.0' + postcss-html: '*' + postcss-jsx: '*' + postcss-less: '*' + postcss-markdown: '*' + postcss-scss: '*' + peerDependenciesMeta: + postcss-html: + optional: true + postcss-jsx: + optional: true + postcss-less: + optional: true + postcss-markdown: + optional: true + postcss-scss: + optional: true + dependencies: + postcss: 7.0.39 + dev: false + /postcss-syntax@0.36.2(postcss@8.4.38): resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==} peerDependencies: @@ -16773,7 +16815,7 @@ packages: postcss-sass: 0.4.4 postcss-scss: 2.1.1 postcss-selector-parser: 6.0.16 - postcss-syntax: 0.36.2(postcss@8.4.38) + postcss-syntax: 0.36.2(postcss@7.0.39) postcss-value-parser: 4.2.0 resolve-from: 5.0.0 slash: 3.0.0 diff --git a/src/app.tsx b/src/app.tsx index 52f81488..d2df5432 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -9,7 +9,7 @@ import { RequestConfig, history } from '@umijs/max'; const loginPath = '/login'; -// 运行时配置 +// runtime configuration export async function getInitialState(): Promise<{ fetchUserInfo: () => Promise; currentUser?: Global.UserInfo; diff --git a/src/components/markdown-viewer/index.tsx b/src/components/markdown-viewer/index.tsx new file mode 100644 index 00000000..45e31fc9 --- /dev/null +++ b/src/components/markdown-viewer/index.tsx @@ -0,0 +1,28 @@ +import { marked, Tokens } from 'marked'; +import React from 'react'; + +interface MarkdownViewerProps { + content: string; + height?: string; +} + +const MarkdownViewer: React.FC = ({ + content, + height = 'auto' +}) => { + const renderer = new marked.Renderer(); + + renderer.link = ({ href, title, text }: Tokens.Link) => { + return `${text}`; + }; + + return ( +
+
+
+ ); +}; + +export default React.memo(MarkdownViewer); diff --git a/src/components/short-cuts/index.tsx b/src/components/short-cuts/index.tsx index 4a2c5a03..85f4ce1a 100644 --- a/src/components/short-cuts/index.tsx +++ b/src/components/short-cuts/index.tsx @@ -1,75 +1,27 @@ -import { platformCall } from '@/utils'; import { SearchOutlined } from '@ant-design/icons'; import { Input, Table, Tag } from 'antd'; import _ from 'lodash'; import React from 'react'; -import IconFont from '../icon-font'; import './index.less'; - -const dataSource = [ - { - scope: 'playground', - command: 'New Message', - keybindingWin: 'Ctrl + N', - keybindingMac: 'N' - }, - { - scope: 'models', - span: { - rowSpan: 3, - colSpan: 1 - }, - command: 'deploy model from Hugging Face', - keybindingWin: 'Ctrl + 1', - keybindingMac: '1' - }, - { - scope: 'models', - command: 'deploy model from Ollama Library', - keybindingWin: 'Ctrl + 2', - keybindingMac: '2', - span: { - rowSpan: 0, - colSpan: 0 - } - }, - { - scope: 'models', - command: '从 Hugging Face 搜索模型', - keybindingWin: 'Ctrl + K', - keybindingMac: 'K', - span: { - rowSpan: 0, - colSpan: 0 - } - } -]; +import KeyMapConfig from './keymap'; const ShortCuts: React.FC<{ intl: any }> = ({ intl }) => { - const platform = platformCall(); - - const [dataList, setDataList] = React.useState(dataSource); + const [dataList, setDataList] = React.useState(KeyMapConfig); const columns = [ { title: 'Scope', dataIndex: 'scope', key: 'scope', - width: 120, - onCell: (row: any, index: number) => { - if (row.span) { - return row.span; - } - return { - rowSpan: 1, - colSpan: 1 - }; - } + width: 160 }, { - title: 'Command', + title: 'Action', dataIndex: 'command', - key: 'command' + key: 'command', + render: (text: string, row: any) => { + return {intl.formatMessage({ id: text })}; + } }, { title: 'Keybinding', @@ -77,21 +29,14 @@ const ShortCuts: React.FC<{ intl: any }> = ({ intl }) => { key: 'keybinding', width: 180, render: (text: string, row: any) => { - if (platform.isMac) { - return ( - - + {row.keybindingMac} - - ); - } - return {row.keybindingWin}; + return {row.keybinding}; } } ]; const handleInputChange = (e: any) => { const value = e.target.value; - const list = _.filter(dataSource, (item: any) => { + const list = _.filter(KeyMapConfig, (item: any) => { return ( item.command.toLowerCase().includes(value.toLowerCase()) || item.scope.toLowerCase().includes(value.toLowerCase()) @@ -103,10 +48,12 @@ const ShortCuts: React.FC<{ intl: any }> = ({ intl }) => { const debounceHandleInputChange = _.debounce(handleInputChange, 300); return (
-

GPUStack 快捷方式

+

+ {intl.formatMessage({ id: 'shortcuts.title' })} +

= ({ intl }) => { columns={columns} dataSource={dataList} pagination={false} + scroll={{ y: 450 }} >
); @@ -138,7 +86,7 @@ export const modalConfig = { style: { top: '10%' }, - width: 660 + width: 700 }; export default React.memo(ShortCuts); diff --git a/src/components/short-cuts/keymap.ts b/src/components/short-cuts/keymap.ts new file mode 100644 index 00000000..1415b980 --- /dev/null +++ b/src/components/short-cuts/keymap.ts @@ -0,0 +1,60 @@ +import { KeyMap } from '@/config/hotkeys'; +export default [ + { + scope: 'playground', + command: 'shortcuts.playground.newmessage', + keybinding: KeyMap.CREATE.iconKeybinding + }, + { + scope: 'playground', + command: 'shortcuts.playground.clearmessage', + keybinding: KeyMap.CLEAR.iconKeybinding + }, + { + scope: 'playground', + command: 'shortcuts.playground.toggleparams', + keybinding: KeyMap.RIGHT.iconKeybinding + }, + { + scope: 'models', + // span: { + // rowSpan: 3, + // colSpan: 1 + // }, + command: 'shortcuts.models.newmodelHF', + keybinding: KeyMap.NEW1.iconKeybinding + }, + { + scope: 'models', + command: 'shortcuts.models.newmodelLM', + keybinding: KeyMap.NEW2.iconKeybinding + // span: { + // rowSpan: 0, + // colSpan: 0 + // } + }, + { + scope: 'models', + command: 'shortcuts.models.search', + keybinding: KeyMap.SEARCH.iconKeybinding + // span: { + // rowSpan: 0, + // colSpan: 0 + // } + }, + { + scope: 'resources', + command: 'shortcuts.resources.addworker', + keybinding: KeyMap.CREATE.iconKeybinding + }, + { + scope: 'API keys', + command: 'shortcuts.apikeys.new', + keybinding: KeyMap.CREATE.iconKeybinding + }, + { + scope: 'users', + command: 'shortcuts.users.new', + keybinding: KeyMap.CREATE.iconKeybinding + } +]; diff --git a/src/config/hotkeys.ts b/src/config/hotkeys.ts index 5c6a6714..09347d81 100644 --- a/src/config/hotkeys.ts +++ b/src/config/hotkeys.ts @@ -1,17 +1,60 @@ -export default { - CREATE: ['ctrl+alt+n', 'option+meta+n'], - SAVE: ['ctrl+s', 'meta+s'], +import { platformCall } from '@/utils'; +const platform = platformCall(); +const KeybindingsMap = { + CREATE: ['alt+ctrl+N', 'alt+meta+N'], + CLEAR: ['alt+ctrl+W', 'alt+meta+W'], + RIGHT: ['ctrl+RIGHT', 'meta+RIGHT'], + SAVE: ['ctrl+S', 'meta+S'], SUBMIT: ['ctrl+enter', 'meta+enter'], - SAVEAS: ['ctrl+shift+s', 'meta+shift+s'], - OPEN: ['ctrl+o', 'meta+o'], - CANCEL: ['ctrl+w', 'meta+w'], + SAVEAS: ['alt+ctrl+S', 'alt+meta+S'], + OPEN: ['alt+ctrl+O', 'alt+meta+O'], + CANCEL: ['ctrl+W', 'meta+W'], DELETE: ['delete'], - COPY: ['ctrl+c', 'meta+c'], - REFRESH: ['ctrl+r', 'meta+r'], - EDIT: ['ctrl+e', 'meta+e'], - SEARCH: ['ctrl+f', 'meta+f'], - RESET: ['ctrl+shift+r', 'meta+shift+r'], - INPUT: ['ctrl+k', 'meta+k'], + COPY: ['ctrl+C', 'meta+C'], + REFRESH: ['ctrl+R', 'meta+R'], + EDIT: ['ctrl+E', 'meta+E'], + SEARCH: ['ctrl+K', 'meta+K'], + RESET: ['alt+ctrl+R', 'alt+meta+R'], + INPUT: ['ctrl+K', 'meta+K'], NEW1: ['ctrl+1', 'meta+1'], NEW2: ['ctrl+2', 'meta+2'] }; + +type KeyBindingType = keyof typeof KeybindingsMap; + +type KeybindingValue = { + keybinding: string; + command: KeyBindingType; + textKeybinding: string; + iconKeybinding: string; +}; + +const KeybiningList: KeybindingValue[] = Object.entries(KeybindingsMap).map( + ([key, value]) => { + const keybinding = platform.isMac ? value[1] || value[0] : value[0]; + return { + keybinding: keybinding, + command: key, + textKeybinding: platform.isMac + ? keybinding.replace('meta', 'Command').replace('alt', 'Option') + : keybinding.replace('ctrl', 'Ctrl'), + iconKeybinding: platform.isMac + ? keybinding.replace('meta', '⌘').replace('alt', '⌥') + : keybinding.replace('ctrl', 'Ctrl') + } as KeybindingValue; + } +); + +const KeyMap: Record = KeybiningList.reduce( + (acc: any, item) => { + acc[item.command] = item; + return acc; + }, + {} +); + +console.log('KeyMap=========', KeyMap); + +export { KeyMap, KeybiningList }; + +export default KeybindingsMap; diff --git a/src/global.tsx b/src/global.tsx index ba8421f1..117953dc 100644 --- a/src/global.tsx +++ b/src/global.tsx @@ -1,4 +1,4 @@ -// 应用前置、全局运行的逻辑时 会在这里执行 +// Logic that runs globally and before the application will be executed here import dayjs from 'dayjs'; import localizedFormat from 'dayjs/plugin/localizedFormat'; diff --git a/src/layouts/Layout.css b/src/layouts/Layout.css index a3a3edc5..d0ede72a 100644 --- a/src/layouts/Layout.css +++ b/src/layouts/Layout.css @@ -1,23 +1,27 @@ @media screen and (max-width: 480px) { - /* 在小屏幕的时候可以有更好的体验 */ .umi-plugin-layout-container { width: 100% !important; } + .umi-plugin-layout-container > * { border-radius: 0 !important; } } + .umi-plugin-layout-menu .anticon { margin-right: 8px; } + .umi-plugin-layout-menu .ant-dropdown-menu-item { min-width: 160px; } + .umi-plugin-layout-right { display: flex !important; height: 100%; overflow: hidden; } + .umi-plugin-layout-right .umi-plugin-layout-action { display: flex; align-items: center; @@ -26,25 +30,32 @@ cursor: pointer; transition: all 0.3s; } + .umi-plugin-layout-right .umi-plugin-layout-action > i { - color: rgba(255, 255, 255, 0.85); + color: rgba(255, 255, 255, 85%); vertical-align: middle; } + .umi-plugin-layout-right .umi-plugin-layout-action:hover { - background: rgba(0, 0, 0, 0.025); + background: rgba(0, 0, 0, 2.5%); } + .umi-plugin-layout-right .umi-plugin-layout-action.opened { - background: rgba(0, 0, 0, 0.025); + background: rgba(0, 0, 0, 2.5%); } + .umi-plugin-layout-right .umi-plugin-layout-search { padding: 0 12px; } + .umi-plugin-layout-right .umi-plugin-layout-search:hover { background: transparent; } + .umi-plugin-layout-name { margin-left: 8px; } + .umi-plugin-layout-name.umi-plugin-layout-hide-avatar-img { margin-left: 0; } diff --git a/src/layouts/Logo.tsx b/src/layouts/Logo.tsx index c5319e95..a436dd84 100644 --- a/src/layouts/Logo.tsx +++ b/src/layouts/Logo.tsx @@ -1,6 +1,4 @@ // @ts-nocheck -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! import GpustackLogo from '@/assets/images/gpustack-logo.png'; import SmallLogo from '@/assets/images/small-logo-200x200.png'; import React from 'react'; diff --git a/src/layouts/index.tsx b/src/layouts/index.tsx index d2dba414..1f3d1722 100644 --- a/src/layouts/index.tsx +++ b/src/layouts/index.tsx @@ -35,7 +35,7 @@ type InitialStateType = { currentUser?: Global.UserInfo; }; -// 过滤出需要显示的路由, 这里的filterFn 指 不希望显示的层级 +// Filter out the routes that need to be displayed, where filterFn indicates the levels that should not be shown const filterRoutes = ( routes: IRoute[], filterFn: (route: IRoute) => boolean @@ -99,8 +99,6 @@ export default (props: any) => { setInitialState: null }; - // initialState: InitialStateType - const { initialState, loading, setInitialState } = initialInfo; const userConfig = { @@ -189,6 +187,8 @@ export default (props: any) => { const { location } = history; console.log('onPageChange', userInfo, initialState); + + // if user is not change password, redirect to change password page if ( location.pathname !== loginPath && userInfo?.require_password_change @@ -198,8 +198,7 @@ export default (props: any) => { return; } - // 如果没有登录,重定向到 login - + // if user is not logged in, redirect to login page if (!initialState?.currentUser && location.pathname !== loginPath) { history.push(loginPath); } else if (location.pathname === '/') { diff --git a/src/layouts/runtime.tsx b/src/layouts/runtime.tsx index f926ef11..10a92e6f 100644 --- a/src/layouts/runtime.tsx +++ b/src/layouts/runtime.tsx @@ -1,6 +1,4 @@ // @ts-nocheck -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! import React from 'react'; import icons from './icons'; @@ -13,7 +11,6 @@ function formatIcon(name: string) { } export function patchRoutes({ routes, initialState }) { - console.log('patchRoutes99999', routes); Object.keys(routes).forEach((key) => { const { icon } = routes[key]; if (icon && typeof icon === 'string') { diff --git a/src/layouts/runtimeConfig.d.ts b/src/layouts/runtimeConfig.d.ts index ea5ee28a..79e819a2 100644 --- a/src/layouts/runtimeConfig.d.ts +++ b/src/layouts/runtimeConfig.d.ts @@ -1,5 +1,3 @@ -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! import type { RunTimeLayoutConfig } from './types'; export interface IRuntimeConfig { layout?: RunTimeLayoutConfig; diff --git a/src/layouts/types.d.ts b/src/layouts/types.d.ts index 2f10f470..a571f761 100644 --- a/src/layouts/types.d.ts +++ b/src/layouts/types.d.ts @@ -1,8 +1,5 @@ -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! -/// - import type InitialStateType from '@@/plugin-initialState/@@initialState'; +import '@ant-design/pro-components'; import type { HeaderProps, ProLayoutProps } from '@ant-design/pro-components'; type InitDataType = ReturnType; @@ -26,12 +23,12 @@ export type RunTimeLayoutConfig = (initData: InitDataType) => Omit< loading: InitDataType['loading']; initialState: InitDataType['initialState']; setInitialState: InitDataType['setInitialState']; - }, + } ) => JSX.Element) | false; rightRender?: ( initialState: InitDataType['initialState'], setInitialState: InitDataType['setInitialState'], - runtimeConfig: RunTimeLayoutConfig, + runtimeConfig: RunTimeLayoutConfig ) => JSX.Element; }; diff --git a/src/locales/en-US.ts b/src/locales/en-US.ts index 6601455f..eb69fe7d 100644 --- a/src/locales/en-US.ts +++ b/src/locales/en-US.ts @@ -5,6 +5,7 @@ import menu from './en-US/menu'; import models from './en-US/models'; import playground from './en-US/playground'; import resources from './en-US/resources'; +import shortcuts from './en-US/shortcuts'; import usage from './en-US/usage'; import users from './en-US/users'; @@ -17,5 +18,6 @@ export default { ...apikeys, ...users, ...dashboard, - ...usage + ...usage, + ...shortcuts }; diff --git a/src/locales/en-US/shortcuts.ts b/src/locales/en-US/shortcuts.ts new file mode 100644 index 00000000..829b4d85 --- /dev/null +++ b/src/locales/en-US/shortcuts.ts @@ -0,0 +1,13 @@ +export default { + 'shortcuts.search.placeholder': 'Search keybindings', + 'shortcuts.title': 'Keyboard shortcuts', + 'shortcuts.playground.newmessage': 'New message', + 'shortcuts.playground.clearmessage': 'Clear messages', + 'shortcuts.playground.toggleparams': 'Collapse/Expand parameters', + 'shortcuts.models.newmodelHF': 'Deploy Hugging Face model', + 'shortcuts.models.newmodelLM': 'Deploy Ollama model', + 'shortcuts.models.search': 'Search models from Hugging Face', + 'shortcuts.resources.addworker': 'Add worker', + 'shortcuts.apikeys.new': 'New API key', + 'shortcuts.users.new': 'New user' +}; diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index fbb797a6..1aa6a287 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -5,6 +5,7 @@ import menu from './zh-CN/menu'; import models from './zh-CN/models'; import playground from './zh-CN/playground'; import resources from './zh-CN/resources'; +import shortcuts from './zh-CN/shortcuts'; import usage from './zh-CN/usage'; import users from './zh-CN/users'; @@ -17,5 +18,6 @@ export default { ...apikeys, ...users, ...dashboard, - ...usage + ...usage, + ...shortcuts }; diff --git a/src/locales/zh-CN/shortcuts.ts b/src/locales/zh-CN/shortcuts.ts new file mode 100644 index 00000000..916d3ed7 --- /dev/null +++ b/src/locales/zh-CN/shortcuts.ts @@ -0,0 +1,14 @@ +// keyborad shortcuts +export default { + 'shortcuts.title': '快捷键', + 'shortcuts.search.placeholder': '搜索快捷键', + 'shortcuts.playground.newmessage': '新建消息', + 'shortcuts.playground.clearmessage': '清空消息', + 'shortcuts.playground.toggleparams': '收起/展开参数', + 'shortcuts.models.newmodelHF': '部署 Hugging Face 模型', + 'shortcuts.models.newmodelLM': '部署 Ollama 模型', + 'shortcuts.models.search': '从 Hugging Face 搜索模型', + 'shortcuts.resources.addworker': '添加节点', + 'shortcuts.apikeys.new': '新建 API 密钥', + 'shortcuts.users.new': '新建用户' +}; diff --git a/src/pages/access/index.tsx b/src/pages/access/index.tsx index f41ad541..16faee1a 100644 --- a/src/pages/access/index.tsx +++ b/src/pages/access/index.tsx @@ -8,11 +8,11 @@ const AccessPage: React.FC = () => { - + ); diff --git a/src/pages/api-keys/index.tsx b/src/pages/api-keys/index.tsx index 38e41a04..aafa8609 100644 --- a/src/pages/api-keys/index.tsx +++ b/src/pages/api-keys/index.tsx @@ -1,6 +1,7 @@ import DeleteModal from '@/components/delete-modal'; import PageTools from '@/components/page-tools'; import { PageAction } from '@/config'; +import HotKeys from '@/config/hotkeys'; import type { PageActionType } from '@/config/types'; import useTableRowSelection from '@/hooks/use-table-row-selection'; import useTableSort from '@/hooks/use-table-sort'; @@ -12,6 +13,7 @@ import { Button, Input, Space, Table, Tooltip } from 'antd'; import dayjs from 'dayjs'; import _ from 'lodash'; import { useEffect, useRef, useState } from 'react'; +import { useHotkeys } from 'react-hotkeys-hook'; import { deleteApisKey, queryApisKeysList } from './apis'; import AddAPIKeyModal from './components/add-apikey'; import { ListItem } from './config/types'; @@ -140,6 +142,16 @@ const APIKeys: React.FC = () => { fetchData(); }, [queryParams]); + useHotkeys( + HotKeys.CREATE, + () => { + handleAddUser(); + }, + { + enabled: !openAddModal + } + ); + return ( <> (null); - const platform = platformCall(); useHotkeys(hotkeys.INPUT.join(','), () => { inputRef.current?.focus?.(); diff --git a/src/pages/llmodels/components/separator.tsx b/src/pages/llmodels/components/separator.tsx index 53af1442..206ac7f8 100644 --- a/src/pages/llmodels/components/separator.tsx +++ b/src/pages/llmodels/components/separator.tsx @@ -10,7 +10,6 @@ const Separator: React.FC = () => { style={{ height: 'calc(100vh - 89px)', marginInline: '0px' }} > - {/* */}
); }; diff --git a/src/pages/llmodels/style/separator.less b/src/pages/llmodels/style/separator.less index 47d4e304..bd58eb33 100644 --- a/src/pages/llmodels/style/separator.less +++ b/src/pages/llmodels/style/separator.less @@ -3,6 +3,7 @@ .shape { position: absolute; + border-radius: 0 2px 0 0; top: 10px; left: -10px; width: 22px; @@ -14,15 +15,4 @@ background-color: var(--color-white-1); z-index: 100; } - - .shape-s { - position: absolute; - top: 50%; - left: 4px; - width: 30px; - height: 30px; - border: 16px solid transparent; - border-left: 16px solid var(--color-fill-sider); - z-index: 100; - } } diff --git a/src/pages/playground/components/ground-left.tsx b/src/pages/playground/components/ground-left.tsx index c1201cb6..b8da02a5 100644 --- a/src/pages/playground/components/ground-left.tsx +++ b/src/pages/playground/components/ground-left.tsx @@ -239,6 +239,30 @@ const MessageList: React.FC = forwardRef((props, ref) => { } ); + useHotkeys( + HotKeys.CREATE.join(','), + () => { + handleNewMessage(); + }, + { + enabled: !loading, + enableOnFormTags: !loading, + preventDefault: true + } + ); + + useHotkeys( + HotKeys.CLEAR.join(','), + () => { + handleClear(); + }, + { + enabled: !loading, + enableOnFormTags: !loading, + preventDefault: true + } + ); + return (
{ groundLeftRef.current?.viewCode?.(); }; + useHotkeys( + HotKeys.RIGHT.join(','), + () => { + setCollapse((pre) => { + return !pre; + }); + }, + { + preventDefault: true + } + ); + return ( { fetchData(); }, [queryParams]); + useHotkeys(Hotkeys.CREATE.join(','), handleAddWorker, { + enabled: !open + }); + return ( <> { fetchData(); }, [queryParams]); + useHotkeys( + HotKeys.CREATE, + () => { + handleAddUser(); + }, + { + enabled: !openAddModal + } + ); + return ( <> { /** - * 生成一组用于折线图的数据,具有自然且美观的趋势。 + * Generate a set of data for a line chart with a natural and aesthetically pleasing trend. * - * 参数: - * total (number): 生成数据点的数量 - * trendType (string): 数据趋势类型, 可选'linear', 'sine', 'exponential' - * max (number): 波动幅度 - * f (number): 波动频率 - * phase (number): 波动相位 - * min (number): 数据的最小值 + * Parameters: + * total (number): Number of data points to generate + * trendType (string): Type of data trend, options are 'linear', 'sine', 'exponential' + * max (number): Fluctuation amplitude + * f (number): Fluctuation frequency + * phase (number): Fluctuation phase + * min (number): Minimum value of the data * - * 返回: - * x (number[]): x轴数据 - * y (number[]): y轴数据 + * Returns: + * x (number[]): x-axis data + * y (number[]): y-axis data */ const x = Array.from({ length: total }, (_, i) => (i * 10) / (total - 1)); @@ -131,11 +130,11 @@ export const generateFluctuatingData = ({ break; default: throw new Error( - '无效的trendType参数,请选择"linear", "sine"或"exponential".' + 'Invalid trendType parameter. Please choose "linear", "sine", or "exponential".' ); } - // 将数据调整到最小值 + // Adjust the data to the minimum value const minY = Math.min(...y); y = y.map((val) => _.round(val - minY + min, 2));