aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2019-10-24 17:49:18 +0200
committersonartech <sonartech@sonarsource.com>2019-11-06 10:04:29 +0100
commit7cb2dd55ce43a61c49b5ce390312cb3327ec565f (patch)
treeec48a0922cc81ec768f86cdb324801c56c672194 /server/sonar-web
parent22c6e4a22a6b07b41d61bae95c8b800452be1a77 (diff)
downloadsonarqube-7cb2dd55ce43a61c49b5ce390312cb3327ec565f.tar.gz
sonarqube-7cb2dd55ce43a61c49b5ce390312cb3327ec565f.zip
Fixes from review
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/public/images/alm/azure.svg3
-rw-r--r--server/sonar-web/public/images/alm/bitbucket.svg10
-rw-r--r--server/sonar-web/public/images/alm/github.svg3
-rw-r--r--server/sonar-web/src/main/js/app/styles/init/tables.css12
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx22
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx14
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx20
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx26
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx24
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx29
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx50
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx13
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap5
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap46
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap39
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap25
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap88
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap39
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap30
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap114
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap39
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap45
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap24
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx43
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx62
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx117
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx9
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap166
-rw-r--r--server/sonar-web/src/main/js/apps/settings/utils.ts7
-rw-r--r--server/sonar-web/src/main/js/types/alm-settings.ts7
35 files changed, 618 insertions, 538 deletions
diff --git a/server/sonar-web/public/images/alm/azure.svg b/server/sonar-web/public/images/alm/azure.svg
new file mode 100644
index 00000000000..a4350954295
--- /dev/null
+++ b/server/sonar-web/public/images/alm/azure.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.009 22">
+ <path fill="#0078d7" d="M2.916 15.015v-7.25l19.093-3.758v13.446L16.62 21.92l-8.226-2.757V22l-5.478-6.985 13.216 1.728V5.052L9.812 0l.044 2.3-7.516 3L0 8.1v6.3z"/>
+</svg> \ No newline at end of file
diff --git a/server/sonar-web/public/images/alm/bitbucket.svg b/server/sonar-web/public/images/alm/bitbucket.svg
new file mode 100644
index 00000000000..984afdaa426
--- /dev/null
+++ b/server/sonar-web/public/images/alm/bitbucket.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-361.924 -3545.014 58.441 52.551">
+ <defs>
+ <linearGradient id="a" x1="1.086" x2=".469" y1=".138" y2=".788" gradientUnits="objectBoundingBox">
+ <stop offset=".18" stop-color="#0052cc"/>
+ <stop offset="1" stop-color="#2684ff"/>
+ </linearGradient>
+ </defs>
+ <path fill="#2684ff" d="M-360.027-3545.013a1.872 1.872 0 0 0-1.871 2.172l7.947 48.253a2.547 2.547 0 0 0 2.49 2.125h38.133a1.872 1.872 0 0 0 1.872-1.573l7.949-48.8a1.872 1.872 0 0 0-1.872-2.172zm33.47 34.875h-12.171l-3.3-17.217h18.42z"/>
+ <path fill="url(#a)" d="M56.464 25.12H38.891l-2.949 17.217H23.771L9.4 59.4a2.537 2.537 0 0 0 1.638.618H49.18a1.872 1.872 0 0 0 1.872-1.573z" transform="translate(-362.499 -3552.476)"/>
+</svg> \ No newline at end of file
diff --git a/server/sonar-web/public/images/alm/github.svg b/server/sonar-web/public/images/alm/github.svg
new file mode 100644
index 00000000000..97c8f324e50
--- /dev/null
+++ b/server/sonar-web/public/images/alm/github.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-738.601 -3545.014 54.017 52.551">
+ <path fill="#191717" fill-rule="evenodd" d="M-711.675-3545.014a26.975 26.975 0 0 0-8.59 52.53c1.322.165 1.817-.661 1.817-1.322v-4.625c-7.433 1.652-9.085-3.634-9.085-3.634-1.156-3.139-2.973-3.965-2.973-3.965-2.478-1.652.165-1.652.165-1.652 2.643.165 4.13 2.808 4.13 2.808 2.478 4.13 6.277 2.973 7.764 2.313a5.752 5.752 0 0 1 1.646-3.634c-5.947-.661-12.224-2.973-12.224-13.38a10.24 10.24 0 0 1 2.808-7.268 9.781 9.781 0 0 1 .33-6.938s2.313-.661 7.433 2.808a23.083 23.083 0 0 1 6.773-.826 30.4 30.4 0 0 1 6.773.826c5.121-3.469 7.433-2.808 7.433-2.808a10.343 10.343 0 0 1 .33 7.1 10.684 10.684 0 0 1 2.815 7.267c0 10.407-6.277 12.554-12.224 13.215.991.826 1.817 2.478 1.817 4.956v7.433c0 .661.5 1.487 1.817 1.322a26.976 26.976 0 0 0-8.755-52.526z"/>
+</svg> \ No newline at end of file
diff --git a/server/sonar-web/src/main/js/app/styles/init/tables.css b/server/sonar-web/src/main/js/app/styles/init/tables.css
index fc224d72663..a0bfecf7831 100644
--- a/server/sonar-web/src/main/js/app/styles/init/tables.css
+++ b/server/sonar-web/src/main/js/app/styles/init/tables.css
@@ -287,3 +287,15 @@ table.data.zebra.zebra-inversed > tbody > tr:nth-child(odd) {
table#project-history tr > td {
vertical-align: top;
}
+
+table.fixed {
+ table-layout: fixed;
+}
+
+table.fixed th.action-small {
+ width: 30px;
+}
+
+table.fixed th.action {
+ width: 50px;
+}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx
index d462c0e829f..1e758a1671d 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx
@@ -24,48 +24,48 @@ import { AlmSettingsBinding } from '../../../../types/alm-settings';
export interface AlmDefinitionFormFieldProps<B extends AlmSettingsBinding> {
autoFocus?: boolean;
- formData: B;
- help: boolean;
+ help?: React.ReactNode;
id: string;
- isTextArea: boolean;
- maxLength: number;
+ isTextArea?: boolean;
+ maxLength?: number;
onFieldChange: (id: keyof B, value: string) => void;
propKey: keyof B;
+ value: string;
}
export function AlmDefinitionFormField<B extends AlmSettingsBinding>(
props: AlmDefinitionFormFieldProps<B>
) {
- const { autoFocus, formData, help, id, isTextArea, maxLength, onFieldChange, propKey } = props;
+ const { autoFocus, help, id, isTextArea, maxLength, onFieldChange, propKey, value } = props;
return (
<div className="modal-field">
<label className="display-flex-center" htmlFor={id}>
{translate('settings.pr_decoration.form', id)}
<em className="mandatory spacer-right">*</em>
- {help && <HelpTooltip overlay={translate('settings.pr_decoration.form', id, 'help')} />}
+ {help && <HelpTooltip overlay={help} placement="right" />}
</label>
{isTextArea ? (
<textarea
className="settings-large-input"
- id="privateKey"
- maxLength={maxLength}
+ id={id}
+ maxLength={maxLength || 2000}
onChange={e => onFieldChange(propKey, e.currentTarget.value)}
required={true}
rows={5}
- value={String(formData[propKey])}
+ value={value}
/>
) : (
<input
autoFocus={autoFocus}
className="input-super-large"
id={id}
- maxLength={maxLength}
+ maxLength={maxLength || 100}
name={id}
onChange={e => onFieldChange(propKey, e.currentTarget.value)}
size={50}
type="text"
- value={String(formData[propKey])}
+ value={value}
/>
)}
</div>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx
index 07722a00cf5..6afe96824e2 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx
@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { translate } from 'sonar-ui-common/helpers/l10n';
import { AzureBindingDefinition } from '../../../../types/alm-settings';
import { AlmDefinitionFormField } from './AlmDefinitionFormField';
@@ -33,22 +34,19 @@ export default function AzureFormModal(props: AzureFormModalProps) {
<>
<AlmDefinitionFormField
autoFocus={true}
- formData={formData}
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help={translate('settings.pr_decoration.form.azure.name.help')}
+ id="azure.name"
onFieldChange={onFieldChange}
propKey="key"
+ value={formData.key}
/>
<AlmDefinitionFormField
- formData={formData}
- help={true}
+ help={translate('settings.pr_decoration.form.personal_access_token.help')}
id="personal_access_token"
isTextArea={true}
- maxLength={2000}
onFieldChange={onFieldChange}
propKey="personalAccessToken"
+ value={formData.personalAccessToken}
/>
</>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx
index 24d4039f794..5435f791243 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx
@@ -42,11 +42,9 @@ export default function AzureTabRenderer(props: AzureTabRendererProps) {
<>
<TabHeader alm={ALM_KEYS.AZURE} onCreate={props.onCreate} />
- {loading ? (
- <DeferredSpinner />
- ) : (
+ <DeferredSpinner loading={loading}>
<AzureTable definitions={definitions} onDelete={props.onDelete} onEdit={props.onEdit} />
- )}
+ </DeferredSpinner>
{editedDefinition && (
<AlmPRDecorationFormModal
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx
index 11cfba29a46..066da515e1a 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx
@@ -33,29 +33,35 @@ export default function AzureTable(props: AzureTableProps) {
const { definitions } = props;
return (
- <table className="data zebra spacer-bottom">
+ <table className="data zebra fixed spacer-bottom">
<thead>
<tr>
<th>{translate('settings.pr_decoration.table.column.name')}</th>
- <th className="thin">{translate('settings.pr_decoration.table.column.edit')}</th>
- <th className="thin">{translate('settings.pr_decoration.table.column.delete')}</th>
+ <th className="action-small text-center">
+ {translate('settings.pr_decoration.table.column.edit')}
+ </th>
+ <th className="action text-center">
+ {translate('settings.pr_decoration.table.column.delete')}
+ </th>
</tr>
</thead>
<tbody>
- {definitions.length < 1 ? (
+ {definitions.length === 0 ? (
<tr>
<td colSpan={3}>{translate('settings.pr_decoration.table.empty.azure')}</td>
</tr>
) : (
definitions.map(definition => (
<tr key={definition.key}>
- <td>{definition.key}</td>
- <td>
+ <td className="nowrap hide-overflow" title={definition.key}>
+ {definition.key}
+ </td>
+ <td className="text-center">
<ButtonIcon onClick={() => props.onEdit(definition)}>
<EditIcon />
</ButtonIcon>
</td>
- <td>
+ <td className="text-center">
<DeleteButton onClick={() => props.onDelete(definition.key)} />
</td>
</tr>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx
index 9484ceebf80..59058c93407 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx
@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
import { BitbucketBindingDefinition } from '../../../../types/alm-settings';
import { AlmDefinitionFormField } from './AlmDefinitionFormField';
@@ -33,31 +35,33 @@ export default function BitbucketFormModal(props: BitbucketFormModalProps) {
<>
<AlmDefinitionFormField
autoFocus={true}
- formData={formData}
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help={translate('settings.pr_decoration.form.url.bitbucket.name.help')}
+ id="bitbucket.name"
+ maxLength={100}
onFieldChange={onFieldChange}
propKey="key"
+ value={formData.key}
/>
<AlmDefinitionFormField
- formData={formData}
- help={false}
+ help={
+ <FormattedMessage
+ defaultMessage={translate('settings.pr_decoration.form.url.bitbucket.help')}
+ id="settings.pr_decoration.form.url.bitbucket.help"
+ values={{ example: 'https://bitbucket-server.your-company.com' }}
+ />
+ }
id="url.bitbucket"
- isTextArea={false}
maxLength={2000}
onFieldChange={onFieldChange}
propKey="url"
+ value={formData.url}
/>
<AlmDefinitionFormField
- formData={formData}
- help={false}
id="personal_access_token"
isTextArea={true}
- maxLength={2000}
onFieldChange={onFieldChange}
propKey="personalAccessToken"
+ value={formData.personalAccessToken}
/>
</>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx
index 2f048c81ff8..c24b30b4120 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx
@@ -42,11 +42,9 @@ export default function BitbucketTabRenderer(props: BitbucketTabRendererProps) {
<>
<TabHeader alm={ALM_KEYS.BITBUCKET} onCreate={props.onCreate} />
- {loading ? (
- <DeferredSpinner />
- ) : (
+ <DeferredSpinner loading={loading}>
<BitbucketTable definitions={definitions} onDelete={props.onDelete} onEdit={props.onEdit} />
- )}
+ </DeferredSpinner>
{editedDefinition && (
<AlmPRDecorationFormModal
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx
index 3183e625fb5..dc173e19788 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx
@@ -33,31 +33,39 @@ export default function BitbucketTable(props: BitbucketTableProps) {
const { definitions } = props;
return (
- <table className="data zebra spacer-bottom">
+ <table className="data zebra fixed spacer-bottom">
<thead>
<tr>
<th>{translate('settings.pr_decoration.table.column.name')}</th>
<th>{translate(`settings.pr_decoration.table.column.bitbucket.url`)}</th>
- <th className="thin">{translate('settings.pr_decoration.table.column.edit')}</th>
- <th className="thin">{translate('settings.pr_decoration.table.column.delete')}</th>
+ <th className="action-small text-center">
+ {translate('settings.pr_decoration.table.column.edit')}
+ </th>
+ <th className="action text-center">
+ {translate('settings.pr_decoration.table.column.delete')}
+ </th>
</tr>
</thead>
<tbody>
- {definitions.length < 1 ? (
+ {definitions.length === 0 ? (
<tr>
<td colSpan={4}>{translate('settings.pr_decoration.table.empty.bitbucket')}</td>
</tr>
) : (
definitions.map(definition => (
<tr key={definition.key}>
- <td>{definition.key}</td>
- <td>{definition.url}</td>
- <td>
+ <td className="nowrap hide-overflow" title={definition.key}>
+ {definition.key}
+ </td>
+ <td className="nowrap hide-overflow" title={definition.url}>
+ {definition.url}
+ </td>
+ <td className="text-center">
<ButtonIcon onClick={() => props.onEdit(definition)}>
<EditIcon />
</ButtonIcon>
</td>
- <td>
+ <td className="text-center">
<DeleteButton onClick={() => props.onDelete(definition.key)} />
</td>
</tr>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx
index 728008eb947..a9d8a03eb6b 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx
@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
import { GithubBindingDefinition } from '../../../../types/alm-settings';
import { AlmDefinitionFormField } from './AlmDefinitionFormField';
@@ -33,40 +35,39 @@ export default function GithubFormModal(props: GithubFormModalProps) {
<>
<AlmDefinitionFormField
autoFocus={true}
- formData={formData}
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help={translate('settings.pr_decoration.form.github.name.help')}
+ id="github.name"
onFieldChange={onFieldChange}
propKey="key"
+ value={formData.key}
/>
<AlmDefinitionFormField
- formData={formData}
- help={false}
+ help={
+ <FormattedMessage
+ defaultMessage={translate('settings.pr_decoration.form.url.github.help')}
+ id="settings.pr_decoration.form.url.github.help"
+ values={{ example: 'https://github.company.com/api/v3' }}
+ />
+ }
id="url.github"
- isTextArea={false}
maxLength={2000}
onFieldChange={onFieldChange}
propKey="url"
+ value={formData.url}
/>
<AlmDefinitionFormField
- formData={formData}
- help={false}
id="app_id"
- isTextArea={false}
maxLength={80}
onFieldChange={onFieldChange}
propKey="appId"
+ value={formData.appId}
/>
<AlmDefinitionFormField
- formData={formData}
- help={false}
id="private_key"
isTextArea={true}
- maxLength={2000}
onFieldChange={onFieldChange}
propKey="privateKey"
+ value={formData.privateKey}
/>
</>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx
index 811178734e3..e135049b98d 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx
@@ -42,11 +42,9 @@ export default function GithubTabRenderer(props: GithubTabRendererProps) {
<>
<TabHeader alm={ALM_KEYS.GITHUB} onCreate={props.onCreate} />
- {loading ? (
- <DeferredSpinner />
- ) : (
+ <DeferredSpinner loading={loading}>
<GithubTable definitions={definitions} onDelete={props.onDelete} onEdit={props.onEdit} />
- )}
+ </DeferredSpinner>
{editedDefinition && (
<AlmPRDecorationFormModal
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx
index f9d6db98f75..6c992dac1f8 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx
@@ -33,32 +33,48 @@ export default function GithubTable(props: GithubTableProps) {
const { definitions } = props;
return (
- <table className="data zebra spacer-bottom">
+ <table className="data zebra fixed spacer-bottom">
<thead>
<tr>
<th>{translate('settings.pr_decoration.table.column.name')}</th>
<th>{translate(`settings.pr_decoration.table.column.github.url`)}</th>
<th>{translate('settings.pr_decoration.table.column.app_id')}</th>
- <th className="thin">{translate('settings.pr_decoration.table.column.edit')}</th>
- <th className="thin">{translate('settings.pr_decoration.table.column.delete')}</th>
+ <th className="action-small text-center">
+ {translate('settings.pr_decoration.table.column.edit')}
+ </th>
+ <th className="action text-center">
+ {translate('settings.pr_decoration.table.column.delete')}
+ </th>
</tr>
</thead>
<tbody>
- {definitions.map(definition => (
- <tr key={definition.key}>
- <td>{definition.key}</td>
- <td>{definition.url}</td>
- <td>{definition.appId}</td>
- <td>
- <ButtonIcon onClick={() => props.onEdit(definition)}>
- <EditIcon />
- </ButtonIcon>
- </td>
- <td>
- <DeleteButton onClick={() => props.onDelete(definition.key)} />
- </td>
+ {definitions.length === 0 ? (
+ <tr>
+ <td colSpan={5}>{translate('settings.pr_decoration.table.empty.github')}</td>
</tr>
- ))}
+ ) : (
+ definitions.map(definition => (
+ <tr key={definition.key}>
+ <td className="nowrap hide-overflow" title={definition.key}>
+ {definition.key}
+ </td>
+ <td className="nowrap hide-overflow" title={definition.url}>
+ {definition.url}
+ </td>
+ <td className="nowrap hide-overflow" title={definition.appId}>
+ {definition.appId}
+ </td>
+ <td className="text-center">
+ <ButtonIcon onClick={() => props.onEdit(definition)}>
+ <EditIcon />
+ </ButtonIcon>
+ </td>
+ <td className="text-center">
+ <DeleteButton onClick={() => props.onDelete(definition.key)} />
+ </td>
+ </tr>
+ ))
+ )}
</tbody>
</table>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx
index 680fa4a6aab..2e006acec97 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx
@@ -22,7 +22,6 @@ import BoxedTabs from 'sonar-ui-common/components/controls/BoxedTabs';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { AlmSettingsBindingDefinitions, ALM_KEYS } from '../../../../types/alm-settings';
-import { almName } from '../../utils';
import AzureTab from './AzureTab';
import BitbucketTab from './BitbucketTab';
import DeleteModal from './DeleteModal';
@@ -41,6 +40,12 @@ export interface PRDecorationTabsProps {
projectCount?: number;
}
+export const almName = {
+ [ALM_KEYS.AZURE]: 'Azure DevOps Server',
+ [ALM_KEYS.BITBUCKET]: 'Bitbucket Server',
+ [ALM_KEYS.GITHUB]: 'Github Enterprise'
+};
+
export default function PRDecorationTabs(props: PRDecorationTabsProps) {
const { definitionKeyForDeletion, definitions, currentAlm, loading, projectCount } = props;
@@ -64,7 +69,7 @@ export default function PRDecorationTabs(props: PRDecorationTabsProps) {
<img
alt="github"
className="spacer-right"
- src={`${getBaseUrl()}/images/sonarcloud/github.svg`}
+ src={`${getBaseUrl()}/images/alm/github.svg`}
width={16}
/>
{almName[ALM_KEYS.GITHUB]}
@@ -78,7 +83,7 @@ export default function PRDecorationTabs(props: PRDecorationTabsProps) {
<img
alt="bitbucket"
className="spacer-right"
- src={`${getBaseUrl()}/images/sonarcloud/bitbucket.svg`}
+ src={`${getBaseUrl()}/images/alm/bitbucket.svg`}
width={16}
/>
{almName[ALM_KEYS.BITBUCKET]}
@@ -92,7 +97,7 @@ export default function PRDecorationTabs(props: PRDecorationTabsProps) {
<img
alt="azure"
className="spacer-right"
- src={`${getBaseUrl()}/images/sonarcloud/azure.svg`}
+ src={`${getBaseUrl()}/images/alm/azure.svg`}
width={16}
/>
{almName[ALM_KEYS.AZURE]}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx
index a30e8533ede..2d90411888e 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx
@@ -24,7 +24,7 @@ import { AlmDefinitionFormField, AlmDefinitionFormFieldProps } from '../AlmDefin
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
- expect(shallowRender({ help: true })).toMatchSnapshot();
+ expect(shallowRender({ help: 'help' })).toMatchSnapshot();
expect(shallowRender({ isTextArea: true })).toMatchSnapshot();
});
@@ -45,13 +45,12 @@ it('should call onFieldChange', () => {
function shallowRender(props: Partial<AlmDefinitionFormFieldProps<AlmSettingsBinding>> = {}) {
return shallow(
<AlmDefinitionFormField
- formData={{ key: 'key' }}
- help={false}
id="key"
isTextArea={false}
maxLength={40}
onFieldChange={jest.fn()}
propKey="key"
+ value="key"
{...props}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap
index 21d0c24cc8e..0d975f13e19 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap
@@ -43,7 +43,8 @@ exports[`should render correctly 2`] = `
*
</em>
<HelpTooltip
- overlay="settings.pr_decoration.form.key.help"
+ overlay="help"
+ placement="right"
/>
</label>
<input
@@ -76,7 +77,7 @@ exports[`should render correctly 3`] = `
</label>
<textarea
className="settings-large-input"
- id="privateKey"
+ id="key"
maxLength={40}
onChange={[Function]}
required={true}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap
index ec50eab5e05..4629360ad17 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap
@@ -4,32 +4,19 @@ exports[`should render correctly 1`] = `
<Fragment>
<AlmDefinitionFormField
autoFocus={true}
- formData={
- Object {
- "key": "",
- "personalAccessToken": "",
- }
- }
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help="settings.pr_decoration.form.azure.name.help"
+ id="azure.name"
onFieldChange={[MockFunction]}
propKey="key"
+ value=""
/>
<AlmDefinitionFormField
- formData={
- Object {
- "key": "",
- "personalAccessToken": "",
- }
- }
- help={true}
+ help="settings.pr_decoration.form.personal_access_token.help"
id="personal_access_token"
isTextArea={true}
- maxLength={2000}
onFieldChange={[MockFunction]}
propKey="personalAccessToken"
+ value=""
/>
</Fragment>
`;
@@ -38,32 +25,19 @@ exports[`should render correctly 2`] = `
<Fragment>
<AlmDefinitionFormField
autoFocus={true}
- formData={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- }
- }
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help="settings.pr_decoration.form.azure.name.help"
+ id="azure.name"
onFieldChange={[MockFunction]}
propKey="key"
+ value="key"
/>
<AlmDefinitionFormField
- formData={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- }
- }
- help={true}
+ help="settings.pr_decoration.form.personal_access_token.help"
id="personal_access_token"
isTextArea={true}
- maxLength={2000}
onFieldChange={[MockFunction]}
propKey="personalAccessToken"
+ value="asdf1234"
/>
</Fragment>
`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap
index 769cf16ba05..8e5d8722a57 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap
@@ -7,8 +7,15 @@ exports[`should render correctly 1`] = `
onCreate={[MockFunction]}
/>
<DeferredSpinner
+ loading={true}
timeout={100}
- />
+ >
+ <AzureTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
</Fragment>
`;
@@ -18,11 +25,16 @@ exports[`should render correctly 2`] = `
alm="azure"
onCreate={[MockFunction]}
/>
- <AzureTable
- definitions={Array []}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <AzureTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
</Fragment>
`;
@@ -32,11 +44,16 @@ exports[`should render correctly 3`] = `
alm="azure"
onCreate={[MockFunction]}
/>
- <AzureTable
- definitions={Array []}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <AzureTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
<AlmPRDecorationFormModal
bindingDefinition={
Object {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap
index 05b1adfd0be..167cec1a957 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap
@@ -2,7 +2,7 @@
exports[`should render correctly 1`] = `
<table
- className="data zebra spacer-bottom"
+ className="data zebra fixed spacer-bottom"
>
<thead>
<tr>
@@ -10,12 +10,12 @@ exports[`should render correctly 1`] = `
settings.pr_decoration.table.column.name
</th>
<th
- className="thin"
+ className="action-small text-center"
>
settings.pr_decoration.table.column.edit
</th>
<th
- className="thin"
+ className="action text-center"
>
settings.pr_decoration.table.column.delete
</th>
@@ -35,7 +35,7 @@ exports[`should render correctly 1`] = `
exports[`should render correctly 2`] = `
<table
- className="data zebra spacer-bottom"
+ className="data zebra fixed spacer-bottom"
>
<thead>
<tr>
@@ -43,12 +43,12 @@ exports[`should render correctly 2`] = `
settings.pr_decoration.table.column.name
</th>
<th
- className="thin"
+ className="action-small text-center"
>
settings.pr_decoration.table.column.edit
</th>
<th
- className="thin"
+ className="action text-center"
>
settings.pr_decoration.table.column.delete
</th>
@@ -58,17 +58,24 @@ exports[`should render correctly 2`] = `
<tr
key="key"
>
- <td>
+ <td
+ className="nowrap hide-overflow"
+ title="key"
+ >
key
</td>
- <td>
+ <td
+ className="text-center"
+ >
<ButtonIcon
onClick={[Function]}
>
<EditIcon />
</ButtonIcon>
</td>
- <td>
+ <td
+ className="text-center"
+ >
<DeleteButton
onClick={[Function]}
/>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap
index f1fb7f72c31..9b90ffbbaba 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap
@@ -4,49 +4,37 @@ exports[`should render correctly 1`] = `
<Fragment>
<AlmDefinitionFormField
autoFocus={true}
- formData={
- Object {
- "key": "",
- "personalAccessToken": "",
- "url": "",
- }
- }
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help="settings.pr_decoration.form.url.bitbucket.name.help"
+ id="bitbucket.name"
+ maxLength={100}
onFieldChange={[MockFunction]}
propKey="key"
+ value=""
/>
<AlmDefinitionFormField
- formData={
- Object {
- "key": "",
- "personalAccessToken": "",
- "url": "",
- }
+ help={
+ <FormattedMessage
+ defaultMessage="settings.pr_decoration.form.url.bitbucket.help"
+ id="settings.pr_decoration.form.url.bitbucket.help"
+ values={
+ Object {
+ "example": "https://bitbucket-server.your-company.com",
+ }
+ }
+ />
}
- help={false}
id="url.bitbucket"
- isTextArea={false}
maxLength={2000}
onFieldChange={[MockFunction]}
propKey="url"
+ value=""
/>
<AlmDefinitionFormField
- formData={
- Object {
- "key": "",
- "personalAccessToken": "",
- "url": "",
- }
- }
- help={false}
id="personal_access_token"
isTextArea={true}
- maxLength={2000}
onFieldChange={[MockFunction]}
propKey="personalAccessToken"
+ value=""
/>
</Fragment>
`;
@@ -55,49 +43,37 @@ exports[`should render correctly 2`] = `
<Fragment>
<AlmDefinitionFormField
autoFocus={true}
- formData={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- "url": "http://bbs.enterprise.com",
- }
- }
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help="settings.pr_decoration.form.url.bitbucket.name.help"
+ id="bitbucket.name"
+ maxLength={100}
onFieldChange={[MockFunction]}
propKey="key"
+ value="key"
/>
<AlmDefinitionFormField
- formData={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- "url": "http://bbs.enterprise.com",
- }
+ help={
+ <FormattedMessage
+ defaultMessage="settings.pr_decoration.form.url.bitbucket.help"
+ id="settings.pr_decoration.form.url.bitbucket.help"
+ values={
+ Object {
+ "example": "https://bitbucket-server.your-company.com",
+ }
+ }
+ />
}
- help={false}
id="url.bitbucket"
- isTextArea={false}
maxLength={2000}
onFieldChange={[MockFunction]}
propKey="url"
+ value="http://bbs.enterprise.com"
/>
<AlmDefinitionFormField
- formData={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- "url": "http://bbs.enterprise.com",
- }
- }
- help={false}
id="personal_access_token"
isTextArea={true}
- maxLength={2000}
onFieldChange={[MockFunction]}
propKey="personalAccessToken"
+ value="asdf1234"
/>
</Fragment>
`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap
index 033e8cb82ec..e8d9c8283b9 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap
@@ -7,8 +7,15 @@ exports[`should render correctly 1`] = `
onCreate={[MockFunction]}
/>
<DeferredSpinner
+ loading={true}
timeout={100}
- />
+ >
+ <BitbucketTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
</Fragment>
`;
@@ -18,11 +25,16 @@ exports[`should render correctly 2`] = `
alm="bitbucket"
onCreate={[MockFunction]}
/>
- <BitbucketTable
- definitions={Array []}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <BitbucketTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
</Fragment>
`;
@@ -32,11 +44,16 @@ exports[`should render correctly 3`] = `
alm="bitbucket"
onCreate={[MockFunction]}
/>
- <BitbucketTable
- definitions={Array []}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <BitbucketTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
<AlmPRDecorationFormModal
bindingDefinition={
Object {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap
index 95b21970235..8af449d84b7 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap
@@ -2,7 +2,7 @@
exports[`should render correctly 1`] = `
<table
- className="data zebra spacer-bottom"
+ className="data zebra fixed spacer-bottom"
>
<thead>
<tr>
@@ -13,12 +13,12 @@ exports[`should render correctly 1`] = `
settings.pr_decoration.table.column.bitbucket.url
</th>
<th
- className="thin"
+ className="action-small text-center"
>
settings.pr_decoration.table.column.edit
</th>
<th
- className="thin"
+ className="action text-center"
>
settings.pr_decoration.table.column.delete
</th>
@@ -38,7 +38,7 @@ exports[`should render correctly 1`] = `
exports[`should render correctly 2`] = `
<table
- className="data zebra spacer-bottom"
+ className="data zebra fixed spacer-bottom"
>
<thead>
<tr>
@@ -49,12 +49,12 @@ exports[`should render correctly 2`] = `
settings.pr_decoration.table.column.bitbucket.url
</th>
<th
- className="thin"
+ className="action-small text-center"
>
settings.pr_decoration.table.column.edit
</th>
<th
- className="thin"
+ className="action text-center"
>
settings.pr_decoration.table.column.delete
</th>
@@ -64,20 +64,30 @@ exports[`should render correctly 2`] = `
<tr
key="key"
>
- <td>
+ <td
+ className="nowrap hide-overflow"
+ title="key"
+ >
key
</td>
- <td>
+ <td
+ className="nowrap hide-overflow"
+ title="http://bbs.enterprise.com"
+ >
http://bbs.enterprise.com
</td>
- <td>
+ <td
+ className="text-center"
+ >
<ButtonIcon
onClick={[Function]}
>
<EditIcon />
</ButtonIcon>
</td>
- <td>
+ <td
+ className="text-center"
+ >
<DeleteButton
onClick={[Function]}
/>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap
index 9cdbcc5b7f3..61ea7a13a8b 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap
@@ -4,68 +4,43 @@ exports[`should render correctly 1`] = `
<Fragment>
<AlmDefinitionFormField
autoFocus={true}
- formData={
- Object {
- "appId": "",
- "key": "",
- "privateKey": "",
- "url": "",
- }
- }
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help="settings.pr_decoration.form.github.name.help"
+ id="github.name"
onFieldChange={[MockFunction]}
propKey="key"
+ value=""
/>
<AlmDefinitionFormField
- formData={
- Object {
- "appId": "",
- "key": "",
- "privateKey": "",
- "url": "",
- }
+ help={
+ <FormattedMessage
+ defaultMessage="settings.pr_decoration.form.url.github.help"
+ id="settings.pr_decoration.form.url.github.help"
+ values={
+ Object {
+ "example": "https://github.company.com/api/v3",
+ }
+ }
+ />
}
- help={false}
id="url.github"
- isTextArea={false}
maxLength={2000}
onFieldChange={[MockFunction]}
propKey="url"
+ value=""
/>
<AlmDefinitionFormField
- formData={
- Object {
- "appId": "",
- "key": "",
- "privateKey": "",
- "url": "",
- }
- }
- help={false}
id="app_id"
- isTextArea={false}
maxLength={80}
onFieldChange={[MockFunction]}
propKey="appId"
+ value=""
/>
<AlmDefinitionFormField
- formData={
- Object {
- "appId": "",
- "key": "",
- "privateKey": "",
- "url": "",
- }
- }
- help={false}
id="private_key"
isTextArea={true}
- maxLength={2000}
onFieldChange={[MockFunction]}
propKey="privateKey"
+ value=""
/>
</Fragment>
`;
@@ -74,68 +49,43 @@ exports[`should render correctly 2`] = `
<Fragment>
<AlmDefinitionFormField
autoFocus={true}
- formData={
- Object {
- "appId": "123456",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
- }
- }
- help={true}
- id="name"
- isTextArea={false}
- maxLength={40}
+ help="settings.pr_decoration.form.github.name.help"
+ id="github.name"
onFieldChange={[MockFunction]}
propKey="key"
+ value="key"
/>
<AlmDefinitionFormField
- formData={
- Object {
- "appId": "123456",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
- }
+ help={
+ <FormattedMessage
+ defaultMessage="settings.pr_decoration.form.url.github.help"
+ id="settings.pr_decoration.form.url.github.help"
+ values={
+ Object {
+ "example": "https://github.company.com/api/v3",
+ }
+ }
+ />
}
- help={false}
id="url.github"
- isTextArea={false}
maxLength={2000}
onFieldChange={[MockFunction]}
propKey="url"
+ value="http://github.enterprise.com"
/>
<AlmDefinitionFormField
- formData={
- Object {
- "appId": "123456",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
- }
- }
- help={false}
id="app_id"
- isTextArea={false}
maxLength={80}
onFieldChange={[MockFunction]}
propKey="appId"
+ value="123456"
/>
<AlmDefinitionFormField
- formData={
- Object {
- "appId": "123456",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
- }
- }
- help={false}
id="private_key"
isTextArea={true}
- maxLength={2000}
onFieldChange={[MockFunction]}
propKey="privateKey"
+ value="asdf1234"
/>
</Fragment>
`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap
index 032b06c1f53..f37d1b20090 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap
@@ -7,8 +7,15 @@ exports[`should render correctly 1`] = `
onCreate={[MockFunction]}
/>
<DeferredSpinner
+ loading={true}
timeout={100}
- />
+ >
+ <GithubTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
</Fragment>
`;
@@ -18,11 +25,16 @@ exports[`should render correctly 2`] = `
alm="github"
onCreate={[MockFunction]}
/>
- <GithubTable
- definitions={Array []}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <GithubTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
</Fragment>
`;
@@ -32,11 +44,16 @@ exports[`should render correctly 3`] = `
alm="github"
onCreate={[MockFunction]}
/>
- <GithubTable
- definitions={Array []}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <GithubTable
+ definitions={Array []}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
<AlmPRDecorationFormModal
bindingDefinition={
Object {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap
index 9284ab59d0f..e2180fa9773 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap
@@ -2,7 +2,7 @@
exports[`should render correctly 1`] = `
<table
- className="data zebra spacer-bottom"
+ className="data zebra fixed spacer-bottom"
>
<thead>
<tr>
@@ -16,24 +16,32 @@ exports[`should render correctly 1`] = `
settings.pr_decoration.table.column.app_id
</th>
<th
- className="thin"
+ className="action-small text-center"
>
settings.pr_decoration.table.column.edit
</th>
<th
- className="thin"
+ className="action text-center"
>
settings.pr_decoration.table.column.delete
</th>
</tr>
</thead>
- <tbody />
+ <tbody>
+ <tr>
+ <td
+ colSpan={5}
+ >
+ settings.pr_decoration.table.empty.github
+ </td>
+ </tr>
+ </tbody>
</table>
`;
exports[`should render correctly 2`] = `
<table
- className="data zebra spacer-bottom"
+ className="data zebra fixed spacer-bottom"
>
<thead>
<tr>
@@ -47,12 +55,12 @@ exports[`should render correctly 2`] = `
settings.pr_decoration.table.column.app_id
</th>
<th
- className="thin"
+ className="action-small text-center"
>
settings.pr_decoration.table.column.edit
</th>
<th
- className="thin"
+ className="action text-center"
>
settings.pr_decoration.table.column.delete
</th>
@@ -62,23 +70,36 @@ exports[`should render correctly 2`] = `
<tr
key="key"
>
- <td>
+ <td
+ className="nowrap hide-overflow"
+ title="key"
+ >
key
</td>
- <td>
+ <td
+ className="nowrap hide-overflow"
+ title="http://github.enterprise.com"
+ >
http://github.enterprise.com
</td>
- <td>
+ <td
+ className="nowrap hide-overflow"
+ title="123456"
+ >
123456
</td>
- <td>
+ <td
+ className="text-center"
+ >
<ButtonIcon
onClick={[Function]}
>
<EditIcon />
</ButtonIcon>
</td>
- <td>
+ <td
+ className="text-center"
+ >
<DeleteButton
onClick={[Function]}
/>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap
index 277eec9e944..410c129e995 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap
@@ -27,7 +27,7 @@ exports[`should render correctly 1`] = `
<img
alt="github"
className="spacer-right"
- src="/images/sonarcloud/github.svg"
+ src="/images/alm/github.svg"
width={16}
/>
Github Enterprise
@@ -39,7 +39,7 @@ exports[`should render correctly 1`] = `
<img
alt="bitbucket"
className="spacer-right"
- src="/images/sonarcloud/bitbucket.svg"
+ src="/images/alm/bitbucket.svg"
width={16}
/>
Bitbucket Server
@@ -51,7 +51,7 @@ exports[`should render correctly 1`] = `
<img
alt="azure"
className="spacer-right"
- src="/images/sonarcloud/azure.svg"
+ src="/images/alm/azure.svg"
width={16}
/>
Azure DevOps Server
@@ -100,7 +100,7 @@ exports[`should render correctly 2`] = `
<img
alt="github"
className="spacer-right"
- src="/images/sonarcloud/github.svg"
+ src="/images/alm/github.svg"
width={16}
/>
Github Enterprise
@@ -112,7 +112,7 @@ exports[`should render correctly 2`] = `
<img
alt="bitbucket"
className="spacer-right"
- src="/images/sonarcloud/bitbucket.svg"
+ src="/images/alm/bitbucket.svg"
width={16}
/>
Bitbucket Server
@@ -124,7 +124,7 @@ exports[`should render correctly 2`] = `
<img
alt="azure"
className="spacer-right"
- src="/images/sonarcloud/azure.svg"
+ src="/images/alm/azure.svg"
width={16}
/>
Azure DevOps Server
@@ -178,7 +178,7 @@ exports[`should render correctly 3`] = `
<img
alt="github"
className="spacer-right"
- src="/images/sonarcloud/github.svg"
+ src="/images/alm/github.svg"
width={16}
/>
Github Enterprise
@@ -190,7 +190,7 @@ exports[`should render correctly 3`] = `
<img
alt="bitbucket"
className="spacer-right"
- src="/images/sonarcloud/bitbucket.svg"
+ src="/images/alm/bitbucket.svg"
width={16}
/>
Bitbucket Server
@@ -202,7 +202,7 @@ exports[`should render correctly 3`] = `
<img
alt="azure"
className="spacer-right"
- src="/images/sonarcloud/azure.svg"
+ src="/images/alm/azure.svg"
width={16}
/>
Azure DevOps Server
@@ -251,7 +251,7 @@ exports[`should render correctly 4`] = `
<img
alt="github"
className="spacer-right"
- src="/images/sonarcloud/github.svg"
+ src="/images/alm/github.svg"
width={16}
/>
Github Enterprise
@@ -263,7 +263,7 @@ exports[`should render correctly 4`] = `
<img
alt="bitbucket"
className="spacer-right"
- src="/images/sonarcloud/bitbucket.svg"
+ src="/images/alm/bitbucket.svg"
width={16}
/>
Bitbucket Server
@@ -275,7 +275,7 @@ exports[`should render correctly 4`] = `
<img
alt="azure"
className="spacer-right"
- src="/images/sonarcloud/azure.svg"
+ src="/images/alm/azure.svg"
width={16}
/>
Azure DevOps Server
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx
index aae3dc9a12b..e5f40286a53 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx
@@ -36,30 +36,24 @@ interface Props {
interface State {
formData: ProjectAlmBinding;
- hasBinding: boolean;
instances: AlmSettingsInstance[];
isValid: boolean;
loading: boolean;
+ originalData?: ProjectAlmBinding;
saving: boolean;
success: boolean;
}
-const FIELDS_BY_ALM: {
- [almKey: string]: Array<'repository' | 'repositoryKey' | 'repositorySlug'>;
-} = {
+const FIELDS_BY_ALM: { [almKey in ALM_KEYS]: Array<keyof T.Omit<ProjectAlmBinding, 'key'>> } = {
[ALM_KEYS.AZURE]: [],
- [ALM_KEYS.BITBUCKET]: ['repositoryKey', 'repositorySlug'],
+ [ALM_KEYS.BITBUCKET]: ['repository', 'slug'],
[ALM_KEYS.GITHUB]: ['repository']
};
export default class PRDecorationBinding extends React.PureComponent<Props, State> {
mounted = false;
state: State = {
- formData: {
- key: '',
- repository: ''
- },
- hasBinding: false,
+ formData: { key: '' },
instances: [],
isValid: false,
loading: true,
@@ -79,22 +73,18 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
fetchDefinitions = () => {
const project = this.props.component.key;
return Promise.all([getAlmSettings(project), this.getProjectBinding(project)])
- .then(([instances, data]) => {
+ .then(([instances, originalData]) => {
if (this.mounted) {
this.setState(({ formData }) => {
- const newFormData = data || formData;
+ const newFormData = originalData || formData;
return {
formData: newFormData,
- hasBinding: Boolean(data),
instances,
isValid: this.validateForm(newFormData),
- loading: false
+ loading: false,
+ originalData
};
});
-
- if (!data && instances.length === 1) {
- this.handleFieldChange('key', instances[0].key);
- }
}
})
.catch(() => {
@@ -104,7 +94,7 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
});
};
- getProjectBinding(project: string) {
+ getProjectBinding(project: string): Promise<ProjectAlmBinding | undefined> {
return getProjectAlmBinding(project).catch((response: Response) => {
if (response && response.status === 404) {
return Promise.resolve(undefined);
@@ -128,9 +118,10 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
this.setState({
formData: {
key: '',
- repository: ''
+ repository: '',
+ slug: ''
},
- hasBinding: false,
+ originalData: undefined,
saving: false,
success: true
});
@@ -142,7 +133,7 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
submitProjectAlmBinding(
alm: ALM_KEYS,
key: string,
- almSpecificFields?: { repository?: string; repositoryKey?: string; repositorySlug?: string }
+ almSpecificFields?: T.Omit<ProjectAlmBinding, 'key'>
): Promise<void> {
const almSetting = key;
const project = this.props.component.key;
@@ -157,12 +148,12 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
if (!almSpecificFields) {
return Promise.reject();
}
- const { repositoryKey = '', repositorySlug = '' } = almSpecificFields;
+ const { repository = '', slug = '' } = almSpecificFields;
return setProjectBitbucketBinding({
almSetting,
project,
- repositoryKey,
- repositorySlug
+ repository,
+ slug
});
}
case ALM_KEYS.GITHUB: {
@@ -198,12 +189,12 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
.then(() => {
if (this.mounted) {
this.setState({
- hasBinding: true,
saving: false,
success: true
});
}
})
+ .then(this.fetchDefinitions)
.catch(this.catchError);
}
};
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx
index db5aeb9d6e0..7a1eb479ada 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx
@@ -31,19 +31,26 @@ import { AlmSettingsInstance, ALM_KEYS, ProjectAlmBinding } from '../../../../ty
export interface PRDecorationBindingRendererProps {
formData: ProjectAlmBinding;
- hasBinding: boolean;
instances: AlmSettingsInstance[];
isValid: boolean;
loading: boolean;
onFieldChange: (id: keyof ProjectAlmBinding, value: string) => void;
onReset: () => void;
onSubmit: () => void;
+ originalData?: ProjectAlmBinding;
saving: boolean;
success: boolean;
}
-function renderLabel(v: AlmSettingsInstance) {
- return v.url ? `${v.key} — ${v.url}` : v.key;
+function optionRenderer(instance: AlmSettingsInstance) {
+ return instance.url ? (
+ <>
+ <span>{instance.key} — </span>
+ <span className="text-muted">{instance.url}</span>
+ </>
+ ) : (
+ <span>{instance.key}</span>
+ );
}
function renderField(props: {
@@ -86,13 +93,20 @@ function renderField(props: {
);
}
+function isDataSame(
+ { key, repository = '', slug = '' }: ProjectAlmBinding,
+ { key: oKey = '', repository: oRepository = '', slug: oSlug = '' }: ProjectAlmBinding
+) {
+ return key === oKey && repository === oRepository && slug === oSlug;
+}
+
export default function PRDecorationBindingRenderer(props: PRDecorationBindingRendererProps) {
const {
- formData: { key, repository, repositoryKey, repositorySlug },
- hasBinding,
+ formData: { key, repository, slug },
instances,
isValid,
loading,
+ originalData,
saving,
success
} = props;
@@ -124,6 +138,8 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
const selected = key && instances.find(i => i.key === key);
const alm = selected && selected.alm;
+ const isChanged = !isDataSame({ key, repository, slug }, originalData || { key: '' });
+
return (
<div>
<header className="page-header">
@@ -145,13 +161,21 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
<em className="mandatory spacer-right">*</em>
</label>
<Select
+ autosize={true}
className="abs-width-400"
clearable={false}
id="name"
- onChange={({ value }: { value: string }) => props.onFieldChange('key', value)}
- options={instances.map(v => ({ value: v.key, label: renderLabel(v) }))}
+ menuContainerStyle={{
+ maxWidth: '210%' /* Allow double the width of the select */,
+ width: 'auto'
+ }}
+ onChange={(instance: AlmSettingsInstance) => props.onFieldChange('key', instance.key)}
+ optionRenderer={optionRenderer}
+ options={instances}
searchable={false}
value={key}
+ valueKey="key"
+ valueRenderer={optionRenderer}
/>
</div>
@@ -168,10 +192,10 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
</>
)
},
- id: 'repository_key',
+ id: 'bitbucket.repository',
onFieldChange: props.onFieldChange,
- propKey: 'repositoryKey',
- value: repositoryKey || ''
+ propKey: 'repository',
+ value: repository || ''
})}
{renderField({
help: true,
@@ -184,10 +208,10 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
</>
)
},
- id: 'repository_slug',
+ id: 'bitbucket.slug',
onFieldChange: props.onFieldChange,
- propKey: 'repositorySlug',
- value: repositorySlug || ''
+ propKey: 'slug',
+ value: slug || ''
})}
</>
)}
@@ -196,7 +220,7 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
renderField({
help: true,
helpParams: { example: 'SonarSource/sonarqube' },
- id: 'repository',
+ id: 'github.repository',
onFieldChange: props.onFieldChange,
propKey: 'repository',
value: repository || ''
@@ -204,10 +228,12 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
<div className="display-flex-center">
<DeferredSpinner className="spacer-right" loading={saving} />
- <SubmitButton className="spacer-right" disabled={saving || !isValid}>
- {translate('save')}
- </SubmitButton>
- {hasBinding && (
+ {isChanged && (
+ <SubmitButton className="spacer-right button-success" disabled={saving || !isValid}>
+ {translate('save')}
+ </SubmitButton>
+ )}
+ {originalData && (
<Button className="spacer-right" onClick={props.onReset}>
{translate('reset_verb')}
</Button>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx
index 54ee550816d..cf9904ebff3 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx
@@ -64,23 +64,9 @@ it('should fill selects and fill formdata', async () => {
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
- expect(wrapper.state().hasBinding).toBe(true);
expect(wrapper.state().loading).toBe(false);
expect(wrapper.state().formData).toEqual(formdata);
-});
-
-it('should preselect url and key if only 1 item', async () => {
- const instances = [{ key: 'instance1', url: 'github.enterprise.com', alm: 'github' }];
- (getAlmSettings as jest.Mock).mockResolvedValueOnce(instances);
- (getProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status: 404 });
-
- const wrapper = shallowRender();
- await waitAndUpdate(wrapper);
-
- expect(wrapper.state().formData).toEqual({
- key: instances[0].key,
- repository: ''
- });
+ expect(wrapper.state().originalData).toEqual(formdata);
});
const formData = {
@@ -97,63 +83,67 @@ it('should handle reset', async () => {
await waitAndUpdate(wrapper);
expect(deleteProjectAlmBinding).toBeCalledWith(PROJECT_KEY);
- expect(wrapper.state().formData).toEqual({ key: '', repository: '' });
- expect(wrapper.state().hasBinding).toBe(false);
+ expect(wrapper.state().formData).toEqual({ key: '', repository: '', slug: '' });
+ expect(wrapper.state().originalData).toBeUndefined();
});
-it('should handle submit to github, azure or bitbucket', async () => {
- const wrapper = shallowRender();
- await waitAndUpdate(wrapper);
+describe('handleSubmit', () => {
const instances = [
{ key: 'github', alm: ALM_KEYS.GITHUB },
{ key: 'azure', alm: ALM_KEYS.AZURE },
{ key: 'bitbucket', alm: ALM_KEYS.BITBUCKET }
];
- // Github
- const githubKey = 'github';
- const repository = 'repo/path';
- wrapper.setState({ formData: { key: githubKey, repository }, instances });
- wrapper.instance().handleSubmit();
- await waitAndUpdate(wrapper);
-
- expect(setProjectGithubBinding).toBeCalledWith({
- almSetting: githubKey,
- project: PROJECT_KEY,
- repository
+ it('should work for github', async () => {
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ const githubKey = 'github';
+ const repository = 'repo/path';
+ wrapper.setState({ formData: { key: githubKey, repository }, instances });
+ wrapper.instance().handleSubmit();
+ await waitAndUpdate(wrapper);
+
+ expect(setProjectGithubBinding).toBeCalledWith({
+ almSetting: githubKey,
+ project: PROJECT_KEY,
+ repository
+ });
+ expect(wrapper.state().success).toBe(true);
});
- expect(wrapper.state().hasBinding).toBe(true);
- expect(wrapper.state().success).toBe(true);
-
- // azure
- const azureKey = 'azure';
- wrapper.setState({ formData: { key: azureKey } });
- wrapper.instance().handleSubmit();
- await waitAndUpdate(wrapper);
- expect(setProjectAzureBinding).toBeCalledWith({
- almSetting: azureKey,
- project: PROJECT_KEY
+ it('should work for azure', async () => {
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ const azureKey = 'azure';
+ wrapper.setState({ formData: { key: azureKey }, instances });
+ wrapper.instance().handleSubmit();
+ await waitAndUpdate(wrapper);
+
+ expect(setProjectAzureBinding).toBeCalledWith({
+ almSetting: azureKey,
+ project: PROJECT_KEY
+ });
+ expect(wrapper.state().success).toBe(true);
});
- expect(wrapper.state().hasBinding).toBe(true);
- expect(wrapper.state().success).toBe(true);
-
- // bitbucket
- const bitbucketKey = 'bitbucket';
- const repositoryKey = 'repoKey';
- const repositorySlug = 'repoSlug';
- wrapper.setState({ formData: { key: bitbucketKey, repositoryKey, repositorySlug } });
- wrapper.instance().handleSubmit();
- await waitAndUpdate(wrapper);
- expect(setProjectBitbucketBinding).toBeCalledWith({
- almSetting: bitbucketKey,
- project: PROJECT_KEY,
- repositoryKey,
- repositorySlug
+ it('should work for bitbucket', async () => {
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ const bitbucketKey = 'bitbucket';
+ const repository = 'repoKey';
+ const slug = 'repoSlug';
+ wrapper.setState({ formData: { key: bitbucketKey, repository, slug }, instances });
+ wrapper.instance().handleSubmit();
+ await waitAndUpdate(wrapper);
+
+ expect(setProjectBitbucketBinding).toBeCalledWith({
+ almSetting: bitbucketKey,
+ project: PROJECT_KEY,
+ repository,
+ slug
+ });
+ expect(wrapper.state().success).toBe(true);
});
- expect(wrapper.state().hasBinding).toBe(true);
- expect(wrapper.state().success).toBe(true);
});
it('should handle failures gracefully', async () => {
@@ -185,8 +175,7 @@ it('should handle field changes', async () => {
wrapper.instance().handleFieldChange('key', 'instance2');
await waitAndUpdate(wrapper);
expect(wrapper.state().formData).toEqual({
- key: 'instance2',
- repository: ''
+ key: 'instance2'
});
wrapper.instance().handleFieldChange('repository', repository);
@@ -216,11 +205,9 @@ it('should validate form', async () => {
expect(wrapper.instance().validateForm({ key: 'github', repository: '' })).toBe(false);
expect(wrapper.instance().validateForm({ key: 'github', repository: 'asdf' })).toBe(true);
- expect(wrapper.instance().validateForm({ key: 'bitbucket', repositoryKey: 'key' })).toBe(false);
+ expect(wrapper.instance().validateForm({ key: 'bitbucket', repository: 'key' })).toBe(false);
expect(
- wrapper
- .instance()
- .validateForm({ key: 'bitbucket', repositoryKey: 'key', repositorySlug: 'slug' })
+ wrapper.instance().validateForm({ key: 'bitbucket', repository: 'key', slug: 'slug' })
).toBe(true);
});
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx
index bd26eabf33c..b49dddc5d50 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx
@@ -82,9 +82,12 @@ it('should render multiple instances correctly', () => {
key: 'i1',
repository: 'account/repo'
},
- hasBinding: true,
instances,
- loading: false
+ loading: false,
+ originalData: {
+ key: 'i1',
+ repository: 'account/repo'
+ }
})
).toMatchSnapshot();
});
@@ -111,13 +114,13 @@ function shallowRender(props: Partial<PRDecorationBindingRendererProps> = {}) {
key: '',
repository: ''
}}
- hasBinding={false}
instances={[]}
isValid={false}
loading={true}
onFieldChange={jest.fn()}
onReset={jest.fn()}
onSubmit={jest.fn()}
+ originalData={undefined}
saving={false}
success={false}
{...props}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap
index 7e98cac6379..499ffbfa605 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap
@@ -5,10 +5,8 @@ exports[`should render correctly 1`] = `
formData={
Object {
"key": "",
- "repository": "",
}
}
- hasBinding={false}
instances={Array []}
isValid={false}
loading={true}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap
index 9d704e6ba4f..ede66c1ee1e 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap
@@ -33,20 +33,31 @@ exports[`should display action state correctly 1`] = `
</em>
</label>
<Select
+ autosize={true}
className="abs-width-400"
clearable={false}
id="name"
+ menuContainerStyle={
+ Object {
+ "maxWidth": "210%",
+ "width": "auto",
+ }
+ }
onChange={[Function]}
+ optionRenderer={[Function]}
options={
Array [
Object {
- "label": "key — http://url.com",
- "value": "key",
+ "alm": "github",
+ "key": "key",
+ "url": "http://url.com",
},
]
}
searchable={false}
value=""
+ valueKey="key"
+ valueRenderer={[Function]}
/>
</div>
<div
@@ -57,12 +68,6 @@ exports[`should display action state correctly 1`] = `
loading={true}
timeout={100}
/>
- <SubmitButton
- className="spacer-right"
- disabled={true}
- >
- save
- </SubmitButton>
</div>
</form>
</div>
@@ -101,20 +106,31 @@ exports[`should display action state correctly 2`] = `
</em>
</label>
<Select
+ autosize={true}
className="abs-width-400"
clearable={false}
id="name"
+ menuContainerStyle={
+ Object {
+ "maxWidth": "210%",
+ "width": "auto",
+ }
+ }
onChange={[Function]}
+ optionRenderer={[Function]}
options={
Array [
Object {
- "label": "key — http://url.com",
- "value": "key",
+ "alm": "github",
+ "key": "key",
+ "url": "http://url.com",
},
]
}
searchable={false}
value=""
+ valueKey="key"
+ valueRenderer={[Function]}
/>
</div>
<div
@@ -125,12 +141,6 @@ exports[`should display action state correctly 2`] = `
loading={false}
timeout={100}
/>
- <SubmitButton
- className="spacer-right"
- disabled={true}
- >
- save
- </SubmitButton>
<span
className="text-success"
>
@@ -177,20 +187,31 @@ exports[`should display action state correctly 3`] = `
</em>
</label>
<Select
+ autosize={true}
className="abs-width-400"
clearable={false}
id="name"
+ menuContainerStyle={
+ Object {
+ "maxWidth": "210%",
+ "width": "auto",
+ }
+ }
onChange={[Function]}
+ optionRenderer={[Function]}
options={
Array [
Object {
- "label": "key — http://url.com",
- "value": "key",
+ "alm": "github",
+ "key": "key",
+ "url": "http://url.com",
},
]
}
searchable={false}
value=""
+ valueKey="key"
+ valueRenderer={[Function]}
/>
</div>
<div
@@ -201,12 +222,6 @@ exports[`should display action state correctly 3`] = `
loading={false}
timeout={100}
/>
- <SubmitButton
- className="spacer-right"
- disabled={false}
- >
- save
- </SubmitButton>
</div>
</form>
</div>
@@ -276,32 +291,45 @@ exports[`should render multiple instances correctly 1`] = `
</em>
</label>
<Select
+ autosize={true}
className="abs-width-400"
clearable={false}
id="name"
+ menuContainerStyle={
+ Object {
+ "maxWidth": "210%",
+ "width": "auto",
+ }
+ }
onChange={[Function]}
+ optionRenderer={[Function]}
options={
Array [
Object {
- "label": "i1 — http://github.enterprise.com",
- "value": "i1",
+ "alm": "github",
+ "key": "i1",
+ "url": "http://github.enterprise.com",
},
Object {
- "label": "i2 — http://github.enterprise.com",
- "value": "i2",
+ "alm": "github",
+ "key": "i2",
+ "url": "http://github.enterprise.com",
},
Object {
- "label": "i3 — http://bbs.enterprise.com",
- "value": "i3",
+ "alm": "bitbucket",
+ "key": "i3",
+ "url": "http://bbs.enterprise.com",
},
Object {
- "label": "i4",
- "value": "i4",
+ "alm": "azure",
+ "key": "i4",
},
]
}
searchable={false}
value=""
+ valueKey="key"
+ valueRenderer={[Function]}
/>
</div>
<div
@@ -312,12 +340,6 @@ exports[`should render multiple instances correctly 1`] = `
loading={false}
timeout={100}
/>
- <SubmitButton
- className="spacer-right"
- disabled={true}
- >
- save
- </SubmitButton>
</div>
</form>
</div>
@@ -356,32 +378,45 @@ exports[`should render multiple instances correctly 2`] = `
</em>
</label>
<Select
+ autosize={true}
className="abs-width-400"
clearable={false}
id="name"
+ menuContainerStyle={
+ Object {
+ "maxWidth": "210%",
+ "width": "auto",
+ }
+ }
onChange={[Function]}
+ optionRenderer={[Function]}
options={
Array [
Object {
- "label": "i1 — http://github.enterprise.com",
- "value": "i1",
+ "alm": "github",
+ "key": "i1",
+ "url": "http://github.enterprise.com",
},
Object {
- "label": "i2 — http://github.enterprise.com",
- "value": "i2",
+ "alm": "github",
+ "key": "i2",
+ "url": "http://github.enterprise.com",
},
Object {
- "label": "i3 — http://bbs.enterprise.com",
- "value": "i3",
+ "alm": "bitbucket",
+ "key": "i3",
+ "url": "http://bbs.enterprise.com",
},
Object {
- "label": "i4",
- "value": "i4",
+ "alm": "azure",
+ "key": "i4",
},
]
}
searchable={false}
value="i1"
+ valueKey="key"
+ valueRenderer={[Function]}
/>
</div>
<div
@@ -389,9 +424,9 @@ exports[`should render multiple instances correctly 2`] = `
>
<label
className="display-flex-center"
- htmlFor="repository"
+ htmlFor="github.repository"
>
- settings.pr_decoration.binding.form.repository
+ settings.pr_decoration.binding.form.github.repository
<em
className="mandatory spacer-right"
>
@@ -400,8 +435,8 @@ exports[`should render multiple instances correctly 2`] = `
<HelpTooltip
overlay={
<FormattedMessage
- defaultMessage="settings.pr_decoration.binding.form.repository.help"
- id="settings.pr_decoration.binding.form.repository.help"
+ defaultMessage="settings.pr_decoration.binding.form.github.repository.help"
+ id="settings.pr_decoration.binding.form.github.repository.help"
values={
Object {
"example": "SonarSource/sonarqube",
@@ -414,9 +449,9 @@ exports[`should render multiple instances correctly 2`] = `
</label>
<input
className="input-super-large"
- id="repository"
+ id="github.repository"
maxLength={256}
- name="repository"
+ name="github.repository"
onChange={[Function]}
type="text"
value="account/repo"
@@ -430,12 +465,6 @@ exports[`should render multiple instances correctly 2`] = `
loading={false}
timeout={100}
/>
- <SubmitButton
- className="spacer-right"
- disabled={true}
- >
- save
- </SubmitButton>
<Button
className="spacer-right"
onClick={[MockFunction]}
@@ -480,20 +509,31 @@ exports[`should render single instance correctly 1`] = `
</em>
</label>
<Select
+ autosize={true}
className="abs-width-400"
clearable={false}
id="name"
+ menuContainerStyle={
+ Object {
+ "maxWidth": "210%",
+ "width": "auto",
+ }
+ }
onChange={[Function]}
+ optionRenderer={[Function]}
options={
Array [
Object {
- "label": "single — http://single.url",
- "value": "single",
+ "alm": "github",
+ "key": "single",
+ "url": "http://single.url",
},
]
}
searchable={false}
value=""
+ valueKey="key"
+ valueRenderer={[Function]}
/>
</div>
<div
@@ -504,12 +544,6 @@ exports[`should render single instance correctly 1`] = `
loading={false}
timeout={100}
/>
- <SubmitButton
- className="spacer-right"
- disabled={true}
- >
- save
- </SubmitButton>
</div>
</form>
</div>
diff --git a/server/sonar-web/src/main/js/apps/settings/utils.ts b/server/sonar-web/src/main/js/apps/settings/utils.ts
index 72c3c0756e2..997b649e124 100644
--- a/server/sonar-web/src/main/js/apps/settings/utils.ts
+++ b/server/sonar-web/src/main/js/apps/settings/utils.ts
@@ -19,16 +19,9 @@
*/
import { sanitize } from 'dompurify';
import { hasMessage, translate } from 'sonar-ui-common/helpers/l10n';
-import { ALM_KEYS } from '../../types/alm-settings';
export const DEFAULT_CATEGORY = 'general';
-export const almName = {
- [ALM_KEYS.AZURE]: 'Azure DevOps Server',
- [ALM_KEYS.BITBUCKET]: 'Bitbucket Server',
- [ALM_KEYS.GITHUB]: 'Github Enterprise'
-};
-
export type DefaultSpecializedInputProps = T.Omit<DefaultInputProps, 'setting'> & {
isDefault: boolean;
name: string;
diff --git a/server/sonar-web/src/main/js/types/alm-settings.ts b/server/sonar-web/src/main/js/types/alm-settings.ts
index f2153fe214f..c7d6b5d6114 100644
--- a/server/sonar-web/src/main/js/types/alm-settings.ts
+++ b/server/sonar-web/src/main/js/types/alm-settings.ts
@@ -57,8 +57,7 @@ export interface GithubBindingDefinition extends AlmSettingsBinding {
export interface ProjectAlmBinding {
key: string;
repository?: string;
- repositoryKey?: string;
- repositorySlug?: string;
+ slug?: string;
}
export interface AzureProjectAlmBinding {
@@ -69,8 +68,8 @@ export interface AzureProjectAlmBinding {
export interface BitbucketProjectAlmBinding {
almSetting: string;
project: string;
- repositoryKey: string;
- repositorySlug: string;
+ repository: string;
+ slug: string;
}
export interface GithubProjectAlmBinding {