This commit is contained in:
josc146 2023-05-19 10:08:28 +08:00
parent de7d6b3417
commit bb8d121991
7 changed files with 107 additions and 36 deletions

View File

@ -7,8 +7,10 @@
"Manage your configs": "管理你的配置", "Manage your configs": "管理你的配置",
"Manage models": "管理模型", "Manage models": "管理模型",
"Run": "运行", "Run": "运行",
"Offline": "离线",
"Starting": "启动中", "Starting": "启动中",
"Loading": "读取模型中", "Loading": "读取模型中",
"Working": "运行中",
"Stop": "停止", "Stop": "停止",
"Enable High Precision For Last Layer": "输出层使用高精度", "Enable High Precision For Last Layer": "输出层使用高精度",
"Stored Layers": "载入显存层数", "Stored Layers": "载入显存层数",
@ -60,5 +62,6 @@
"Start Converting": "开始转换", "Start Converting": "开始转换",
"Convert Success": "转换成功", "Convert Success": "转换成功",
"Convert Failed": "转换失败", "Convert Failed": "转换失败",
"Model Not Found": "模型不存在" "Model Not Found": "模型不存在",
"Model Status": "模型状态"
} }

View File

@ -0,0 +1,18 @@
import {FC} from 'react';
import {observer} from 'mobx-react-lite';
import {Dropdown, Option} from '@fluentui/react-components';
import commonStore from '../stores/commonStore';
export const ConfigSelector: FC<{ size?: 'small' | 'medium' | 'large' }> = observer(({size}) => {
return <Dropdown size={size} style={{minWidth: 0}} listbox={{style: {minWidth: 0}}}
value={commonStore.getCurrentModelConfig().name}
selectedOptions={[commonStore.currentModelConfigIndex.toString()]}
onOptionSelect={(_, data) => {
if (data.optionValue)
commonStore.setCurrentConfigIndex(Number(data.optionValue));
}}>
{commonStore.modelConfigs.map((config, index) =>
<Option key={index} value={index.toString()}>{config.name}</Option>
)}
</Dropdown>;
});

View File

@ -1,4 +1,4 @@
import React, {FC, MouseEventHandler} from 'react'; import React, {FC, MouseEventHandler, ReactElement} from 'react';
import commonStore, {ModelStatus} from '../stores/commonStore'; import commonStore, {ModelStatus} from '../stores/commonStore';
import {StartServer} from '../../wailsjs/go/backend_golang/App'; import {StartServer} from '../../wailsjs/go/backend_golang/App';
import {Button} from '@fluentui/react-components'; import {Button} from '@fluentui/react-components';
@ -9,6 +9,8 @@ import manifest from '../../../manifest.json';
import {getStrategy} from '../utils'; import {getStrategy} from '../utils';
import {useTranslation} from 'react-i18next'; import {useTranslation} from 'react-i18next';
import {t} from 'i18next'; import {t} from 'i18next';
import {ToolTipButton} from './ToolTipButton';
import {Play16Regular, Stop16Regular} from '@fluentui/react-icons';
const mainButtonText = { const mainButtonText = {
[ModelStatus.Offline]: 'Run', [ModelStatus.Offline]: 'Run',
@ -17,6 +19,13 @@ const mainButtonText = {
[ModelStatus.Working]: 'Stop' [ModelStatus.Working]: 'Stop'
}; };
const iconModeButtonIcon: { [modelStatus: number]: ReactElement } = {
[ModelStatus.Offline]: <Play16Regular/>,
[ModelStatus.Starting]: <Stop16Regular/>,
[ModelStatus.Loading]: <Stop16Regular/>,
[ModelStatus.Working]: <Stop16Regular/>
};
const onClickMainButton = async () => { const onClickMainButton = async () => {
const modelConfig = commonStore.getCurrentModelConfig(); const modelConfig = commonStore.getCurrentModelConfig();
const port = modelConfig.apiParameters.apiPort; const port = modelConfig.apiParameters.apiPort;
@ -74,17 +83,28 @@ const onClickMainButton = async () => {
} }
}; };
export const RunButton: FC<{ onClickRun?: MouseEventHandler }> = observer(({onClickRun}) => { export const RunButton: FC<{ onClickRun?: MouseEventHandler, iconMode?: boolean }>
= observer(({
onClickRun,
iconMode
}) => {
const {t} = useTranslation(); const {t} = useTranslation();
return ( const onClick = async (e: any) => {
<Button disabled={commonStore.modelStatus === ModelStatus.Starting} appearance="primary" size="large" if (commonStore.modelStatus === ModelStatus.Offline)
onClick={async (e) => { await onClickRun?.(e);
if (commonStore.modelStatus === ModelStatus.Offline) await onClickMainButton();
await onClickRun?.(e); };
await onClickMainButton();
}}> return (iconMode ?
{t(mainButtonText[commonStore.modelStatus])} <ToolTipButton disabled={commonStore.modelStatus === ModelStatus.Starting}
</Button> icon={iconModeButtonIcon[commonStore.modelStatus]}
desc={t(mainButtonText[commonStore.modelStatus])}
size="small" onClick={onClick}/>
:
<Button disabled={commonStore.modelStatus === ModelStatus.Starting} appearance="primary" size="large"
onClick={onClick}>
{t(mainButtonText[commonStore.modelStatus])}
</Button>
); );
}); });

View File

