Skip to content

Commit 4f00f56

Browse files
committed
added tab
1 parent 781de2b commit 4f00f56

File tree

11 files changed

+400
-8
lines changed

11 files changed

+400
-8
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { Extension } from '@openshift/dynamic-plugin-sdk';
2+
import type { ComponentCodeRef } from '@odh-dashboard/plugin-core/extension-points';
3+
import type { ModelVersionRegisteredDeploymentsViewProps } from '../upstream/frontend/types';
4+
5+
export type ModelRegistryDeploymentsTabExtension = Extension<
6+
'model-registry.version-details/tab',
7+
{
8+
id: string;
9+
title: string;
10+
component: ComponentCodeRef<ModelVersionRegisteredDeploymentsViewProps>;
11+
}
12+
>;
13+
14+
export const isModelRegistryDeploymentsTabExtension = (
15+
extension: Extension,
16+
): extension is ModelRegistryDeploymentsTabExtension =>
17+
extension.type === 'model-registry.version-details/tab';

frontend/packages/model-registry/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,8 @@
3131
"name": "model-registry-ui-service",
3232
"port": 8080
3333
}
34+
},
35+
"exports": {
36+
"./extension-points": "./extension-points/index.ts"
3437
}
3538
}

frontend/packages/model-registry/upstream/frontend/src/app/pages/modelRegistry/screens/ModelVersionDetails/ModelVersionDetailsTabs.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@ import * as React from 'react';
22
import { useNavigate } from 'react-router-dom';
33
import { PageSection, Tab, Tabs, TabTitleText } from '@patternfly/react-core';
44
import {
5-
DeploymentMode,
65
FetchStateObject,
76
InferenceServiceKind,
8-
PlatformMode,
97
ServingRuntimeKind,
10-
useModularArchContext,
118
} from 'mod-arch-shared';
129
import { ModelVersion } from '~/app/types';
1310
import { ModelVersionDetailsTabTitle, ModelVersionDetailsTab } from './const';
1411
import ModelVersionDetailsView from './ModelVersionDetailsView';
15-
import ModelVersionRegisteredDeploymentsView from './ModelVersionRegisteredDeploymentsView';
12+
import { LazyCodeRefComponent, useExtensions } from '@odh-dashboard/plugin-core';
13+
import { isModelRegistryDeploymentsTabExtension } from '@odh-dashboard/model-registry/extension-points';
1614

