Skip to content

Commit 16132d2

Browse files
author
Daniel Duong
committed
Merge branch 'main' of https://github.com/opendatahub-io/odh-dashboard into feat/automl-create
2 parents 2220365 + 8329bce commit 16132d2

91 files changed

Lines changed: 15098 additions & 1206 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
1-
import { HelperText, HelperTextItem } from '@patternfly/react-core';
1+
import { FormHelperText, HelperText, HelperTextItem } from '@patternfly/react-core';
22
import React from 'react';
33

44
interface CharLimitHelperTextProps {
55
limit: number;
6+
currentLength: number;
67
}
78

8-
export const CharLimitHelperText: React.FC<CharLimitHelperTextProps> = ({ limit }) => (
9-
<HelperText>
10-
<HelperTextItem>{`Cannot exceed ${limit} characters`}</HelperTextItem>
11-
</HelperText>
12-
);
9+
export const CharLimitHelperText: React.FC<CharLimitHelperTextProps> = ({
10+
limit,
11+
currentLength,
12+
}) => {
13+
// Threshold of 10 is consistent with K8sNameDescriptionField (showNameWarning),
14+
// which uses `maxLength - 10` to only warn when the user is close to the limit.
15+
if (currentLength < limit - 10) {
16+
return null;
17+
}
18+
return (
19+
<FormHelperText>
20+
<HelperText>
21+
<HelperTextItem variant={currentLength >= limit ? 'error' : 'warning'}>
22+
{`Cannot exceed ${limit} characters (${Math.max(0, limit - currentLength)} remaining)`}
23+
</HelperTextItem>
24+
</HelperText>
25+
</FormHelperText>
26+
);
27+
};

