Skip to content

Commit ec93e41

Browse files
committed
add global no projects page
1 parent 9d9e1c3 commit ec93e41

File tree

4 files changed

+57
-10
lines changed

4 files changed

+57
-10
lines changed

frontend/packages/modelServing/extensions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ const extensions: (
5656
properties: {
5757
id: 'modelServing',
5858
title: 'Model deployments',
59-
href: '/modelServing',
59+
href: '/model-serving',
6060
section: 'models',
61-
path: '/modelServing/:namespace?/*',
61+
path: '/model-serving/:namespace?/*',
6262
},
6363
},
6464
{
6565
type: 'app.route',
6666
properties: {
67-
path: '/modelServing/:namespace?/*',
67+
path: '/model-serving/:namespace?/*',
6868
component: () => import('./src/GlobalModelsPage'),
6969
},
7070
flags: {

frontend/packages/modelServing/src/GlobalModelsPage.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { ProjectsContext } from '@odh-dashboard/internal/concepts/projects/Proje
33
import { useExtensions, useResolvedExtensions } from '@odh-dashboard/plugin-core';
44
import { Bullseye, Spinner } from '@patternfly/react-core';
55
import { useNavigate, useParams } from 'react-router-dom';
6+
import ApplicationsPage from '@odh-dashboard/internal/pages/ApplicationsPage';
67
import GlobalDeploymentsView from './components/global/GlobalDeploymentsView';
8+
import NoProjectsPage from './components/global/NoProjectsPage';
79
import { ModelDeploymentsProvider } from './concepts/ModelDeploymentsContext';
810
import { ModelServingPlatformProvider } from './concepts/ModelServingPlatformContext';
911
import {
@@ -17,14 +19,20 @@ const GlobalModelsPage: React.FC = () => (
1719
</ModelServingPlatformProvider>
1820
);
1921

22+
type ApplicationPageProps = React.ComponentProps<typeof ApplicationsPage>;
23+
type EmptyStateProps = 'emptyStatePage' | 'empty';
24+
type ApplicationPageRenderState = Pick<ApplicationPageProps, EmptyStateProps>;
25+
2026
const GlobalModelsPageCoreLoader: React.FC = () => {
2127
const availablePlatforms = useExtensions(isModelServingPlatformExtension);
2228
const [deploymentWatchers] = useResolvedExtensions(isModelServingPlatformWatchDeployments);
29+
2330
const {
2431
projects,
2532
loaded: projectsLoaded,
2633
preferredProject: currentProject,
2734
} = React.useContext(ProjectsContext);
35+
2836
const selectedProject = currentProject
2937
? projects.find((project) => project.metadata.name === currentProject.metadata.name)
3038
: null;
@@ -34,9 +42,12 @@ const GlobalModelsPageCoreLoader: React.FC = () => {
3442

3543
React.useEffect(() => {
3644
if (!namespace && currentProject) {
37-
navigate(`/modelServing/${currentProject.metadata.name}`, { replace: true });
45+
navigate(`/model-serving/${currentProject.metadata.name}`, { replace: true });
3846
}
3947
}, [namespace, currentProject, navigate]);
48+
let renderStateProps: ApplicationPageRenderState & { children?: React.ReactNode } = {
49+
empty: false,
50+
};
4051

4152
if (!projectsLoaded) {
4253
return (
@@ -45,16 +56,21 @@ const GlobalModelsPageCoreLoader: React.FC = () => {
4556
</Bullseye>
4657
);
4758
}
59+
4860
if (projects.length === 0) {
49-
return <div>No projects found component</div>;
61+
renderStateProps = {
62+
empty: true,
63+
emptyStatePage: <NoProjectsPage />,
64+
};
5065
}
66+
5167
return (
5268
<ModelDeploymentsProvider
5369
modelServingPlatforms={availablePlatforms}
5470
projects={projectsToShow}
5571
deploymentWatchers={deploymentWatchers}
5672
>
57-
<GlobalDeploymentsView currentProject={selectedProject} />
73+
<GlobalDeploymentsView {...renderStateProps} currentProject={selectedProject} />
5874
</ModelDeploymentsProvider>
5975
);
6076
};

frontend/packages/modelServing/src/components/global/GlobalDeploymentsView.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,34 @@ import ModelServingProjectSelection from './ModelServingProjectSelection';
99
import { ModelDeploymentsContext } from '../../concepts/ModelDeploymentsContext';
1010

1111
type GlobalDeploymentsViewProps = {
12+
empty?: boolean;
13+
emptyStatePage?: React.ReactNode;
1214
currentProject?: ProjectKind | null;
1315
};
1416

15-
const GlobalDeploymentsView: React.FC<GlobalDeploymentsViewProps> = ({ currentProject }) => {
17+
const GlobalDeploymentsView: React.FC<GlobalDeploymentsViewProps> = ({
18+
empty,
19+
emptyStatePage,
20+
currentProject,
21+
}) => {
1622
const { deployments, loaded: deploymentsLoaded } = React.useContext(ModelDeploymentsContext);
1723
const hasDeployments = deployments && deployments.length > 0;
1824
const isLoading = !deploymentsLoaded;
25+
const isEmpty = empty || (!isLoading && !hasDeployments);
1926

2027
return (
2128
<ApplicationsPage
2229
loaded={!isLoading}
23-
empty={!hasDeployments}
24-
emptyStatePage={<GlobalNoModelsView project={currentProject ?? undefined} />}
30+
empty={isEmpty}
31+
emptyStatePage={
32+
emptyStatePage ?? <GlobalNoModelsView project={currentProject ?? undefined} />
33+
}
2534
description="Manage and view the health and performance of your deployed models."
2635
title={
2736
<TitleWithIcon title="Model deployments" objectType={ProjectObjectType.deployedModels} />
2837
}
2938
headerContent={
30-
<ModelServingProjectSelection getRedirectPath={(ns: string) => `/modelServing/${ns}`} />
39+
<ModelServingProjectSelection getRedirectPath={(ns: string) => `/model-serving/${ns}`} />
3140
}
3241
>
3342
<GlobalDeploymentsTable />
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as React from 'react';
2+
import { EmptyState, EmptyStateBody, EmptyStateFooter } from '@patternfly/react-core';
3+
import { WrenchIcon } from '@patternfly/react-icons/dist/esm/icons/wrench-icon';
4+
import { useNavigate } from 'react-router-dom';
5+
import NewProjectButton from '@odh-dashboard/internal/pages/projects/screens/projects/NewProjectButton';
6+
7+
const NoProjectsPage: React.FC = () => {
8+
const navigate = useNavigate();
9+
return (
10+
<EmptyState headingLevel="h4" icon={WrenchIcon} titleText="No data science projects">
11+
<EmptyStateBody>To deploy a model, first create a data science project.</EmptyStateBody>
12+
<EmptyStateFooter>
13+
<NewProjectButton
14+
closeOnCreate
15+
onProjectCreated={(projectName) => navigate(`/model-serving/${projectName}`)}
16+
/>
17+
</EmptyStateFooter>
18+
</EmptyState>
19+
);
20+
};
21+
22+
export default NoProjectsPage;

0 commit comments

Comments
 (0)