diff --git a/frontend/src/components/WhosMyAdministrator.tsx b/frontend/src/components/WhosMyAdministrator.tsx new file mode 100644 index 0000000000..4ca7dae516 --- /dev/null +++ b/frontend/src/components/WhosMyAdministrator.tsx @@ -0,0 +1,50 @@ +import * as React from 'react'; +import { Button, Popover } from '@patternfly/react-core'; +import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; +import PopoverListContent from '~/components/PopoverListContent'; +import { FindAdministratorOptions } from '~/pages/projects/screens/projects/const'; + +type Props = { + buttonLabel?: string; + headerContent?: string; + leadText?: string; + isInline?: boolean; + contentTestId?: string; + linkTestId?: string; +}; + +const WhosMyAdministrator: React.FC = ({ + buttonLabel = "Who's my administrator?", + headerContent, + leadText, + isInline, + contentTestId, + linkTestId, +}) => ( + + } + > + + +); + +export default WhosMyAdministrator; diff --git a/frontend/src/pages/distributedWorkloads/global/GlobalDistributedWorkloadsTabs.tsx b/frontend/src/pages/distributedWorkloads/global/GlobalDistributedWorkloadsTabs.tsx index c5e09dbf26..630a99119d 100644 --- a/frontend/src/pages/distributedWorkloads/global/GlobalDistributedWorkloadsTabs.tsx +++ b/frontend/src/pages/distributedWorkloads/global/GlobalDistributedWorkloadsTabs.tsx @@ -11,12 +11,14 @@ import { EmptyStateBody, EmptyStateHeader, EmptyStateIcon, + EmptyStateFooter, } from '@patternfly/react-core'; import { WrenchIcon } from '@patternfly/react-icons'; import MetricsPageToolbar from '~/concepts/metrics/MetricsPageToolbar'; import { DistributedWorkloadsContext } from '~/concepts/distributedWorkloads/DistributedWorkloadsContext'; import EmptyStateErrorMessage from '~/components/EmptyStateErrorMessage'; import { LoadingState } from '~/pages/distributedWorkloads/components/LoadingState'; +import WhosMyAdministrator from '~/components/WhosMyAdministrator'; import { DistributedWorkloadsTabId, useDistributedWorkloadsTabs, @@ -52,8 +54,9 @@ const GlobalDistributedWorkloadsTabs: React.FC} /> {message} + {nonAdmin ? ( + + + + ) : null} ); } diff --git a/frontend/src/pages/home/projects/EmptyProjectsCard.tsx b/frontend/src/pages/home/projects/EmptyProjectsCard.tsx index 0768764632..dbdae06849 100644 --- a/frontend/src/pages/home/projects/EmptyProjectsCard.tsx +++ b/frontend/src/pages/home/projects/EmptyProjectsCard.tsx @@ -12,6 +12,7 @@ import { } from '@patternfly/react-core'; import { ArrowRightIcon } from '@patternfly/react-icons'; import getStartedImage from '~/images/AI_ML-illustration-Blog-thumbnail.svg'; +import WhosMyAdministrator from '~/components/WhosMyAdministrator'; type EmptyProjectsCardProps = { allowCreate: boolean; @@ -53,7 +54,11 @@ const EmptyProjectsCard: React.FC = ({ allowCreate, onCr Create a project - ) : null} + ) : ( + + + + )} diff --git a/frontend/src/pages/modelRegistry/ModelRegistryCoreLoader.tsx b/frontend/src/pages/modelRegistry/ModelRegistryCoreLoader.tsx index bdb5fe2219..cfaf7db178 100644 --- a/frontend/src/pages/modelRegistry/ModelRegistryCoreLoader.tsx +++ b/frontend/src/pages/modelRegistry/ModelRegistryCoreLoader.tsx @@ -1,15 +1,13 @@ import * as React from 'react'; import { Navigate, Outlet, useParams } from 'react-router'; - -import { Bullseye, Alert, Popover, List, ListItem, Button } from '@patternfly/react-core'; -import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; - +import { Bullseye, Alert } from '@patternfly/react-core'; import { conditionalArea, SupportedArea } from '~/concepts/areas'; import { ModelRegistryContextProvider } from '~/concepts/modelRegistry/context/ModelRegistryContext'; import ApplicationsPage from '~/pages/ApplicationsPage'; import TitleWithIcon from '~/concepts/design/TitleWithIcon'; import { ProjectObjectType, typedEmptyImage } from '~/concepts/design/utils'; import { ModelRegistrySelectorContext } from '~/concepts/modelRegistry/context/ModelRegistrySelectorContext'; +import WhosMyAdministrator from '~/components/WhosMyAdministrator'; import InvalidModelRegistry from './screens/InvalidModelRegistry'; import EmptyModelRegistryState from './screens/components/EmptyModelRegistryState'; import ModelRegistrySelectorNavigator from './screens/ModelRegistrySelectorNavigator'; @@ -82,27 +80,7 @@ const ModelRegistryCoreLoader: React.FC = headerIcon={() => ( )} - customAction={ - - - The person who gave you your username, or who helped you to log in for the - first time - - Someone in your IT department or help desk - A project manager or developer - - } - > - - - } + customAction={} /> ), headerContent: null, diff --git a/frontend/src/pages/modelServing/screens/projects/EmptyModelServingPlatform.tsx b/frontend/src/pages/modelServing/screens/projects/EmptyModelServingPlatform.tsx index c7460e123d..b84b6ced27 100644 --- a/frontend/src/pages/modelServing/screens/projects/EmptyModelServingPlatform.tsx +++ b/frontend/src/pages/modelServing/screens/projects/EmptyModelServingPlatform.tsx @@ -2,11 +2,12 @@ import * as React from 'react'; import { EmptyState, EmptyStateBody, + EmptyStateFooter, EmptyStateHeader, EmptyStateIcon, } from '@patternfly/react-core'; -import EmptyDetailsList from '~/pages/projects/screens/detail/EmptyDetailsList'; import gearsImg from '~/images/gears.svg'; +import WhosMyAdministrator from '~/components/WhosMyAdministrator'; const EmptyModelServingPlatform: React.FC = () => ( @@ -20,13 +21,10 @@ const EmptyModelServingPlatform: React.FC = () => ( To enable model serving, an administrator must first select a model serving platform in the cluster settings. + + + ); - settings} -/>; - export default EmptyModelServingPlatform; diff --git a/frontend/src/pages/projects/screens/projects/EmptyProjects.tsx b/frontend/src/pages/projects/screens/projects/EmptyProjects.tsx index a2e9c9e830..0cd9f864ed 100644 --- a/frontend/src/pages/projects/screens/projects/EmptyProjects.tsx +++ b/frontend/src/pages/projects/screens/projects/EmptyProjects.tsx @@ -5,15 +5,10 @@ import { EmptyStateIcon, EmptyStateHeader, EmptyStateFooter, - Popover, - Button, - Icon, } from '@patternfly/react-core'; import { useNavigate } from 'react-router-dom'; -import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; -import PopoverListContent from '~/components/PopoverListContent'; import projectsEmptyStateImg from '~/images/empty-state-projects-color.svg'; -import { FindAdministratorOptions } from '~/pages/projects/screens/projects/const'; +import WhosMyAdministrator from '~/components/WhosMyAdministrator'; import NewProjectButton from './NewProjectButton'; type EmptyProjectsProps = { @@ -49,29 +44,10 @@ const EmptyProjects: React.FC = ({ allowCreate }) => { /> ) : ( - - } - > - - + )} diff --git a/frontend/src/pages/projects/screens/projects/ProjectsToolbar.tsx b/frontend/src/pages/projects/screens/projects/ProjectsToolbar.tsx index e87a71f0ee..2d75ea8c2b 100644 --- a/frontend/src/pages/projects/screens/projects/ProjectsToolbar.tsx +++ b/frontend/src/pages/projects/screens/projects/ProjectsToolbar.tsx @@ -1,22 +1,13 @@ import * as React from 'react'; -import { - Button, - Icon, - Popover, - SearchInput, - ToolbarGroup, - ToolbarItem, -} from '@patternfly/react-core'; +import { SearchInput, ToolbarGroup, ToolbarItem } from '@patternfly/react-core'; import { useNavigate } from 'react-router-dom'; -import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; -import PopoverListContent from '~/components/PopoverListContent'; import FilterToolbar from '~/components/FilterToolbar'; import { - FindAdministratorOptions, ProjectsFilterDataType, projectsFilterOptions, ProjectsFilterOptions, } from '~/pages/projects/screens/projects/const'; +import WhosMyAdministrator from '~/components/WhosMyAdministrator'; import NewProjectButton from './NewProjectButton'; type ProjectsToolbarProps = { @@ -64,25 +55,12 @@ const ProjectsToolbar: React.FC = ({ onProjectCreated={(projectName) => navigate(`/projects/${projectName}`)} /> ) : ( - - } - > - - + leadText="To request a new project, contact your administrator." + contentTestId="projects-admin-help-content" + /> )} diff --git a/frontend/src/pages/projects/screens/projects/const.ts b/frontend/src/pages/projects/screens/projects/const.ts index df08bb8368..6100a53312 100644 --- a/frontend/src/pages/projects/screens/projects/const.ts +++ b/frontend/src/pages/projects/screens/projects/const.ts @@ -16,7 +16,7 @@ export const initialProjectsFilterData: ProjectsFilterDataType = { }; export const FindAdministratorOptions = [ - 'The person who gave you your username', - 'Someone in your IT department or Help desk (at a company or school)', - 'The person who manages your email service or web site (in a small business or club)', + 'The person who gave you your username, or who helped you to log in for the first time', + 'Someone in your IT department or help desk', + 'A project manager or developer', ]; diff --git a/frontend/src/pages/storageClasses/StorageClassesPage.tsx b/frontend/src/pages/storageClasses/StorageClassesPage.tsx index 4737038523..80eff69d97 100644 --- a/frontend/src/pages/storageClasses/StorageClassesPage.tsx +++ b/frontend/src/pages/storageClasses/StorageClassesPage.tsx @@ -1,5 +1,4 @@ import React from 'react'; - import { EmptyState, EmptyStateVariant, @@ -8,11 +7,12 @@ import { Title, Alert, AlertActionCloseButton, + EmptyStateFooter, } from '@patternfly/react-core'; - import { ProjectObjectType, typedEmptyImage } from '~/concepts/design/utils'; import ApplicationsPage from '~/pages/ApplicationsPage'; import useStorageClasses from '~/concepts/k8s/useStorageClasses'; +import WhosMyAdministrator from '~/components/WhosMyAdministrator'; import { StorageClassesTable } from './StorageClassesTable'; import { StorageClassContextProvider, useStorageClassContext } from './StorageClassesContext'; @@ -55,6 +55,9 @@ const StorageClassesPageInternal: React.FC = ({ At least one OpenShift storage class is required to use OpenShift AI. Configure a storage class in OpenShift, or request that your admin configure one. + + + }