diff --git a/src/assets/logo/moore-logo.png b/src/assets/logo/moore-logo.png new file mode 100644 index 00000000..7d3c5d9b Binary files /dev/null and b/src/assets/logo/moore-logo.png differ diff --git a/src/components/collapse-container/index.tsx b/src/components/collapse-container/index.tsx index ecf56b81..5a497535 100644 --- a/src/components/collapse-container/index.tsx +++ b/src/components/collapse-container/index.tsx @@ -7,6 +7,7 @@ import styled from 'styled-components'; const CardStyled = styled(Card)` box-shadow: none !important; + background-color: none; &.isOpen { .ant-card-head { border-bottom: 1px solid var(--ant-color-border-secondary); diff --git a/src/components/icon-font/index.tsx b/src/components/icon-font/index.tsx index 2c4fbc7b..666b43f1 100644 --- a/src/components/icon-font/index.tsx +++ b/src/components/icon-font/index.tsx @@ -1,8 +1,8 @@ import { createFromIconfontCN } from '@ant-design/icons'; -import './iconfont/iconfont.js'; +// import './iconfont/iconfont.js'; const IconFont = createFromIconfontCN({ - scriptUrl: '' + scriptUrl: '//at.alicdn.com/t/c/font_4613488_jo5x7z2z718.js' }); export default IconFont; diff --git a/src/components/seal-table/index.tsx b/src/components/seal-table/index.tsx index 74410c4a..03fb5296 100644 --- a/src/components/seal-table/index.tsx +++ b/src/components/seal-table/index.tsx @@ -21,6 +21,8 @@ const Wrapper = styled.div<{ $token: any }>` --ant-table-row-selected-hover-bg: ${(props) => props.$token.rowSelectedHoverBg}; --ant-table-row-hover-bg: ${(props) => props.$token.rowHoverBg}; + --ant-table-header-icon-color: ${(props) => + props.$token.tableHeaderIconColor}; `; const SealTable: React.FC = ( @@ -143,10 +145,13 @@ const SealTable: React.FC = ( pagination?.onShowSizeChange?.(current, size); }; + console.log('token.table', token); + return ( diff --git a/src/components/seal-table/styles/header.less b/src/components/seal-table/styles/header.less index be39bcae..ba4cda3a 100644 --- a/src/components/seal-table/styles/header.less +++ b/src/components/seal-table/styles/header.less @@ -53,8 +53,8 @@ margin-left: 4px; .anticon { - font-size: 10px; - color: rgba(0, 0, 0, 29%); + font-size: 12px; + color: var(--ant-table-header-icon-color); } .sorter-up { diff --git a/src/layouts/index.tsx b/src/layouts/index.tsx index 3608edc4..55a6e570 100644 --- a/src/layouts/index.tsx +++ b/src/layouts/index.tsx @@ -127,12 +127,7 @@ export default (props: any) => { const { clientRoutes } = useAppData(); const requestResourceRef = useRef(false); - const { - setLoadingStatus, - fetchResourceData, - NoResourceModal, - loadingStatus - } = useAddResource({ + const { fetchResourceData, NoResourceModal } = useAddResource({ onCreated() { requestResourceRef.current = false; } diff --git a/src/pages/_components/collapse-panel/index.tsx b/src/pages/_components/collapse-panel/index.tsx index 66bdd665..d8058f21 100644 --- a/src/pages/_components/collapse-panel/index.tsx +++ b/src/pages/_components/collapse-panel/index.tsx @@ -13,10 +13,7 @@ const CollapseInner = styled(Collapse)` border-radius: var(--border-radius-base) !important; font-size: 14px !important; font-weight: 600 !important; - - &:hover { - background-color: var(--ant-color-fill-tertiary) !important; - } + background-color: var(--ant-color-fill-tertiary) !important; } .ant-collapse-body { diff --git a/src/pages/cluster-management/cluster-create.tsx b/src/pages/cluster-management/cluster-create.tsx index 7c5b3dbe..534821d2 100644 --- a/src/pages/cluster-management/cluster-create.tsx +++ b/src/pages/cluster-management/cluster-create.tsx @@ -3,6 +3,7 @@ import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; import ColumnWrapper from '@/pages/_components/column-wrapper'; import { useIntl, useSearchParams } from '@umijs/max'; +import { Typography } from 'antd'; import { useAtom } from 'jotai'; import _ from 'lodash'; import React, { useEffect, useMemo, useRef, useState } from 'react'; @@ -29,6 +30,8 @@ import useSystemConfig from './services/use-system-config'; import { moduleMap, moduleRegistry } from './step-forms/module-registry'; import useStepList from './step-forms/use-step-list'; +const { Title, Text } = Typography; + const Container = styled.div` width: 100%; display: flex; @@ -41,14 +44,10 @@ const Content = styled.div` `; const StepsWrapper = styled.div` - width: 230px; + width: 240px; padding-inline: 24px; padding-block: 16px; - // background-color: var(--ant-color-fill-quaternary); border-right: 1px solid var(--ant-color-split); - .ant-steps.ant-steps-vertical { - height: 600px; - } `; const MainWrapper = styled.div` @@ -308,14 +307,15 @@ const ClusterCreate: React.FC<{ }; const handleCancel = () => { - if (clusterSession?.firstAddCluster) { - setClusterSession({ - firstAddCluster: false, - firstAddWorker: false - }); - onClose?.(); - return; - } + // TODO: delete it if created by drawer + // if (clusterSession?.firstAddCluster) { + // setClusterSession({ + // firstAddCluster: false, + // firstAddWorker: false + // }); + // onClose?.(); + // return; + // } onClose?.(); }; @@ -326,7 +326,7 @@ const ClusterCreate: React.FC<{ } > -
+ + {steps[currentStep]?.subTitle || steps[currentStep]?.title} + + + {steps[currentStep]?.description || steps[currentStep]?.content} + +
{currentStep === startStep && ( { } }, [clusterSession, dataSource.loadend, dataSource.dataList]); + useEffect(() => { + if (clusterSession?.firstAddCluster && dataSource.loadend) { + openClusterModal(); + // reset session + setClusterSession(null); + } + }, [clusterSession, dataSource.loadend]); + const renderChildren = ( list: any, options: { parent?: any; [key: string]: any } diff --git a/src/pages/cluster-management/components/cluster-steps.tsx b/src/pages/cluster-management/components/cluster-steps.tsx index 0e326a26..ae19f203 100644 --- a/src/pages/cluster-management/components/cluster-steps.tsx +++ b/src/pages/cluster-management/components/cluster-steps.tsx @@ -1,34 +1,106 @@ -import { Steps } from 'antd'; +import { CheckCircleFilled, CheckCircleOutlined } from '@ant-design/icons'; import React from 'react'; import styled from 'styled-components'; const Wrapper = styled.div` - width: min(1200px, 100%); - margin: 0 auto; - padding-block: 0px; - .ant-steps-item-description { - max-width: 300px !important; - color: var(--ant-color-text-description) !important; + display: flex; + flex-direction: column; + gap: 24px; +`; + +const Box = styled.div` + .indicates { + color: var(--ant-color-text-tertiary); + font-size: 14px; + margin-bottom: 24px; } `; +const StepItemWrapper = styled.div` + display: flex; + align-items: flex-start; + gap: 12px; + padding-bottom: 16px; + // border-bottom: 1px solid var(--ant-color-split); + .description { + display: flex; + flex-direction: column; + gap: 4px; + + .title { + font-weight: 500; + line-height: 20px; + color: var(--ant-color-text-tertiary); + } + .content { + line-height: 22px; + font-size: 14px; + color: var(--ant-color-text-tertiary); + } + } + &.active { + .description { + .title { + color: var(--ant-color-text); + font-weight: 600; + } + .content { + color: var(--ant-color-text); + } + } + } +`; + +const StepsItem: React.FC<{ + active: boolean; + item: { + title: string; + content: string; + }; +}> = ({ active, item }) => { + return ( + +
+ {active ? ( + + ) : ( + + )} +
+
+
{item.title}
+
{item.content}
+
+
+ ); +}; + const ClusterSteps: React.FC<{ currentStep: number; onChange?: (step: number) => void; steps: any[]; }> = (props) => { - const { steps, currentStep, onChange } = props; + const { steps, currentStep = 0, onChange } = props; return ( - - - + +
+ STEP {currentStep + 1} OF {steps.length} +
+ + {steps.map((item, index) => ( + + ))} + +
); }; diff --git a/src/pages/cluster-management/components/footer-buttons.tsx b/src/pages/cluster-management/components/footer-buttons.tsx index 9a1cbf13..defa227e 100644 --- a/src/pages/cluster-management/components/footer-buttons.tsx +++ b/src/pages/cluster-management/components/footer-buttons.tsx @@ -1,4 +1,4 @@ -import { LeftOutlined, RightOutlined } from '@ant-design/icons'; +import { ArrowLeftOutlined, ArrowRightOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button } from 'antd'; import styled from 'styled-components'; @@ -37,10 +37,14 @@ const FooterButtons: React.FC = (props) => { onNext(); }; return ( - + <Title style={{ padding: '16px 24px 24px' }}> <div className="flex-center gap-20"> {showButtons.previous && ( - <Button type="default" icon={<LeftOutlined />} onClick={onPrevious}> + <Button + type="default" + icon={<ArrowLeftOutlined />} + onClick={onPrevious} + > {intl.formatMessage({ id: 'common.button.prev' })} </Button> )} @@ -51,7 +55,7 @@ const FooterButtons: React.FC<FooterButtonsProps> = (props) => { style={{ minWidth: 100 }} > {intl.formatMessage({ id: 'common.button.next' })} - <RightOutlined /> + <ArrowRightOutlined /> </Button> )} {showButtons.skip && ( diff --git a/src/pages/cluster-management/components/provider-catalog.tsx b/src/pages/cluster-management/components/provider-catalog.tsx index 5aef2af1..c29bbe46 100644 --- a/src/pages/cluster-management/components/provider-catalog.tsx +++ b/src/pages/cluster-management/components/provider-catalog.tsx @@ -29,7 +29,7 @@ const Title = styled.span` display: flex; gap: 8px; align-items: center; - font-weight: 700; + font-weight: 500; font-size: 14px; margin-bottom: 16px; .icon { @@ -100,6 +100,9 @@ const ProviderCatalog: React.FC<ProviderCatalogProps> = ({ }, [dataList]); const renderTitle = (item: any) => { + if (item.hiddenTitle) { + return <>{item.extra && <span className="extra">{item.extra}</span>}</>; + } return ( <Header> <span className="title"> @@ -110,6 +113,7 @@ const ProviderCatalog: React.FC<ProviderCatalogProps> = ({ {intl.formatMessage({ id: item.description })} </span> )} + {item.extra && <span className="extra">{item.extra}</span>} </Header> ); }; diff --git a/src/pages/cluster-management/components/support-gpus.tsx b/src/pages/cluster-management/components/support-gpus.tsx index 8c9bbaea..a937e3fc 100644 --- a/src/pages/cluster-management/components/support-gpus.tsx +++ b/src/pages/cluster-management/components/support-gpus.tsx @@ -3,7 +3,8 @@ import CambriconPNG from '@/assets/logo/cambricon.png'; import hyponPNG from '@/assets/logo/hygon.png'; import iluvatarWEBP from '@/assets/logo/Iluvatar.png'; import metaxLogo from '@/assets/logo/metax.png'; -import moorePNG from '@/assets/logo/moore _threads.png'; +import mooreLogo from '@/assets/logo/moore-logo.png'; +import nvidiaLogo from '@/assets/logo/nvidia.png'; import IconFont from '@/components/icon-font'; import { AddWorkerDockerNotes, @@ -15,21 +16,45 @@ import ProviderCatalog from './provider-catalog'; const Box = styled.div` .template-card-wrapper { + position: relative; + justify-content: center; + background-color: rgba(255, 255, 255, 0.1); + &.active { + background-color: var(--ant-color-fill-tertiary); + } + .template-card-icon { + margin-right: 0; + } .template-card-inner { line-height: 1; + flex-direction: row; + height: auto; + width: 0; + overflow: visible; .template-card-content { font-size: 13px; } } + .extra { + position: absolute; + right: 2px; + top: 2px; + padding: 2px; + border-radius: 2px; + font-size: 10px; + font-weight: 400; + background-color: var(--ant-blue-1); + color: var(--ant-color-info); + } } `; -const ProviderImage = ({ src, showBg }: { src: string; showBg?: boolean }) => { +const ProviderImage = ({ src, height }: { src: string; height?: number }) => { return ( <img src={src} style={{ - width: 32, + height: height || 20, objectFit: 'contain' }} /> @@ -52,16 +77,18 @@ const SupportedHardware: React.FC<SupportedHardwareProps> = ({ const supportedHardPlatforms = [ { label: 'NVIDIA', + hiddenTitle: true, value: GPUDriverMap.NVIDIA, description: '', key: GPUDriverMap.NVIDIA, locale: false, notes: AddWorkerDockerNotes[GPUDriverMap.NVIDIA], link: 'https://docs.gpustack.ai/latest/installation/requirements/#nvidia-gpu', - icon: <IconFont type="icon-nvidia2" style={{ fontSize: 32 }} /> + icon: <ProviderImage src={nvidiaLogo} height={20} /> }, { label: 'AMD', + hiddenTitle: true, description: '', value: GPUDriverMap.AMD, key: GPUDriverMap.AMD, @@ -70,70 +97,80 @@ const SupportedHardware: React.FC<SupportedHardwareProps> = ({ link: 'https://docs.gpustack.ai/latest/installation/requirements/#amd-gpu', icon: ( <IconFont - type="icon-amd" - style={{ fontSize: 32, color: 'var(--ant-color-text)' }} + type="icon-amd-logo" + style={{ fontSize: 60, color: 'var(--ant-color-text)' }} /> ) }, { label: intl.formatMessage({ id: 'vendor.ascend' }), + hiddenTitle: true, description: '', value: GPUDriverMap.ASCEND, key: GPUDriverMap.ASCEND, locale: false, notes: AddWorkerDockerNotes[GPUDriverMap.ASCEND], link: 'https://docs.gpustack.ai/latest/installation/requirements/#ascend-npu', - icon: <ProviderImage src={ascendLogo} showBg /> + icon: <ProviderImage src={ascendLogo} height={32} /> }, { label: intl.formatMessage({ id: 'vendor.hygon' }), + hiddenTitle: true, description: '', value: GPUDriverMap.HYGON, key: GPUDriverMap.HYGON, locale: false, notes: AddWorkerDockerNotes[GPUDriverMap.HYGON], link: 'https://docs.gpustack.ai/latest/installation/requirements/#hygon-dcu', - icon: <ProviderImage src={hyponPNG} /> + icon: <ProviderImage src={hyponPNG} height={20} /> }, { label: intl.formatMessage({ id: 'vendor.moorthreads' }), - description: 'common.tag.experimental', + hiddenTitle: true, + // description: 'common.tag.experimental', + extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.MOORE_THREADS, key: GPUDriverMap.MOORE_THREADS, locale: false, notes: AddWorkerDockerNotes[GPUDriverMap.MOORE_THREADS], link: 'https://docs.gpustack.ai/latest/installation/requirements/#mthreads-gpu', - icon: <ProviderImage src={moorePNG} /> + icon: <ProviderImage src={mooreLogo} height={26} /> }, { label: intl.formatMessage({ id: 'vendor.iluvatar' }), - description: 'common.tag.experimental', + hiddenTitle: true, + // description: 'common.tag.experimental', + extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.ILUVATAR, key: GPUDriverMap.ILUVATAR, locale: false, notes: AddWorkerDockerNotes[GPUDriverMap.ILUVATAR], link: 'https://docs.gpustack.ai/latest/installation/requirements/#iluvatar-gpu', - icon: <ProviderImage src={iluvatarWEBP} showBg /> + icon: <ProviderImage src={iluvatarWEBP} height={26} /> }, { label: intl.formatMessage({ id: 'vendor.cambricon' }), - description: 'common.tag.experimental', + hiddenTitle: true, + // description: 'common.tag.experimental', + extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.CAMBRICON, key: GPUDriverMap.CAMBRICON, locale: false, notes: AddWorkerDockerNotes[GPUDriverMap.CAMBRICON], link: 'https://docs.gpustack.ai/latest/installation/requirements/#cambricon-mlu', - icon: <ProviderImage src={CambriconPNG} /> + icon: <ProviderImage src={CambriconPNG} height={26} /> }, { label: intl.formatMessage({ id: 'vendor.metax' }), - description: 'common.tag.experimental', + hiddenTitle: true, + // description: 'common.tag.experimental', + extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.METAX, key: GPUDriverMap.METAX, locale: false, link: 'https://docs.gpustack.ai/latest/installation/requirements/#metax-gpu', notes: AddWorkerDockerNotes[GPUDriverMap.METAX], - icon: <ProviderImage src={metaxLogo} showBg /> + icon: <ProviderImage src={metaxLogo} height={20} /> } ]; @@ -145,7 +182,7 @@ const SupportedHardware: React.FC<SupportedHardwareProps> = ({ current={current} dataList={supportedHardPlatforms} clickable={clickable} - cols={3} + cols={4} /> </Box> ); diff --git a/src/pages/cluster-management/step-forms/basic-form.tsx b/src/pages/cluster-management/step-forms/basic-form.tsx index 72a91726..d750b580 100644 --- a/src/pages/cluster-management/step-forms/basic-form.tsx +++ b/src/pages/cluster-management/step-forms/basic-form.tsx @@ -1,4 +1,3 @@ -import PageTools from '@/components/page-tools'; import { PageActionType } from '@/config/types'; import { useIntl } from '@umijs/max'; import { forwardRef, useImperativeHandle, useRef } from 'react'; @@ -40,7 +39,7 @@ const BasicForm = forwardRef((props: BasicFormProps, ref) => { return ( <div> - <PageTools + {/* <PageTools marginBottom={16} left={ <Title> @@ -48,7 +47,7 @@ const BasicForm = forwardRef((props: BasicFormProps, ref) => { } marginTop={0} - > + > */} [ { - title: intl.formatMessage({ id: 'clusters.create.selectProvider' }), - content: '', + title: intl.formatMessage({ id: 'clusters.table.provider' }), + content: 'Choose where your cluster will run.', + subTitle: 'Select Provider', + description: + 'Choose the environment where your cluster will be deployed.', showButtons: (provider?: ProviderType) => { return { previous: false, @@ -31,8 +34,10 @@ export default function useStepList() { providers: [] }, { - title: intl.formatMessage({ id: 'clusters.create.configBasic' }), - content: '', + title: intl.formatMessage({ id: 'common.title.config' }), + content: 'Configure your cluster settings.', + description: + 'Set the cluster name, description, or other essential parameters in advanced settings.', showButtons: (provider?: ProviderType) => { return { previous: true, @@ -48,7 +53,7 @@ export default function useStepList() { }, { title: intl.formatMessage({ id: 'clusters.button.addNodePool' }), - content: '', + content: 'Add worker pools to your cluster.', showButtons: (provider?: ProviderType) => { return { previous: true, @@ -65,7 +70,9 @@ export default function useStepList() { }, { title: intl.formatMessage({ id: 'resources.button.create' }), - content: '', + content: 'The cluster is created successfully.', + description: + 'The cluster is now set up and you can add workers to it. You can also add workers later from the cluster list.', showButtons: (provider?: ProviderType) => { return { previous: false, @@ -82,6 +89,8 @@ export default function useStepList() { { title: intl.formatMessage({ id: 'clusters.button.register' }), content: '', + description: + 'Register an existing Kubernetes cluster to manage its workers. You can also register a cluster later from the cluster list.', showButtons: (provider?: ProviderType) => { return { previous: false, diff --git a/src/pages/cluster-management/step-forms/worker-pools-form.tsx b/src/pages/cluster-management/step-forms/worker-pools-form.tsx index 76382b50..0a123081 100644 --- a/src/pages/cluster-management/step-forms/worker-pools-form.tsx +++ b/src/pages/cluster-management/step-forms/worker-pools-form.tsx @@ -181,20 +181,15 @@ const WorkerPoolsForm = forwardRef((props: WorkerPoolsFormProps, ref) => { + // + // {intl.formatMessage({ id: 'clusters.workerpool.title' })} + // + // + // } left={ - - - {intl.formatMessage({ id: 'clusters.workerpool.title' })} - - - } - right={ - } diff --git a/src/pages/dashboard/hooks/use-add-resource.tsx b/src/pages/dashboard/hooks/use-add-resource.tsx index fcfc8c43..7b9f608c 100644 --- a/src/pages/dashboard/hooks/use-add-resource.tsx +++ b/src/pages/dashboard/hooks/use-add-resource.tsx @@ -2,7 +2,6 @@ import { clusterSessionAtom } from '@/atoms/clusters'; import { hideModalTemporarilyAtom } from '@/atoms/settings'; import IconFont from '@/components/icon-font'; import ScrollerModal from '@/components/scroller-modal/index'; -import { PageAction } from '@/config'; import useUserSettings from '@/hooks/use-user-settings'; import useClusterList from '@/pages/cluster-management/hooks/use-cluster-list'; import { useIntl, useNavigate } from '@umijs/max'; @@ -105,9 +104,7 @@ export default function useAddResource(options?: { onCreated?: () => void }) { firstAddCluster: true }); - navigate( - `/cluster-management/clusters/create?action=${PageAction.CREATE}` - ); + navigate(`/cluster-management/clusters/list`); return; } diff --git a/src/pages/llmodels/hooks/use-no-resource-result.tsx b/src/pages/llmodels/hooks/use-no-resource-result.tsx index a15013de..714ac119 100644 --- a/src/pages/llmodels/hooks/use-no-resource-result.tsx +++ b/src/pages/llmodels/hooks/use-no-resource-result.tsx @@ -1,6 +1,5 @@ import { clusterSessionAtom } from '@/atoms/clusters'; import IconFont from '@/components/icon-font'; -import { PageAction } from '@/config'; import NoResult from '@/pages/_components/no-result'; import { useIntl, useNavigate } from '@umijs/max'; import { useMemoizedFn } from 'ahooks'; @@ -54,9 +53,7 @@ const useNoResourceResult = (props: { firstAddCluster: true }); - navigate( - `/cluster-management/clusters/create?action=${PageAction.CREATE}` - ); + navigate(`/cluster-management/clusters/list`); return; }