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 { Button, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
24 import Select from 'sonar-ui-common/components/controls/Select';
25 import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon';
26 import { Alert } from 'sonar-ui-common/components/ui/Alert';
27 import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
28 import { translate } from 'sonar-ui-common/helpers/l10n';
29 import { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../../../types/alm-settings';
30 import AlmSpecificForm from './AlmSpecificForm';
32 export interface PRDecorationBindingRendererProps {
33 formData: T.Omit<ProjectAlmBindingResponse, 'alm'>;
34 instances: AlmSettingsInstance[];
36 isConfigured: boolean;
39 onFieldChange: (id: keyof ProjectAlmBindingResponse, value: string | boolean) => void;
44 monorepoEnabled: boolean;
47 function optionRenderer(instance: AlmSettingsInstance) {
48 return instance.url ? (
50 <span>{instance.key} — </span>
51 <span className="text-muted">{instance.url}</span>
54 <span>{instance.key}</span>
58 export default function PRDecorationBindingRenderer(props: PRDecorationBindingRendererProps) {
72 return <DeferredSpinner />;
75 if (instances.length < 1) {
78 <Alert className="spacer-top huge-spacer-bottom" variant="info">
80 defaultMessage={translate('settings.pr_decoration.binding.no_bindings')}
81 id="settings.pr_decoration.binding.no_bindings"
84 <Link to="/documentation/analysis/pull-request/#pr-decoration">
85 {translate('learn_more')}
95 const selected = formData.key && instances.find(i => i.key === formData.key);
96 const alm = selected && selected.alm;
100 <header className="page-header">
101 <h1 className="page-title">{translate('settings.pr_decoration.binding.title')}</h1>
104 <div className="markdown small spacer-top big-spacer-bottom">
105 {translate('settings.pr_decoration.binding.description')}
109 onSubmit={(event: React.SyntheticEvent<HTMLFormElement>) => {
110 event.preventDefault();
113 <div className="form-field">
114 <label htmlFor="name">
115 {translate('settings.pr_decoration.binding.form.name')}
116 <em className="mandatory spacer-right">*</em>
120 className="abs-width-400"
123 menuContainerStyle={{
124 maxWidth: '210%' /* Allow double the width of the select */,
127 onChange={(instance: AlmSettingsInstance) => props.onFieldChange('key', instance.key)}
128 optionRenderer={optionRenderer}
133 valueRenderer={optionRenderer}
141 onFieldChange={props.onFieldChange}
142 monorepoEnabled={monorepoEnabled}
146 <div className="display-flex-center">
147 <DeferredSpinner className="spacer-right" loading={saving} />
149 <SubmitButton className="spacer-right button-success" disabled={saving || !isValid}>
150 <span data-test="project-settings__alm-save">{translate('save')}</span>
154 <Button className="spacer-right" onClick={props.onReset}>
155 <span data-test="project-settings__alm-reset">{translate('reset_verb')}</span>
158 {!saving && success && (
159 <span className="text-success">
160 <AlertSuccessIcon className="spacer-right" />
161 {translate('settings.state.saved')}