Skip to content

Commit

Permalink
Update context selector bar and show API endpoint URL
Browse files Browse the repository at this point in the history
  • Loading branch information
ppadti committed Nov 14, 2024
1 parent f93a992 commit 2d35118
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 27 deletions.
9 changes: 9 additions & 0 deletions frontend/src/__mocks__/mockModelRegistryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@ import { ServiceKind } from '~/k8sTypes';
type MockServiceType = {
name?: string;
namespace?: string;
description?: string;
serverUrl?: string;
};

export const mockModelRegistryService = ({
name = 'modelregistry-sample',
namespace = 'odh-model-registries',
description = 'Model registry description',
serverUrl = 'modelregistry-sample-rest.apps.kserve-pm.dev.datahub.redhat.com:443',
}: MockServiceType): ServiceKind => ({
kind: 'Service',
apiVersion: 'v1',
metadata: {
name,
namespace,
annotations: {
'openshift.io/description': description,
'openshift.io/display-name': name,
'routing.opendatahub.io/external-address-rest': serverUrl,
},
},
spec: {
selector: {
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/__tests__/cypress/cypress/pages/modelRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,22 @@ class ModelRegistry {
cy.findByTestId('empty-registered-models').should('exist');
}

findViewDetailsButton() {
return cy.findByTestId('view-details-button');
}

findDetailsPopover() {
return cy.findByTestId('mr-details-popover');
}

findHelpContentButton() {
return cy.findByTestId('model-registry-help-button');
}

findHelpContentPopover() {
return cy.findByTestId('model-registry-help-content');
}

shouldmodelVersionsEmpty() {
cy.findByTestId('empty-model-versions').should('exist');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ const initIntercepts = ({
disableModelRegistryFeature = false,
modelRegistries = [
mockModelRegistryService({ name: 'modelregistry-sample' }),
mockModelRegistryService({ name: 'modelregistry-sample-2' }),
mockModelRegistryService({
name: 'modelregistry-sample-2',
serverUrl: 'modelregistry-sample-2-rest.apps.kserve-pm.dev.datahub.redhat.com:443',
description: '',
}),
],
registeredModels = [
mockRegisteredModel({
Expand Down Expand Up @@ -228,6 +232,34 @@ describe('Model Registry core', () => {
modelRegistry.navigate();
modelRegistry.shouldModelRegistrySelectorExist();
modelRegistry.shouldregisteredModelsEmpty();

modelRegistry.findViewDetailsButton().click();
modelRegistry.findDetailsPopover().should('exist');
modelRegistry.findDetailsPopover().findByText('Model registry description').should('exist');
modelRegistry
.findDetailsPopover()
.findByText('https://modelregistry-sample-rest.apps.kserve-pm.dev.datahub.redhat.com:443')
.should('exist');

// Model registry with no description
modelRegistry.findModelRegistry().findSelectOption('modelregistry-sample-2').click();
modelRegistry.findViewDetailsButton().click();
modelRegistry.findDetailsPopover().should('exist');
modelRegistry.findDetailsPopover().findByText('No description').should('exist');
modelRegistry
.findDetailsPopover()
.findByText('https://modelregistry-sample-2-rest.apps.kserve-pm.dev.datahub.redhat.com:443')
.should('exist');

// Model registry help content
modelRegistry.findHelpContentButton().click();
modelRegistry.findHelpContentPopover().should('exist');
modelRegistry
.findHelpContentPopover()
.findByText(
'To request access to a new or existing model registry, contact your administrator.',
)
.should('exist');
});

describe('Registered model table', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ describe('Model Versions', () => {
});

modelRegistry.visit();
modelRegistry.findModelRegistry().findSelectOption('modelregistry-sample').click();
modelRegistry
.findModelRegistry()
.findSelectOption('modelregistry-sample Model registry description')
.click();
cy.reload();
const registeredModelRow = modelRegistry.getRow('Fraud detection model');
registeredModelRow.findName().contains('Fraud detection model').click();
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/PopoverListContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const PopoverListContent: React.FC<PopoverListContentProps> = ({
<TextContent {...props}>
{leadText ? <ContentText>{leadText}</ContentText> : null}
{listHeading ? <Text component="h4">{listHeading}</Text> : null}
<TextList>
<TextList style={{ margin: 0 }}>
{listItems.map((item, index) => (
<TextListItem key={index}>
<ContentText>{item}</ContentText>
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/WhosMyAdministrator.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { Button, Popover } from '@patternfly/react-core';
import { Button, Popover, PopoverPosition } from '@patternfly/react-core';
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
import PopoverListContent from '~/components/PopoverListContent';
import { FindAdministratorOptions } from '~/pages/projects/screens/projects/const';
Expand All @@ -11,6 +11,7 @@ type Props = {
isInline?: boolean;
contentTestId?: string;
linkTestId?: string;
popoverPosition?: PopoverPosition;
};

const WhosMyAdministrator: React.FC<Props> = ({
Expand All @@ -20,10 +21,11 @@ const WhosMyAdministrator: React.FC<Props> = ({
isInline,
contentTestId,
linkTestId,
popoverPosition = PopoverPosition.bottom,
}) => (
<Popover
showClose
position="bottom"
position={popoverPosition}
headerContent={headerContent || 'Your administrator might be:'}
hasAutoWidth
maxWidth="370px"
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/k8sTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,11 @@ export type SelfSubjectRulesReviewKind = K8sResourceCommon & {

export type ServiceKind = K8sResourceCommon & {
metadata: {
annotations?: DisplayNameAnnotations;
annotations?: DisplayNameAnnotations &
Partial<{
'routing.opendatahub.io/external-address-rest': string;
'routing.opendatahub.io/external-address-grpc': string;
}>;
name: string;
namespace: string;
labels?: Partial<{
Expand Down
80 changes: 59 additions & 21 deletions frontend/src/pages/modelRegistry/screens/ModelRegistrySelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@ import {
FlexItem,
Icon,
Popover,
PopoverPosition,
Tooltip,
} from '@patternfly/react-core';
import text from '@patternfly/react-styles/css/utilities/Text/text';
import truncateStyles from '@patternfly/react-styles/css/components/Truncate/truncate';
import { InfoCircleIcon, BlueprintIcon } from '@patternfly/react-icons';
import { useBrowserStorage } from '~/components/browserStorage';
import { ModelRegistrySelectorContext } from '~/concepts/modelRegistry/context/ModelRegistrySelectorContext';
import { getDescriptionFromK8sResource, getDisplayNameFromK8sResource } from '~/concepts/k8s/utils';
import { ServiceKind } from '~/k8sTypes';
import SimpleSelect, { SimpleSelectOption } from '~/components/SimpleSelect';
import WhosMyAdministrator from '~/components/WhosMyAdministrator';
import InlineTruncatedClipboardCopy from '~/components/InlineTruncatedClipboardCopy';
import { getServerAddress } from './utils';

const MODEL_REGISTRY_FAVORITE_STORAGE_KEY = 'odh.dashboard.model.registry.favorite';

Expand Down Expand Up @@ -133,29 +138,62 @@ const ModelRegistrySelector: React.FC<ModelRegistrySelectorProps> = ({
}

return (
<Flex spaceItems={{ default: 'spaceItemsXs' }} alignItems={{ default: 'alignItemsCenter' }}>
<Icon>
<BlueprintIcon />
</Icon>
<Flex spaceItems={{ default: 'spaceItemsSm' }} alignItems={{ default: 'alignItemsCenter' }}>
<Flex spaceItems={{ default: 'spaceItemsSm' }} alignItems={{ default: 'alignItemsCenter' }}>
<FlexItem>
<Icon>
<BlueprintIcon />
</Icon>
</FlexItem>
<FlexItem>
<Bullseye>Model registry</Bullseye>
</FlexItem>
<FlexItem>{selector}</FlexItem>
{selection && (
<FlexItem>
<Bullseye>Model registry</Bullseye>
<Popover
aria-label="Model registry description popover"
data-testid="mr-details-popover"
position="right"
headerContent={`${getDisplayNameFromK8sResource(selection)} details`}
bodyContent={
<DescriptionList>
<DescriptionListGroup>
<DescriptionListTerm>Description</DescriptionListTerm>
<DescriptionListDescription
className={
!getDescriptionFromK8sResource(selection) ? text.disabledColor_100 : ''
}
>
{getDescriptionFromK8sResource(selection) || 'No description'}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Server URL</DescriptionListTerm>
<DescriptionListDescription>
<InlineTruncatedClipboardCopy
textToCopy={`https://${getServerAddress(selection)}`}
/>
</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
}
>
<Button variant="link" icon={<InfoCircleIcon />} data-testid="view-details-button">
View details
</Button>
</Popover>
</FlexItem>
<FlexItem>{selector}</FlexItem>
{selection && getDescriptionFromK8sResource(selection) && (
<FlexItem>
<Popover
aria-label="Model registry description popover"
headerContent={getDisplayNameFromK8sResource(selection)}
bodyContent={getDescriptionFromK8sResource(selection)}
>
<Button variant="link" icon={<InfoCircleIcon />}>
View Description
</Button>
</Popover>
</FlexItem>
)}
</Flex>
)}
<FlexItem align={{ default: 'alignRight' }}>
<WhosMyAdministrator
buttonLabel="Need another registry?"
headerContent="Need another registry?"
leadText="To request access to a new or existing model registry, contact your administrator."
contentTestId="model-registry-help-content"
linkTestId="model-registry-help-button"
popoverPosition={PopoverPosition.left}
/>
</FlexItem>
</Flex>
);
};
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/pages/modelRegistry/screens/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ModelVersion,
RegisteredModel,
} from '~/concepts/modelRegistry/types';
import { ServiceKind } from '~/k8sTypes';
import { KeyValuePair } from '~/types';

// Retrieves the labels from customProperties that have non-empty string_value.
Expand Down Expand Up @@ -153,3 +154,6 @@ export const filterRegisteredModels = (
}
});
};

export const getServerAddress = (resource: ServiceKind): string =>
resource.metadata.annotations?.['routing.opendatahub.io/external-address-rest'] || '';

0 comments on commit 2d35118

Please sign in to comment.