1715
type ModelVersionDetailTabsProps = {
1816
tab: ModelVersionDetailsTab;
@@ -32,7 +30,10 @@ const ModelVersionDetailsTabs: React.FC<ModelVersionDetailTabsProps> = ({
3230
refresh,
3331
}) => {
3432
const navigate = useNavigate();
35-
const { deploymentMode, platformMode } = useModularArchContext();
33+
const extensions = useExtensions(isModelRegistryDeploymentsTabExtension);
34+
const modelRegistryDeploymentsTab = extensions.find(
35+
(tab) => tab.properties.id === 'model-registry-deployments',
36+
);
3637
return (
3738
<Tabs
3839
activeKey={tab}
@@ -59,7 +60,19 @@ const ModelVersionDetailsTabs: React.FC<ModelVersionDetailTabsProps> = ({
5960
/>
6061
</PageSection>
6162
</Tab>
62-
{!isArchiveVersion &&
63+
{modelRegistryDeploymentsTab && (
64+
<LazyCodeRefComponent
65+
component={modelRegistryDeploymentsTab.properties.component}
66+
props={{
67+
id: modelRegistryDeploymentsTab.properties.id,
68+
title: modelRegistryDeploymentsTab.properties.title,
69+
inferenceServices,
70+
servingRuntimes,
71+
refresh,
72+
}}
73+
/>
74+
)}
75+
{/* {!isArchiveVersion &&
6376
(deploymentMode === DeploymentMode.Standalone ||
6477
platformMode !== PlatformMode.Kubeflow) && (
6578
<Tab
@@ -76,7 +89,7 @@ const ModelVersionDetailsTabs: React.FC<ModelVersionDetailTabsProps> = ({
7689
/>
7790
</PageSection>
7891
</Tab>
79-
)}
92+
)} */}
8093
</Tabs>
8194
);
8295
};

frontend/packages/model-registry/upstream/frontend/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"**/*.tsx",
3939
"**/*.jsx",
4040
"**/*.js"
41-
],
41+
, "../typesTest.ts" ],
4242
"exclude": [
4343
"node_modules",
4444
"dist",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { FetchStateObject } from '@odh-dashboard/internal/utilities/useFetch.js';
2+
import { InferenceServiceKind, ServingRuntimeKind } from 'mod-arch-shared';
3+
4+
export type ModelVersionRegisteredDeploymentsViewProps = {
5+
id: string;
6+
title: string;
7+
inferenceServices: FetchStateObject<InferenceServiceKind[]>;
8+
servingRuntimes: FetchStateObject<ServingRuntimeKind[]>;
9+
refresh: () => void;
10+
};

frontend/packages/modelServing/extensions.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
// Allow this import as it consists of types and enums only.
99
// eslint-disable-next-line no-restricted-syntax
1010
import { SupportedArea } from '@odh-dashboard/internal/concepts/areas/types';
11+
import type { ModelRegistryDeploymentsTabExtension } from '@odh-dashboard/model-registry/extension-points';
1112

1213
const PLUGIN_MODEL_SERVING = 'plugin-model-serving';
1314

@@ -17,6 +18,7 @@ const extensions: (
1718
| HrefNavItemExtension
1819
| RouteExtension
1920
| OverviewSectionExtension
21+
| ModelRegistryDeploymentsTabExtension
2022
)[] = [
2123
{
2224
type: 'app.area',
@@ -37,6 +39,14 @@ const extensions: (
3739
required: [PLUGIN_MODEL_SERVING],
3840
},
3941
},
42+
{
43+
type: 'model-registry.version-details/tab',
44+
properties: {
45+
id: 'model-registry-deployments',
46+
title: 'Deployments',
47+
component: () => import('./src/components/deployments/DeploymentsTab'),
48+
},
49+
},
4050
{
4151
type: 'app.project-details/overview-section',
4252
properties: {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Tab, TabTitleText, PageSection } from '@patternfly/react-core';
2+
import * as React from 'react';
3+
import ModelVersionRegisteredDeploymentsView from './ModelVersionRegisteredDeploymentsView';
4+
import { ModelVersionRegisteredDeploymentsViewProps } from './types';
5+
6+
const DeploymentsTab: React.FC<ModelVersionRegisteredDeploymentsViewProps> = ({
7+
id,
8+
title,
9+
inferenceServices,
10+
servingRuntimes,
11+
refresh,
12+
}) => (
13+
<Tab
14+
eventKey={id}
15+
title={<TabTitleText>{title}</TabTitleText>}
16+
aria-label="Deployments tab"
17+
data-testid="deployments-tab"
18+
>
19+
<PageSection hasBodyWrapper={false} isFilled data-testid="deployments-tab-content">
20+
<ModelVersionRegisteredDeploymentsView
21+
inferenceServices={inferenceServices}
22+
servingRuntimes={servingRuntimes}
23+
refresh={refresh}
24+
/>
25+
</PageSection>
26+
</Tab>
27+
);
28+
29+
export default DeploymentsTab;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React from 'react';
2+
import {
3+
Button,
4+
ButtonVariant,
5+
EmptyState,
6+
EmptyStateActions,
7+
EmptyStateBody,
8+
EmptyStateFooter,
9+
EmptyStateVariant,
10+
} from '@patternfly/react-core';
11+
import { PlusCircleIcon } from '@patternfly/react-icons';
12+
13+
type EmptyModelRegistryStateType = {
14+
testid?: string;
15+
title: string;
16+
description: string;
17+
primaryActionText?: string;
18+
primaryActionOnClick?: () => void;
19+
secondaryActionText?: string;
20+
secondaryActionOnClick?: () => void;
21+
headerIcon?: React.ComponentType;
22+
customAction?: React.ReactNode;
23+
};
24+
25+
const EmptyModelRegistryState: React.FC<EmptyModelRegistryStateType> = ({
26+
testid,
27+
title,
28+
description,
29+
primaryActionText,
30+
secondaryActionText,
31+
primaryActionOnClick,
32+
secondaryActionOnClick,
33+
headerIcon,
34+
customAction,
35+
}) => (
36+
<EmptyState
37+
icon={headerIcon ?? PlusCircleIcon}
38+
titleText={title}
39+
variant={EmptyStateVariant.sm}
40+
data-testid={testid}
41+
>
42+
<EmptyStateBody>{description}</EmptyStateBody>
43+
<EmptyStateFooter>
44+
{primaryActionText && (
45+
<EmptyStateActions>
46+
<Button
47+
data-testid="empty-model-registry-primary-action"
48+
variant={ButtonVariant.primary}
49+
onClick={primaryActionOnClick}
50+
>
51+
{primaryActionText}
52+
</Button>
53+
</EmptyStateActions>
54+
)}
55+
56+
{secondaryActionText && (
57+
<EmptyStateActions>
58+
<Button
59+
data-testid="empty-model-registry-secondary-action"
60+
variant="link"
61+
onClick={secondaryActionOnClick}
62+
>
63+
{secondaryActionText}
64+
</Button>
65+
</EmptyStateActions>
66+
)}
67+
68+
{customAction && <EmptyStateActions>{customAction}</EmptyStateActions>}
69+
</EmptyStateFooter>
70+
</EmptyState>
71+
);
72+
73+
export default EmptyModelRegistryState;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React from 'react';
2+
import { ProjectObjectType, typedEmptyImage } from '@odh-dashboard/internal/concepts/design/utils';
3+
import EmptyModelRegistryState from './EmptyModelRegistryState';
4+
import { ModelVersionRegisteredDeploymentsViewProps } from './types';
5+
// import some stuff from mod-arch-shared
6+
7+
const ModelVersionRegisteredDeploymentsView: React.FC<
8+
Omit<ModelVersionRegisteredDeploymentsViewProps, 'id' | 'title'>
9+
// TODO: [Model Serving] Remove this when model serving is available
10+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
11+
> = ({ inferenceServices, servingRuntimes, refresh }) => {
12+
const isLoading = !inferenceServices.loaded || !servingRuntimes.loaded;
13+
14+
if (!isLoading && !inferenceServices.data.length) {
15+
return (
16+
<EmptyModelRegistryState
17+
title="No deployments from model registry"
18+
headerIcon={() => (
19+
<img
20+
src={typedEmptyImage(ProjectObjectType.registeredModels, 'MissingDeployment')}
21+
alt="missing deployment"
22+
/>
23+
)}
24+
description="No deployments initiated from model registry for this model version."
25+
testid="model-version-deployments-empty-state"
26+
/>
27+
);
28+
}
29+
30+
return (
31+
<EmptyModelRegistryState
32+
title="No deployments from model registry"
33+
headerIcon={() => (
34+
<img
35+
src={typedEmptyImage(ProjectObjectType.registeredModels, 'MissingDeployment')}
36+
alt="missing deployment"
37+
/>
38+
)}
39+
description="No deployments initiated from model registry for this model version."
40+
testid="model-version-deployments-empty-state"
41+
/>
42+
);
43+
44+
// TODO: [Model Serving] Uncomment when model serving is available
45+
// return (
46+
// <Stack hasGutter>
47+
// <Alert variant="info" isInline title="Filtered list: Deployments from model registry only">
48+
// This list includes only deployments that were initiated from the model registry. To view and
49+
// manage all of your deployments, go to the <Link to="/modelServing">Model Serving</Link>{' '}
50+
// page.
51+
// </Alert>
52+
53+
// <InferenceServiceTable
54+
// isGlobal
55+
// getColumns={getVersionDetailsInferenceServiceColumns}
56+
// inferenceServices={inferenceServices.data}
57+
// servingRuntimes={servingRuntimes.data}
58+
// isLoading={isLoading}
59+
// refresh={refresh}
60+
// />
61+
// </Stack>
62+
// );
63+
};
64+
65+
export default ModelVersionRegisteredDeploymentsView;

0 commit comments

Comments
 (0)