frontend/src/concepts/k8s/NameDescriptionField.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ const NameDescriptionField: React.FC<NameDescriptionFieldProps> = ({
8686
validated={hasNameError ? 'error' : 'default'}
8787
/>
8888
{nameHelperText}
89-
{maxLengthName && <CharLimitHelperText limit={maxLengthName} />}
89+
{!!maxLengthName && (
90+
<CharLimitHelperText limit={maxLengthName} currentLength={data.name.length} />
91+
)}
9092
</FormGroup>
9193
</StackItem>
9294
{showK8sName && (
@@ -145,7 +147,9 @@ const NameDescriptionField: React.FC<NameDescriptionFieldProps> = ({
145147
maxLength={maxLengthDesc}
146148
/>
147149

148-
{maxLengthDesc && <CharLimitHelperText limit={maxLengthDesc} />}
150+
{!!maxLengthDesc && (
151+
<CharLimitHelperText limit={maxLengthDesc} currentLength={data.description.length} />
152+
)}
149153
</FormGroup>
150154
</StackItem>
151155
</Stack>

frontend/src/concepts/pipelines/content/createRun/RunPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ const RunPage: React.FC<RunPageProps> = ({
9292
nameDesc: duplicateRun
9393
? {
9494
name: `Duplicate of ${duplicateRun.display_name}`,
95-
description: duplicateRun.description,
95+
description: duplicateRun.description ?? '',
9696
}
9797
: locationNameDesc || { name: '', description: '' },
9898
runType: runTypeData,

frontend/src/concepts/pipelines/content/experiment/CreateExperimentModal.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const CreateExperimentModal: React.FC<CreateExperimentModalProps> = ({ onClose }
7676
maxLength={NAME_CHARACTER_LIMIT}
7777
/>
7878

79-
<CharLimitHelperText limit={NAME_CHARACTER_LIMIT} />
79+
<CharLimitHelperText limit={NAME_CHARACTER_LIMIT} currentLength={name.length} />
8080
</FormGroup>
8181
</StackItem>
8282
<StackItem>
@@ -91,7 +91,10 @@ const CreateExperimentModal: React.FC<CreateExperimentModalProps> = ({ onClose }
9191
maxLength={DESCRIPTION_CHARACTER_LIMIT}
9292
/>
9393

94-
<CharLimitHelperText limit={DESCRIPTION_CHARACTER_LIMIT} />
94+
<CharLimitHelperText
95+
limit={DESCRIPTION_CHARACTER_LIMIT}
96+
currentLength={description.length}
97+
/>
9598
</FormGroup>
9699
</StackItem>
97100
{error && (

packages/contract-tests/scripts/run-go-bff-consumer.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,12 @@ fi
198198

199199
log_info "Starting Mock BFF server on port $PORT..."
200200

201-
log_info "Starting Mock BFF server with go run"
201+
BFF_BINARY="$(mktemp -d)/bff-test"
202+
log_info "Building Mock BFF binary..."
203+
go build -o "$BFF_BINARY" ./cmd
202204

203-
go run ./cmd $BFF_MOCK_FLAGS --port "$PORT" --allowed-origins="*" > "$BFF_LOG_FILE" 2>&1 &
205+
log_info "Starting Mock BFF server"
206+
"$BFF_BINARY" $BFF_MOCK_FLAGS --port "$PORT" --allowed-origins="*" > "$BFF_LOG_FILE" 2>&1 &
204207

205208
BFF_PID=$!
206209
echo "$BFF_PID" > "$RESULTS_DIR/bff.pid"
@@ -215,6 +218,7 @@ cleanup() {
215218
sleep 2
216219
kill -9 "$BFF_PID" 2>/dev/null || true
217220
fi
221+
rm -f "$BFF_BINARY"
218222
}
219223
trap cleanup EXIT INT TERM
220224

packages/cypress/cypress/pages/modelsAsAService.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,57 @@ class DeleteSubscriptionModal extends DeleteModal {
657657
return this.find().findByRole('button', { name: /Delete/, hidden: true });
658658
}
659659
}
660+
class ViewSubscriptionPage {
661+
visit(name: string): void {
662+
cy.visitWithLogin(`/maas/subscriptions/view/${name}`);
663+
this.wait();
664+
}
665+
666+
private wait(): void {
667+
cy.findByTestId('app-page-title').should('exist');
668+
cy.testA11y();
669+
}
670+
671+
findTitle(): Cypress.Chainable<JQuery<HTMLElement>> {
672+
return cy.findByTestId('app-page-title');
673+
}
674+
675+
findBreadcrumb(): Cypress.Chainable<JQuery<HTMLElement>> {
676+
return cy.findByTestId('app-page-breadcrumb');
677+
}
678+
679+
findBreadcrumbSubscriptionsLink(): Cypress.Chainable<JQuery<HTMLElement>> {
680+
return cy.findByTestId('breadcrumb-subscriptions-link');
681+
}
682+
683+
findDetailsSection(): Cypress.Chainable<JQuery<HTMLElement>> {
684+
return cy.findByTestId('subscription-details-section');
685+
}
686+
687+
findGroupsSection(): Cypress.Chainable<JQuery<HTMLElement>> {
688+
return cy.findByTestId('subscription-groups-section');
689+
}
690+
691+
findGroupsTable(): Cypress.Chainable<JQuery<HTMLElement>> {
692+
return cy.findByTestId('subscription-groups-table');
693+
}
694+
695+
findModelsSection(): Cypress.Chainable<JQuery<HTMLElement>> {
696+
return cy.findByTestId('subscription-models-section');
697+
}
698+
699+
findModelsTable(): Cypress.Chainable<JQuery<HTMLElement>> {
700+
return cy.findByTestId('subscription-models-table');
701+
}
702+
703+
findPageError(): Cypress.Chainable<JQuery<HTMLElement>> {
704+
return cy.findByTestId('error-empty-state-body');
705+
}
706+
707+
findDetailsTab(): Cypress.Chainable<JQuery<HTMLElement>> {
708+
return cy.findByTestId('subscription-details-tab');
709+
}
710+
}
660711

661712
export const tiersPage = new TiersPage();
662713
export const createTierPage = new CreateTierPage();
@@ -670,3 +721,4 @@ export const createApiKeyModal = new CreateApiKeyModal();
670721
export const copyApiKeyModal = new CopyApiKeyModal();
671722
export const subscriptionsPage = new SubscriptionsPage();
672723
export const deleteSubscriptionModal = new DeleteSubscriptionModal();
724+
export const viewSubscriptionPage = new ViewSubscriptionPage();

packages/cypress/cypress/support/commands/odh.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ import type {
9797
BulkRevokeResponse,
9898
CreateAPIKeyResponse,
9999
} from '@odh-dashboard/maas/types/api-key';
100-
import type { MaaSSubscription } from '@odh-dashboard/maas/types/subscriptions';
100+
import type {
101+
MaaSSubscription,
102+
SubscriptionInfoResponse,
103+
} from '@odh-dashboard/maas/types/subscriptions';
101104

102105
type SuccessErrorResponse = {
103106
success: boolean;
@@ -1151,6 +1154,11 @@ declare global {
11511154
type: 'DELETE /maas/api/v1/subscription/:name',
11521155
options: { path: { name: string } },
11531156
response: OdhResponse<{ message: string }>,
1157+
) => Cypress.Chainable<null>) &
1158+
((
1159+
type: 'GET /maas/api/v1/subscription-info/:name',
1160+
options: { path: { name: string } },
1161+
response: OdhResponse<SubscriptionInfoResponse>,
11541162
) => Cypress.Chainable<null>);
11551163
}
11561164
}

packages/cypress/cypress/tests/mocked/modelRegistry/modelVersion/modelVersionArchive.cy.ts

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { DataScienceStackComponent } from '@odh-dashboard/internal/concepts/area
2222
import { mockModelArtifact } from '@odh-dashboard/internal/__mocks__/mockModelArtifact';
2323
import { modelRegistry } from '../../../../pages/modelRegistry';
2424
import { modelVersionArchive } from '../../../../pages/modelRegistry/modelVersionArchive';
25-
import { InferenceServiceModel, ProjectModel } from '../../../../utils/models';
25+
import { ProjectModel } from '../../../../utils/models';
2626

2727
const MODEL_REGISTRY_API_VERSION = 'v1';
2828

@@ -224,39 +224,48 @@ describe('Archiving version', () => {
224224
});
225225

226226
it('Cannot archive version that has a deployment from versions table', () => {
227+
const inferenceServiceResponse = mockK8sResourceList([
228+
mockInferenceServiceK8sResource({
229+
additionalLabels: {
230+
[KnownLabels.REGISTERED_MODEL_ID]: '1',
231+
[KnownLabels.MODEL_VERSION_ID]: '3',
232+
},
233+
}),
234+
]);
227235
cy.interceptK8sList(ProjectModel, mockK8sResourceList([mockProjectK8sResource({})]));
228-
cy.interceptK8sList(
229-
InferenceServiceModel,
230-
mockK8sResourceList([
231-
mockInferenceServiceK8sResource({
232-
additionalLabels: {
233-
[KnownLabels.REGISTERED_MODEL_ID]: '1',
234-
[KnownLabels.MODEL_VERSION_ID]: '3',
235-
},
236-
}),
237-
]),
238-
);
236+
cy.intercept(
237+
{ method: 'GET', url: /\/inferenceservices(\?|$)/ },
238+
{ body: inferenceServiceResponse },
239+
).as('inferenceServices');
239240
initIntercepts({});
240241

241242
modelVersionArchive.visitModelVersionList();
242243

243-
const modelVersionRow = modelRegistry.getModelVersionRow('model version 3');
244-
modelVersionRow.findKebabAction('Archive model version').should('have.attr', 'aria-disabled');
244+
modelRegistry
245+
.getModelVersionRow('model version 3')
246+
.find()
247+
.findByRole('button', { name: 'Kebab toggle' })
248+
.click();
249+
cy.findByRole('menuitem', { name: 'Archive model version' }).should(
250+
'have.attr',
251+
'aria-disabled',
252+
);
245253
});
246254

247255
it('Cannot archive model that has versions with a deployment', () => {
256+
const inferenceServiceResponse = mockK8sResourceList([
257+
mockInferenceServiceK8sResource({
258+
additionalLabels: {
259+
[KnownLabels.REGISTERED_MODEL_ID]: '1',
260+
[KnownLabels.MODEL_VERSION_ID]: '3',
261+
},
262+
}),
263+
]);
248264
cy.interceptK8sList(ProjectModel, mockK8sResourceList([mockProjectK8sResource({})]));
249-
cy.interceptK8sList(
250-
InferenceServiceModel,
251-
mockK8sResourceList([
252-
mockInferenceServiceK8sResource({
253-
additionalLabels: {
254-
[KnownLabels.REGISTERED_MODEL_ID]: '1',
255-
[KnownLabels.MODEL_VERSION_ID]: '3',
256-
},
257-
}),
258-
]),
259-
);
265+
cy.intercept(
266+
{ method: 'GET', url: /\/inferenceservices(\?|$)/ },
267+
{ body: inferenceServiceResponse },
268+
).as('inferenceServices');
260269
initIntercepts({});
261270

262271
modelVersionArchive.visitModelVersionList();
@@ -268,20 +277,23 @@ describe('Archiving version', () => {
268277
});
269278

270279
it('Cannot archive model version with deployment from the version detail page', () => {
280+
const inferenceServiceResponse = mockK8sResourceList([
281+
mockInferenceServiceK8sResource({
282+
additionalLabels: {
283+
[KnownLabels.REGISTERED_MODEL_ID]: '1',
284+
[KnownLabels.MODEL_VERSION_ID]: '3',
285+
},
286+
}),
287+
]);
271288
cy.interceptK8sList(ProjectModel, mockK8sResourceList([mockProjectK8sResource({})]));
272-
cy.interceptK8sList(
273-
InferenceServiceModel,
274-
mockK8sResourceList([
275-
mockInferenceServiceK8sResource({
276-
additionalLabels: {
277-
[KnownLabels.REGISTERED_MODEL_ID]: '1',
278-
[KnownLabels.MODEL_VERSION_ID]: '3',
279-
},
280-
}),
281-
]),
282-
);
289+
cy.intercept(
290+
{ method: 'GET', url: /\/inferenceservices(\?|$)/ },
291+
{ body: inferenceServiceResponse },
292+
).as('inferenceServices');
283293
initIntercepts({});
294+
284295
modelVersionArchive.visitModelVersionDetails();
296+
285297
modelVersionArchive
286298
.findModelVersionsDetailsHeaderAction()
287299
.findDropdownItem('Archive model version')

0 commit comments

Comments
 (0)