diff --git a/frontend/src/__tests__/cypress/cypress/pages/pipelines/topology.ts b/frontend/src/__tests__/cypress/cypress/pages/pipelines/topology.ts index 39a30bac84..de5fe41bac 100644 --- a/frontend/src/__tests__/cypress/cypress/pages/pipelines/topology.ts +++ b/frontend/src/__tests__/cypress/cypress/pages/pipelines/topology.ts @@ -111,6 +111,10 @@ class RunDetails extends PipelinesTopology { return cy.findByTestId('pipeline-run-tab-graph'); } + findInputParameterTab() { + return cy.findByTestId('pipeline-run-tab-parameters'); + } + findDetailsTab() { return cy.findByTestId('pipeline-run-tab-details'); } diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesTopology.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesTopology.cy.ts index 9faea96600..067acb4826 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesTopology.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesTopology.cy.ts @@ -405,6 +405,21 @@ describe('Pipeline topology', () => { }); }); + it('Test pipeline recurring run tab parameters', () => { + initIntercepts(); + + pipelineRecurringRunDetails.visit( + projectId, + mockVersion.pipeline_id, + mockVersion.pipeline_version_id, + mockRecurringRun.recurring_run_id, + ); + pipelineRecurringRunDetails.findDetailsTab().click(); + pipelineRecurringRunDetails.findInputParameterTab().click(); + pipelineRecurringRunDetails.findDetailItem('min_max_scaler').findValue().contains('False'); + pipelineRecurringRunDetails.findDetailItem('neighbors').findValue().contains('0'); + }); + it('Test pipeline recurring run tab details', () => { initIntercepts(); @@ -494,6 +509,19 @@ describe('Pipeline topology', () => { pipelineRunDetails.findDetailItem('Duration').findValue().contains('0:50'); }); + it('Test pipeline triggered run tab parameters', () => { + initIntercepts(); + pipelineRunDetails.visit( + projectId, + mockVersion.pipeline_id, + mockVersion.pipeline_version_id, + mockRun.run_id, + ); + pipelineRunDetails.findInputParameterTab().click(); + pipelineRunDetails.findDetailItem('min_max_scaler').findValue().contains('False'); + pipelineRunDetails.findDetailItem('neighbors').findValue().contains('1'); + }); + it('Test pipeline triggered run YAML output', () => { initIntercepts(); pipelineRunDetails.visit( diff --git a/frontend/src/concepts/pipelines/content/pipelinesDetails/pipelineRun/PipelineRunDetailsTabs.tsx b/frontend/src/concepts/pipelines/content/pipelinesDetails/pipelineRun/PipelineRunDetailsTabs.tsx index 196b40080f..e0e1157ff6 100644 --- a/frontend/src/concepts/pipelines/content/pipelinesDetails/pipelineRun/PipelineRunDetailsTabs.tsx +++ b/frontend/src/concepts/pipelines/content/pipelinesDetails/pipelineRun/PipelineRunDetailsTabs.tsx @@ -19,10 +19,12 @@ import { } from '~/concepts/pipelines/kfTypes'; import { isPipelineRecurringRun } from '~/concepts/pipelines/content/utils'; import PipelineRunTabDetails from './PipelineRunTabDetails'; +import PipelineRunTabParameters from './PipelineRunTabParameters'; enum DetailsTabKey { Graph = 'graph', Details = 'details', + InputParameter = 'input-parameter', Spec = 'spec', } @@ -77,6 +79,16 @@ export const PipelineRunDetailsTabs: React.FC = ({ + Input parameters} + aria-label="Input parameter tab" + data-testid="pipeline-run-tab-parameters" + > + + + + {!isRecurringRun && ( = ({ + run, + pipelineSpec, +}) => { + if (!run) { + return ( + + + + + ); + } + + const specParameters = + pipelineSpec?.root?.inputDefinitions?.parameters || + pipelineSpec?.pipeline_spec?.root.inputDefinitions?.parameters; + + const parameters = run.runtime_config?.parameters + ? Object.entries(run.runtime_config.parameters) + : []; + + if (parameters.length === 0) { + return ( + + + This pipeline run does not have any parameters defined. + + ); + } + + const details: DetailItem[] = parameters.map(([key, initialValue]) => { + let value: React.ReactNode; + const paramType = specParameters?.[key].parameterType; + switch (paramType) { + case InputDefinitionParameterType.DOUBLE: + value = Number.isInteger(Number(initialValue)) + ? Number(initialValue).toFixed(1) + : Number(initialValue); + break; + case InputDefinitionParameterType.INTEGER: + value = Number(initialValue); + break; + case InputDefinitionParameterType.BOOLEAN: + value = initialValue ? 'True' : 'False'; + break; + case InputDefinitionParameterType.STRING: + value = String(initialValue); + break; + case InputDefinitionParameterType.LIST: + value = ( + + ); + break; + case InputDefinitionParameterType.STRUCT: + value = ( + + ); + break; + default: + value = JSON.stringify(initialValue); + } + return { + key, + value, + }; + }); + + return <>{renderDetailItems(details)}; +}; + +export default PipelineRunTabParameters;