@ -2,16 +2,23 @@ import React, {FC, MouseEventHandler, ReactElement} from 'react';
import {Button, Tooltip} from '@fluentui/react-components'; import {Button, Tooltip} from '@fluentui/react-components';
export const ToolTipButton: FC<{ export const ToolTipButton: FC<{
text?: string | null, desc: string, icon?: ReactElement, onClick?: MouseEventHandler text?: string | null,
desc: string,
icon?: ReactElement,
size?: 'small' | 'medium' | 'large',
disabled?: boolean,
onClick?: MouseEventHandler
}> = ({ }> = ({
text, text,
desc, desc,
icon, icon,
size,
disabled,
onClick onClick
}) => { }) => {
return ( return (
<Tooltip content={desc} showDelay={0} hideDelay={0} relationship="label"> <Tooltip content={desc} showDelay={0} hideDelay={0} relationship="label">
<Button icon={icon} onClick={onClick}>{text}</Button> <Button disabled={disabled} icon={icon} onClick={onClick} size={size}>{text}</Button>
</Tooltip> </Tooltip>
); );
}; };

View File

@ -1,16 +1,49 @@
import React, {FC} from 'react'; import React, {FC} from 'react';
import {Page} from '../components/Page';
import {PresenceBadge} from '@fluentui/react-components';
import {useTranslation} from 'react-i18next'; import {useTranslation} from 'react-i18next';
import {RunButton} from '../components/RunButton';
import {Divider, PresenceBadge, Text} from '@fluentui/react-components';
import commonStore, {ModelStatus} from '../stores/commonStore';
import {observer} from 'mobx-react-lite';
import {PresenceBadgeStatus} from '@fluentui/react-badge';
import {ConfigSelector} from '../components/ConfigSelector';
export const Chat: FC = () => { const ChatPanel: FC = () => {
return (
<div></div>
);
};
const statusText = {
[ModelStatus.Offline]: 'Offline',
[ModelStatus.Starting]: 'Starting',
[ModelStatus.Loading]: 'Loading',
[ModelStatus.Working]: 'Working'
};
const badgeStatus: { [modelStatus: number]: PresenceBadgeStatus } = {
[ModelStatus.Offline]: 'unknown',
[ModelStatus.Starting]: 'away',
[ModelStatus.Loading]: 'away',
[ModelStatus.Working]: 'available'
};
export const Chat: FC = observer(() => {
const {t} = useTranslation(); const {t} = useTranslation();
return ( return (
<Page title={t('Chat')} content={ <div className="flex flex-col gap-1 p-2 h-full overflow-hidden">
<div className="flex flex-col gap-2 overflow-hidden"> <div className="flex justify-between items-center">
<PresenceBadge/> <div className="flex items-center gap-2">
<PresenceBadge status={badgeStatus[commonStore.modelStatus]}/>
<Text size={100}>{t('Model Status') + ': ' + t(statusText[commonStore.modelStatus])}</Text>
</div>
<div className="flex items-center gap-2">
<ConfigSelector size="small"/>
<RunButton iconMode/>
</div>
</div> </div>
}/> <Divider style={{flexGrow: 0}}/>
<ChatPanel/>
</div>
); );
}; });

View File

@ -1,4 +1,4 @@
import {CompoundButton, Dropdown, Link, Option, Text} from '@fluentui/react-components'; import {CompoundButton, Link, Text} from '@fluentui/react-components';
import React, {FC, ReactElement} from 'react'; import React, {FC, ReactElement} from 'react';
import banner from '../assets/images/banner.jpg'; import banner from '../assets/images/banner.jpg';
import { import {
@ -8,12 +8,12 @@ import {
Storage20Regular Storage20Regular
} from '@fluentui/react-icons'; } from '@fluentui/react-icons';
import {useNavigate} from 'react-router'; import {useNavigate} from 'react-router';
import commonStore from '../stores/commonStore';
import {observer} from 'mobx-react-lite'; import {observer} from 'mobx-react-lite';
import {RunButton} from '../components/RunButton'; import {RunButton} from '../components/RunButton';
import manifest from '../../../manifest.json'; import manifest from '../../../manifest.json';
import {BrowserOpenURL} from '../../wailsjs/runtime'; import {BrowserOpenURL} from '../../wailsjs/runtime';
import {useTranslation} from 'react-i18next'; import {useTranslation} from 'react-i18next';
import {ConfigSelector} from '../components/ConfigSelector';
type NavCard = { type NavCard = {
label: string; label: string;
@ -78,17 +78,7 @@ export const Home: FC = observer(() => {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="flex flex-row-reverse sm:fixed bottom-2 right-2"> <div className="flex flex-row-reverse sm:fixed bottom-2 right-2">
<div className="flex gap-3"> <div className="flex gap-3">
<Dropdown style={{minWidth: 0}} listbox={{style: {minWidth: 0}}} <ConfigSelector/>
value={commonStore.getCurrentModelConfig().name}
selectedOptions={[commonStore.currentModelConfigIndex.toString()]}
onOptionSelect={(_, data) => {
if (data.optionValue)
commonStore.setCurrentConfigIndex(Number(data.optionValue));
}}>
{commonStore.modelConfigs.map((config, index) =>
<Option key={index} value={index.toString()}>{config.name}</Option>
)}
</Dropdown>
<RunButton/> <RunButton/>
</div> </div>
</div> </div>

View File

@ -149,7 +149,7 @@ export const Models: FC = observer(() => {
<Page title={t('Models')} content={ <Page title={t('Models')} content={
<div className="flex flex-col gap-2 overflow-hidden"> <div className="flex flex-col gap-2 overflow-hidden">
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<div className="flex justify-between"> <div className="flex justify-between items-center">
<Text weight="medium">{t('Model Source Manifest List')}</Text> <Text weight="medium">{t('Model Source Manifest List')}</Text>
<ToolTipButton desc={t('Refresh')} icon={<ArrowClockwise20Regular/>} onClick={() => { <ToolTipButton desc={t('Refresh')} icon={<ArrowClockwise20Regular/>} onClick={() => {
refreshModels(false); refreshModels(false);