import { keyBy, truncate } from 'lodash'; import memoizeOne from 'memoize-one'; import React from 'react'; import type { IDisplayableParameter } from './ExecutionParameters'; import { ExecutionParameters } from './ExecutionParameters'; import { ResolvedArtifactList } from './ResolvedArtifactList'; import type { IExecution, IPipeline } from '../../domain'; export interface IParametersAndArtifactsProps { execution: IExecution; pipelineConfig: IPipeline; expandParamsOnInit: boolean; } export interface IParametersAndArtifactsState { showingParams: boolean; } export class ParametersAndArtifacts extends React.Component< IParametersAndArtifactsProps, IParametersAndArtifactsState > { constructor(props: IParametersAndArtifactsProps) { super(props); this.state = { showingParams: props.expandParamsOnInit, }; } private toggleParams = (): void => { const { showingParams } = this.state; this.setState({ showingParams: !showingParams }); }; private getDisplayableParameters = memoizeOne((execution: IExecution, pipelineConfig: IPipeline): { displayableParameters: IDisplayableParameter[]; pinnedDisplayableParameters: IDisplayableParameter[]; } => { // these are internal parameters that are not useful to end users const strategyExclusions = ['parentPipelineId', 'strategy', 'parentStageId', 'deploymentDetails', 'cloudProvider']; const truncateLength = 200; const isParamDisplayable = (paramKey: string) => execution.isStrategy ? !strategyExclusions.includes(paramKey) : true; const displayableParameters: IDisplayableParameter[] = Object.keys( (execution.trigger && execution.trigger.parameters) || {}, ) .filter(isParamDisplayable) .sort() .map((key: string) => { const value = JSON.stringify(execution.trigger.parameters[key]); const showTruncatedValue = value.length > truncateLength; let valueTruncated; if (showTruncatedValue) { valueTruncated = truncate(value, { length: truncateLength }); } return { key, value, valueTruncated, showTruncatedValue }; }); let pinnedDisplayableParameters: IDisplayableParameter[] = []; if (pipelineConfig) { const paramConfigIndexByName = keyBy(pipelineConfig.parameterConfig, 'name'); const isParamPinned = (param: IDisplayableParameter): boolean => paramConfigIndexByName[param.key] && paramConfigIndexByName[param.key].pinned; // an older execution's parameter might be missing from a newer pipelineConfig.parameterConfig pinnedDisplayableParameters = displayableParameters.filter(isParamPinned); } return { displayableParameters, pinnedDisplayableParameters }; }); private getLabel(displayableParameters: IDisplayableParameter[]): string { const { execution } = this.props; const { trigger } = execution; const { resolvedExpectedArtifacts } = trigger; const showParameters = displayableParameters.length > 0; const showArtifacts = resolvedExpectedArtifacts.length > 0; if (showParameters && showArtifacts) { return `Parameters/Artifacts (${displayableParameters.length}/${resolvedExpectedArtifacts.length})`; } if (showParameters) { return `Parameters (${displayableParameters.length})`; } return `Artifacts (${resolvedExpectedArtifacts.length})`; } public render() { const { execution, pipelineConfig } = this.props; const { showingParams } = this.state; const { displayableParameters, pinnedDisplayableParameters } = this.getDisplayableParameters( execution, pipelineConfig, ); const { trigger } = execution; const { artifacts, resolvedExpectedArtifacts } = trigger; const parametersAndArtifactsExpanded = showingParams || (displayableParameters.length === pinnedDisplayableParameters.length && !resolvedExpectedArtifacts.length); if (!displayableParameters.length && !resolvedExpectedArtifacts.length) { return null; } const label = this.getLabel(displayableParameters); return ( <>
{parametersAndArtifactsExpanded ? '' : 'View All '} {label}
); } }