From df3ec3c583eec300a7325254dae89421b7b9eded Mon Sep 17 00:00:00 2001 From: Saravana Date: Mon, 13 Nov 2023 23:28:31 +0530 Subject: [PATCH] Edge Model Registry - Sidebar and EmptyState --- docs/dashboard-config.md | 2 ++ frontend/src/__mocks__/mockDashboardConfig.ts | 3 +++ .../pages/edge/ModelRegistry.spec.ts | 9 +++++++ .../pages/edge/ModelRegistry.stories.tsx | 13 +++++++++ frontend/src/app/AppRoutes.tsx | 4 +-- frontend/src/concepts/areas/const.ts | 3 +++ frontend/src/concepts/areas/types.ts | 3 +++ frontend/src/k8sTypes.ts | 1 + frontend/src/pages/edge/EdgeModelRegistry.tsx | 15 +++++++++++ frontend/src/pages/edge/EdgeModelsRoutes.tsx | 11 ++++++++ .../src/pages/edge/EmptyModelRegistry.tsx | 27 +++++++++++++++++++ frontend/src/utilities/NavData.tsx | 12 +++++++++ ...dhdashboardconfigs.opendatahub.io.crd.yaml | 2 ++ .../odh-dashboard-config.yaml | 1 + 14 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 frontend/src/__tests__/integration/pages/edge/ModelRegistry.spec.ts create mode 100644 frontend/src/__tests__/integration/pages/edge/ModelRegistry.stories.tsx create mode 100644 frontend/src/pages/edge/EdgeModelRegistry.tsx create mode 100644 frontend/src/pages/edge/EdgeModelsRoutes.tsx create mode 100644 frontend/src/pages/edge/EmptyModelRegistry.tsx diff --git a/docs/dashboard-config.md b/docs/dashboard-config.md index cf20d49269..1f431fa5a7 100644 --- a/docs/dashboard-config.md +++ b/docs/dashboard-config.md @@ -47,6 +47,7 @@ spec: disableModelServing: false disableProjectSharing: false disableCustomServingRuntimes: false + disableEdge: false modelMetricsNamespace: '' ``` @@ -136,6 +137,7 @@ spec: disableModelServing: true disableProjectSharing: true disableCustomServingRuntimes: false + disableEdge: true modelMetricsNamespace: '' notebookController: enabled: true diff --git a/frontend/src/__mocks__/mockDashboardConfig.ts b/frontend/src/__mocks__/mockDashboardConfig.ts index 960f2ed437..ddbbe43928 100644 --- a/frontend/src/__mocks__/mockDashboardConfig.ts +++ b/frontend/src/__mocks__/mockDashboardConfig.ts @@ -13,6 +13,7 @@ type MockDashboardConfigType = { disablePipelines?: boolean; disableModelServing?: boolean; disableCustomServingRuntimes?: boolean; + disableEdge?: boolean; }; export const mockDashboardConfig = ({ @@ -28,6 +29,7 @@ export const mockDashboardConfig = ({ disableModelServing = false, disableCustomServingRuntimes = false, disablePipelines = false, + disableEdge = false, }: MockDashboardConfigType): DashboardConfigKind => ({ apiVersion: 'opendatahub.io/v1alpha', kind: 'OdhDashboardConfig', @@ -55,6 +57,7 @@ export const mockDashboardConfig = ({ disablePipelines, modelMetricsNamespace: 'test-project', disableProjectSharing: false, + disableEdge, }, notebookController: { enabled: true, diff --git a/frontend/src/__tests__/integration/pages/edge/ModelRegistry.spec.ts b/frontend/src/__tests__/integration/pages/edge/ModelRegistry.spec.ts new file mode 100644 index 0000000000..10b13a102a --- /dev/null +++ b/frontend/src/__tests__/integration/pages/edge/ModelRegistry.spec.ts @@ -0,0 +1,9 @@ +import { test } from '@playwright/test'; +import { navigateToStory } from '~/__tests__/integration/utils'; + +test('Empty State No models in Registry', async ({ page }) => { + await page.goto(navigateToStory('pages-edge-modelregistry', 'empty-state-no-models-in-registry')); + + // wait for page to load + await page.waitForSelector('text=No models in the registry'); +}); diff --git a/frontend/src/__tests__/integration/pages/edge/ModelRegistry.stories.tsx b/frontend/src/__tests__/integration/pages/edge/ModelRegistry.stories.tsx new file mode 100644 index 0000000000..3ade6d2ba6 --- /dev/null +++ b/frontend/src/__tests__/integration/pages/edge/ModelRegistry.stories.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { StoryFn, StoryObj } from '@storybook/react'; +import EdgeModelRegistry from '~/pages/edge/EdgeModelRegistry'; + +export default { + component: EdgeModelRegistry, +}; + +const Template: StoryFn = (args) => ; + +export const EmptyStateNoModelsInRegistry: StoryObj = { + render: Template, +}; diff --git a/frontend/src/app/AppRoutes.tsx b/frontend/src/app/AppRoutes.tsx index fc24d81c50..b2e84ab042 100644 --- a/frontend/src/app/AppRoutes.tsx +++ b/frontend/src/app/AppRoutes.tsx @@ -18,7 +18,7 @@ const ModelServingRoutes = React.lazy(() => import('../pages/modelServing/ModelS const NotebookController = React.lazy( () => import('../pages/notebookController/NotebookController'), ); - +const EdgeModelsRoutes = React.lazy(() => import('../pages/edge/EdgeModelsRoutes')); const GlobalPipelinesRoutes = React.lazy(() => import('../pages/pipelines/GlobalPipelinesRoutes')); const GlobalPipelineRunsRoutes = React.lazy( () => import('../pages/pipelines/GlobalPipelineRunsRoutes'), @@ -80,7 +80,7 @@ const AppRoutes: React.FC = () => { } /> )} - + } /> } /> diff --git a/frontend/src/concepts/areas/const.ts b/frontend/src/concepts/areas/const.ts index 31c9b2b30b..c6b692c1b9 100644 --- a/frontend/src/concepts/areas/const.ts +++ b/frontend/src/concepts/areas/const.ts @@ -42,4 +42,7 @@ export const SupportedAreasStateMap: SupportedAreasState = { requiredComponents: [StackComponent.WORKBENCHES], reliantAreas: [SupportedArea.DS_PROJECTS_VIEW], }, + [SupportedArea.EDGE]: { + featureFlags: ['disableEdge'], + }, }; diff --git a/frontend/src/concepts/areas/types.ts b/frontend/src/concepts/areas/types.ts index 72db26a798..76b36fbf9e 100644 --- a/frontend/src/concepts/areas/types.ts +++ b/frontend/src/concepts/areas/types.ts @@ -36,6 +36,9 @@ export enum SupportedArea { CUSTOM_RUNTIMES = 'custom-serving-runtimes', K_SERVE = 'kserve', MODEL_MESH = 'model-mesh', + + /* Edge */ + EDGE = 'edge', } /** Components deployed by the Operator. Part of the DSC Status. */ diff --git a/frontend/src/k8sTypes.ts b/frontend/src/k8sTypes.ts index ea280dd4bf..95355a816f 100644 --- a/frontend/src/k8sTypes.ts +++ b/frontend/src/k8sTypes.ts @@ -740,6 +740,7 @@ export type DashboardCommonConfig = { disableCustomServingRuntimes: boolean; modelMetricsNamespace: string; disablePipelines: boolean; + disableEdge: boolean; }; export type OperatorStatus = { diff --git a/frontend/src/pages/edge/EdgeModelRegistry.tsx b/frontend/src/pages/edge/EdgeModelRegistry.tsx new file mode 100644 index 0000000000..a7ffb22e16 --- /dev/null +++ b/frontend/src/pages/edge/EdgeModelRegistry.tsx @@ -0,0 +1,15 @@ +import * as React from 'react'; +import ApplicationsPage from '~/pages/ApplicationsPage'; +import EmptyModelRegistry from './EmptyModelRegistry'; + +const EdgeModelRegistry: React.FC = () => ( + } + /> +); + +export default EdgeModelRegistry; diff --git a/frontend/src/pages/edge/EdgeModelsRoutes.tsx b/frontend/src/pages/edge/EdgeModelsRoutes.tsx new file mode 100644 index 0000000000..42e41445f7 --- /dev/null +++ b/frontend/src/pages/edge/EdgeModelsRoutes.tsx @@ -0,0 +1,11 @@ +import * as React from 'react'; +import { Routes, Route } from 'react-router-dom'; +import EdgeModelRegistry from './EdgeModelRegistry'; + +const EdgeModelsRoutes: React.FC = () => ( + + } /> + +); + +export default EdgeModelsRoutes; diff --git a/frontend/src/pages/edge/EmptyModelRegistry.tsx b/frontend/src/pages/edge/EmptyModelRegistry.tsx new file mode 100644 index 0000000000..4e3a851599 --- /dev/null +++ b/frontend/src/pages/edge/EmptyModelRegistry.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { + EmptyState, + EmptyStateBody, + EmptyStateIcon, + PageSection, + Title, +} from '@patternfly/react-core'; +import { PlusCircleIcon } from '@patternfly/react-icons'; + +const EmptyModelRegistry: React.FC = () => ( + + + + + No models in the registry + + + To get started, add a model to the model registry. Adding a model will also initiate a + pipeline that will build the model and its dependencies into a container image and save that + image in a container image registry. + + + +); + +export default EmptyModelRegistry; diff --git a/frontend/src/utilities/NavData.tsx b/frontend/src/utilities/NavData.tsx index 1ee1561360..de86a9b603 100644 --- a/frontend/src/utilities/NavData.tsx +++ b/frontend/src/utilities/NavData.tsx @@ -90,6 +90,17 @@ const useDSPipelinesNav = (): NavDataItem[] => { ]; }; +const useEdgeMVPNav = (): NavDataItem[] => + useAreaCheck(SupportedArea.EDGE, [ + { + id: 'edgemvp', + group: { id: 'edge', title: 'Edge MVP' }, + children: [ + { id: 'edge-model-registry', label: 'Model registry', href: '/edge/modelRegistry' }, + ], + }, + ]); + const useModelServingNav = (): NavDataItem[] => useAreaCheck(SupportedArea.MODEL_SERVING, [ { id: 'modelServing', label: 'Model Serving', href: '/modelServing' }, @@ -161,6 +172,7 @@ export const useBuildNavData = (): NavDataItem[] => [ ...useApplicationsNav(), ...useDSProjectsNav(), ...useDSPipelinesNav(), + ...useEdgeMVPNav(), ...useModelServingNav(), ...useResourcesNav(), ...useSettingsNav(), diff --git a/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml b/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml index 8108ce32aa..9d2e2cf8f3 100644 --- a/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml +++ b/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml @@ -53,6 +53,8 @@ spec: type: string disablePipelines: type: boolean + disableEdge: + type: boolean groupsConfig: type: object required: diff --git a/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml b/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml index 677c300dc9..574f732838 100644 --- a/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml +++ b/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml @@ -18,6 +18,7 @@ spec: disableModelServing: true disableProjectSharing: true disableCustomServingRuntimes: true + disableEdge: true modelMetricsNamespace: '' notebookController: enabled: true