From 0f7d04e0b91c3d3c6fa7f1008d152efe925e94f4 Mon Sep 17 00:00:00 2001 From: jialin Date: Tue, 25 Feb 2025 14:02:22 +0800 Subject: [PATCH] fix: page error when edit error --- src/components/auto-tooltip/index.tsx | 12 +- .../seal-form/components/wrapper.less | 18 +- src/components/seal-form/seal-cascader.tsx | 44 +++-- src/components/seal-form/seal-input.tsx | 1 + src/components/seal-form/seal-select.tsx | 1 + src/components/tags-wrapper/index.tsx | 4 +- src/global.less | 3 +- src/pages/access/index.tsx | 2 +- src/pages/api-keys/index.tsx | 2 +- src/pages/dashboard/index.tsx | 2 +- src/pages/llmodels/catalog.tsx | 2 +- .../llmodels/components/advance-config.tsx | 76 ++++---- src/pages/llmodels/components/data-form.tsx | 76 +++----- .../llmodels/components/deploy-modal.tsx | 10 +- .../llmodels/components/instance-item.tsx | 3 +- src/pages/llmodels/components/table-list.tsx | 77 ++++++-- .../llmodels/components/update-modal.tsx | 173 ++++-------------- src/pages/llmodels/hooks/index.ts | 80 ++++++++ src/pages/llmodels/index.tsx | 4 + .../components/ground-embedding.tsx | 4 +- .../playground/components/ground-reranker.tsx | 2 +- src/pages/playground/embedding.tsx | 2 +- src/pages/playground/images.tsx | 2 +- src/pages/playground/index.tsx | 2 +- src/pages/playground/rerank.tsx | 2 +- src/pages/playground/speech.tsx | 2 +- src/pages/profile/index.tsx | 2 +- src/pages/resources/index.tsx | 11 +- src/pages/usage/index.tsx | 2 +- src/pages/users/index.tsx | 2 +- 30 files changed, 317 insertions(+), 306 deletions(-) create mode 100644 src/pages/llmodels/hooks/index.ts diff --git a/src/components/auto-tooltip/index.tsx b/src/components/auto-tooltip/index.tsx index 1fffa8b0..509c12e3 100644 --- a/src/components/auto-tooltip/index.tsx +++ b/src/components/auto-tooltip/index.tsx @@ -37,6 +37,7 @@ const AutoTooltip: React.FC = ({ }) => { const contentRef = useRef(null); const [isOverflowing, setIsOverflowing] = useState(false); + const resizeObserver = useRef(null); const checkOverflow = useCallback(() => { if (contentRef.current) { @@ -48,17 +49,20 @@ const AutoTooltip: React.FC = ({ useEffect(() => { const element = contentRef.current; if (!element) return; - - const resizeObserver = new ResizeObserver(() => { + resizeObserver.current?.disconnect(); + resizeObserver.current = new ResizeObserver(() => { checkOverflow(); }); - resizeObserver.observe(element); + resizeObserver.current?.observe(element); // Initial check checkOverflow(); - return () => resizeObserver.disconnect(); + return () => { + resizeObserver.current?.disconnect(); + resizeObserver.current = null; + }; }, [checkOverflow]); useEffect(() => { diff --git a/src/components/seal-form/components/wrapper.less b/src/components/seal-form/components/wrapper.less index 53a986d5..fd31ef20 100644 --- a/src/components/seal-form/components/wrapper.less +++ b/src/components/seal-form/components/wrapper.less @@ -5,7 +5,7 @@ display: flex; justify-content: flex-start; align-items: center; - padding-inline: 8px 12px; + // padding-inline: 2px 2px; height: 54px; border-width: var(--ant-line-width); border-style: var(--ant-line-type); @@ -82,7 +82,7 @@ position: relative; color: var(--ant-color-text-quaternary); font-size: 14px; - // padding-right: calc(var(--ant-padding-sm) - 1px); + padding-right: calc(var(--ant-padding-sm) - 1px); } } @@ -90,7 +90,7 @@ @wrapheight: 54px; @inputheight: 32px; @borderRadius: 8px; - @input-inner-padding: 6px; + @input-inner-padding: 14px; @bgColor: transparent; position: relative; @@ -124,7 +124,7 @@ .label { position: absolute; - left: 6px; + left: @input-inner-padding; color: rgba(0, 0, 0, 45%); font-size: var(--font-size-base); line-height: 1; @@ -172,7 +172,14 @@ } :global(.ant-select-selection-search) { - inset-inline-start: 8px !important; + inset-inline-start: @input-inner-padding; + } + + :global(.ant-select-multiple.ant-select-lg) { + :global(.ant-select-selection-search) { + margin-inline-start: 0 !important; + left: 0 !important; + } } :global(.ant-select-selection-item) { @@ -211,6 +218,7 @@ :global(.ant-select-selection-search-input) { height: @inputheight !important; } + // ==================== input ==================== :global(.ant-input), diff --git a/src/components/seal-form/seal-cascader.tsx b/src/components/seal-form/seal-cascader.tsx index 2f4835ae..46c2b1cc 100644 --- a/src/components/seal-form/seal-cascader.tsx +++ b/src/components/seal-form/seal-cascader.tsx @@ -4,6 +4,7 @@ import type { CascaderAutoProps } from 'antd'; import { Cascader, Form } from 'antd'; import { cloneDeep } from 'lodash'; import { useEffect, useMemo, useRef, useState } from 'react'; +import styled from 'styled-components'; import Wrapper from './components/wrapper'; import { SealFormItemProps } from './types'; @@ -24,6 +25,7 @@ const SealCascader: React.FC = ( const intl = useIntl(); const [isFocus, setIsFocus] = useState(false); const inputRef = useRef(null); + const boxRef = useRef(null); let status = ''; // the status can be controlled by Form.Item @@ -81,26 +83,30 @@ const SealCascader: React.FC = ( props.onBlur?.(e); }; + const Boxer = styled.div``; + return ( - - - + <> + + + + ); }; diff --git a/src/components/seal-form/seal-input.tsx b/src/components/seal-form/seal-input.tsx index d2c4a4fe..4df51b96 100644 --- a/src/components/seal-form/seal-input.tsx +++ b/src/components/seal-form/seal-input.tsx @@ -19,6 +19,7 @@ const SealInput: React.FC = (props) => { addAfter, checkStatus, trim = true, + loading, ...rest } = props; const [isFocus, setIsFocus] = useState(false); diff --git a/src/components/seal-form/seal-select.tsx b/src/components/seal-form/seal-select.tsx index 589844e8..74206264 100644 --- a/src/components/seal-form/seal-select.tsx +++ b/src/components/seal-form/seal-select.tsx @@ -22,6 +22,7 @@ const SealSelect: React.FC = (props) => { const intl = useIntl(); const [isFocus, setIsFocus] = useState(false); const inputRef = useRef(null); + const boxRef = useRef(null); let status = ''; // the status can be controlled by Form.Item diff --git a/src/components/tags-wrapper/index.tsx b/src/components/tags-wrapper/index.tsx index 1dd03749..a338f723 100644 --- a/src/components/tags-wrapper/index.tsx +++ b/src/components/tags-wrapper/index.tsx @@ -31,9 +31,9 @@ const TagsWrapper: React.FC = (props) => { if (!sizeList.length && childNodes?.length) { sizeList = _.map(childNodes, (node: HTMLDivElement, index: number) => { if (index === childNodes.length - 1) { - return node.offsetWidth; + return node?.offsetWidth; } - return node.offsetWidth + gap; + return node?.offsetWidth + gap; }); nodeSizeList.current = sizeList; } diff --git a/src/global.less b/src/global.less index 5881b33e..2b43e3e7 100644 --- a/src/global.less +++ b/src/global.less @@ -31,6 +31,7 @@ html { --color-logs-text: #d4d4d4; --layout-content-blockpadding: 32px; --layout-content-inlinepadding: 32px; + --layout-content-header-inlinepadding: 40px; --border-radius-modal: 6px; --menu-border-radius-base: 4px; --border-radius-base: 4px; @@ -797,7 +798,7 @@ body { } .cascader-popup-wrapper { - width: 100%; + // width: 100%; &.gpu-selector { .ant-cascader-menu:last-child { diff --git a/src/pages/access/index.tsx b/src/pages/access/index.tsx index db253a75..a8dc12d5 100644 --- a/src/pages/access/index.tsx +++ b/src/pages/access/index.tsx @@ -10,7 +10,7 @@ const AccessPage: React.FC = () => { header={{ title: 'permission example', style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' } }} > diff --git a/src/pages/api-keys/index.tsx b/src/pages/api-keys/index.tsx index 1adf95b6..538e4929 100644 --- a/src/pages/api-keys/index.tsx +++ b/src/pages/api-keys/index.tsx @@ -184,7 +184,7 @@ const APIKeys: React.FC = () => { header={{ title: intl.formatMessage({ id: 'apikeys.title' }), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' } }} extra={[]} diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 2e4ab311..d00cdf82 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -13,7 +13,7 @@ const Dashboard: React.FC = () => { extra={[]} header={{ style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' } }} > diff --git a/src/pages/llmodels/catalog.tsx b/src/pages/llmodels/catalog.tsx index d486a4c3..7cc44578 100644 --- a/src/pages/llmodels/catalog.tsx +++ b/src/pages/llmodels/catalog.tsx @@ -209,7 +209,7 @@ const Catalog: React.FC = () => { header={{ title: intl.formatMessage({ id: 'menu.modelCatalog' }), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' }, breadcrumb: {} }} diff --git a/src/pages/llmodels/components/advance-config.tsx b/src/pages/llmodels/components/advance-config.tsx index 043739b8..bb1c004a 100644 --- a/src/pages/llmodels/components/advance-config.tsx +++ b/src/pages/llmodels/components/advance-config.tsx @@ -39,8 +39,7 @@ interface AdvanceConfigProps { } const AdvanceConfig: React.FC = (props) => { - const { form, isGGUF, action, gpuOptions, source } = props; - + const { form, isGGUF, gpuOptions, source } = props; const intl = useIntl(); const wokerSelector = Form.useWatch('worker_selector', form); const EnviromentVars = Form.useWatch('env', form); @@ -50,7 +49,7 @@ const AdvanceConfig: React.FC = (props) => { const categories = Form.useWatch('categories', form); const backend_version = Form.useWatch('backend_version', form); const placement_strategy = Form.useWatch('placement_strategy', form); - const gpuSelectorIds = Form.useWatch('gpu_selector.gpu_ids', form); + const gpuSelectorIds = Form.useWatch(['gpu_selector', 'gpu_ids'], form); const worker_selector = Form.useWatch('worker_selector', form); const placementStrategyTips = [ @@ -208,41 +207,6 @@ const AdvanceConfig: React.FC = (props) => { } > - - name="env" - rules={[ - () => ({ - validator(rule, value) { - if (_.keys(value).length > 0) { - if (_.some(_.keys(value), (k: string) => !value[k])) { - return Promise.reject( - intl.formatMessage( - { - id: 'common.validate.value' - }, - { - name: intl.formatMessage({ - id: 'common.text.variable' - }) - } - ) - ); - } - } - return Promise.resolve(); - } - }) - ]} - > - - name="worker_selector" rules={[ @@ -381,6 +345,41 @@ const AdvanceConfig: React.FC = (props) => { } > + + name="env" + rules={[ + () => ({ + validator(rule, value) { + if (_.keys(value).length > 0) { + if (_.some(_.keys(value), (k: string) => !value[k])) { + return Promise.reject( + intl.formatMessage( + { + id: 'common.validate.value' + }, + { + name: intl.formatMessage({ + id: 'common.text.variable' + }) + } + ) + ); + } + } + return Promise.resolve(); + } + }) + ]} + > + + {backend === backendOptionsMap.llamaBox && (
@@ -467,6 +466,7 @@ const AdvanceConfig: React.FC = (props) => { backend_version, placement_strategy, gpuSelectorIds, + EnviromentVars, worker_selector ]); diff --git a/src/pages/llmodels/components/data-form.tsx b/src/pages/llmodels/components/data-form.tsx index 7a8957c5..8c7effed 100644 --- a/src/pages/llmodels/components/data-form.tsx +++ b/src/pages/llmodels/components/data-form.tsx @@ -17,7 +17,6 @@ import React, { useRef, useState } from 'react'; -import { queryGPUList } from '../apis'; import { HuggingFaceTaskMap, ModelscopeTaskMap, @@ -28,7 +27,7 @@ import { sourceOptions } from '../config'; import { HuggingFaceModels, ModelScopeModels } from '../config/audio-catalog'; -import { FormData, GPUListItem } from '../config/types'; +import { FormData } from '../config/types'; import AdvanceConfig from './advance-config'; interface DataFormProps { @@ -43,6 +42,7 @@ interface DataFormProps { byBuiltIn?: boolean; backendOptions?: Global.BaseOption[]; sourceList?: Global.BaseOption[]; + gpuOptions: any[]; onSizeChange?: (val: number) => void; onQuantizationChange?: (val: string) => void; onSourceChange?: (value: string) => void; @@ -71,6 +71,7 @@ const DataForm: React.FC = forwardRef((props, ref) => { backendOptions, sourceList, byBuiltIn, + gpuOptions = [], sizeOptions = [], quantizationOptions = [], fields = ['source'], @@ -79,7 +80,6 @@ const DataForm: React.FC = forwardRef((props, ref) => { } = props; const [form] = Form.useForm(); const intl = useIntl(); - const [gpuOptions, setGpuOptions] = useState>([]); const [modelTask, setModelTask] = useState>({ type: '', value: '', @@ -119,42 +119,6 @@ const DataForm: React.FC = forwardRef((props, ref) => { } ]; - const generateCascaderOptions = (list: GPUListItem[]) => { - const workerFields = ['worker_name', 'worker_id', 'worker_ip']; - - const workers = _.groupBy(list, 'worker_name'); - - const workerList = _.map(workers, (value: GPUListItem[]) => { - return { - label: `${value[0].worker_name}`, - value: value[0].worker_name, - parent: true, - disableCheckbox: false, - ..._.pick(value[0], workerFields), - children: _.map(value, (item: GPUListItem) => { - return { - label: `${item.name}`, - value: item.id, - disableCheckbox: false, - ..._.omit(item, workerFields) - }; - }) - }; - }); - - return workerList; - }; - - const getGPUList = async () => { - const data = await queryGPUList(); - const gpuList = generateCascaderOptions(data.items); - setGpuOptions(gpuList); - }; - - useEffect(() => { - getGPUList(); - }, []); - const handleSumit = () => { form.submit(); }; @@ -335,24 +299,26 @@ const DataForm: React.FC = forwardRef((props, ref) => { defaultActiveFirstOption disabled={false} options={ollamaModelOptions} - label={intl.formatMessage({ id: 'model.form.ollama.model' })} - placeholder={intl.formatMessage({ id: 'model.form.ollamaholder' })} - addAfter={ - - + {intl.formatMessage({ id: 'model.form.ollama.model' })}{' '} + - - - + + + + + } + placeholder={intl.formatMessage({ id: 'model.form.ollamaholder' })} required > diff --git a/src/pages/llmodels/components/deploy-modal.tsx b/src/pages/llmodels/components/deploy-modal.tsx index d3146c76..bc59ec6e 100644 --- a/src/pages/llmodels/components/deploy-modal.tsx +++ b/src/pages/llmodels/components/deploy-modal.tsx @@ -4,7 +4,7 @@ import { CloseOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button, Drawer } from 'antd'; import { debounce } from 'lodash'; -import { memo, useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { backendOptionsMap, modelSourceMap } from '../config'; import { FormData } from '../config/types'; import ColumnWrapper from './column-wrapper'; @@ -21,6 +21,7 @@ type AddModalProps = { open: boolean; source: string; width?: string | number; + gpuOptions?: any[]; onOk: (values: FormData) => void; onCancel: () => void; }; @@ -44,14 +45,11 @@ const AddModal: React.FC = (props) => { const intl = useIntl(); const [selectedModel, setSelectedModel] = useState({}); const [collapsed, setCollapsed] = useState(false); - const [loadingModel, setLoadingModel] = useState(false); const [isGGUF, setIsGGUF] = useState(false); const modelFileRef = useRef(null); - const [loadfinish, setLoadfinish] = useState(false); const handleSelectModelFile = useCallback((item: any) => { form.current?.setFieldValue?.('file_name', item.fakeName); - setLoadfinish(true); }, []); const handleOnSelectModel = (item: any) => { @@ -151,7 +149,6 @@ const AddModal: React.FC = (props) => { @@ -206,6 +203,7 @@ const AddModal: React.FC = (props) => { onOk={onOk} ref={form} isGGUF={isGGUF} + gpuOptions={props.gpuOptions} onBackendChange={handleBackendChange} > @@ -215,4 +213,4 @@ const AddModal: React.FC = (props) => { ); }; -export default memo(AddModal); +export default AddModal; diff --git a/src/pages/llmodels/components/instance-item.tsx b/src/pages/llmodels/components/instance-item.tsx index 88f7a142..10b34946 100644 --- a/src/pages/llmodels/components/instance-item.tsx +++ b/src/pages/llmodels/components/instance-item.tsx @@ -286,7 +286,8 @@ const InstanceItem: React.FC = ({ : undefined } extra={ - item.state === InstanceStatusMap.Error ? ( + item.state === InstanceStatusMap.Error && + item.worker_id ? (
), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' }, breadcrumb: {} }} diff --git a/src/pages/playground/index.tsx b/src/pages/playground/index.tsx index c1e7dc57..40100ebf 100644 --- a/src/pages/playground/index.tsx +++ b/src/pages/playground/index.tsx @@ -166,7 +166,7 @@ const Playground: React.FC = () => { ), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' }, breadcrumb: {} }} diff --git a/src/pages/playground/rerank.tsx b/src/pages/playground/rerank.tsx index f705b075..f61ade7b 100644 --- a/src/pages/playground/rerank.tsx +++ b/src/pages/playground/rerank.tsx @@ -103,7 +103,7 @@ const PlaygroundRerank: React.FC = () => { header={{ title: intl.formatMessage({ id: 'menu.playground.rerank' }), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' }, breadcrumb: {} }} diff --git a/src/pages/playground/speech.tsx b/src/pages/playground/speech.tsx index b7cf5d16..4b09efc0 100644 --- a/src/pages/playground/speech.tsx +++ b/src/pages/playground/speech.tsx @@ -212,7 +212,7 @@ const Playground: React.FC = () => { ), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' }, breadcrumb: {} }} diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index 4ea156b3..bfaecfc7 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -39,7 +39,7 @@ const Profile: React.FC = () => { header={{ title: intl.formatMessage({ id: 'users.form.updatepassword' }), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' } }} extra={[]} diff --git a/src/pages/resources/index.tsx b/src/pages/resources/index.tsx index 2c334243..7cf34179 100644 --- a/src/pages/resources/index.tsx +++ b/src/pages/resources/index.tsx @@ -2,9 +2,16 @@ import { PageContainer } from '@ant-design/pro-components'; import { useIntl } from '@umijs/max'; import type { TabsProps } from 'antd'; import { useCallback, useState } from 'react'; +import styled from 'styled-components'; import GPUs from './components/gpus'; import Workers from './components/workers'; +const Wrapper = styled.div` + .ant-page-header-heading { + padding-inline: 8px; + } +`; + const items: TabsProps['items'] = [ { key: 'workers', @@ -27,7 +34,7 @@ const Resources = () => { }, []); return ( - <> + { }} extra={[]} > - + ); }; diff --git a/src/pages/usage/index.tsx b/src/pages/usage/index.tsx index 2e4ab311..d00cdf82 100644 --- a/src/pages/usage/index.tsx +++ b/src/pages/usage/index.tsx @@ -13,7 +13,7 @@ const Dashboard: React.FC = () => { extra={[]} header={{ style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' } }} > diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx index a9a83bd4..13661aeb 100644 --- a/src/pages/users/index.tsx +++ b/src/pages/users/index.tsx @@ -244,7 +244,7 @@ const Users: React.FC = () => { header={{ title: intl.formatMessage({ id: 'users.title' }), style: { - paddingInline: 'var(--layout-content-inlinepadding)' + paddingInline: 'var(--layout-content-header-inlinepadding)' } }} extra={[]}