Skip to content
This repository was archived by the owner on Dec 20, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import * as React from 'react';

import { AccountService, IAccount } from 'core/account';
import { ApplicationReader, IApplicationSummary } from 'core/application';
import { IPipeline, IProject } from 'core/domain';
import { IProject } from 'core/domain';
import { WizardModal, WizardPage } from 'core/modal';
import { PipelineConfigService } from 'core/pipeline';
import { IModalComponentProps, ReactModal } from 'core/presentation';
import { TaskMonitor } from 'core/task';
import { noop } from 'core/utils';
Expand All @@ -28,9 +27,6 @@ export interface IConfigureProjectModalState {
allAccounts: IAccount[];
allProjects: IProject[];
allApplications: IApplicationSummary[];
appPipelines: {
[appName: string]: IPipeline[];
};
configuredApps: string[];
loading: boolean;
taskMonitor?: TaskMonitor;
Expand All @@ -47,7 +43,6 @@ export class ConfigureProjectModal extends React.Component<IConfigureProjectModa
allAccounts: [],
allProjects: [],
allApplications: [],
appPipelines: {},
configuredApps: [],
};

Expand All @@ -74,15 +69,12 @@ export class ConfigureProjectModal extends React.Component<IConfigureProjectModa

private handleApplicationsChanged = (configuredApps: string[]) => {
this.setState({ configuredApps });
this.fetchPipelinesForApps(configuredApps);
};

public componentDidMount() {
const { projectConfiguration } = this.props;
const configuredApps = (projectConfiguration && projectConfiguration.config.applications) || [];
Promise.all([this.fetchPipelinesForApps(configuredApps), this.initialFetch()]).then(() =>
this.setState({ loading: false, configuredApps }),
);
Promise.all([this.initialFetch()]).then(() => this.setState({ loading: false, configuredApps }));
}

private submit = (project: IProject) => {
Expand Down Expand Up @@ -110,21 +102,6 @@ export class ConfigureProjectModal extends React.Component<IConfigureProjectModa
);
}

private fetchPipelinesForApps = (applications: string[]) => {
// Only fetch for apps we don't already have results for
const appsToFetch = applications.filter(appName => !this.state.appPipelines[appName]);

const fetches = appsToFetch.map(appName => {
return PipelineConfigService.getPipelinesForApplication(appName).then(pipelines =>
this.setState({
appPipelines: { ...this.state.appPipelines, [appName]: pipelines },
}),
);
});

return Promise.all(fetches);
};

private onDelete = () => {
const { projectConfiguration } = this.props;
const { name } = projectConfiguration;
Expand All @@ -142,7 +119,7 @@ export class ConfigureProjectModal extends React.Component<IConfigureProjectModa

public render() {
const { dismissModal, projectConfiguration } = this.props;
const { allAccounts, allApplications, allProjects, appPipelines, loading, taskMonitor } = this.state;
const { allAccounts, allApplications, allProjects, loading, taskMonitor } = this.state;
const appNames = allApplications.map(app => app.name);

return (
Expand Down Expand Up @@ -190,7 +167,7 @@ export class ConfigureProjectModal extends React.Component<IConfigureProjectModa
label="Pipelines"
wizard={wizard}
order={nextIdx()}
render={({ innerRef }) => <Pipelines ref={innerRef} appsPipelines={appPipelines} />}
render={({ innerRef }) => <Pipelines ref={innerRef} formik={formik} />}
/>
</>
)}
Expand Down
60 changes: 51 additions & 9 deletions app/scripts/modules/core/src/projects/configure/Pipelines.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
import * as React from 'react';
import { FieldArray, FormikErrors, getIn } from 'formik';
import { FieldArray, FormikErrors, FormikProps, getIn } from 'formik';
import { chain, each, get, isEqual } from 'lodash';

import { PipelineConfigService } from 'core/pipeline';
import { FormikFormField, ReactSelectInput, StringsAsOptions } from 'core/presentation';
import { Spinner } from 'core/widgets';
import { IPipeline, IProject, IProjectPipeline } from 'core/domain';
import { IWizardPageComponent } from 'core/modal';

export interface IPipelinesProps {
formik: FormikProps<IProject>;
}

export interface IPipelinesState {
appsPipelines: {
[appName: string]: IPipeline[];
};
}

export class Pipelines extends React.Component<IPipelinesProps> implements IWizardPageComponent<IProject> {
export class Pipelines extends React.Component<IPipelinesProps, IPipelinesState>
implements IWizardPageComponent<IProject> {
private static readonly pipelineConfigsPath = 'config.pipelineConfigs';

public state: IPipelinesState = {
appsPipelines: {},
};

public validate = (value: IProject): FormikErrors<IProject> => {
const projectApplications = (value.config && value.config.applications) || [];
const { appsPipelines } = this.props;
const { appsPipelines } = this.state;

if (value.config && value.config.pipelineConfigs && value.config.pipelineConfigs.length) {
const pipelineConfigErrors = value.config.pipelineConfigs.map(config => {
Expand Down Expand Up @@ -46,8 +59,39 @@ export class Pipelines extends React.Component<IPipelinesProps> implements IWiza
return {};
};

private getProjectPipelines = (props: IPipelinesProps): IProjectPipeline[] => {
return get(props.formik.values, Pipelines.pipelineConfigsPath, []);
};

private fetchPipelinesForApps = (projectPipelines: IProjectPipeline[]) => {
const appsToFetch = chain(projectPipelines)
.map('application')
.uniq()
// Only fetch for apps we don't already have results for
.filter(appName => appName && !this.state.appsPipelines[appName])
.value();

each(appsToFetch, appName => {
PipelineConfigService.getPipelinesForApplication(appName).then(pipelines =>
this.setState({
appsPipelines: { ...this.state.appsPipelines, [appName]: pipelines },
}),
);
});
};

public componentDidMount() {
this.fetchPipelinesForApps(this.getProjectPipelines(this.props));
}

public componentDidUpdate(prevProps: IPipelinesProps) {
if (!isEqual(this.getProjectPipelines(prevProps), this.getProjectPipelines(this.props))) {
this.fetchPipelinesForApps(this.getProjectPipelines(this.props));
}
}

public render() {
const { appsPipelines } = this.props;
const { appsPipelines } = this.state;

const tableHeader = (
<tr>
Expand All @@ -57,14 +101,12 @@ export class Pipelines extends React.Component<IPipelinesProps> implements IWiza
</tr>
);

const pipelineConfigsPath = 'config.pipelineConfigs';

return (
<FieldArray
name={pipelineConfigsPath}
name={Pipelines.pipelineConfigsPath}
render={pipelinesArrayHelper => {
const project: IProject = pipelinesArrayHelper.form.values;
const configs: IProjectPipeline[] = getIn(project, pipelineConfigsPath);
const configs: IProjectPipeline[] = getIn(project, Pipelines.pipelineConfigsPath);
const apps: string[] = getIn(project, 'config.applications');

return (
Expand All @@ -74,7 +116,7 @@ export class Pipelines extends React.Component<IPipelinesProps> implements IWiza
<thead>{tableHeader}</thead>
<tbody>
{configs.map((config, idx) => {
const pipelinePath = `${pipelineConfigsPath}[${idx}]`;
const pipelinePath = `${Pipelines.pipelineConfigsPath}[${idx}]`;
const application = config && config.application;
const appPipelines = application && appsPipelines[application];
const pipelineOptions = appPipelines && appPipelines.map(p => ({ label: p.name, value: p.id }));
Expand Down