Skip to content

Commit

Permalink
[RHOAIENG-7572] Registered Models - Empty View Redesign
Browse files Browse the repository at this point in the history
  • Loading branch information
jpuzz0 committed Aug 7, 2024
1 parent 45b42f2 commit 46854d7
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 25 deletions.
4 changes: 3 additions & 1 deletion frontend/src/concepts/design/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import pipelineEmptyStateImg from '~/images/empty-state-pipelines.svg';
import clusterStorageEmptyStateImg from '~/images/empty-state-cluster-storage.svg';
import modelServerEmptyStateImg from '~/images/empty-state-model-serving.svg';
import dataConnectionEmptyStateImg from '~/images/empty-state-data-connections.svg';
import modelRegistryEmptyStateImg from '~/images/empty-state-model-registries.svg';

import './vars.scss';

Expand Down Expand Up @@ -114,8 +115,9 @@ export const typedEmptyImage = (objectType: ProjectObjectType): string => {
case ProjectObjectType.clusterStorage:
return clusterStorageEmptyStateImg;
case ProjectObjectType.modelServer:
case ProjectObjectType.registeredModels:
return modelServerEmptyStateImg;
case ProjectObjectType.registeredModels:
return modelRegistryEmptyStateImg;
case ProjectObjectType.dataConnection:
return dataConnectionEmptyStateImg;
default:
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/images/empty-state-model-registries.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 56 additions & 14 deletions frontend/src/pages/modelRegistry/screens/ModelRegistry.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import React from 'react';

import { Button, List, ListItem, Popover } from '@patternfly/react-core';
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';

import ApplicationsPage from '~/pages/ApplicationsPage';
import useRegisteredModels from '~/concepts/modelRegistry/apiHooks/useRegisteredModels';
import TitleWithIcon from '~/concepts/design/TitleWithIcon';
import { ProjectObjectType } from '~/concepts/design/utils';
import { ProjectObjectType, typedEmptyImage } from '~/concepts/design/utils';
import { ModelRegistrySelectorContext } from '~/concepts/modelRegistry/context/ModelRegistrySelectorContext';
import RegisteredModelListView from './RegisteredModels/RegisteredModelListView';
import ModelRegistrySelectorNavigator from './ModelRegistrySelectorNavigator';
import { filterLiveModels } from './utils';
import EmptyModelRegistryState from './components/EmptyModelRegistryState';

type ModelRegistryProps = Omit<
React.ComponentProps<typeof ApplicationsPage>,
Expand All @@ -19,29 +25,65 @@ type ModelRegistryProps = Omit<
>;

const ModelRegistry: React.FC<ModelRegistryProps> = ({ ...pageProps }) => {
const [registeredModels, loaded, loadError, refresh] = useRegisteredModels();
const { modelRegistries, modelRegistriesLoaded } = React.useContext(ModelRegistrySelectorContext);
const [registeredModels, registeredModelsLoaded, registeredModelsLoadError, refresh] =
useRegisteredModels();

return (
<ApplicationsPage
{...pageProps}
title={
<TitleWithIcon title="Registered models" objectType={ProjectObjectType.deployedModels} />
}
description="View and manage your registered models."
headerContent={
<ModelRegistrySelectorNavigator
getRedirectPath={(modelRegistryName) => `/modelRegistry/${modelRegistryName}`}
/>
}
loadError={loadError}
loaded={loaded}
description="View and manage all of your registered models. Registering models to model registry allows you to manage their content, metadata, versions, and user access settings."
{...(modelRegistries.length && {
headerContent: (
<ModelRegistrySelectorNavigator
getRedirectPath={(modelRegistryName) => `/modelRegistry/${modelRegistryName}`}
/>
),
})}
loadError={registeredModelsLoadError}
loaded={modelRegistriesLoaded && registeredModelsLoaded}
provideChildrenPadding
removeChildrenTopPadding
>
<RegisteredModelListView
registeredModels={filterLiveModels(registeredModels.items)}
refresh={refresh}
/>
{modelRegistries.length ? (
<RegisteredModelListView
registeredModels={filterLiveModels(registeredModels.items)}
refresh={refresh}
/>
) : (
<EmptyModelRegistryState
testid="empty-registered-models"
title="Request access to model registries"
description="To request a new model registry, or to request permission to access an existing model registry, contact your administrator."
headerIcon={() => (
<img src={typedEmptyImage(ProjectObjectType.registeredModels)} alt="" />
)}
customAction={
<Popover
showClose
position="bottom"
headerContent="Your administrator might be:"
bodyContent={
<List>
<ListItem>
The person who gave you your username, or who helped you to log in for the first
time
</ListItem>
<ListItem>Someone in your IT department or help desk</ListItem>
<ListItem>A project manager or developer</ListItem>
</List>
}
>
<Button variant="link" icon={<OutlinedQuestionCircleIcon />} isInline>
Who&apos;s my administrator?
</Button>
</Popover>
}
/>
)}
</ApplicationsPage>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react';
import {
Button,
ButtonVariant,
Expand All @@ -7,10 +8,10 @@ import {
EmptyStateFooter,
EmptyStateHeader,
EmptyStateIcon,
EmptyStateIconProps,
EmptyStateVariant,
} from '@patternfly/react-core';
import { PlusCircleIcon } from '@patternfly/react-icons';
import * as React from 'react';

type EmptyModelRegistryStateType = {
testid?: string;
Expand All @@ -20,6 +21,8 @@ type EmptyModelRegistryStateType = {
primaryActionOnClick?: () => void;
secondaryActionText?: string;
secondaryActionOnClick?: () => void;
headerIcon?: EmptyStateIconProps['icon'];
customAction?: React.ReactNode;
};

const EmptyModelRegistryState: React.FC<EmptyModelRegistryStateType> = ({
Expand All @@ -30,33 +33,41 @@ const EmptyModelRegistryState: React.FC<EmptyModelRegistryStateType> = ({
secondaryActionText,
primaryActionOnClick,
secondaryActionOnClick,
headerIcon,
customAction,
}) => (
<EmptyState variant={EmptyStateVariant.sm} data-testid={testid}>
<EmptyStateHeader titleText={title} icon={<EmptyStateIcon icon={PlusCircleIcon} />} />
<EmptyStateHeader
titleText={title}
icon={<EmptyStateIcon icon={headerIcon ?? PlusCircleIcon} />}
/>
<EmptyStateBody>{description}</EmptyStateBody>
<EmptyStateFooter>
<EmptyStateActions>
{primaryActionText && (
{primaryActionText && (
<EmptyStateActions>
<Button
data-testid="empty-model-registry-primary-action"
variant={ButtonVariant.primary}
onClick={primaryActionOnClick}
>
{primaryActionText}
</Button>
)}
</EmptyStateActions>
<EmptyStateActions>
{secondaryActionText && (
</EmptyStateActions>
)}

{secondaryActionText && (
<EmptyStateActions>
<Button
data-testid="empty-model-registry-secondary-action"
variant="link"
onClick={secondaryActionOnClick}
>
{secondaryActionText}
</Button>
)}
</EmptyStateActions>
</EmptyStateActions>
)}

{customAction && <EmptyStateActions>{customAction}</EmptyStateActions>}
</EmptyStateFooter>
</EmptyState>
);
Expand Down

0 comments on commit 46854d7

Please sign in to comment.