style: no resource modal
This commit is contained in:
@@ -792,3 +792,7 @@ body {
|
|||||||
.ant-page-header .ant-page-header-heading-extra {
|
.ant-page-header .ant-page-header-heading-extra {
|
||||||
margin-block: 0;
|
margin-block: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-pro-footer-bar {
|
||||||
|
padding-inline: 0 !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export default {
|
|||||||
'clusters.create.configBasic': '基本配置',
|
'clusters.create.configBasic': '基本配置',
|
||||||
'clusters.create.execCommand': '执行命令',
|
'clusters.create.execCommand': '执行命令',
|
||||||
'clusters.create.supportedGpu': '支持的 GPU',
|
'clusters.create.supportedGpu': '支持的 GPU',
|
||||||
'clusters.create.skipfornow': '暂时跳过',
|
'clusters.create.skipfornow': '稍后再说',
|
||||||
'clusters.create.noImages': '无可用的镜像',
|
'clusters.create.noImages': '无可用的镜像',
|
||||||
'clusters.create.noInstanceTypes': '无可用的实例类型',
|
'clusters.create.noInstanceTypes': '无可用的实例类型',
|
||||||
'clusters.create.noRegions': '无可用的区域',
|
'clusters.create.noRegions': '无可用的区域',
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ const AddWorkerSteps: React.FC<AddWorkerProps> = (props) => {
|
|||||||
)}
|
)}
|
||||||
{addedCount > 0 && (
|
{addedCount > 0 && (
|
||||||
<Alert
|
<Alert
|
||||||
|
style={{ width: 'max-content' }}
|
||||||
message={intl.formatMessage(
|
message={intl.formatMessage(
|
||||||
{
|
{
|
||||||
id: 'clusters.addworker.message.success'
|
id: 'clusters.addworker.message.success'
|
||||||
|
|||||||
@@ -11,10 +11,16 @@ import AddWorkerStep from './add-worker-step';
|
|||||||
import { StepName } from './config';
|
import { StepName } from './config';
|
||||||
|
|
||||||
const Footer = styled.div`
|
const Footer = styled.div`
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
gap: 12px;
|
||||||
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
|
.tips {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type AddWorkerProps = {
|
type AddWorkerProps = {
|
||||||
@@ -113,7 +119,7 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
|
|||||||
maxContentHeight={'max(calc(100vh - 200px), 600px)'}
|
maxContentHeight={'max(calc(100vh - 200px), 600px)'}
|
||||||
footer={
|
footer={
|
||||||
<Footer>
|
<Footer>
|
||||||
<span>
|
<span className="tips">
|
||||||
{addedCount > 0 && (
|
{addedCount > 0 && (
|
||||||
<Alert
|
<Alert
|
||||||
message={intl.formatMessage(
|
message={intl.formatMessage(
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ const SwitchSetting: React.FC<{
|
|||||||
tips?: React.ReactNode;
|
tips?: React.ReactNode;
|
||||||
errorMessage?: React.ReactNode;
|
errorMessage?: React.ReactNode;
|
||||||
extra?: React.ReactNode;
|
extra?: React.ReactNode;
|
||||||
|
showSwitch?: boolean;
|
||||||
onInputChange?: (value: string) => void;
|
onInputChange?: (value: string) => void;
|
||||||
onChange: (checked: boolean) => void;
|
onChange: (checked: boolean) => void;
|
||||||
}> = ({
|
}> = ({
|
||||||
|
showSwitch = true,
|
||||||
label,
|
label,
|
||||||
checked,
|
checked,
|
||||||
onChange,
|
onChange,
|
||||||
@@ -42,7 +44,7 @@ const SwitchSetting: React.FC<{
|
|||||||
<span style={{ color: 'var(--ant-color-text)', fontWeight: 500 }}>
|
<span style={{ color: 'var(--ant-color-text)', fontWeight: 500 }}>
|
||||||
<span>{label}</span>
|
<span>{label}</span>
|
||||||
</span>
|
</span>
|
||||||
<Switch checked={checked} onChange={onChange}></Switch>
|
{showSwitch && <Switch checked={checked} onChange={onChange}></Switch>}
|
||||||
</ButtonWrapper>
|
</ButtonWrapper>
|
||||||
{tips && (
|
{tips && (
|
||||||
<Tips
|
<Tips
|
||||||
@@ -97,12 +99,12 @@ const SpecifyArguments = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const containerNameConfig = summary.get('containerNameConfig') || {
|
const containerNameConfig = summary.get('containerNameConfig') || {
|
||||||
enable: false,
|
enable: true,
|
||||||
name: ''
|
name: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
const gpustackDataVolumeConfig = summary.get('gpustackDataVolumeConfig') || {
|
const gpustackDataVolumeConfig = summary.get('gpustackDataVolumeConfig') || {
|
||||||
enable: false,
|
enable: true,
|
||||||
path: ''
|
path: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,12 +181,12 @@ const SpecifyArguments = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
updateField('containerNameConfig', {
|
updateField('containerNameConfig', {
|
||||||
enable: false,
|
enable: true,
|
||||||
name: ''
|
name: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
updateField('gpustackDataVolumeConfig', {
|
updateField('gpustackDataVolumeConfig', {
|
||||||
enable: false,
|
enable: true,
|
||||||
path: ''
|
path: ''
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
@@ -272,56 +274,23 @@ const SpecifyArguments = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
></SwitchSetting>
|
></SwitchSetting>
|
||||||
{/* container name config */}
|
{/* cache directory config */}
|
||||||
<SwitchSetting
|
<SwitchSetting
|
||||||
label={intl.formatMessage({ id: 'clusters.addworker.containerName' })}
|
label={intl.formatMessage({ id: 'clusters.addworker.cacheVolume' })}
|
||||||
tips={intl.formatMessage({
|
tips={intl.formatMessage({
|
||||||
id: 'clusters.addworker.containerName.tips'
|
id: 'clusters.addworker.cacheVolume.tips'
|
||||||
})}
|
})}
|
||||||
placeholder={intl.formatMessage(
|
placeholder={intl.formatMessage({
|
||||||
{
|
id: 'clusters.addworker.cacheVolume.holder'
|
||||||
id: 'common.help.default'
|
})}
|
||||||
},
|
checked={cacheDirConfig.enable}
|
||||||
{ content: 'gpustack-worker' }
|
value={cacheDirConfig.path}
|
||||||
)}
|
|
||||||
checked={containerNameConfig.enable}
|
|
||||||
value={containerNameConfig.name}
|
|
||||||
onChange={(checked) =>
|
onChange={(checked) =>
|
||||||
updateField('containerNameConfig', {
|
setCacheDirConfig({ ...cacheDirConfig, enable: checked })
|
||||||
...containerNameConfig,
|
|
||||||
enable: checked
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
onInputChange={(value) =>
|
onInputChange={(value) =>
|
||||||
updateField('containerNameConfig', {
|
setCacheDirConfig({
|
||||||
...containerNameConfig,
|
...cacheDirConfig,
|
||||||
name: value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
></SwitchSetting>
|
|
||||||
{/* gpustack data volume config */}
|
|
||||||
<SwitchSetting
|
|
||||||
label={intl.formatMessage({ id: 'clusters.addworker.dataVolume' })}
|
|
||||||
tips={intl.formatMessage({
|
|
||||||
id: 'clusters.addworker.dataVolume.tips'
|
|
||||||
})}
|
|
||||||
placeholder={intl.formatMessage(
|
|
||||||
{
|
|
||||||
id: 'common.help.default'
|
|
||||||
},
|
|
||||||
{ content: 'gpustack-data' }
|
|
||||||
)}
|
|
||||||
checked={gpustackDataVolumeConfig.enable}
|
|
||||||
value={gpustackDataVolumeConfig.path}
|
|
||||||
onChange={(checked) =>
|
|
||||||
updateField('gpustackDataVolumeConfig', {
|
|
||||||
...gpustackDataVolumeConfig,
|
|
||||||
enable: checked
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onInputChange={(value) =>
|
|
||||||
updateField('gpustackDataVolumeConfig', {
|
|
||||||
...gpustackDataVolumeConfig,
|
|
||||||
path: value
|
path: value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -347,27 +316,57 @@ const SpecifyArguments = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
></SwitchSetting>
|
></SwitchSetting>
|
||||||
{/* cache directory config */}
|
|
||||||
|
{/* gpustack data volume config */}
|
||||||
<SwitchSetting
|
<SwitchSetting
|
||||||
label={intl.formatMessage({ id: 'clusters.addworker.cacheVolume' })}
|
showSwitch={false}
|
||||||
tips={intl.formatMessage({
|
label={intl.formatMessage({ id: 'clusters.addworker.dataVolume' })}
|
||||||
id: 'clusters.addworker.cacheVolume.tips'
|
placeholder={intl.formatMessage(
|
||||||
})}
|
{
|
||||||
placeholder={intl.formatMessage({
|
id: 'common.help.default'
|
||||||
id: 'clusters.addworker.cacheVolume.holder'
|
},
|
||||||
})}
|
{ content: 'gpustack-data' }
|
||||||
checked={cacheDirConfig.enable}
|
)}
|
||||||
value={cacheDirConfig.path}
|
checked={gpustackDataVolumeConfig.enable}
|
||||||
|
value={gpustackDataVolumeConfig.path}
|
||||||
onChange={(checked) =>
|
onChange={(checked) =>
|
||||||
setCacheDirConfig({ ...cacheDirConfig, enable: checked })
|
updateField('gpustackDataVolumeConfig', {
|
||||||
|
...gpustackDataVolumeConfig,
|
||||||
|
enable: checked
|
||||||
|
})
|
||||||
}
|
}
|
||||||
onInputChange={(value) =>
|
onInputChange={(value) =>
|
||||||
setCacheDirConfig({
|
updateField('gpustackDataVolumeConfig', {
|
||||||
...cacheDirConfig,
|
...gpustackDataVolumeConfig,
|
||||||
path: value
|
path: value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
></SwitchSetting>
|
></SwitchSetting>
|
||||||
|
{/* container name config */}
|
||||||
|
<SwitchSetting
|
||||||
|
showSwitch={false}
|
||||||
|
label={intl.formatMessage({ id: 'clusters.addworker.containerName' })}
|
||||||
|
placeholder={intl.formatMessage(
|
||||||
|
{
|
||||||
|
id: 'common.help.default'
|
||||||
|
},
|
||||||
|
{ content: 'gpustack-worker' }
|
||||||
|
)}
|
||||||
|
checked={containerNameConfig.enable}
|
||||||
|
value={containerNameConfig.name}
|
||||||
|
onChange={(checked) =>
|
||||||
|
updateField('containerNameConfig', {
|
||||||
|
...containerNameConfig,
|
||||||
|
enable: checked
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onInputChange={(value) =>
|
||||||
|
updateField('containerNameConfig', {
|
||||||
|
...containerNameConfig,
|
||||||
|
name: value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
></SwitchSetting>
|
||||||
</div>
|
</div>
|
||||||
</StepCollapse>
|
</StepCollapse>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -99,16 +99,6 @@ const SummaryData: React.FC = () => {
|
|||||||
path: ''
|
path: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
const containerNameConfig = summary.get('containerNameConfig') || {
|
|
||||||
enable: false,
|
|
||||||
name: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
const gpustackDataVolumeConfig = summary.get('gpustackDataVolumeConfig') || {
|
|
||||||
enable: false,
|
|
||||||
path: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigWrapper>
|
<ConfigWrapper>
|
||||||
<Title>
|
<Title>
|
||||||
@@ -143,18 +133,6 @@ const SummaryData: React.FC = () => {
|
|||||||
required={true}
|
required={true}
|
||||||
></DataItem>
|
></DataItem>
|
||||||
|
|
||||||
<DataItem
|
|
||||||
label={intl.formatMessage({ id: 'clusters.addworker.containerName' })}
|
|
||||||
enable={containerNameConfig.enable}
|
|
||||||
value={containerNameConfig.name}
|
|
||||||
></DataItem>
|
|
||||||
|
|
||||||
<DataItem
|
|
||||||
label={intl.formatMessage({ id: 'clusters.addworker.dataVolume' })}
|
|
||||||
enable={gpustackDataVolumeConfig.enable}
|
|
||||||
value={gpustackDataVolumeConfig.path}
|
|
||||||
></DataItem>
|
|
||||||
|
|
||||||
<DataItem
|
<DataItem
|
||||||
label={intl.formatMessage({ id: 'clusters.addworker.extraVolume' })}
|
label={intl.formatMessage({ id: 'clusters.addworker.extraVolume' })}
|
||||||
enable={modelDirConfig.enable}
|
enable={modelDirConfig.enable}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const Title = styled.span`
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
padding-inline: 24px;
|
||||||
.text {
|
.text {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
import IconFont from '@/components/icon-font';
|
||||||
|
import ScrollerModal from '@/components/scroller-modal/index';
|
||||||
|
import useClusterList from '@/pages/cluster-management/hooks/use-cluster-list';
|
||||||
|
import { useIntl, useNavigate } from '@umijs/max';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Content = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 32px auto 0px;
|
||||||
|
.title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.tips,
|
||||||
|
.sub-title {
|
||||||
|
color: var(--ant-color-text-tertiary);
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
font-size: 32px;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--ant-color-primary);
|
||||||
|
background-color: var(--ant-color-primary-bg);
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.btn-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 16px;
|
||||||
|
margin-top: 32px;
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function useAddResource() {
|
||||||
|
const intl = useIntl();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const { fetchAll, clusterList, workerList, clustersAtom, workersAtom } =
|
||||||
|
useClusterList();
|
||||||
|
|
||||||
|
const [hiddenModal, setHiddenModal] = useState(false);
|
||||||
|
const [loadingStatus, setLoadingStatus] = useState({
|
||||||
|
loading: false,
|
||||||
|
loadend: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const isNoResource = useMemo(() => {
|
||||||
|
const noResource = workerList.length === 0 || clusterList.length === 0;
|
||||||
|
return noResource && !loadingStatus.loading && loadingStatus.loadend;
|
||||||
|
}, [workersAtom.length, clustersAtom.length, loadingStatus]);
|
||||||
|
|
||||||
|
const contentInfo = useMemo(() => {
|
||||||
|
if (clusterList.length === 0) {
|
||||||
|
return {
|
||||||
|
title: intl.formatMessage({ id: 'noresult.cluster.title' }),
|
||||||
|
subTitle: intl.formatMessage({ id: 'noresult.resources.cluster' }),
|
||||||
|
btnText: intl.formatMessage({ id: 'noresult.resources.gotocluster' })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title: intl.formatMessage({ id: 'noresult.workers.title' }),
|
||||||
|
subTitle: intl.formatMessage({ id: 'noresult.resources.worker' }),
|
||||||
|
btnText: intl.formatMessage({ id: 'noresult.workers.button.add' })
|
||||||
|
};
|
||||||
|
}, [clusterList.length, workerList.length, intl]);
|
||||||
|
|
||||||
|
const open: boolean = useMemo(() => {
|
||||||
|
return isNoResource && !hiddenModal;
|
||||||
|
}, [isNoResource, hiddenModal]);
|
||||||
|
|
||||||
|
const handleCreate = () => {};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
setHiddenModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Modal = (
|
||||||
|
<ScrollerModal
|
||||||
|
open={open}
|
||||||
|
footer={null}
|
||||||
|
maskClosable={false}
|
||||||
|
closeIcon={null}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
>
|
||||||
|
<Content>
|
||||||
|
<div className="icon">
|
||||||
|
<IconFont type="icon-dashboard" />
|
||||||
|
</div>
|
||||||
|
<div className="title">{contentInfo.title}</div>
|
||||||
|
<div className="desc">
|
||||||
|
<div className="sub-title">{contentInfo.subTitle}</div>
|
||||||
|
</div>
|
||||||
|
<div className="btn-wrapper">
|
||||||
|
<Button onClick={handleCancel} type="default" style={{ flex: 1 }}>
|
||||||
|
{intl.formatMessage({ id: 'clusters.create.skipfornow' })}
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleCreate} type="primary" style={{ flex: 1 }}>
|
||||||
|
{contentInfo.btnText}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Content>
|
||||||
|
</ScrollerModal>
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
open,
|
||||||
|
contentInfo,
|
||||||
|
loadingStatus,
|
||||||
|
clusterList,
|
||||||
|
Modal,
|
||||||
|
handleCreate,
|
||||||
|
setLoadingStatus,
|
||||||
|
handleCancel,
|
||||||
|
fetchAll
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
import useClusterList from '@/pages/cluster-management/hooks/use-cluster-list';
|
|
||||||
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
|
|
||||||
import { useIntl } from '@umijs/max';
|
|
||||||
import { useMemoizedFn } from 'ahooks';
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -9,36 +6,12 @@ import { queryDashboardData } from './apis';
|
|||||||
import DashboardInner from './components/dahboard-inner';
|
import DashboardInner from './components/dahboard-inner';
|
||||||
import DashboardContext from './config/dashboard-context';
|
import DashboardContext from './config/dashboard-context';
|
||||||
import { DashboardProps } from './config/types';
|
import { DashboardProps } from './config/types';
|
||||||
|
import useAddResource from './hooks/use-add-resource';
|
||||||
|
|
||||||
const Dashboard: React.FC = () => {
|
const Dashboard: React.FC = () => {
|
||||||
const intl = useIntl();
|
const { setLoadingStatus, fetchAll, Modal, loadingStatus, clusterList } =
|
||||||
const [loadingStatus, setLoadingStatus] = useState({
|
useAddResource();
|
||||||
loading: false,
|
|
||||||
loadend: false
|
|
||||||
});
|
|
||||||
const [data, setData] = useState<DashboardProps>({} as DashboardProps);
|
const [data, setData] = useState<DashboardProps>({} as DashboardProps);
|
||||||
const { fetchAll, clusterList, workerList, clustersAtom, workersAtom } =
|
|
||||||
useClusterList();
|
|
||||||
|
|
||||||
const { noResourceResult } = useNoResourceResult({
|
|
||||||
loadend: true,
|
|
||||||
loading: false,
|
|
||||||
dataSource: clusterList.length > 0 ? workerList : [],
|
|
||||||
queryParams: {},
|
|
||||||
iconType: 'icon-dashboard',
|
|
||||||
title:
|
|
||||||
clusterList.length > 0
|
|
||||||
? intl.formatMessage({ id: 'noresult.workers.title' })
|
|
||||||
: intl.formatMessage({ id: 'noresult.cluster.title' }),
|
|
||||||
noClusters: !clusterList.length,
|
|
||||||
noWorkers: workerList.length === 0 && clusterList.length > 0,
|
|
||||||
defaultContent: {
|
|
||||||
subTitle: intl.formatMessage({ id: 'noresult.workers.subTitle' }),
|
|
||||||
noFoundText: intl.formatMessage({ id: 'noresult.workers.nofound' }),
|
|
||||||
buttonText: intl.formatMessage({ id: 'noresult.workers.button.add' }),
|
|
||||||
onClick: () => {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fetchDashboardData = useMemoizedFn(async () => {
|
const fetchDashboardData = useMemoizedFn(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -80,13 +53,10 @@ const Dashboard: React.FC = () => {
|
|||||||
>
|
>
|
||||||
<PageBox>
|
<PageBox>
|
||||||
<Spin spinning={loadingStatus.loading} style={{ minHeight: 300 }}>
|
<Spin spinning={loadingStatus.loading} style={{ minHeight: 300 }}>
|
||||||
{workersAtom.length > 0 && clustersAtom.length > 0 ? (
|
<DashboardInner />
|
||||||
<DashboardInner />
|
|
||||||
) : loadingStatus.loading || !loadingStatus.loadend ? null : (
|
|
||||||
noResourceResult
|
|
||||||
)}
|
|
||||||
</Spin>
|
</Spin>
|
||||||
</PageBox>
|
</PageBox>
|
||||||
|
{Modal}
|
||||||
</DashboardContext.Provider>
|
</DashboardContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ const useNoResourceResult = (props: {
|
|||||||
></NoResult>
|
></NoResult>
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
noResourceResult
|
noResourceResult,
|
||||||
|
handleCreate: handleClick
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user