From 53dc6685ccb5f3b5765c5df5e01eab19bc728b26 Mon Sep 17 00:00:00 2001 From: Jeffrey Phillips Date: Wed, 17 Apr 2024 10:25:36 -0400 Subject: [PATCH] [RHOAIENG-5487] Initial "empty state" of home page --- backend/src/types.ts | 1 + backend/src/utils/constants.ts | 1 + docs/dashboard-config.md | 5 ++- frontend/src/__mocks__/mockDashboardConfig.ts | 3 ++ .../cypress/cypress/e2e/home/home.cy.ts | 33 +++++++++++++++++++ .../cypress/cypress/pages/enabled.ts | 4 +-- frontend/src/app/AppRoutes.tsx | 14 +++++++- frontend/src/concepts/areas/const.ts | 3 ++ frontend/src/concepts/areas/types.ts | 2 ++ frontend/src/k8sTypes.ts | 1 + frontend/src/pages/home/Home.tsx | 27 +++++++++++++++ frontend/src/utilities/NavData.tsx | 28 ++++++++++------ ...dhdashboardconfigs.opendatahub.io.crd.yaml | 2 ++ .../odh-dashboard-config.yaml | 1 + .../odhdashboardconfig.yaml | 3 +- 15 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 frontend/src/__tests__/cypress/cypress/e2e/home/home.cy.ts create mode 100644 frontend/src/pages/home/Home.tsx diff --git a/backend/src/types.ts b/backend/src/types.ts index 8308d931d6..467e1c8619 100644 --- a/backend/src/types.ts +++ b/backend/src/types.ts @@ -23,6 +23,7 @@ export type DashboardConfig = K8sResourceCommon & { disableISVBadges: boolean; disableAppLauncher: boolean; disableUserManagement: boolean; + disableHome: boolean; disableProjects: boolean; disableModelServing: boolean; disableProjectSharing: boolean; diff --git a/backend/src/utils/constants.ts b/backend/src/utils/constants.ts index 4e8a43dc71..4d39f675f1 100644 --- a/backend/src/utils/constants.ts +++ b/backend/src/utils/constants.ts @@ -48,6 +48,7 @@ export const blankDashboardCR: DashboardConfig = { disableISVBadges: false, disableAppLauncher: false, disableUserManagement: false, + disableHome: true, disableProjects: false, disableModelServing: false, disableProjectSharing: false, diff --git a/docs/dashboard-config.md b/docs/dashboard-config.md index cc8d0a9de5..7edd859781 100644 --- a/docs/dashboard-config.md +++ b/docs/dashboard-config.md @@ -9,7 +9,7 @@ By default the ODH Dashboard comes with a set of core features enabled that are The following are a list of features that are supported, along with there default settings. | Feature | Default | Description | -| ---------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +|------------------------------|---------|------------------------------------------------------------------------------------------------------| | enablement | true | Enables the ability to enable ISVs to the dashboard | | disableInfo | false | Removes the information panel in Explore Application section | | disableSupport | false | Disables components related to support. | @@ -19,6 +19,7 @@ The following are a list of features that are supported, along with there defaul | disableISVBadges | false | Removes the badge that indicate if a product is ISV or not. | | disableAppLauncher | false | Removes the application launcher that is used in OKD environments | | disableUserManagement | false | Removes the User Management panel in Settings. | +| disableHome | true | Disables Data Science Home page from the dashboard. | | disableProjects | false | Disables Data Science Projects from the dashboard. | | disablePipelines | false | Disables Data Science Pipelines from the dashboard. | | disableModelServing | false | Disables Model Serving from the dashboard and from Data Science Projects. | @@ -50,6 +51,7 @@ spec: disableISVBadges: false disableAppLauncher: false disableUserManagement: false + disableHome: true disableProjects: false disablePipelines: false disableModelServing: false @@ -144,6 +146,7 @@ spec: disableInfo: false disableSupport: false disableTracking: true + disableHome: true disableProjects: true disablePipelines: true disableModelServing: true diff --git a/frontend/src/__mocks__/mockDashboardConfig.ts b/frontend/src/__mocks__/mockDashboardConfig.ts index e428f91c45..b954c9055b 100644 --- a/frontend/src/__mocks__/mockDashboardConfig.ts +++ b/frontend/src/__mocks__/mockDashboardConfig.ts @@ -9,6 +9,7 @@ type MockDashboardConfigType = { disableISVBadges?: boolean; disableAppLauncher?: boolean; disableUserManagement?: boolean; + disableHome?: boolean; disableProjects?: boolean; disablePipelines?: boolean; disableModelServing?: boolean; @@ -33,6 +34,7 @@ export const mockDashboardConfig = ({ disableISVBadges = false, disableAppLauncher = false, disableUserManagement = false, + disableHome = true, disableProjects = false, disableModelServing = false, disableCustomServingRuntimes = false, @@ -67,6 +69,7 @@ export const mockDashboardConfig = ({ disableISVBadges, disableAppLauncher, disableUserManagement, + disableHome, disableProjects, disableModelServing, disableCustomServingRuntimes, diff --git a/frontend/src/__tests__/cypress/cypress/e2e/home/home.cy.ts b/frontend/src/__tests__/cypress/cypress/e2e/home/home.cy.ts new file mode 100644 index 0000000000..847948fc5a --- /dev/null +++ b/frontend/src/__tests__/cypress/cypress/e2e/home/home.cy.ts @@ -0,0 +1,33 @@ +import { mockDashboardConfig } from '~/__mocks__/mockDashboardConfig'; +import { mockComponents } from '~/__mocks__/mockComponents'; +import { enabledPage } from '~/__tests__/cypress/cypress/pages/enabled'; + +type HandlersProps = { + disableHome?: boolean; +}; + +const initIntercepts = ({ disableHome }: HandlersProps) => { + cy.interceptOdh( + 'GET /api/config', + mockDashboardConfig({ + disableHome, + }), + ); + cy.interceptOdh('GET /api/components', { query: { installed: 'true' } }, mockComponents()); +}; + +describe('Home page', () => { + it('should not be shown by default', () => { + initIntercepts({}); + cy.visit('/'); + cy.findByTestId('enabled-application').should('be.visible'); + }); + it('should be shown when enabled', () => { + initIntercepts({ disableHome: false }); + cy.visit('/'); + cy.findByTestId('home-page').should('be.visible'); + + // enabled applications page is still navigable + enabledPage.visit(true); + }); +}); diff --git a/frontend/src/__tests__/cypress/cypress/pages/enabled.ts b/frontend/src/__tests__/cypress/cypress/pages/enabled.ts index 52823b26e4..a8750a8c4e 100644 --- a/frontend/src/__tests__/cypress/cypress/pages/enabled.ts +++ b/frontend/src/__tests__/cypress/cypress/pages/enabled.ts @@ -1,6 +1,6 @@ class EnabledPage { - visit() { - cy.visit('/'); + visit(homeEnabled = false) { + cy.visit(homeEnabled ? '/enabled' : '/'); this.wait(); } diff --git a/frontend/src/app/AppRoutes.tsx b/frontend/src/app/AppRoutes.tsx index d337dac202..92135435f9 100644 --- a/frontend/src/app/AppRoutes.tsx +++ b/frontend/src/app/AppRoutes.tsx @@ -6,6 +6,10 @@ import UnauthorizedError from '~/pages/UnauthorizedError'; import { useUser } from '~/redux/selectors'; import { globExperimentsAll, globPipelineRunsAll, globPipelinesAll } from '~/routes'; import { useCheckJupyterEnabled } from '~/utilities/notebookControllerUtils'; +import { SupportedArea } from '~/concepts/areas'; +import useIsAreaAvailable from '~/concepts/areas/useIsAreaAvailable'; + +const HomePage = React.lazy(() => import('../pages/home/Home')); const InstalledApplications = React.lazy( () => import('../pages/enabledApplications/EnabledApplications'), @@ -56,6 +60,7 @@ const ModelRegistryRoutes = React.lazy(() => import('../pages/modelRegistry/Mode const AppRoutes: React.FC = () => { const { isAdmin, isAllowed } = useUser(); const isJupyterEnabled = useCheckJupyterEnabled(); + const isHomeAvailable = useIsAreaAvailable(SupportedArea.HOME).status; if (!isAllowed) { return ( @@ -69,7 +74,14 @@ const AppRoutes: React.FC = () => { }> - } /> + {isHomeAvailable ? ( + <> + } /> + } /> + + ) : ( + } /> + )} } /> } /> diff --git a/frontend/src/concepts/areas/const.ts b/frontend/src/concepts/areas/const.ts index 1c4fe82376..4a13cbbdc7 100644 --- a/frontend/src/concepts/areas/const.ts +++ b/frontend/src/concepts/areas/const.ts @@ -18,6 +18,9 @@ export const SupportedAreasStateMap: SupportedAreasState = { featureFlags: ['disablePipelines'], requiredComponents: [StackComponent.DS_PIPELINES], }, + [SupportedArea.HOME]: { + featureFlags: ['disableHome'], + }, [SupportedArea.DS_PROJECTS_VIEW]: { featureFlags: ['disableProjects'], }, diff --git a/frontend/src/concepts/areas/types.ts b/frontend/src/concepts/areas/types.ts index e29456ae05..bbfad94248 100644 --- a/frontend/src/concepts/areas/types.ts +++ b/frontend/src/concepts/areas/types.ts @@ -22,6 +22,8 @@ export type IsAreaAvailableStatus = { /** All areas that we need to support in some fashion or another */ export enum SupportedArea { + HOME = 'home', + /* Standalone areas */ DS_PIPELINES = 'ds-pipelines', // TODO: Jupyter Tile Support? (outside of feature flags today) diff --git a/frontend/src/k8sTypes.ts b/frontend/src/k8sTypes.ts index a3a4ff9c27..59439f3a08 100644 --- a/frontend/src/k8sTypes.ts +++ b/frontend/src/k8sTypes.ts @@ -1196,6 +1196,7 @@ export type DashboardCommonConfig = { disableISVBadges: boolean; disableAppLauncher: boolean; disableUserManagement: boolean; + disableHome: boolean; disableProjects: boolean; disableModelServing: boolean; disableProjectSharing: boolean; diff --git a/frontend/src/pages/home/Home.tsx b/frontend/src/pages/home/Home.tsx new file mode 100644 index 0000000000..044e2d1a38 --- /dev/null +++ b/frontend/src/pages/home/Home.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { + Bullseye, + EmptyState, + EmptyStateHeader, + EmptyStateIcon, + PageSection, + PageSectionVariants, +} from '@patternfly/react-core'; +import { HomeIcon } from '@patternfly/react-icons'; + +const Home: React.FC = () => ( + + + + } + alt="" + /> + + + +); + +export default Home; diff --git a/frontend/src/utilities/NavData.tsx b/frontend/src/utilities/NavData.tsx index 32458e9942..0575a20cad 100644 --- a/frontend/src/utilities/NavData.tsx +++ b/frontend/src/utilities/NavData.tsx @@ -30,16 +30,23 @@ export const isNavDataGroup = (navData: NavDataItem): navData is NavDataGroup => const useAreaCheck = (area: SupportedArea, success: T[]): T[] => useIsAreaAvailable(area).status ? success : []; -const useApplicationsNav = (): NavDataItem[] => [ - { - id: 'applications', - group: { id: 'apps', title: 'Applications' }, - children: [ - { id: 'apps-installed', label: 'Enabled', href: '/' }, - { id: 'apps-explore', label: 'Explore', href: '/explore' }, - ], - }, -]; +const useApplicationsNav = (): NavDataItem[] => { + const isHomeAvailable = useIsAreaAvailable(SupportedArea.HOME).status; + + return [ + { + id: 'applications', + group: { id: 'apps', title: 'Applications' }, + children: [ + { id: 'apps-installed', label: 'Enabled', href: isHomeAvailable ? '/enabled' : '/' }, + { id: 'apps-explore', label: 'Explore', href: '/explore' }, + ], + }, + ]; +}; + +const useHomeNav = (): NavDataItem[] => + useAreaCheck(SupportedArea.HOME, [{ id: 'home', label: 'Home', href: '/' }]); const useDSProjectsNav = (): NavDataItem[] => useAreaCheck(SupportedArea.DS_PROJECTS_VIEW, [ @@ -171,6 +178,7 @@ const useSettingsNav = (): NavDataGroup[] => { }; export const useBuildNavData = (): NavDataItem[] => [ + ...useHomeNav(), ...useApplicationsNav(), ...useDSProjectsNav(), ...useDSPipelinesNav(), diff --git a/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml b/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml index a6d5a781c1..8a1b8dbe6f 100644 --- a/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml +++ b/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml @@ -41,6 +41,8 @@ spec: type: boolean disableUserManagement: type: boolean + disableHome: + type: boolean disableProjects: type: boolean disableModelServing: diff --git a/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml b/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml index 2976cbcb7d..ef5b2b03f6 100644 --- a/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml +++ b/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml @@ -13,6 +13,7 @@ spec: disableSupport: false disableTracking: true enablement: true + disableHome: true disableProjects: true disablePipelines: true disablePipelineExperiments: true diff --git a/manifests/overlays/odhdashboardconfig/odhdashboardconfig.yaml b/manifests/overlays/odhdashboardconfig/odhdashboardconfig.yaml index 8e8cdb60a3..8f62e794f4 100644 --- a/manifests/overlays/odhdashboardconfig/odhdashboardconfig.yaml +++ b/manifests/overlays/odhdashboardconfig/odhdashboardconfig.yaml @@ -13,6 +13,7 @@ spec: disableSupport: false disableTracking: false enablement: true + disableHome: false disableProjects: false disablePipelines: false disableModelServing: false @@ -92,4 +93,4 @@ spec: cpu: "6" memory: 16Gi templateOrder: [] - templateDisablement: [] \ No newline at end of file + templateDisablement: []