chore: npu ux for add worker
This commit is contained in:
@@ -280,3 +280,29 @@
|
|||||||
.color-white-light-4 {
|
.color-white-light-4 {
|
||||||
color: var(--color-white-light-4);
|
color: var(--color-white-light-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
padding-inline: 6px 0;
|
||||||
|
padding-block: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea::-webkit-scrollbar {
|
||||||
|
width: var(--scrollbar-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea::-webkit-scrollbar-track {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea::-webkit-scrollbar-thumb {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:hover {
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--color-scrollbar-thumb);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
.editor-header {
|
.editor-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 40px;
|
padding-block: 0;
|
||||||
padding: 0 10px;
|
padding-inline: 12px 10px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: rgb(56, 56, 56);
|
background-color: rgb(56, 56, 56);
|
||||||
|
|||||||
@@ -1,33 +1,40 @@
|
|||||||
import { Select } from 'antd';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
import CopyButton from '../copy-button';
|
import CopyButton from '../copy-button';
|
||||||
|
import SegmentLine from '../segment-line';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
|
const Wrapper = styled.div<{ $height: number }>`
|
||||||
|
height: ${(props) => props.$height}px;
|
||||||
|
`;
|
||||||
|
|
||||||
interface EditorwrapProps {
|
interface EditorwrapProps {
|
||||||
|
headerHeight?: number;
|
||||||
header?: React.ReactNode;
|
header?: React.ReactNode;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
showHeader?: boolean;
|
showHeader?: boolean;
|
||||||
copyText: string;
|
copyText: string;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
langOptions?: { label: string; value: string }[];
|
langOptions?: Global.BaseOption<string | number>[];
|
||||||
styles?: {
|
styles?: {
|
||||||
wrapper?: React.CSSProperties;
|
wrapper?: React.CSSProperties;
|
||||||
header?: React.CSSProperties;
|
header?: React.CSSProperties;
|
||||||
content?: React.CSSProperties;
|
content?: React.CSSProperties;
|
||||||
};
|
};
|
||||||
onChangeLang?: (value: string) => void;
|
onChangeLang?: (value: string | number) => void;
|
||||||
}
|
}
|
||||||
const EditorWrap: React.FC<EditorwrapProps> = ({
|
const EditorWrap: React.FC<EditorwrapProps> = ({
|
||||||
|
headerHeight = 40,
|
||||||
header,
|
header,
|
||||||
children,
|
children,
|
||||||
copyText,
|
copyText,
|
||||||
langOptions,
|
langOptions = [],
|
||||||
onChangeLang,
|
onChangeLang,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
styles = {},
|
styles = {},
|
||||||
showHeader = true
|
showHeader = true
|
||||||
}) => {
|
}) => {
|
||||||
const handleChangeLang = (value: string) => {
|
const handleChangeLang = (value: string | number) => {
|
||||||
onChangeLang?.(value);
|
onChangeLang?.(value);
|
||||||
};
|
};
|
||||||
const renderHeader = () => {
|
const renderHeader = () => {
|
||||||
@@ -36,15 +43,14 @@ const EditorWrap: React.FC<EditorwrapProps> = ({
|
|||||||
}
|
}
|
||||||
if (showHeader) {
|
if (showHeader) {
|
||||||
return (
|
return (
|
||||||
<div className="editor-header">
|
<Wrapper className="editor-header" $height={headerHeight}>
|
||||||
<Select
|
<SegmentLine
|
||||||
|
height={headerHeight}
|
||||||
defaultValue={defaultValue}
|
defaultValue={defaultValue}
|
||||||
style={{ width: 120 }}
|
size="small"
|
||||||
size="middle"
|
|
||||||
variant="filled"
|
|
||||||
options={langOptions}
|
options={langOptions}
|
||||||
onChange={handleChangeLang}
|
onChange={handleChangeLang}
|
||||||
></Select>
|
></SegmentLine>
|
||||||
<CopyButton
|
<CopyButton
|
||||||
text={copyText}
|
text={copyText}
|
||||||
size="small"
|
size="small"
|
||||||
@@ -52,7 +58,7 @@ const EditorWrap: React.FC<EditorwrapProps> = ({
|
|||||||
color: 'rgba(255,255,255,.7)'
|
color: 'rgba(255,255,255,.7)'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -107,4 +107,7 @@ export default {
|
|||||||
Password: SealPassword,
|
Password: SealPassword,
|
||||||
Number: SealInputNumber,
|
Number: SealInputNumber,
|
||||||
Search: SealInputSearch
|
Search: SealInputSearch
|
||||||
} as Record<string, React.FC<InputProps & SealFormItemProps>>;
|
} as Record<
|
||||||
|
string,
|
||||||
|
React.FC<InputProps & SealFormItemProps & { scaleSize?: boolean }>
|
||||||
|
>;
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
import { Form, Input } from 'antd';
|
import { Form, Input } from 'antd';
|
||||||
import type { TextAreaProps } from 'antd/es/input/TextArea';
|
import type { TextAreaProps } from 'antd/es/input/TextArea';
|
||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, {
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState
|
||||||
|
} from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
import { SealFormItemProps } from './types';
|
import { SealFormItemProps } from './types';
|
||||||
import Wrapper from './wrapper';
|
import Wrapper from './wrapper';
|
||||||
import InputWrapper from './wrapper/input';
|
import InputWrapper from './wrapper/input';
|
||||||
|
|
||||||
const SealTextArea: React.FC<TextAreaProps & SealFormItemProps> = (props) => {
|
const LabelWrapper = styled.div`
|
||||||
|
background-color: var(--color-white-1);
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface InputTextareaProps extends TextAreaProps {
|
||||||
|
scaleSize?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SealTextArea: React.FC<InputTextareaProps & SealFormItemProps> = (
|
||||||
|
props
|
||||||
|
) => {
|
||||||
const {
|
const {
|
||||||
label,
|
label,
|
||||||
placeholder,
|
placeholder,
|
||||||
@@ -21,6 +38,7 @@ const SealTextArea: React.FC<TextAreaProps & SealFormItemProps> = (props) => {
|
|||||||
extra,
|
extra,
|
||||||
addAfter,
|
addAfter,
|
||||||
trim,
|
trim,
|
||||||
|
scaleSize,
|
||||||
...rest
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
const [isFocus, setIsFocus] = useState(false);
|
const [isFocus, setIsFocus] = useState(false);
|
||||||
@@ -37,6 +55,16 @@ const SealTextArea: React.FC<TextAreaProps & SealFormItemProps> = (props) => {
|
|||||||
}
|
}
|
||||||
}, [props.value]);
|
}, [props.value]);
|
||||||
|
|
||||||
|
const autoSize = useMemo(() => {
|
||||||
|
const focusRows = props.autoSize || { minRows: 2, maxRows: 5 };
|
||||||
|
|
||||||
|
if (scaleSize) {
|
||||||
|
return isFocus ? focusRows : { minRows: 1, maxRows: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
return focusRows;
|
||||||
|
}, [props.autoSize, isFocus, scaleSize]);
|
||||||
|
|
||||||
const handleClickWrapper = useCallback(() => {
|
const handleClickWrapper = useCallback(() => {
|
||||||
if (!props.disabled && !isFocus) {
|
if (!props.disabled && !isFocus) {
|
||||||
inputRef.current?.focus?.({
|
inputRef.current?.focus?.({
|
||||||
@@ -68,7 +96,7 @@ const SealTextArea: React.FC<TextAreaProps & SealFormItemProps> = (props) => {
|
|||||||
onBlur?.(e);
|
onBlur?.(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onBlur]
|
[onBlur, scaleSize]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleInput = useCallback(
|
const handleInput = useCallback(
|
||||||
@@ -82,7 +110,7 @@ const SealTextArea: React.FC<TextAreaProps & SealFormItemProps> = (props) => {
|
|||||||
<InputWrapper>
|
<InputWrapper>
|
||||||
<Wrapper
|
<Wrapper
|
||||||
status={status}
|
status={status}
|
||||||
label={label}
|
label={<LabelWrapper>{label}</LabelWrapper>}
|
||||||
isFocus={isFocus}
|
isFocus={isFocus}
|
||||||
required={required}
|
required={required}
|
||||||
description={description}
|
description={description}
|
||||||
@@ -94,7 +122,7 @@ const SealTextArea: React.FC<TextAreaProps & SealFormItemProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
{...rest}
|
{...rest}
|
||||||
autoSize={rest.autoSize || { minRows: 2, maxRows: 5 }}
|
autoSize={autoSize}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
style={{ minHeight: '80px', ...style }}
|
style={{ minHeight: '80px', ...style }}
|
||||||
className="seal-textarea"
|
className="seal-textarea"
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ export const Label = styled.div.attrs<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.blur-no-value {
|
&.blur-no-value {
|
||||||
top: 21px;
|
top: 20px;
|
||||||
transition: all 0.2s var(--seal-transition-func);
|
transition: all 0.2s var(--seal-transition-func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ const InputWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
.seal-textarea-wrapper {
|
.seal-textarea-wrapper {
|
||||||
height: auto;
|
height: auto;
|
||||||
padding-bottom: 10px;
|
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { Segmented, type SegmentedProps } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
interface SegmentLineProps extends SegmentedProps {
|
||||||
|
height?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SegmentedQwrapper = styled.div<{ $height: number }>`
|
||||||
|
.ant-segmented.segment-line {
|
||||||
|
padding: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--color-white-tertiary);
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
height: ${(props) => props.$height}px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.ant-segmented-group {
|
||||||
|
gap: 16px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.ant-segmented-item:hover {
|
||||||
|
color: var(--color-white-secondary);
|
||||||
|
}
|
||||||
|
.ant-segmented-thumb {
|
||||||
|
height: 2px;
|
||||||
|
padding: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
top: unset;
|
||||||
|
}
|
||||||
|
.ant-segmented-item-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
}
|
||||||
|
.ant-segmented-item {
|
||||||
|
background-color: transparent;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
&::after {
|
||||||
|
background-color: var(--color-white-primary) !important;
|
||||||
|
width: 100%;
|
||||||
|
height: 0px;
|
||||||
|
border-radius: 2px;
|
||||||
|
bottom: 0px;
|
||||||
|
top: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-segmented-item-selected {
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--color-white-primary);
|
||||||
|
&::after {
|
||||||
|
height: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const SegmentLine: React.FC<SegmentLineProps> = (props) => {
|
||||||
|
const {
|
||||||
|
height = 32,
|
||||||
|
size = 'small',
|
||||||
|
options = [],
|
||||||
|
className = 'segment-line',
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
return (
|
||||||
|
<SegmentedQwrapper $height={height}>
|
||||||
|
<Segmented
|
||||||
|
{...rest}
|
||||||
|
size={size}
|
||||||
|
options={options}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
</SegmentedQwrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SegmentLine.displayName = 'SegmentLine';
|
||||||
|
|
||||||
|
export default SegmentLine;
|
||||||
@@ -21,8 +21,7 @@ export default {
|
|||||||
'model.form.ollama.model': 'Ollama Model',
|
'model.form.ollama.model': 'Ollama Model',
|
||||||
'model.form.ollamaholder': 'Please select or input model name',
|
'model.form.ollamaholder': 'Please select or input model name',
|
||||||
'model.deploy.sort': 'Sort',
|
'model.deploy.sort': 'Sort',
|
||||||
'model.deploy.search.placeholder':
|
'model.deploy.search.placeholder': 'Type <kbd>/</kbd> to search models',
|
||||||
'Type <kbd>/</kbd> to search models from {source}',
|
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
'Tip: The following are the preconfigured Ollama models in GPUStack. Please select the model you want, or directly enter the model you wish to deploy in the 【{name}】 input box on the right.',
|
'Tip: The following are the preconfigured Ollama models in GPUStack. Please select the model you want, or directly enter the model you wish to deploy in the 【{name}】 input box on the right.',
|
||||||
'models.sort.name': 'Name',
|
'models.sort.name': 'Name',
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ export default {
|
|||||||
'model.form.ollama.model': 'Ollamaモデル',
|
'model.form.ollama.model': 'Ollamaモデル',
|
||||||
'model.form.ollamaholder': 'モデル名を選択または入力してください',
|
'model.form.ollamaholder': 'モデル名を選択または入力してください',
|
||||||
'model.deploy.sort': '並び替え',
|
'model.deploy.sort': '並び替え',
|
||||||
'model.deploy.search.placeholder':
|
'model.deploy.search.placeholder': 'Type <kbd>/</kbd> to search models',
|
||||||
'Type <kbd>/</kbd> to search models from {source}',
|
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
'ヒント: 以下はGPUStackで事前設定されたOllamaモデルです。希望するモデルを選択するか、右側の【{name}】入力ボックスにデプロイしたいモデルを直接入力してください。',
|
'ヒント: 以下はGPUStackで事前設定されたOllamaモデルです。希望するモデルを選択するか、右側の【{name}】入力ボックスにデプロイしたいモデルを直接入力してください。',
|
||||||
'models.sort.name': '名前',
|
'models.sort.name': '名前',
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ export default {
|
|||||||
'model.form.ollama.model': 'Модель Ollama',
|
'model.form.ollama.model': 'Модель Ollama',
|
||||||
'model.form.ollamaholder': 'Выберите или введите название модели',
|
'model.form.ollamaholder': 'Выберите или введите название модели',
|
||||||
'model.deploy.sort': 'Сортировка',
|
'model.deploy.sort': 'Сортировка',
|
||||||
'model.deploy.search.placeholder':
|
'model.deploy.search.placeholder': 'Type <kbd>/</kbd> to search models',
|
||||||
'Type <kbd>/</kbd> to search models from {source}',
|
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
'Подсказка: ниже представлены предустановленные модели Ollama в GPUStack. Выберите нужную или введите модель для развертывания в поле 【{name}】 справа.',
|
'Подсказка: ниже представлены предустановленные модели Ollama в GPUStack. Выберите нужную или введите модель для развертывания в поле 【{name}】 справа.',
|
||||||
'models.sort.name': 'По имени',
|
'models.sort.name': 'По имени',
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default {
|
|||||||
'model.form.ollama.model': 'Ollama 模型',
|
'model.form.ollama.model': 'Ollama 模型',
|
||||||
'model.form.ollamaholder': '请选择或输入模型名称',
|
'model.form.ollamaholder': '请选择或输入模型名称',
|
||||||
'model.deploy.sort': '排序',
|
'model.deploy.sort': '排序',
|
||||||
'model.deploy.search.placeholder': '按 <kbd>/</kbd> 开始从 {source} 搜索模型',
|
'model.deploy.search.placeholder': '按 <kbd>/</kbd> 开始搜索模型',
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
'提示:以下为 GPUStack 预设的 Ollama 模型,请选择你想要的模型或者直接在右侧表单 【{name}】 输入框中输入你要部署的模型。',
|
'提示:以下为 GPUStack 预设的 Ollama 模型,请选择你想要的模型或者直接在右侧表单 【{name}】 输入框中输入你要部署的模型。',
|
||||||
'models.sort.name': '名称',
|
'models.sort.name': '名称',
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ interface CompatibilityAlertProps {
|
|||||||
|
|
||||||
const DivWrapper = styled.div`
|
const DivWrapper = styled.div`
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-inline: 8px;
|
padding-inline: 24px;
|
||||||
|
padding-block: 10px 0;
|
||||||
&:hover {
|
&:hover {
|
||||||
.close-wrapper {
|
.close-wrapper {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -36,11 +37,10 @@ const DivWrapper = styled.div`
|
|||||||
const CloseWrapper = styled.div`
|
const CloseWrapper = styled.div`
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 6px;
|
top: 14px;
|
||||||
right: 12px;
|
right: 28px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: var(--ant-color-warning-bg);
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const MessageWrapper = styled.div`
|
const MessageWrapper = styled.div`
|
||||||
@@ -104,7 +104,7 @@ const CompatibilityAlert: React.FC<CompatibilityAlertProps> = (props) => {
|
|||||||
type={type || 'warning'}
|
type={type || 'warning'}
|
||||||
icon={renderIcon}
|
icon={renderIcon}
|
||||||
></AlertBlockInfo>
|
></AlertBlockInfo>
|
||||||
{showClose && !['transition', 'success'].includes(type) && (
|
{showClose && !['transition'].includes(type) && (
|
||||||
<CloseWrapper className="close-wrapper">
|
<CloseWrapper className="close-wrapper">
|
||||||
<Button
|
<Button
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
|
|||||||
@@ -325,6 +325,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData> name="description">
|
<Form.Item<FormData> name="description">
|
||||||
<SealInput.TextArea
|
<SealInput.TextArea
|
||||||
|
scaleSize={true}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: 'common.table.description'
|
id: 'common.table.description'
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -320,13 +320,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<FormWrapper>
|
<FormWrapper>
|
||||||
<ColumnWrapper
|
<ColumnWrapper
|
||||||
paddingBottom={
|
paddingBottom={warningStatus.show ? 170 : 50}
|
||||||
warningStatus.show
|
|
||||||
? Array.isArray(warningStatus.message)
|
|
||||||
? 150
|
|
||||||
: 125
|
|
||||||
: 50
|
|
||||||
}
|
|
||||||
footer={
|
footer={
|
||||||
<>
|
<>
|
||||||
<CompatibilityAlert
|
<CompatibilityAlert
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const CompatibleTag = styled(Tag)`
|
|||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
|
padding-inline: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ClaimTag = styled(Tag)`
|
const ClaimTag = styled(Tag)`
|
||||||
|
|||||||
@@ -432,11 +432,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
<ColumnWrapper
|
<ColumnWrapper
|
||||||
maxHeight={550}
|
maxHeight={550}
|
||||||
paddingBottom={
|
paddingBottom={
|
||||||
warningStatus.show
|
warningStatus.show ? (warningStatus.isDefault ? 50 : 100) : 0
|
||||||
? Array.isArray(warningStatus.message)
|
|
||||||
? 100
|
|
||||||
: 70
|
|
||||||
: 0
|
|
||||||
}
|
}
|
||||||
footer={
|
footer={
|
||||||
<>
|
<>
|
||||||
@@ -584,6 +580,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData> name="description">
|
<Form.Item<FormData> name="description">
|
||||||
<SealInput.TextArea
|
<SealInput.TextArea
|
||||||
|
scaleSize={true}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: 'common.table.description'
|
id: 'common.table.description'
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.hf-model-item {
|
.hf-model-item {
|
||||||
height: 80px;
|
min-height: 82px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
|||||||
const { title, open, onCancel, viewCodeContent } = props || {};
|
const { title, open, onCancel, viewCodeContent } = props || {};
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [lang, setLang] = useState(langMap.shell);
|
const [lang, setLang] = useState<string>(langMap.shell);
|
||||||
|
|
||||||
const codeValue = useMemo(() => {
|
const codeValue = useMemo(() => {
|
||||||
if (lang === langMap.shell) {
|
if (lang === langMap.shell) {
|
||||||
@@ -47,8 +47,8 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
|||||||
return '';
|
return '';
|
||||||
}, [lang, viewCodeContent]);
|
}, [lang, viewCodeContent]);
|
||||||
|
|
||||||
const handleOnChangeLang = (value: string) => {
|
const handleOnChangeLang = (value: string | number) => {
|
||||||
setLang(value);
|
setLang(value as string);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { GPUStackVersionAtom } from '@/atoms/user';
|
import { GPUStackVersionAtom } from '@/atoms/user';
|
||||||
import { getAtomStorage } from '@/atoms/utils';
|
import { getAtomStorage } from '@/atoms/utils';
|
||||||
|
import EditorWrap from '@/components/editor-wrap';
|
||||||
import HighlightCode from '@/components/highlight-code';
|
import HighlightCode from '@/components/highlight-code';
|
||||||
import { WarningOutlined } from '@ant-design/icons';
|
import { WarningOutlined } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
@@ -12,11 +13,17 @@ type ViewModalProps = {
|
|||||||
token: string;
|
token: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const npuOptions = [
|
||||||
|
{ label: '910B', value: 'npu' },
|
||||||
|
{ label: '310P', value: 'npu310p' }
|
||||||
|
];
|
||||||
|
|
||||||
const AddWorker: React.FC<ViewModalProps> = (props) => {
|
const AddWorker: React.FC<ViewModalProps> = (props) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const origin = window.location.origin;
|
const origin = window.location.origin;
|
||||||
const [activeKey, setActiveKey] = React.useState('cuda');
|
const [activeKey, setActiveKey] = React.useState('cuda');
|
||||||
|
const [npuKey, setNpuKey] = React.useState('npu');
|
||||||
const versionInfo = getAtomStorage(GPUStackVersionAtom);
|
const versionInfo = getAtomStorage(GPUStackVersionAtom);
|
||||||
|
|
||||||
const code = React.useMemo(() => {
|
const code = React.useMemo(() => {
|
||||||
@@ -25,7 +32,11 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
|
|||||||
version = 'main';
|
version = 'main';
|
||||||
}
|
}
|
||||||
|
|
||||||
const commandCode = addWorkerGuide[activeKey];
|
let commandCode = addWorkerGuide[activeKey];
|
||||||
|
|
||||||
|
if (npuKey === 'npu310p') {
|
||||||
|
commandCode = addWorkerGuide[npuKey];
|
||||||
|
}
|
||||||
|
|
||||||
if (activeKey === 'cuda') {
|
if (activeKey === 'cuda') {
|
||||||
return commandCode?.registerWorker({
|
return commandCode?.registerWorker({
|
||||||
@@ -41,20 +52,15 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
|
|||||||
token: '${token}',
|
token: '${token}',
|
||||||
workerip: '${workerip}'
|
workerip: '${workerip}'
|
||||||
});
|
});
|
||||||
}, [versionInfo, activeKey, props.token]);
|
}, [versionInfo, activeKey, props.token, npuKey]);
|
||||||
|
|
||||||
|
const handleOnChange = (value: string | number) => {
|
||||||
|
setNpuKey(value as string);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container-install">
|
<div className="container-install">
|
||||||
<ul className="notes">
|
<ul className="notes">
|
||||||
<li>
|
|
||||||
<span>
|
|
||||||
{intl.formatMessage({ id: 'resources.worker.container.supported' })}
|
|
||||||
</span>
|
|
||||||
<WarningOutlined
|
|
||||||
style={{ color: 'var(--ant-color-warning)' }}
|
|
||||||
className="font-size-14 m-l-5"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
{intl.formatMessage(
|
{intl.formatMessage(
|
||||||
{ id: 'resources.worker.current.version' },
|
{ id: 'resources.worker.current.version' },
|
||||||
@@ -125,7 +131,31 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
<HighlightCode theme="dark" code={code} lang="bash"></HighlightCode>
|
{activeKey === 'npu' ? (
|
||||||
|
<EditorWrap
|
||||||
|
headerHeight={32}
|
||||||
|
copyText={code}
|
||||||
|
langOptions={npuOptions}
|
||||||
|
defaultValue="npu"
|
||||||
|
showHeader={true}
|
||||||
|
onChangeLang={handleOnChange}
|
||||||
|
styles={{
|
||||||
|
wrapper: {
|
||||||
|
backgroundColor: 'var(--color-editor-dark)'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HighlightCode
|
||||||
|
theme="dark"
|
||||||
|
code={code}
|
||||||
|
lang="bash"
|
||||||
|
copyable={false}
|
||||||
|
height={160}
|
||||||
|
></HighlightCode>
|
||||||
|
</EditorWrap>
|
||||||
|
) : (
|
||||||
|
<HighlightCode theme="dark" code={code} lang="bash"></HighlightCode>
|
||||||
|
)}
|
||||||
<h3 className="m-b-0 m-t-10 font-size-14 font-600">
|
<h3 className="m-b-0 m-t-10 font-size-14 font-600">
|
||||||
3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}
|
3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}
|
||||||
</h3>
|
</h3>
|
||||||
|
|||||||
Reference in New Issue
Block a user