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';
34 ProjectAlmBindingResponse
35 } from '../../../../types/alm-settings';
36 import PRDecorationBindingRenderer from './PRDecorationBindingRenderer';
38 type FormData = T.Omit<ProjectAlmBindingResponse, 'alm'>;
41 component: T.Component;
46 instances: AlmSettingsInstance[];
48 isConfigured: boolean;
51 orignalData?: FormData;
56 const REQUIRED_FIELDS_BY_ALM: {
57 [almKey in AlmKeys]: Array<keyof T.Omit<FormData, 'key'>>;
60 [AlmKeys.Bitbucket]: ['repository', 'slug'],
61 [AlmKeys.GitHub]: ['repository'],
65 export default class PRDecorationBinding extends React.PureComponent<Props, State> {
68 formData: { key: '' },
80 this.fetchDefinitions();
83 componentWillUnmount() {
87 fetchDefinitions = () => {
88 const project = this.props.component.key;
89 return Promise.all([getAlmSettings(project), this.getProjectBinding(project)])
90 .then(([instances, originalData]) => {
92 this.setState(({ formData }) => {
93 const newFormData = originalData || formData;
95 formData: newFormData,
96 instances: instances || [],
98 isConfigured: !!originalData,
99 isValid: this.validateForm(newFormData),
101 orignalData: newFormData
108 this.setState({ loading: false });
113 getProjectBinding(project: string): Promise<ProjectAlmBindingResponse | undefined> {
114 return getProjectAlmBinding(project).catch((response: Response) => {
115 if (response && response.status === 404) {
118 return throwGlobalError(response);
124 this.setState({ saving: false });
128 handleReset = () => {
129 const { component } = this.props;
130 this.setState({ saving: true });
131 deleteProjectAlmBinding(component.key)
147 .catch(this.catchError);
150 submitProjectAlmBinding(
153 almSpecificFields?: T.Omit<FormData, 'key'>
155 const almSetting = key;
156 const project = this.props.component.key;
160 return setProjectAzureBinding({
164 case AlmKeys.Bitbucket: {
165 if (!almSpecificFields) {
166 return Promise.reject();
168 const { repository = '', slug = '' } = almSpecificFields;
169 return setProjectBitbucketBinding({
176 case AlmKeys.GitHub: {
177 const repository = almSpecificFields?.repository;
178 // By default it must remain true.
179 const summaryCommentEnabled =
180 almSpecificFields?.summaryCommentEnabled === undefined
182 : almSpecificFields?.summaryCommentEnabled;
184 return Promise.reject();
186 return setProjectGithubBinding({
190 summaryCommentEnabled
194 case AlmKeys.GitLab: {
195 const repository = almSpecificFields && almSpecificFields.repository;
196 return setProjectGitlabBinding({
204 return Promise.reject();
208 handleSubmit = () => {
209 this.setState({ saving: true });
211 formData: { key, ...additionalFields },
215 const selected = instances.find(i => i.key === key);
216 if (!key || !selected) {
220 this.submitProjectAlmBinding(selected.alm, key, additionalFields)
229 .then(this.fetchDefinitions)
230 .catch(this.catchError);
234 { key, repository = '', slug = '', summaryCommentEnabled = false }: FormData,
237 repository: oRepository = '',
239 summaryCommentEnabled: osummaryCommentEnabled = false
244 repository === oRepository &&
246 summaryCommentEnabled === osummaryCommentEnabled
250 handleFieldChange = (id: keyof ProjectAlmBindingResponse, value: string | boolean) => {
251 this.setState(({ formData, orignalData }) => {
252 const newFormData = {
257 formData: newFormData,
258 isValid: this.validateForm(newFormData),
259 isChanged: !this.isDataSame(newFormData, orignalData || { key: '' }),
265 validateForm = ({ key, ...additionalFields }: State['formData']) => {
266 const { instances } = this.state;
267 const selected = instances.find(i => i.key === key);
268 if (!key || !selected) {
271 return REQUIRED_FIELDS_BY_ALM[selected.alm].reduce(
272 (result: boolean, field) => result && Boolean(additionalFields[field]),
279 <PRDecorationBindingRenderer
280 onFieldChange={this.handleFieldChange}
281 onReset={this.handleReset}
282 onSubmit={this.handleSubmit}