fix: playground message flashing

This commit is contained in:
jialin
2024-07-11 14:49:57 +08:00
parent 8607815240
commit c5327d3e56
18 changed files with 130 additions and 129 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ export default {
iconSize: 16, iconSize: 16,
iconMarginInlineEnd: 12, iconMarginInlineEnd: 12,
itemHeight: 44, itemHeight: 44,
// itemColor: 'rgba(0,0,0,.88)', itemColor: 'rgba(0,0,0,1)',
itemHoverBg: 'rgba(0,0,0,0.04)', itemHoverBg: 'rgba(0,0,0,0.04)',
itemActiveBg: 'rgba(0,0,0,0.04)' itemActiveBg: 'rgba(0,0,0,0.04)'
}, },
@@ -10,8 +10,11 @@ interface NoteInfoProps {
} }
const NoteInfo: React.FC<NoteInfoProps> = (props) => { const NoteInfo: React.FC<NoteInfoProps> = (props) => {
const { required, description, label } = props || {}; const { required, description, label } = props || {};
return ( return (
<span className="label-text"> <span className="label-text">
{description ? (
<Tooltip title={description}>
<span>{label}</span> <span>{label}</span>
<span className="note-info"> <span className="note-info">
{required && ( {required && (
@@ -19,14 +22,26 @@ const NoteInfo: React.FC<NoteInfoProps> = (props) => {
* *
</span> </span>
)} )}
{description && ( <span
<span style={{ marginLeft: 5, color: 'gray' }} className="desc"> style={{ marginLeft: required ? 5 : 0, color: 'gray' }}
<Tooltip title={description}> className="desc"
>
<InfoCircleOutlined /> <InfoCircleOutlined />
</span>
</span>
</Tooltip> </Tooltip>
) : (
<>
<span>{label}</span>
<span className="note-info">
{required && (
<span style={{ color: 'red' }} className="star">
*
</span> </span>
)} )}
</span> </span>
</>
)}
</span> </span>
); );
}; };
@@ -39,8 +39,8 @@ const TableRow: React.FC<
console.log('table row===='); console.log('table row====');
const { updateChunkedList } = useUpdateChunkedList({ const { updateChunkedList } = useUpdateChunkedList({
setDataList: setChildrenData, setDataList: setChildrenData
callback: (list) => renderChildren?.(list) // callback: (list) => renderChildren?.(list)
}); });
useEffect(() => { useEffect(() => {
@@ -101,6 +101,7 @@ const TableRow: React.FC<
setChildrenData([]); setChildrenData([]);
setLoading(false); setLoading(false);
} finally { } finally {
childrenDataRef.current = childrenData;
setFirstLoad(false); setFirstLoad(false);
} }
}; };
+2 -4
View File
@@ -30,10 +30,10 @@ const SealTable: React.FC<SealTableProps> = (props) => {
useEffect(() => { useEffect(() => {
if (rowSelection) { if (rowSelection) {
const { selectedRowKeys } = rowSelection; const { selectedRowKeys } = rowSelection;
if (selectedRowKeys.length === 0) { if (selectedRowKeys?.length === 0) {
setSelectAll(false); setSelectAll(false);
setIndeterminate(false); setIndeterminate(false);
} else if (selectedRowKeys.length === props.dataSource.length) { } else if (selectedRowKeys?.length === props.dataSource.length) {
setSelectAll(true); setSelectAll(true);
setIndeterminate(false); setIndeterminate(false);
} else { } else {
@@ -45,12 +45,10 @@ const SealTable: React.FC<SealTableProps> = (props) => {
const handleSelectAllChange = (e: any) => { const handleSelectAllChange = (e: any) => {
if (e.target.checked) { if (e.target.checked) {
// update selectedRowKeys
rowSelection?.onChange(props.dataSource.map((record) => record[rowKey])); rowSelection?.onChange(props.dataSource.map((record) => record[rowKey]));
setSelectAll(true); setSelectAll(true);
setIndeterminate(false); setIndeterminate(false);
} else { } else {
// update selectedRowKeys
rowSelection?.onChange([]); rowSelection?.onChange([]);
setSelectAll(false); setSelectAll(false);
setIndeterminate(false); setIndeterminate(false);
+5 -3
View File
@@ -12,7 +12,7 @@
overflow: hidden; overflow: hidden;
&.download { &.download {
border: 1px solid var(--ant-color-border) !important; border: 1px solid #93ecc5 !important;
} }
.download { .download {
@@ -24,12 +24,14 @@
top: 0; top: 0;
bottom: 0; bottom: 0;
height: 100%; height: 100%;
background-color: rgba(0, 0, 0, 15%); // background-color: rgba(0, 0, 0, 15%);
background-color: #e0f5ec;
} }
.progress { .progress {
position: relative; position: relative;
z-index: 10; z-index: 10;
color: var(--ant-color-text); // color: var(--ant-color-text);
color: var(--color-progress-green);
} }
} }
+6 -2
View File
@@ -27,7 +27,11 @@ type StatusTagProps = {
const StatusTag: React.FC<StatusTagProps> = ({ statusValue, download }) => { const StatusTag: React.FC<StatusTagProps> = ({ statusValue, download }) => {
const { text, status } = statusValue; const { text, status } = statusValue;
const [statusColor, setStatusColor] = useState<{ text: string; bg: string }>({ const [statusColor, setStatusColor] = useState<{
text: string;
bg: string;
border?: string;
}>({
text: '', text: '',
bg: '' bg: ''
}); });
@@ -56,7 +60,7 @@ const StatusTag: React.FC<StatusTagProps> = ({ statusValue, download }) => {
})} })}
style={{ style={{
color: statusColor?.text, color: statusColor?.text,
border: `1px solid ${statusColor?.text}` border: `1px solid ${statusColor?.border || statusColor?.text}`
}} }}
> >
{statusValue.message ? ( {statusValue.message ? (
+7 -4
View File
@@ -6,8 +6,10 @@ export const PageAction: Record<string, PageActionType> = {
VIEW: 'view' VIEW: 'view'
}; };
export const StatusColorMap: Record<StatusType, { text: string; bg: string }> = export const StatusColorMap: Record<
{ StatusType,
{ text: string; bg: string; border?: string }
> = {
error: { error: {
text: `var(--ant-red-6)`, text: `var(--ant-red-6)`,
bg: `var(--ant-red-1)` bg: `var(--ant-red-1)`
@@ -25,10 +27,11 @@ export const StatusColorMap: Record<StatusType, { text: string; bg: string }> =
bg: `var(--ant-green-1)` bg: `var(--ant-green-1)`
}, },
inactive: { inactive: {
text: `var(--ant-color-text-secondary)`, text: `var(--ant-color-text-tertiary)`,
border: `rgba(200,200,200,1)`,
bg: `var(--ant-color-fill)` bg: `var(--ant-color-fill)`
} }
}; };
export const StatusMaps = { export const StatusMaps = {
error: 'error', error: 'error',
+7 -5
View File
@@ -50,6 +50,7 @@ html {
--ant-input-hover-border-color: #2997ff; --ant-input-hover-border-color: #2997ff;
--box-shadow-base: 0 4px 6px rgba(227, 232, 240, 70%); --box-shadow-base: 0 4px 6px rgba(227, 232, 240, 70%);
--ant-border-radius-lg: 8px; --ant-border-radius-lg: 8px;
--ant-menu-item-color: var(--color-text-1);
// --box-shadow-base: none; // --box-shadow-base: none;
.css-var-rf { .css-var-rf {
@@ -283,7 +284,6 @@ body {
.ant-pro-sider .ant-layout-sider-children { .ant-pro-sider .ant-layout-sider-children {
background-color: var(--color-fill-sider); background-color: var(--color-fill-sider);
// box-shadow: var(--box-shadow-base);
border-right: 1px solid var(--ant-color-border); border-right: 1px solid var(--ant-color-border);
} }
} }
@@ -300,9 +300,7 @@ body {
.ant-table-tbody { .ant-table-tbody {
.ant-table-row { .ant-table-row {
border-radius: var(--table-td-radius); border-radius: var(--table-td-radius);
// background-color: var(--color-white-1);
background-color: var(--color-fill-sider); background-color: var(--color-fill-sider);
// box-shadow: var(--box-shadow-base);
> td { > td {
background-color: unset; background-color: unset;
@@ -348,6 +346,7 @@ body {
.ant-menu { .ant-menu {
.ant-menu-item { .ant-menu-item {
border-radius: var(--border-radius-small); border-radius: var(--border-radius-small);
color: var(--color-text-1) !important;
&:active { &:active {
background-color: var(--ant-menu-item-selected-bg); background-color: var(--ant-menu-item-selected-bg);
@@ -363,12 +362,12 @@ body {
} }
.ant-menu-item.ant-menu-item-selected:hover { .ant-menu-item.ant-menu-item-selected:hover {
color: var(--ant-color-primary); color: var(--ant-color-primary) !important;
background-color: var(--ant-menu-item-selected-bg); background-color: var(--ant-menu-item-selected-bg);
} }
.ant-menu-item.ant-menu-item-selected { .ant-menu-item.ant-menu-item-selected {
color: var(--ant-color-primary); color: var(--ant-color-primary) !important;
background-color: var(--ant-menu-item-selected-bg); background-color: var(--ant-menu-item-selected-bg);
} }
} }
@@ -380,6 +379,7 @@ body {
.ant-menu-item-only-child { .ant-menu-item-only-child {
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
color: var(--color-text-1);
.anticon { .anticon {
font-size: var(--font-size-middle); font-size: var(--font-size-middle);
@@ -392,6 +392,7 @@ body {
.user-avatar.ant-menu-submenu { .user-avatar.ant-menu-submenu {
.ant-menu-submenu-title { .ant-menu-submenu-title {
padding-left: 10px; padding-left: 10px;
color: var(--color-text-1) !important;
} }
} }
@@ -413,6 +414,7 @@ body {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
color: var(--color-text-1) !important;
} }
} }
@@ -98,7 +98,7 @@ const ActiveTable = () => {
} }
}, },
{ {
title: intl.formatMessage({ id: 'dashboard.runninginstances' }), title: intl.formatMessage({ id: 'models.form.replicas' }),
dataIndex: 'instance_count', dataIndex: 'instance_count',
key: 'instance_count' key: 'instance_count'
}, },
+2 -11
View File
@@ -2,31 +2,22 @@ export const overviewConfigs = [
{ {
key: 'worker_count', key: 'worker_count',
label: 'dashboard.workers', label: 'dashboard.workers',
// backgroundColor: 'linear-gradient(135deg, #ffffff, rgb(232 249 240 / 60%))'
backgroundColor: 'var(--color-white-1)' backgroundColor: 'var(--color-white-1)'
}, },
{ {
key: 'gpu_count', key: 'gpu_count',
label: 'dashboard.totalgpus', label: 'dashboard.totalgpus',
backgroundColor: 'var(--color-white-1)' backgroundColor: 'var(--color-white-1)'
// backgroundColor: 'linear-gradient(135deg, #ffffff, rgb(232 249 240 / 60%))'
}, },
// {
// key: 'allocatedGpus',
// label: 'dashboard.allocategpus',
// backgroundColor: 'var(--color-white-1)'
// // backgroundColor: 'linear-gradient(135deg, #ffffff, rgb(232 249 240 / 60%))'
// },
{ {
key: 'model_count', key: 'model_count',
label: 'dashboard.models', label: 'dashboard.models',
backgroundColor: 'var(--color-white-1)' backgroundColor: 'var(--color-white-1)'
// backgroundColor: 'linear-gradient(135deg, #ffffff, rgb(232 249 240 / 60%))'
}, },
{ {
key: 'model_instance_count', key: 'model_instance_count',
label: 'dashboard.instances', label: 'models.form.replicas',
backgroundColor: 'var(--color-white-1)' backgroundColor: 'var(--color-white-1)'
// backgroundColor: 'linear-gradient(135deg, #ffffff, rgb(232 249 240 / 60%))'
} }
]; ];
@@ -19,11 +19,17 @@ interface InstanceItemProps {
) => void; ) => void;
} }
const testStatus = {
state: InstanceStatusMap.Downloading,
text: 'Downloading'
};
const InstanceItem: React.FC<InstanceItemProps> = ({ const InstanceItem: React.FC<InstanceItemProps> = ({
list, list,
handleChildSelect handleChildSelect
}) => { }) => {
console.log('instance item===='); console.log('instance item====');
const intl = useIntl(); const intl = useIntl();
const childActionList = [ const childActionList = [
{ {
+1 -1
View File
@@ -4,7 +4,7 @@
width: max-content; width: max-content;
height: max-content; height: max-content;
padding: 32px; padding: 32px;
background-color: rgba(255, 255, 255, 50%); background-color: rgba(255, 255, 255, 90%);
:global(.field-wrapper) { :global(.field-wrapper) {
background-color: transparent !important; background-color: transparent !important;
@@ -26,6 +26,7 @@ interface ChatFooterProps {
} }
const ChatFooter: React.FC<ChatFooterProps> = (props) => { const ChatFooter: React.FC<ChatFooterProps> = (props) => {
console.log('chat footer=====');
const platform = platformCall(); const platform = platformCall();
const intl = useIntl(); const intl = useIntl();
const { const {
@@ -69,12 +69,14 @@ const MessageList: React.FC<MessageProps> = (props) => {
}; };
const joinMessage = (chunk: any) => { const joinMessage = (chunk: any) => {
if (!chunk) {
return;
}
if (_.get(chunk, 'choices.0.finish_reason')) { if (_.get(chunk, 'choices.0.finish_reason')) {
setTokenResult({ setTokenResult({
...chunk?.usage ...chunk?.usage
}); });
return;
return true;
} }
contentRef.current = contentRef.current =
contentRef.current + _.get(chunk, 'choices.0.delta.content', ''); contentRef.current + _.get(chunk, 'choices.0.delta.content', '');
@@ -86,8 +88,6 @@ const MessageList: React.FC<MessageProps> = (props) => {
uid: messageId.current uid: messageId.current
} }
]); ]);
console.log('messageList=====', messageList, messageId.current, chunk);
return false;
}; };
const handleStopConversation = () => { const handleStopConversation = () => {
controllerRef.current?.abort?.(); controllerRef.current?.abort?.();
@@ -3,7 +3,7 @@ import HotKeys from '@/config/hotkeys';
import { MinusCircleOutlined } from '@ant-design/icons'; import { MinusCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button, Input, Space } from 'antd'; import { Button, Input, Space } from 'antd';
import { memo, useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { Roles } from '../config'; import { Roles } from '../config';
import '../style/message-item.less'; import '../style/message-item.less';
@@ -23,10 +23,7 @@ const MessageItem: React.FC<{
onDelete: () => void; onDelete: () => void;
}> = ({ message, isFocus, onDelete, updateMessage, onSubmit, loading }) => { }> = ({ message, isFocus, onDelete, updateMessage, onSubmit, loading }) => {
const intl = useIntl(); const intl = useIntl();
const [roleType, setRoleType] = useState(message.role);
const [isTyping, setIsTyping] = useState(false); const [isTyping, setIsTyping] = useState(false);
const [messageContent, setMessageContent] = useState(message.content);
const isInitialRender = useRef(true);
const [isAnimating, setIsAnimating] = useState(false); const [isAnimating, setIsAnimating] = useState(false);
const [currentIsFocus, setCurrentIsFocus] = useState(isFocus); const [currentIsFocus, setCurrentIsFocus] = useState(isFocus);
const inputRef = useRef<any>(null); const inputRef = useRef<any>(null);
@@ -57,29 +54,20 @@ const MessageItem: React.FC<{
// return () => clearInterval(intervalId); // return () => clearInterval(intervalId);
// }, [message.content, isTyping]); // }, [message.content, isTyping]);
useEffect(() => { const handleUpdateMessage = (params: { role: string; message: string }) => {
setMessageContent(message.content);
}, [message.content]);
useEffect(() => {
if (!isInitialRender.current) {
updateMessage({ updateMessage({
role: roleType, role: params.role,
content: messageContent, content: params.message,
uid: message.uid uid: message.uid
}); });
} else { };
isInitialRender.current = false;
}
}, [roleType, messageContent]);
const handleMessageChange = (e: any) => { const handleMessageChange = (e: any) => {
setIsTyping(true); // setIsTyping(true);
setMessageContent(e.target.value); handleUpdateMessage({ role: message.role, message: e.target.value });
}; };
const handleBlur = () => { const handleBlur = () => {
setIsTyping(true); // setIsTyping(true);
setCurrentIsFocus(false); setCurrentIsFocus(false);
}; };
@@ -88,11 +76,10 @@ const MessageItem: React.FC<{
}; };
const handleRoleChange = () => { const handleRoleChange = () => {
setRoleType((prevRoleType) => {
const newRoleType = const newRoleType =
prevRoleType === Roles.User ? Roles.Assistant : Roles.User; message.role === Roles.User ? Roles.Assistant : Roles.User;
return newRoleType;
}); handleUpdateMessage({ role: newRoleType, message: message.content });
}; };
const handleDelete = () => { const handleDelete = () => {
@@ -116,14 +103,14 @@ const MessageItem: React.FC<{
<div className="message-item"> <div className="message-item">
<div className="role-type"> <div className="role-type">
<Button onClick={handleRoleChange} type="text"> <Button onClick={handleRoleChange} type="text">
{intl.formatMessage({ id: `playground.${roleType}` })} {intl.formatMessage({ id: `playground.${message.role}` })}
</Button> </Button>
</div> </div>
<div className="message-content-input"> <div className="message-content-input">
<Input.TextArea <Input.TextArea
ref={inputRef} ref={inputRef}
style={{ paddingBlock: '12px' }} style={{ paddingBlock: '12px' }}
value={messageContent} value={message.content}
autoSize={true} autoSize={true}
variant="filled" variant="filled"
readOnly={loading} readOnly={loading}
@@ -134,8 +121,8 @@ const MessageItem: React.FC<{
</div> </div>
<div className="delete-btn"> <div className="delete-btn">
<Space size={5}> <Space size={5}>
{messageContent && ( {message.content && (
<CopyButton text={messageContent} size="small"></CopyButton> <CopyButton text={message.content} size="small"></CopyButton>
)} )}
<Button <Button
type="text" type="text"
@@ -151,4 +138,4 @@ const MessageItem: React.FC<{
); );
}; };
export default memo(MessageItem); export default MessageItem;
@@ -112,13 +112,15 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
style={{ width: INPUT_WIDTH.mini }} style={{ width: INPUT_WIDTH.mini }}
> >
<span className="text"> <span className="text">
<span> {args.label}</span> {args.description ? (
{args.description && (
<span className="m-l-5">
<Tooltip title={args.description}> <Tooltip title={args.description}>
<span> {args.label}</span>
<span className="m-l-5">
<InfoCircleOutlined /> <InfoCircleOutlined />
</Tooltip>
</span> </span>
</Tooltip>
) : (
<span>{args.label}</span>
)} )}
</span> </span>
@@ -240,26 +242,14 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
name="seed" name="seed"
rules={[{ required: true }]} rules={[{ required: true }]}
> >
<FieldWrapper <SealInput.Number
label={renderLabel({ label="Seed"
field: 'seed', min={0}
label: 'Seed', description={intl.formatMessage({
description: intl.formatMessage({
id: 'playground.params.seed.tips' id: 'playground.params.seed.tips'
})
})} })}
style={{ paddingInline: 0 }} style={{ width: INPUT_WIDTH.mini }}
variant="borderless" ></SealInput.Number>
>
<Slider
defaultValue={undefined}
step={1}
tooltip={{ open: false }}
value={form.getFieldValue('seed') || undefined}
onChange={(val) => handleFieldValueChange(val, 'seed')}
style={{ marginBottom: 0, marginTop: 16 }}
></Slider>
</FieldWrapper>
</Form.Item> </Form.Item>
<Form.Item<ParamsSettingsFormProps> <Form.Item<ParamsSettingsFormProps>
name="stop" name="stop"
+1
View File
@@ -116,6 +116,7 @@ const Profile: React.FC = () => {
> >
<SealInput.Password <SealInput.Password
required={true} required={true}
style={{ width: INPUT_WIDTH.default }}
label={intl.formatMessage({ id: 'users.password.confirm' })} label={intl.formatMessage({ id: 'users.password.confirm' })}
/> />
</Form.Item> </Form.Item>
+1 -1
View File
@@ -217,7 +217,7 @@ const Resources: React.FC = () => {
return ( return (
<StatusTag <StatusTag
statusValue={{ statusValue={{
status: ['Inactive', 'unknown'].includes(record.state) status: ['Inactive', 'Unknown'].includes(record.state)
? 'inactive' ? 'inactive'
: 'success', : 'success',
text: record.state text: record.state