]> source.dussan.org Git - sonarqube.git/blob
a36aca0c226e3fbd60c447dfbfaf54ef5cc0b632
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
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
30 export interface PRDecorationBindingRendererProps {
31   formData: T.GithubBinding;
32   hasBinding: boolean;
33   instances: T.AlmSettingsInstance[];
34   isValid: boolean;
35   loading: boolean;
36   onFieldChange: (id: keyof T.GithubBinding, value: string) => void;
37   onReset: () => void;
38   onSubmit: () => void;
39   saving: boolean;
40   success: boolean;
41 }
42
43 function renderLabel(v: T.AlmSettingsInstance) {
44   return v.url ? `${v.key} — ${v.url}` : v.key;
45 }
46
47 export default function PRDecorationBindingRenderer(props: PRDecorationBindingRendererProps) {
48   const {
49     formData: { repository, key },
50     hasBinding,
51     instances,
52     isValid,
53     loading,
54     saving,
55     success
56   } = props;
57
58   if (loading) {
59     return <DeferredSpinner />;
60   }
61
62   if (instances.length < 1) {
63     return (
64       <div>
65         <Alert className="spacer-top huge-spacer-bottom" variant="info">
66           <FormattedMessage
67             defaultMessage={translate('settings.pr_decoration.binding.no_bindings')}
68             id="settings.pr_decoration.binding.no_bindings"
69             values={{
70               link: (
71                 <Link to="/documentation/analysis/pull-request/#pr-decoration">
72                   {translate('learn_more')}
73                 </Link>
74               )
75             }}
76           />
77         </Alert>
78       </div>
79     );
80   }
81
82   return (
83     <div>
84       <header className="page-header">
85         <h1 className="page-title">{translate('settings.pr_decoration.binding.title')}</h1>
86       </header>
87
88       <div className="markdown small spacer-top big-spacer-bottom">
89         {translate('settings.pr_decoration.binding.description')}
90       </div>
91
92       <form
93         onSubmit={(event: React.SyntheticEvent<HTMLFormElement>) => {
94           event.preventDefault();
95           props.onSubmit();
96         }}>
97         <div className="form-field">
98           <label htmlFor="name">
99             {translate('settings.pr_decoration.binding.form.name')}
100             <em className="mandatory spacer-right">*</em>
101           </label>
102           <Select
103             className="abs-width-400"
104             clearable={false}
105             id="name"
106             onChange={({ value }: { value: string }) => props.onFieldChange('key', value)}
107             options={instances.map(v => ({ value: v.key, label: renderLabel(v) }))}
108             searchable={false}
109             value={key}
110           />
111         </div>
112
113         {key && (
114           <div className="form-field">
115             <label htmlFor="repository">
116               {translate('settings.pr_decoration.binding.form.repository')}
117               <em className="mandatory spacer-right">*</em>
118             </label>
119             <input
120               className="input-super-large"
121               id="repository"
122               maxLength={256}
123               name="repository"
124               onChange={e => props.onFieldChange('repository', e.currentTarget.value)}
125               type="text"
126               value={repository}
127             />
128           </div>
129         )}
130
131         <div className="display-flex-center">
132           <DeferredSpinner className="spacer-right" loading={saving} />
133           <SubmitButton className="spacer-right" disabled={saving || !isValid}>
134             {translate('save')}
135           </SubmitButton>
136           {hasBinding && (
137             <Button className="spacer-right" onClick={props.onReset}>
138               {translate('reset_verb')}
139             </Button>
140           )}
141           {!saving && success && (
142             <span className="text-success">
143               <AlertSuccessIcon className="spacer-right" />
144               {translate('settings.state.saved')}
145             </span>
146           )}
147         </div>
148       </form>
149     </div>
150   );
151 }