import React from 'react'; import type { Option } from 'react-select'; import VirtualizedSelect from 'react-virtualized-select'; import { ApplicationReader } from '../../application/service/ApplicationReader'; import type { IParameter, IPipeline } from '../../domain'; import { HelpField } from '../../help/HelpField'; import { PipelineConfigService } from '../../pipeline/config/services/PipelineConfigService'; import { Spinner } from '../../widgets'; interface IPipelineSelectorCommand { application?: string; pipelineId?: string; pipelineParameters?: { [key: string]: any }; strategyPipeline?: string; strategyApplication?: string; } export interface IPipelineSelectorProps { command: IPipelineSelectorCommand; type: 'pipelines' | 'strategies'; } export interface IPipelineSelectorState { applicationsLoaded: boolean; pipelinesLoaded: boolean; applicationOptions: Array>; pipelines: IPipeline[]; pipelineOptions: Option[]; pipelineParameters?: IParameter[]; useDefaultParameters: { [key: string]: boolean }; userSuppliedParameters: { [key: string]: any }; } export class PipelineSelector extends React.Component { public state: IPipelineSelectorState = { applicationsLoaded: false, pipelinesLoaded: false, applicationOptions: [], pipelineOptions: [], pipelines: [], pipelineParameters: [], useDefaultParameters: {}, userSuppliedParameters: {}, }; private clearParams(): void { this.setState({ pipelineParameters: [], useDefaultParameters: {}, userSuppliedParameters: {} }); } private configureParamDefaults(pipelineParameters: IParameter[]): void { const useDefaultParameters = this.state.useDefaultParameters; pipelineParameters.forEach((param: any) => { const defaultValue = param.default; if (defaultValue !== null && defaultValue !== undefined) { const configuredParamValue = this.props.command.pipelineParameters[param.name]; if (configuredParamValue === undefined || configuredParamValue === defaultValue) { useDefaultParameters[param.name] = true; this.props.command.pipelineParameters[param.name] = defaultValue; } } }); this.setState({ useDefaultParameters }); } public updatePipelineConfig(pipelines: IPipeline[]): void { const { command, type } = this.props; const pipelineId = type === 'pipelines' ? command.pipelineId : command.strategyPipeline; if (command && pipelineId) { const config = pipelines.find((p) => p.id === pipelineId); if (config && config.parameterConfig) { if (!command.pipelineParameters) { command.pipelineParameters = {}; } this.setState({ pipelineParameters: config.parameterConfig, userSuppliedParameters: command.pipelineParameters, useDefaultParameters: {}, }); this.configureParamDefaults(this.state.pipelineParameters); } else { this.clearParams(); } } else { this.clearParams(); } } protected validateCurrentPipeline(pipelines: IPipeline[]) { const { command, type } = this.props; if (type === 'pipelines' && pipelines.every((p) => p.id !== command.pipelineId)) { command.pipelineId = ''; } if (type === 'strategies' && pipelines.every((p) => p.id !== command.strategyPipeline)) { command.pipelineId = ''; } } private updatePipelines(pipelines: IPipeline[]) { const pipelinesLoaded = true; this.updatePipelineConfig(pipelines); const pipelineOptions = pipelines.map((p) => ({ label: p.name, value: p.id })); this.setState({ pipelines, pipelinesLoaded, pipelineOptions }); } public initializePipelines(): void { this.setState({ pipelinesLoaded: false }); const { command, type } = this.props; if (type === 'pipelines' && command.application) { PipelineConfigService.getPipelinesForApplication(command.application).then((pipelines) => { this.validateCurrentPipeline(pipelines); this.updatePipelines(pipelines); }); } else if (type === 'strategies' && command.strategyApplication) { PipelineConfigService.getStrategiesForApplication(command.strategyApplication).then((pipelines) => { this.validateCurrentPipeline(pipelines); this.updatePipelines(pipelines); }); } else { this.forceUpdate(); } } public componentDidMount() { if (this.props.type === 'strategies' && !this.props.command.strategyApplication) { this.props.command.strategyApplication = this.props.command.application; } ApplicationReader.listApplications().then((applications) => { const applicationOptions = applications .map((a) => a.name) .sort() .map((a) => ({ label: a, value: a })); this.setState({ applicationOptions, applicationsLoaded: true }); this.initializePipelines(); }); } private applicationChange = (option: Option) => { if (this.props.type === 'pipelines') { this.props.command.application = option ? option.value : ''; } else { this.props.command.strategyApplication = option ? option.value : ''; } this.initializePipelines(); }; private pipelineChange = (option: Option) => { if (this.props.type === 'pipelines') { this.props.command.pipelineId = option ? option.value : ''; } else { this.props.command.strategyPipeline = option ? option.value : ''; } this.updatePipelineConfig(this.state.pipelines); }; public updateParam(parameter: string, value: any): void { const { userSuppliedParameters } = this.state; userSuppliedParameters[parameter] = value; if (this.state.useDefaultParameters[parameter] === true) { delete userSuppliedParameters[parameter]; delete this.props.command.pipelineParameters[parameter]; } else if (this.state.userSuppliedParameters[parameter]) { this.props.command.pipelineParameters[parameter] = this.state.userSuppliedParameters[parameter]; } this.setState({ userSuppliedParameters }); } public render() { const { command, type } = this.props; const { applicationsLoaded, applicationOptions, pipelineParameters, pipelineOptions, pipelinesLoaded, useDefaultParameters, userSuppliedParameters, } = this.state; const application = type === 'pipelines' ? command.application : command.strategyApplication; const pipelineId = type === 'pipelines' ? command.pipelineId : command.strategyPipeline; return (
{!applicationsLoaded && (
)} {applicationsLoaded && ( )}
{application && pipelinesLoaded && (
)} {pipelineParameters.length > 0 && (
Parameters {pipelineParameters.map((parameter) => (
{!parameter.description && {parameter.name}} {parameter.description && }
{useDefaultParameters[parameter.name] && ( )} {useDefaultParameters[parameter.name] && !parameter.hasOptions && ( this.updateParam(parameter.name, e.target.value)} /> )} {!useDefaultParameters[parameter.name] && parameter.hasOptions && ( ) => this.updateParam(parameter.name, o ? o.value : '')} options={parameter.options.map((o) => ({ label: o.value, value: o.value }))} /> )}
{parameter.default !== null && parameter.default !== undefined && (
)}
))}
)}
); } }