3 * Copyright (C) 2009-2020 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 import * as React from 'react';
22 deleteProjectAlmBinding,
25 setProjectAzureBinding,
26 setProjectBitbucketBinding,
27 setProjectGithubBinding,
28 setProjectGitlabBinding
29 } from '../../../../api/alm-settings';
30 import throwGlobalError from '../../../../app/utils/throwGlobalError';
31 import { AlmKeys, AlmSettingsInstance, ProjectAlmBinding } from '../../../../types/alm-settings';
32 import PRDecorationBindingRenderer from './PRDecorationBindingRenderer';
35 component: T.Component;
39 formData: ProjectAlmBinding;
40 instances: AlmSettingsInstance[];
43 originalData?: ProjectAlmBinding;
48 const REQUIRED_FIELDS_BY_ALM: {
49 [almKey in AlmKeys]: Array<keyof T.Omit<ProjectAlmBinding, 'key'>>;
52 [AlmKeys.Bitbucket]: ['repository', 'slug'],
53 [AlmKeys.GitHub]: ['repository'],
57 export default class PRDecorationBinding extends React.PureComponent<Props, State> {
60 formData: { key: '' },
70 this.fetchDefinitions();
73 componentWillUnmount() {
77 fetchDefinitions = () => {
78 const project = this.props.component.key;
79 return Promise.all([getAlmSettings(project), this.getProjectBinding(project)])
80 .then(([instances, originalData]) => {
82 this.setState(({ formData }) => {
83 const newFormData = originalData || formData;
85 formData: newFormData,
86 instances: instances || [],
87 isValid: this.validateForm(newFormData),
96 this.setState({ loading: false });
101 getProjectBinding(project: string): Promise<ProjectAlmBinding | undefined> {
102 return getProjectAlmBinding(project).catch((response: Response) => {
103 if (response && response.status === 404) {
104 return Promise.resolve(undefined);
106 return throwGlobalError(response);
112 this.setState({ saving: false });
116 handleReset = () => {
117 const { component } = this.props;
118 this.setState({ saving: true });
119 deleteProjectAlmBinding(component.key)
128 originalData: undefined,
134 .catch(this.catchError);
137 submitProjectAlmBinding(
140 almSpecificFields?: T.Omit<ProjectAlmBinding, 'key'>
142 const almSetting = key;
143 const project = this.props.component.key;
147 return setProjectAzureBinding({
151 case AlmKeys.Bitbucket: {
152 if (!almSpecificFields) {
153 return Promise.reject();
155 const { repository = '', slug = '' } = almSpecificFields;
156 return setProjectBitbucketBinding({
163 case AlmKeys.GitHub: {
164 const repository = almSpecificFields && almSpecificFields.repository;
166 return Promise.reject();
168 return setProjectGithubBinding({
175 case AlmKeys.GitLab: {
176 const repository = almSpecificFields && almSpecificFields.repository;
177 return setProjectGitlabBinding({
185 return Promise.reject();
189 handleSubmit = () => {
190 this.setState({ saving: true });
192 formData: { key, ...additionalFields },
196 const selected = instances.find(i => i.key === key);
197 if (!key || !selected) {
202 this.submitProjectAlmBinding(selected.alm, key, additionalFields)
211 .then(this.fetchDefinitions)
212 .catch(this.catchError);
216 handleFieldChange = (id: keyof ProjectAlmBinding, value: string) => {
217 this.setState(({ formData }) => {
218 const newFormData = {
223 formData: newFormData,
224 isValid: this.validateForm(newFormData),
230 validateForm = ({ key, ...additionalFields }: State['formData']) => {
231 const { instances } = this.state;
232 const selected = instances.find(i => i.key === key);
233 if (!key || !selected) {
236 return REQUIRED_FIELDS_BY_ALM[selected.alm].reduce(
237 (result: boolean, field) => result && Boolean(additionalFields[field]),
244 <PRDecorationBindingRenderer
245 onFieldChange={this.handleFieldChange}
246 onReset={this.handleReset}
247 onSubmit={this.handleSubmit}