feat: user settings
This commit is contained in:
+9
-1
@@ -26,7 +26,7 @@ export default [
|
|||||||
path: '/models',
|
path: '/models',
|
||||||
key: 'models',
|
key: 'models',
|
||||||
icon: 'Block',
|
icon: 'Block',
|
||||||
component: './llm-models'
|
component: './llmodels'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Nodes',
|
name: 'Nodes',
|
||||||
@@ -49,6 +49,14 @@ export default [
|
|||||||
icon: 'Team',
|
icon: 'Team',
|
||||||
component: './users'
|
component: './users'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Profile',
|
||||||
|
path: '/profile',
|
||||||
|
key: 'profile',
|
||||||
|
hideInMenu: true,
|
||||||
|
component: './profile',
|
||||||
|
icon: 'User'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '404',
|
name: '404',
|
||||||
path: '*',
|
path: '*',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"@ant-design/icons": "^5.3.7",
|
"@ant-design/icons": "^5.3.7",
|
||||||
"@ant-design/plots": "^2.2.2",
|
"@ant-design/plots": "^2.2.2",
|
||||||
"@ant-design/pro-components": "^2.7.1",
|
"@ant-design/pro-components": "^2.7.1",
|
||||||
|
"@monaco-editor/react": "^4.6.0",
|
||||||
"@types/lodash": "^4.17.4",
|
"@types/lodash": "^4.17.4",
|
||||||
"@umijs/max": "^4.2.1",
|
"@umijs/max": "^4.2.1",
|
||||||
"antd": "^5.17.0",
|
"antd": "^5.17.0",
|
||||||
|
|||||||
Generated
+33
@@ -14,6 +14,9 @@ dependencies:
|
|||||||
'@ant-design/pro-components':
|
'@ant-design/pro-components':
|
||||||
specifier: ^2.7.1
|
specifier: ^2.7.1
|
||||||
version: 2.7.1(antd@5.17.0)(rc-field-form@1.44.0)(react-dom@18.3.1)(react@18.3.1)
|
version: 2.7.1(antd@5.17.0)(rc-field-form@1.44.0)(react-dom@18.3.1)(react@18.3.1)
|
||||||
|
'@monaco-editor/react':
|
||||||
|
specifier: ^4.6.0
|
||||||
|
version: 4.6.0(monaco-editor@0.49.0)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@types/lodash':
|
'@types/lodash':
|
||||||
specifier: ^4.17.4
|
specifier: ^4.17.4
|
||||||
version: 4.17.4
|
version: 4.17.4
|
||||||
@@ -2418,6 +2421,28 @@ packages:
|
|||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@monaco-editor/loader@1.4.0(monaco-editor@0.49.0):
|
||||||
|
resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==}
|
||||||
|
peerDependencies:
|
||||||
|
monaco-editor: '>= 0.21.0 < 1'
|
||||||
|
dependencies:
|
||||||
|
monaco-editor: 0.49.0
|
||||||
|
state-local: 1.0.7
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@monaco-editor/react@4.6.0(monaco-editor@0.49.0)(react-dom@18.3.1)(react@18.3.1):
|
||||||
|
resolution: {integrity: sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==}
|
||||||
|
peerDependencies:
|
||||||
|
monaco-editor: '>= 0.25.0 < 1'
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
dependencies:
|
||||||
|
'@monaco-editor/loader': 1.4.0(monaco-editor@0.49.0)
|
||||||
|
monaco-editor: 0.49.0
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1:
|
/@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1:
|
||||||
resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
|
resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8316,6 +8341,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/monaco-editor@0.49.0:
|
||||||
|
resolution: {integrity: sha512-2I8/T3X/hLxB2oPHgqcNYUVdA/ZEFShT7IAujifIPMfKkNbLOqY8XCoyHCXrsdjb36dW9MwoTwBCFpXKMwNwaQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/ms@2.0.0:
|
/ms@2.0.0:
|
||||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -11552,6 +11581,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==}
|
resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/state-local@1.0.7:
|
||||||
|
resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/statuses@2.0.1:
|
/statuses@2.0.1:
|
||||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
.editor-wrap {
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
.editor-header {
|
||||||
|
display: flex;
|
||||||
|
padding: 6px 10px;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: rgb(56, 56, 56);
|
||||||
|
.ant-select-selector {
|
||||||
|
background-color: rgba(255, 255, 255, 0.09) !important;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
.ant-select-selection-item {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-select-arrow {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// set scrollbar style
|
||||||
|
|
||||||
|
.scrollbar {
|
||||||
|
.slider {
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { Select } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import CopyButton from '../copy-button';
|
||||||
|
import './index.less';
|
||||||
|
|
||||||
|
interface EditorwrapProps {
|
||||||
|
header?: React.ReactNode;
|
||||||
|
children: React.ReactNode;
|
||||||
|
showHeader?: boolean;
|
||||||
|
copyText: string;
|
||||||
|
langOptions?: { label: string; value: string }[];
|
||||||
|
onChangeLang?: (value: string) => void;
|
||||||
|
}
|
||||||
|
const EditorWrap: React.FC<EditorwrapProps> = ({
|
||||||
|
header,
|
||||||
|
children,
|
||||||
|
copyText,
|
||||||
|
langOptions,
|
||||||
|
onChangeLang,
|
||||||
|
showHeader = true
|
||||||
|
}) => {
|
||||||
|
const handleChangeLang = (value: string) => {
|
||||||
|
onChangeLang && onChangeLang(value);
|
||||||
|
};
|
||||||
|
const renderHeader = () => {
|
||||||
|
if (header) {
|
||||||
|
return <div className="editor-header">{header}</div>;
|
||||||
|
}
|
||||||
|
if (showHeader) {
|
||||||
|
return (
|
||||||
|
<div className="editor-header">
|
||||||
|
<Select
|
||||||
|
defaultValue="JSON"
|
||||||
|
style={{ width: 120 }}
|
||||||
|
size="middle"
|
||||||
|
variant="filled"
|
||||||
|
options={langOptions}
|
||||||
|
onChange={handleChangeLang}
|
||||||
|
></Select>
|
||||||
|
<CopyButton text={copyText} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="editor-wrap">
|
||||||
|
{renderHeader()}
|
||||||
|
<div className="editor-content">{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditorWrap;
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Button, Space } from 'antd';
|
||||||
|
|
||||||
|
type FormButtonsProps = {
|
||||||
|
onOk: () => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
cancelText?: string;
|
||||||
|
okText?: string;
|
||||||
|
};
|
||||||
|
const FormButtons: React.FC<FormButtonsProps> = ({
|
||||||
|
onOk,
|
||||||
|
onCancel,
|
||||||
|
cancelText,
|
||||||
|
okText
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Space size={40} style={{ marginTop: '80px' }}>
|
||||||
|
<Button type="primary" onClick={onOk} style={{ width: '120px' }}>
|
||||||
|
{okText || '保存'}
|
||||||
|
</Button>
|
||||||
|
<Button onClick={onCancel} style={{ width: '98px' }}>
|
||||||
|
{cancelText || '取消'}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FormButtons;
|
||||||
@@ -230,5 +230,11 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ======== menu style end ============
|
// ======== menu style end ============
|
||||||
|
|
||||||
|
// ======== monaco editor style ============
|
||||||
|
.monaco-editor {
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
@import url('src/assets/styles/common.less');
|
@import url('src/assets/styles/common.less');
|
||||||
@import url('src/assets/styles/menu.less');
|
@import url('src/assets/styles/menu.less');
|
||||||
|
|||||||
+45
-15
@@ -1,7 +1,13 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|
||||||
import avatarImg from '@/assets/images/avatar.png';
|
import avatarImg from '@/assets/images/avatar.png';
|
||||||
import { LogoutOutlined } from '@ant-design/icons';
|
import {
|
||||||
|
GlobalOutlined,
|
||||||
|
LogoutOutlined,
|
||||||
|
SettingOutlined,
|
||||||
|
SunOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import { useNavigate } from '@umijs/max';
|
||||||
import { Avatar, Dropdown, Menu, Spin, version } from 'antd';
|
import { Avatar, Dropdown, Menu, Spin, version } from 'antd';
|
||||||
|
|
||||||
export function getRightRenderContent(opts: {
|
export function getRightRenderContent(opts: {
|
||||||
@@ -52,10 +58,48 @@ export function getRightRenderContent(opts: {
|
|||||||
// 如果没有打开Locale,并且头像为空就取消掉这个返回的内容
|
// 如果没有打开Locale,并且头像为空就取消掉这个返回的内容
|
||||||
if (!avatar) return null;
|
if (!avatar) return null;
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const langMenu = {
|
const langMenu = {
|
||||||
className: 'umi-plugin-layout-menu',
|
className: 'umi-plugin-layout-menu',
|
||||||
selectedKeys: [],
|
selectedKeys: [],
|
||||||
items: [
|
items: [
|
||||||
|
{
|
||||||
|
key: 'settings',
|
||||||
|
label: (
|
||||||
|
<>
|
||||||
|
<SettingOutlined />
|
||||||
|
设置
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
onClick: () => {
|
||||||
|
navigate('/profile');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'theme',
|
||||||
|
label: (
|
||||||
|
<>
|
||||||
|
<SunOutlined />
|
||||||
|
外观
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
onClick: () => {
|
||||||
|
console.log('theme');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
label: (
|
||||||
|
<>
|
||||||
|
<GlobalOutlined />
|
||||||
|
语言
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
onClick: () => {
|
||||||
|
console.log('lang');
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'logout',
|
key: 'logout',
|
||||||
label: (
|
label: (
|
||||||
@@ -67,20 +111,6 @@ export function getRightRenderContent(opts: {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
opts?.runtimeConfig?.logout?.(opts.initialState);
|
opts?.runtimeConfig?.logout?.(opts.initialState);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'theme',
|
|
||||||
label: <>外观</>,
|
|
||||||
onClick: () => {
|
|
||||||
console.log('theme');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'lang',
|
|
||||||
label: '语言',
|
|
||||||
onClick: () => {
|
|
||||||
console.log('lang');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import '../style/ground-left.less';
|
|||||||
import ChatFooter from './chat-footer';
|
import ChatFooter from './chat-footer';
|
||||||
import MessageItem from './message-item';
|
import MessageItem from './message-item';
|
||||||
import ReferenceParams from './reference-params';
|
import ReferenceParams from './reference-params';
|
||||||
|
import ViewCodeModal from './view-code-modal';
|
||||||
|
|
||||||
const MessageList: React.FC = () => {
|
const MessageList: React.FC = () => {
|
||||||
const [messageList, setMessageList] = useState<any[]>([
|
const [messageList, setMessageList] = useState<any[]>([
|
||||||
@@ -16,6 +17,7 @@ const MessageList: React.FC = () => {
|
|||||||
message: 'hello, nice to meet you!'
|
message: 'hello, nice to meet you!'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
const [show, setShow] = useState(false);
|
||||||
const [activeIndex, setActiveIndex] = useState(-1);
|
const [activeIndex, setActiveIndex] = useState(-1);
|
||||||
|
|
||||||
const handleNewMessage = () => {
|
const handleNewMessage = () => {
|
||||||
@@ -33,13 +35,17 @@ const MessageList: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleView = () => {
|
const handleView = () => {
|
||||||
console.log('view');
|
setShow(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
console.log('submit');
|
console.log('submit');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCloseViewCode = () => {
|
||||||
|
setShow(false);
|
||||||
|
};
|
||||||
|
|
||||||
const handleDelete = (index: number) => {
|
const handleDelete = (index: number) => {
|
||||||
messageList.splice(index, 1);
|
messageList.splice(index, 1);
|
||||||
setMessageList([...messageList]);
|
setMessageList([...messageList]);
|
||||||
@@ -71,6 +77,11 @@ const MessageList: React.FC = () => {
|
|||||||
feedback={<ReferenceParams></ReferenceParams>}
|
feedback={<ReferenceParams></ReferenceParams>}
|
||||||
></ChatFooter>
|
></ChatFooter>
|
||||||
</div>
|
</div>
|
||||||
|
<ViewCodeModal
|
||||||
|
open={show}
|
||||||
|
onCancel={handleCloseViewCode}
|
||||||
|
title="View code"
|
||||||
|
></ViewCodeModal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -68,10 +68,9 @@ const ParamsSettings: React.FC<{ onClose: () => void }> = ({ onClose }) => {
|
|||||||
name="temperature"
|
name="temperature"
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<SealInput.Input
|
<FieldWrapper label="Temperature">
|
||||||
label="Temperature"
|
<Slider defaultValue={50}></Slider>
|
||||||
style={{ width: INPUT_WIDTH.mini }}
|
</FieldWrapper>
|
||||||
></SealInput.Input>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<ParamsSettingsProps>
|
<Form.Item<ParamsSettingsProps>
|
||||||
name="maxTokens"
|
name="maxTokens"
|
||||||
@@ -86,7 +85,7 @@ const ParamsSettings: React.FC<{ onClose: () => void }> = ({ onClose }) => {
|
|||||||
name="topP"
|
name="topP"
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<FieldWrapper label="TopP">
|
<FieldWrapper label="Top P">
|
||||||
<Slider defaultValue={50}></Slider>
|
<Slider defaultValue={50}></Slider>
|
||||||
</FieldWrapper>
|
</FieldWrapper>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import EditorWrap from '@/components/editor-wrap';
|
||||||
|
import Editor from '@monaco-editor/react';
|
||||||
|
import { Modal } from 'antd';
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
|
||||||
|
type ViewModalProps = {
|
||||||
|
title: string;
|
||||||
|
open: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||||
|
const { title, open, onCancel } = props || {};
|
||||||
|
if (!open) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const editorRef = useRef(null);
|
||||||
|
const [codeValue, setCodeValue] = useState('');
|
||||||
|
const [lang, setLang] = useState('json');
|
||||||
|
|
||||||
|
const langOptions = [
|
||||||
|
{ label: 'curl', value: 'curl' },
|
||||||
|
{ label: 'JSON', value: 'json' },
|
||||||
|
{ label: 'JavaScript', value: 'javascript' },
|
||||||
|
{ label: 'Python', value: 'python' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleEditorDidMount = (editor: any, monaco: any) => {
|
||||||
|
editorRef.current = editor;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnChangeLang = (value: string) => {
|
||||||
|
setLang(value);
|
||||||
|
};
|
||||||
|
const editorConfig = {
|
||||||
|
minimap: {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
scrollbar: {
|
||||||
|
verticalSliderSize: 8
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={title}
|
||||||
|
open={open}
|
||||||
|
onCancel={onCancel}
|
||||||
|
destroyOnClose={true}
|
||||||
|
closeIcon={true}
|
||||||
|
maskClosable={false}
|
||||||
|
keyboard={false}
|
||||||
|
width={600}
|
||||||
|
style={{ top: '80px' }}
|
||||||
|
footer={null}
|
||||||
|
>
|
||||||
|
<div style={{ marginBottom: '10px' }}>
|
||||||
|
You can use the following code to start integrating your current prompt
|
||||||
|
and settings into your application.
|
||||||
|
</div>
|
||||||
|
<EditorWrap
|
||||||
|
copyText={codeValue}
|
||||||
|
langOptions={langOptions}
|
||||||
|
onChangeLang={handleOnChangeLang}
|
||||||
|
>
|
||||||
|
<Editor
|
||||||
|
height="400px"
|
||||||
|
theme="vs-dark"
|
||||||
|
className="monaco-editor"
|
||||||
|
defaultLanguage="javascript"
|
||||||
|
defaultValue="// some comment"
|
||||||
|
language={lang}
|
||||||
|
options={editorConfig}
|
||||||
|
onMount={handleEditorDidMount}
|
||||||
|
/>
|
||||||
|
</EditorWrap>
|
||||||
|
<div style={{ marginTop: '10px' }}>
|
||||||
|
our API Key can be foundhere You should use environment variables or a
|
||||||
|
secret management tool to expose your key to your applications.
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ViewCodeModal;
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import FormButtons from '@/components/form-buttons';
|
||||||
|
import SealInput from '@/components/seal-form/seal-input';
|
||||||
|
import { INPUT_WIDTH } from '@/constants';
|
||||||
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
|
import { Form } from 'antd';
|
||||||
|
import { StrictMode } from 'react';
|
||||||
|
|
||||||
|
interface ProfileProps {
|
||||||
|
name: string;
|
||||||
|
password: string;
|
||||||
|
originalPassword: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
const Profile: React.FC = () => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
const handleOnFinish = (values: any) => {
|
||||||
|
console.log('handleOnFinish', values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnFinishFailed = (errorInfo: any) => {
|
||||||
|
console.log('handleOnFinishFailed', errorInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StrictMode>
|
||||||
|
<PageContainer
|
||||||
|
ghost
|
||||||
|
header={{
|
||||||
|
title: 'Profile'
|
||||||
|
}}
|
||||||
|
extra={[]}
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
style={{ width: '524px' }}
|
||||||
|
name="profileForm"
|
||||||
|
form={form}
|
||||||
|
onFinish={handleOnFinish}
|
||||||
|
onFinishFailed={handleOnFinishFailed}
|
||||||
|
>
|
||||||
|
<Form.Item<ProfileProps> name="name" rules={[{ required: true }]}>
|
||||||
|
<SealInput.Input
|
||||||
|
label="Name"
|
||||||
|
required
|
||||||
|
style={{ width: INPUT_WIDTH.default }}
|
||||||
|
></SealInput.Input>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item<ProfileProps> name="email" rules={[{ required: true }]}>
|
||||||
|
<SealInput.Input
|
||||||
|
label="Email"
|
||||||
|
required
|
||||||
|
style={{ width: INPUT_WIDTH.default }}
|
||||||
|
></SealInput.Input>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item<ProfileProps>
|
||||||
|
name="originalPassword"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
|
<SealInput.Password
|
||||||
|
label="Original Password"
|
||||||
|
required
|
||||||
|
style={{ width: INPUT_WIDTH.default }}
|
||||||
|
></SealInput.Password>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item<ProfileProps> name="password" rules={[{ required: true }]}>
|
||||||
|
<SealInput.Password
|
||||||
|
label="Password"
|
||||||
|
required
|
||||||
|
style={{ width: INPUT_WIDTH.default }}
|
||||||
|
></SealInput.Password>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
<FormButtons></FormButtons>
|
||||||
|
</PageContainer>
|
||||||
|
</StrictMode>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Profile;
|
||||||
Reference in New Issue
Block a user