From d9359a69bcacf03c07ead332b5e4863c86b4b3d4 Mon Sep 17 00:00:00 2001 From: Jeff Puzzo Date: Wed, 24 Jul 2024 16:08:44 -0400 Subject: [PATCH] [RHOAIENG-7943] Navigate to pipeline details on import --- frontend/src/__mocks__/index.ts | 2 + .../tests/mocked/pipelines/pipelines.cy.ts | 43 ++++++++++------- .../mocked/pipelines/pipelinesList.cy.ts | 9 ++-- .../content/import/PipelineImportModal.tsx | 46 +++++++++++++++---- 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/frontend/src/__mocks__/index.ts b/frontend/src/__mocks__/index.ts index 37611da8a9..b73f92d395 100644 --- a/frontend/src/__mocks__/index.ts +++ b/frontend/src/__mocks__/index.ts @@ -13,3 +13,5 @@ export * from './mockDscStatus'; export * from './mockNotebookK8sResource'; export * from './mockPipelineKF'; export * from './mockSecretK8sResource'; +export * from './mockGoogleRpcStatusKF'; +export * from './mockK8sStatus'; diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts index c6001bb912..4c789e806e 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts @@ -1,13 +1,16 @@ /* eslint-disable camelcase */ -import { mockDataSciencePipelineApplicationK8sResource } from '~/__mocks__/mockDataSciencePipelinesApplicationK8sResource'; -import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList'; -import { buildMockPipelineV2, buildMockPipelines } from '~/__mocks__/mockPipelinesProxy'; import { + mockDataSciencePipelineApplicationK8sResource, + mockK8sResourceList, + buildMockPipelineV2, + buildMockPipelines, buildMockPipelineVersionV2, buildMockPipelineVersionsV2, -} from '~/__mocks__/mockPipelineVersionsProxy'; -import { mockProjectK8sResource } from '~/__mocks__/mockProjectK8sResource'; -import { mockRouteK8sResource } from '~/__mocks__/mockRouteK8sResource'; + mockProjectK8sResource, + mockRouteK8sResource, + mockSecretK8sResource, + mockSuccessGoogleRpcStatus, +} from '~/__mocks__'; import { pipelinesGlobal, pipelinesTable, @@ -26,10 +29,8 @@ import { SecretModel, } from '~/__tests__/cypress/cypress/utils/models'; import { asProductAdminUser } from '~/__tests__/cypress/cypress/utils/mockUsers'; -import { mockSecretK8sResource } from '~/__mocks__/mockSecretK8sResource'; import type { PipelineKFv2 } from '~/concepts/pipelines/kfTypes'; import { tablePagination } from '~/__tests__/cypress/cypress/pages/components/Pagination'; -import { mockSuccessGoogleRpcStatus } from '~/__mocks__/mockGoogleRpcStatusKF'; const projectName = 'test-project-name'; const initialMockPipeline = buildMockPipelineV2({ display_name: 'Test pipeline' }); @@ -560,6 +561,11 @@ describe('Pipelines', () => { // Intercept upload/re-fetch of pipelines pipelineImportModal.mockUploadPipeline(uploadPipelineParams, projectName).as('uploadPipeline'); pipelinesTable.mockGetPipelines([initialMockPipeline], projectName); + pipelinesTable.mockGetPipelineVersions( + [initialMockPipelineVersion], + 'new-pipeline', + projectName, + ); // Wait for the pipelines table to load pipelinesTable.find(); @@ -601,8 +607,10 @@ describe('Pipelines', () => { }); }); - // Verify the uploaded pipeline is in the table - pipelinesTable.getRowById(uploadedMockPipeline.pipeline_id).find().should('exist'); + cy.url().should( + 'include', + `/pipelines/${projectName}/${uploadedMockPipeline.pipeline_id}/${initialMockPipelineVersion.pipeline_version_id}/view`, + ); }); it('fails to import a too-large file', () => { @@ -637,17 +645,16 @@ describe('Pipelines', () => { }, }; const createdMockPipeline = buildMockPipelineV2(createPipelineAndVersionParams.pipeline); + const createdVersion = buildMockPipelineVersionV2( + createPipelineAndVersionParams.pipeline_version, + ); // Intercept upload/re-fetch of pipelines pipelineImportModal .mockCreatePipelineAndVersion(createPipelineAndVersionParams, projectName) .as('createPipelineAndVersion'); pipelinesTable.mockGetPipelines([initialMockPipeline], projectName); - pipelinesTable.mockGetPipelineVersions( - [buildMockPipelineVersionV2(createPipelineAndVersionParams.pipeline_version)], - initialMockPipeline.pipeline_id, - projectName, - ); + pipelinesTable.mockGetPipelineVersions([createdVersion], 'new-pipeline', projectName); // Wait for the pipelines table to load pipelinesTable.find(); @@ -669,8 +676,10 @@ describe('Pipelines', () => { cy.wait('@createPipelineAndVersion'); cy.wait('@refreshPipelines'); - // Verify the uploaded pipeline is in the table - pipelinesTable.getRowById(createdMockPipeline.pipeline_id).find().should('exist'); + cy.url().should( + 'include', + `/pipelines/${projectName}/${createdMockPipeline.pipeline_id}/${createdVersion.pipeline_version_id}/view`, + ); }); it('uploads a new pipeline version', () => { diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts index 0381c581b3..91cac8b2cc 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts @@ -5,11 +5,12 @@ import { mockProjectK8sResource, mockRouteK8sResource, mockSecretK8sResource, + mockDataSciencePipelineApplicationK8sResource, + mockK8sResourceList, + mock404Error, + buildMockPipelineV2, + buildMockPipelines, } from '~/__mocks__'; -import { mockDataSciencePipelineApplicationK8sResource } from '~/__mocks__/mockDataSciencePipelinesApplicationK8sResource'; -import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList'; -import { mock404Error } from '~/__mocks__/mockK8sStatus'; -import { buildMockPipelineV2, buildMockPipelines } from '~/__mocks__/mockPipelinesProxy'; import { pipelinesTable, configurePipelineServerModal, diff --git a/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx b/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx index 4e155bbdb5..c6fa26b328 100644 --- a/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx +++ b/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx @@ -1,4 +1,6 @@ import * as React from 'react'; +import { useNavigate } from 'react-router-dom'; + import { Alert, Button, @@ -10,6 +12,7 @@ import { TextArea, TextInput, } from '@patternfly/react-core'; + import { usePipelinesAPI } from '~/concepts/pipelines/context'; import { usePipelineImportModalData } from '~/concepts/pipelines/content/import/useImportModalData'; import { PipelineKFv2 } from '~/concepts/pipelines/kfTypes'; @@ -17,6 +20,7 @@ import { getDisplayNameFromK8sResource } from '~/concepts/k8s/utils'; import { DuplicateNameHelperText } from '~/concepts/pipelines/content/DuplicateNameHelperText'; import { getNameEqualsFilter } from '~/concepts/pipelines/utils'; import useDebounceCallback from '~/utilities/useDebounceCallback'; +import { pipelineVersionDetailsRoute } from '~/routes'; import PipelineUploadRadio from './PipelineUploadRadio'; import { PipelineUploadOption } from './utils'; @@ -26,7 +30,8 @@ type PipelineImportModalProps = { }; const PipelineImportModal: React.FC = ({ isOpen, onClose }) => { - const { project, api, apiAvailable } = usePipelinesAPI(); + const navigate = useNavigate(); + const { project, api, apiAvailable, namespace } = usePipelinesAPI(); const [importing, setImporting] = React.useState(false); const [error, setError] = React.useState(); const [{ name, description, fileContents, pipelineUrl, uploadOption }, setData, resetData] = @@ -39,12 +44,35 @@ const PipelineImportModal: React.FC = ({ isOpen, onClo !name || (uploadOption === PipelineUploadOption.URL_IMPORT ? !pipelineUrl : !fileContents); - const onBeforeClose = (pipeline?: PipelineKFv2) => { - onClose(pipeline); - setImporting(false); - setError(undefined); - resetData(); - }; + const onBeforeClose = React.useCallback( + (pipeline?: PipelineKFv2) => { + onClose(pipeline); + setImporting(false); + setError(undefined); + resetData(); + }, + [onClose, resetData], + ); + + const onSubmitSuccess = React.useCallback( + async (pipeline: PipelineKFv2) => { + onBeforeClose(pipeline); + + const { pipeline_versions: versions } = await api.listPipelineVersions( + {}, + pipeline.pipeline_id, + { + pageSize: 1, + }, + ); + const versionId = versions?.[0].pipeline_version_id; + + if (versionId) { + navigate(pipelineVersionDetailsRoute(namespace, pipeline.pipeline_id, versionId)); + } + }, + [api, namespace, navigate, onBeforeClose], + ); const checkForDuplicateName = useDebounceCallback( React.useCallback( @@ -72,7 +100,7 @@ const PipelineImportModal: React.FC = ({ isOpen, onClo if (uploadOption === PipelineUploadOption.FILE_UPLOAD) { api .uploadPipeline({}, name, description, fileContents) - .then((pipeline) => onBeforeClose(pipeline)) + .then(onSubmitSuccess) .catch((e) => { setImporting(false); setError(e); @@ -97,7 +125,7 @@ const PipelineImportModal: React.FC = ({ isOpen, onClo }, }, ) - .then((pipeline) => onBeforeClose(pipeline)) + .then(onSubmitSuccess) .catch((e) => { setImporting(false); setError(e);