3 * Copyright (C) 2009-2021 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';
21 import { FormattedMessage } from 'react-intl';
22 import { Link } from 'react-router';
23 import { Alert } from '../../../../components/ui/Alert';
24 import MandatoryFieldMarker from '../../../../components/ui/MandatoryFieldMarker';
25 import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
26 import { translate } from '../../../../helpers/l10n';
27 import { convertGithubApiUrlToLink, stripTrailingSlash } from '../../../../helpers/urls';
31 ProjectAlmBindingResponse
32 } from '../../../../types/alm-settings';
33 import InputForBoolean from '../inputs/InputForBoolean';
35 export interface AlmSpecificFormProps {
37 instances: AlmSettingsInstance[];
38 formData: T.Omit<ProjectAlmBindingResponse, 'alm'>;
39 onFieldChange: (id: keyof ProjectAlmBindingResponse, value: string | boolean) => void;
40 monorepoEnabled: boolean;
43 interface LabelProps {
48 interface CommonFieldProps extends LabelProps {
50 helpParams?: T.Dict<string | JSX.Element>;
51 helpExample?: JSX.Element;
52 onFieldChange: (id: keyof ProjectAlmBindingResponse, value: string | boolean) => void;
53 propKey: keyof ProjectAlmBindingResponse;
56 function renderFieldWrapper(
57 label: React.ReactNode,
58 input: React.ReactNode,
59 help?: React.ReactNode
62 <div className="settings-definition">
63 <div className="settings-definition-left">
65 {help && <div className="markdown small spacer-top">{help}</div>}
67 <div className="settings-definition-right padded-top">{input}</div>
72 function renderHelp({ help, helpExample, helpParams, id }: CommonFieldProps) {
77 defaultMessage={translate('settings.pr_decoration.binding.form', id, 'help')}
78 id={`settings.pr_decoration.binding.form.${id}.help`}
82 <div className="spacer-top nowrap">
83 {translate('example')}: <em>{helpExample}</em>
91 function renderLabel(props: LabelProps) {
92 const { optional, id } = props;
94 <label className="h3" htmlFor={id}>
95 {translate('settings.pr_decoration.binding.form', id)}
96 {!optional && <MandatoryFieldMarker />}
101 function renderBooleanField(
102 props: Omit<CommonFieldProps, 'optional'> & {
104 inputExtra?: React.ReactNode;
107 const { id, value, onFieldChange, propKey, inputExtra } = props;
108 return renderFieldWrapper(
109 renderLabel({ ...props, optional: true }),
110 <div className="display-flex-center big-spacer-top">
114 onChange={v => onFieldChange(propKey, v)}
123 function renderField(
124 props: CommonFieldProps & {
128 const { id, propKey, value, onFieldChange } = props;
129 return renderFieldWrapper(
132 className="input-super-large big-spacer-top"
136 onChange={e => onFieldChange(propKey, e.currentTarget.value)}
144 export default function AlmSpecificForm(props: AlmSpecificFormProps) {
148 formData: { repository, slug, summaryCommentEnabled, monorepo },
152 let formFields: JSX.Element;
153 const instance = instances.find(i => i.alm === alm);
161 helpExample: <strong>My Project</strong>,
163 onFieldChange: props.onFieldChange,
169 helpExample: <strong>My Repository</strong>,
170 id: 'azure.repository',
171 onFieldChange: props.onFieldChange,
172 propKey: 'repository',
173 value: repository || ''
178 case AlmKeys.BitbucketServer:
186 ? `${stripTrailingSlash(instance.url)}/projects/`
187 : 'https://bb.company.com/projects/'}
188 <strong>{'MY_PROJECT_KEY'}</strong>
189 {'/repos/my-repository-slug/browse'}
192 id: 'bitbucket.repository',
193 onFieldChange: props.onFieldChange,
194 propKey: 'repository',
195 value: repository || ''
202 ? `${stripTrailingSlash(instance.url)}/projects/MY_PROJECT_KEY/repos/`
203 : 'https://bb.company.com/projects/MY_PROJECT_KEY/repos/'}
204 <strong>{'my-repository-slug'}</strong>
208 id: 'bitbucket.slug',
209 onFieldChange: props.onFieldChange,
216 case AlmKeys.BitbucketCloud:
223 {'https://bitbucket.org/my-workspace/'}
224 <strong>{'my-repository-slug'}</strong>
227 id: 'bitbucketcloud.repository',
228 onFieldChange: props.onFieldChange,
229 propKey: 'repository',
230 value: repository || ''
243 ? `${stripTrailingSlash(convertGithubApiUrlToLink(instance.url))}/`
244 : 'https://github.com/'}
245 <strong>{'sonarsource/sonarqube'}</strong>
248 id: 'github.repository',
249 onFieldChange: props.onFieldChange,
250 propKey: 'repository',
251 value: repository || ''
253 {renderBooleanField({
255 id: 'github.summary_comment_setting',
256 onFieldChange: props.onFieldChange,
257 propKey: 'summaryCommentEnabled',
258 value: summaryCommentEnabled === undefined ? true : summaryCommentEnabled
268 helpExample: <strong>123456</strong>,
269 id: 'gitlab.repository',
270 onFieldChange: props.onFieldChange,
271 propKey: 'repository',
272 value: repository || ''
287 <Link to={ALM_DOCUMENTATION_PATHS[alm]} target="_blank">
288 {translate('learn_more')}
293 onFieldChange: props.onFieldChange,
296 inputExtra: monorepo && (
297 <Alert className="no-margin-bottom spacer-left" variant="warning" display="inline">
298 {translate('settings.pr_decoration.binding.form.monorepo.warning')}