From 52db191b96cdd311706bbf19ced0647d8cad09fe Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Thu, 29 Oct 2020 18:20:21 +0100 Subject: [PATCH] SONAR-13988 better handle errors --- .../AlmBindingDefinitionBox.tsx | 138 +++-- .../AlmBindingDefinitionForm.tsx | 78 +-- .../AlmBindingDefinitionFormRenderer.tsx | 97 --- .../AlmBindingDefinitionsTable.tsx | 104 ---- .../almIntegration/AlmIntegration.tsx | 25 +- .../AlmIntegrationFeatureBox.tsx | 67 -- .../components/almIntegration/AlmTab.tsx | 20 +- .../almIntegration/AlmTabRenderer.tsx | 213 +++---- .../components/almIntegration/AzureTab.tsx | 9 - .../almIntegration/BitbucketTab.tsx | 38 +- .../components/almIntegration/GithubTab.tsx | 63 -- .../components/almIntegration/GitlabTab.tsx | 48 -- .../AlmBindingDefinitionBox-test.tsx | 29 +- .../AlmBindingDefinitionForm-test.tsx | 9 +- .../AlmBindingDefinitionFormRenderer-test.tsx | 68 -- .../AlmBindingDefinitionsTable-test.tsx | 80 --- .../__tests__/AlmIntegration-test.tsx | 30 +- .../AlmIntegrationFeatureBox-test.tsx | 39 -- .../__tests__/AlmTabRenderer-test.tsx | 18 - .../AlmBindingDefinitionBox-test.tsx.snap | 372 +++++------ .../AlmBindingDefinitionForm-test.tsx.snap | 14 +- ...indingDefinitionFormRenderer-test.tsx.snap | 160 ----- .../AlmBindingDefinitionsTable-test.tsx.snap | 304 --------- .../AlmIntegrationFeatureBox-test.tsx.snap | 97 --- .../__snapshots__/AlmTab-test.tsx.snap | 2 - .../AlmTabRenderer-test.tsx.snap | 579 +++++++++++------- .../__snapshots__/AzureTab-test.tsx.snap | 10 - .../__snapshots__/BitbucketTab-test.tsx.snap | 44 -- .../__snapshots__/GithubTab-test.tsx.snap | 64 -- .../__snapshots__/GitlabTab-test.tsx.snap | 132 ---- .../src/main/js/helpers/mocks/alm-settings.ts | 7 +- .../src/main/js/types/alm-settings.ts | 13 +- .../resources/org/sonar/l10n/core.properties | 44 +- 33 files changed, 802 insertions(+), 2213 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionsTable.tsx delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationFeatureBox.tsx delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionsTable-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationFeatureBox-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionsTable-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationFeatureBox-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx index e335ab9ebbe..74203d53f70 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx @@ -20,16 +20,23 @@ import * as React from 'react'; import { Button } from 'sonar-ui-common/components/controls/buttons'; import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip'; +import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; import AlertErrorIcon from 'sonar-ui-common/components/icons/AlertErrorIcon'; import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon'; import DeleteIcon from 'sonar-ui-common/components/icons/DeleteIcon'; import EditIcon from 'sonar-ui-common/components/icons/EditIcon'; import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { AlmBindingDefinition, AlmSettingsBindingStatus } from '../../../../types/alm-settings'; +import { + AlmBindingDefinition, + AlmKeys, + AlmSettingsBindingStatus, + AlmSettingsBindingStatusType +} from '../../../../types/alm-settings'; +import { VALIDATED_ALMS } from './utils'; export interface AlmBindingDefinitionBoxProps { + alm: AlmKeys; definition: AlmBindingDefinition; multipleDefinitions: boolean; onCheck: (definitionKey: string) => void; @@ -38,9 +45,21 @@ export interface AlmBindingDefinitionBoxProps { status?: AlmSettingsBindingStatus; } -const DEFAULT_STATUS = { alert: false, errorMessage: '', validating: true }; +const DEFAULT_STATUS: AlmSettingsBindingStatus = { + alertSuccess: false, + failureMessage: '', + type: AlmSettingsBindingStatusType.Validating +}; -function getImportFeatureStatus(multipleDefinitions: boolean, error: boolean) { +const STATUS_ICON = { + [AlmSettingsBindingStatusType.Failure]: , + [AlmSettingsBindingStatusType.Success]: +}; + +function getImportFeatureStatus( + multipleDefinitions: boolean, + type: AlmSettingsBindingStatusType.Success | AlmSettingsBindingStatusType.Failure +) { if (multipleDefinitions) { return (
@@ -54,16 +73,22 @@ function getImportFeatureStatus(multipleDefinitions: boolean, error: boolean) {
); } else { - return error ? ( - - ) : ( - - ); + return STATUS_ICON[type]; } } export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxProps) { - const { definition, multipleDefinitions, status = DEFAULT_STATUS } = props; + const { alm, definition, multipleDefinitions, status = DEFAULT_STATUS } = props; + + const importFeatureTitle = + alm === AlmKeys.GitLab + ? translate('settings.almintegration.feature.mr_decoration.title') + : translate('settings.almintegration.feature.pr_decoration.title'); + + const importFeatureDescription = + alm === AlmKeys.GitLab + ? translate('settings.almintegration.feature.mr_decoration.description') + : translate('settings.almintegration.feature.pr_decoration.description'); return (
@@ -83,41 +108,74 @@ export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxPr {definition.url && {definition.url}}
- - - {translate('settings.almintegration.checking_configuration')} - - } - loading={status.validating}> -
-
- {translate('settings.almintegration.feature.pr_decoration.title')} - {status.errorMessage ? ( - - ) : ( - - )} -
-
- {translate('settings.almintegration.feature.alm_repo_import.title')} - {getImportFeatureStatus(multipleDefinitions, Boolean(status.errorMessage))} + {!VALIDATED_ALMS.includes(alm) && ( + <> +
+ + {importFeatureTitle} + +
-
- {status.alert && (
- - {status.errorMessage || translate('settings.almintegration.configuration_valid')} - + {translate('settings.almintegration.no_validation')}
- )} + + )} - - + {VALIDATED_ALMS.includes(alm) && + (status.type === AlmSettingsBindingStatusType.Validating ? ( + <> + + {translate('settings.almintegration.checking_configuration')} + + ) : ( + <> + {status.type !== AlmSettingsBindingStatusType.Warning && ( +
+ +
+ {importFeatureTitle} + {STATUS_ICON[status.type]} +
+
+
+ + + {translate('settings.almintegration.feature.alm_repo_import.title')} + + + {getImportFeatureStatus(multipleDefinitions, status.type)} +
+
+ )} + +
+ {status.type === AlmSettingsBindingStatusType.Warning && ( + + {translate('settings.almintegration.could_not_validate')} + + )} + + {status.type === AlmSettingsBindingStatusType.Failure && ( + {status.failureMessage} + )} + + {status.type === AlmSettingsBindingStatusType.Success && status.alertSuccess && ( + + {translate('settings.almintegration.configuration_valid')} + + )} +
+ + + + ))}
); } diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx index a0c132fbf8f..ad555bc1bbe 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx @@ -21,7 +21,6 @@ import { isEqual, omit } from 'lodash'; import * as React from 'react'; import { AlmBindingDefinition } from '../../../../types/alm-settings'; import AlmBindingDefinitionFormModalRenderer from './AlmBindingDefinitionFormModalRenderer'; -import AlmBindingDefinitionFormRenderer from './AlmBindingDefinitionFormRenderer'; export interface AlmBindingDefinitionFormChildrenProps { formData: B; @@ -36,15 +35,11 @@ interface Props { help?: React.ReactNode; hideKeyField?: boolean; isSecondInstance?: boolean; - loading?: boolean; onCancel?: () => void; onDelete?: (definitionKey: string) => void; onEdit?: (definitionKey: string) => void; onSubmit: (data: B, originalKey: string) => void; optionalFields?: Array; - readOnly?: boolean; - showInModal?: boolean; - success?: boolean; } interface State { @@ -118,59 +113,24 @@ export default class AlmBindingDefinitionForm< }; render() { - const { - bindingDefinition, - children, - help, - hideKeyField, - isSecondInstance, - showInModal, - loading = false, - readOnly = false, - success = false - } = this.props; - const { formData, touched } = this.state; - - if (showInModal) { - const action = bindingDefinition.key ? 'edit' : 'create'; - - return ( - - {children({ - formData, - onFieldChange: this.handleFieldChange - })} - - ); - } else { - const showEdit = this.props.onEdit !== undefined; - const showCancel = touched || !showEdit; - const showDelete = showEdit && this.props.onDelete !== undefined; - - return ( - - {children({ - formData, - hideKeyField, - onFieldChange: this.handleFieldChange, - readOnly - })} - - ); - } + const { bindingDefinition, children, help, isSecondInstance } = this.props; + const { formData } = this.state; + + const action = bindingDefinition.key ? 'edit' : 'create'; + + return ( + + {children({ + formData, + onFieldChange: this.handleFieldChange + })} + + ); } } diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx deleted file mode 100644 index 812ba48a61a..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { Button, ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/controls/buttons'; -import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate } from 'sonar-ui-common/helpers/l10n'; - -export interface AlmBindingDefinitionFormRendererProps { - canSubmit: () => boolean; - children: React.ReactNode; - help?: React.ReactNode; - onCancel?: () => void; - onDelete?: () => void; - onEdit?: () => void; - onSubmit: () => void; - loading: boolean; - success: boolean; -} - -export default function AlmBindingDefinitionFormRenderer( - props: AlmBindingDefinitionFormRendererProps -) { - const { children, help, loading, success } = props; - - return ( -
) => { - e.preventDefault(); - props.onSubmit(); - }}> -
-
- {children} - -
- {props.onEdit === undefined ? ( - - {translate('settings.almintegration.form.save')} - - ) : ( - - )} - {props.onDelete && ( - - )} - {props.onCancel && ( - - {translate('cancel')} - - )} - {loading && } - {!loading && success && ( - - - {translate('settings.state.saved')} - - )} -
-
- - {help && ( - - {help} - - )} -
-
- ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionsTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionsTable.tsx deleted file mode 100644 index c1bcc5bb36f..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionsTable.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { Button, ButtonIcon, DeleteButton } from 'sonar-ui-common/components/controls/buttons'; -import EditIcon from 'sonar-ui-common/components/icons/EditIcon'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { AlmKeys } from '../../../../types/alm-settings'; - -export interface AlmBindingDefinitionsTableProps { - additionalColumnsHeaders: Array; - additionalTableInfo?: React.ReactNode; - alm: AlmKeys; - definitions: Array<{ - key: string; - additionalColumns: Array; - }>; - loading: boolean; - onCreate: () => void; - onDelete: (definitionKey: string) => void; - onEdit: (definitionKey: string) => void; -} - -export default function AlmBindingDefinitionsTable(props: AlmBindingDefinitionsTableProps) { - const { additionalColumnsHeaders, additionalTableInfo, alm, definitions, loading } = props; - - return ( - <> -
-

- {translate('settings.almintegration.table.title')} -

- -
- - {additionalTableInfo} - - - - - - {additionalColumnsHeaders.map(h => ( - - ))} - - - - - - {definitions.length === 0 ? ( - - - - ) : ( - definitions.map(({ key, additionalColumns }) => ( - - - {additionalColumns.map(value => ( - - ))} - - - - )) - )} - -
{translate('settings.almintegration.table.column.name')}{h} - {translate('settings.almintegration.table.column.edit')} - - {translate('settings.almintegration.table.column.delete')} -
- {translate('settings.almintegration.table.empty', alm)} -
- {key} - - {value} - - props.onEdit(key)}> - - - - props.onDelete(key)} /> -
- - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx index a985b48f733..ed6c0c964f0 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx @@ -29,7 +29,8 @@ import { AlmBindingDefinition, AlmKeys, AlmSettingsBindingDefinitions, - AlmSettingsBindingStatus + AlmSettingsBindingStatus, + AlmSettingsBindingStatusType } from '../../../../types/alm-settings'; import AlmIntegrationRenderer from './AlmIntegrationRenderer'; import { VALIDATED_ALMS } from './utils'; @@ -151,20 +152,30 @@ export class AlmIntegration extends React.PureComponent { this.setState(({ definitionStatus }) => { definitionStatus[definitionKey] = { ...definitionStatus[definitionKey], - validating: true + type: AlmSettingsBindingStatusType.Validating }; return { definitionStatus: { ...definitionStatus } }; }); - const errorMessage = await validateAlmSettings(definitionKey).catch(() => undefined); + let type: AlmSettingsBindingStatusType; + let failureMessage = ''; - if (this.mounted && errorMessage !== undefined) { + try { + failureMessage = await validateAlmSettings(definitionKey); + type = failureMessage + ? AlmSettingsBindingStatusType.Failure + : AlmSettingsBindingStatusType.Success; + } catch (_) { + type = AlmSettingsBindingStatusType.Warning; + } + + if (this.mounted) { this.setState(({ definitionStatus }) => { definitionStatus[definitionKey] = { - alert: alertSuccess || Boolean(errorMessage), - errorMessage, - validating: false + alertSuccess, + failureMessage, + type }; return { definitionStatus: { ...definitionStatus } }; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationFeatureBox.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationFeatureBox.tsx deleted file mode 100644 index dfdeb10bbd5..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationFeatureBox.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as classNames from 'classnames'; -import * as React from 'react'; -import CheckIcon from 'sonar-ui-common/components/icons/CheckIcon'; -import ClearIcon from 'sonar-ui-common/components/icons/ClearIcon'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { colors } from '../../../../app/theme'; - -export interface AlmIntegrationFeatureBoxProps { - active: boolean; - description: React.ReactNode; - inactiveReason?: React.ReactNode; - name: React.ReactNode; -} - -export default function AlmIntegrationFeatureBox(props: AlmIntegrationFeatureBoxProps) { - const { active, description, inactiveReason, name } = props; - - return ( -
- {active ? ( - - ) : ( - - )} -
-

{name}

- -
{description}
- -
- {active ? ( - {translate('settings.almintegration.feature.enabled')} - ) : ( - - {inactiveReason || translate('settings.almintegration.feature.disabled')} - - )} -
-
-
- ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx index d603bd64027..34a31756ac7 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx @@ -24,19 +24,15 @@ import { AlmSettingsBindingStatus } from '../../../../types/alm-settings'; import { AlmBindingDefinitionFormChildrenProps } from './AlmBindingDefinitionForm'; -import { AlmIntegrationFeatureBoxProps } from './AlmIntegrationFeatureBox'; import AlmTabRenderer from './AlmTabRenderer'; +import { VALIDATED_ALMS } from './utils'; interface Props { alm: AlmKeys; - additionalColumnsHeaders?: string[]; - additionalColumnsKeys?: Array; - additionalTableInfo?: React.ReactNode; createConfiguration: (data: B) => Promise; defaultBinding: B; definitions: B[]; definitionStatus: T.Dict; - features?: AlmIntegrationFeatureBoxProps[]; form: (props: AlmBindingDefinitionFormChildrenProps) => React.ReactNode; help?: React.ReactNode; loadingAlmDefinitions: boolean; @@ -101,7 +97,11 @@ export default class AlmTab extends React.PureCo } }) .then(this.props.onUpdateDefinitions) - .then(() => this.props.onCheck(config.key)) + .then(() => { + if (VALIDATED_ALMS.includes(this.props.alm)) { + this.props.onCheck(config.key); + } + }) .catch(() => { if (this.mounted) { this.setState({ submitting: false, success: false }); @@ -111,14 +111,10 @@ export default class AlmTab extends React.PureCo render() { const { - additionalColumnsHeaders = [], - additionalColumnsKeys = [], - additionalTableInfo, alm, defaultBinding, definitions, definitionStatus, - features, form, help, loadingAlmDefinitions, @@ -130,15 +126,11 @@ export default class AlmTab extends React.PureCo return ( { - additionalColumnsHeaders: string[]; - additionalColumnsKeys: Array; - additionalTableInfo?: React.ReactNode; alm: AlmKeys; definitionStatus: T.Dict; editedDefinition?: B; defaultBinding: B; definitions: B[]; - features?: AlmIntegrationFeatureBoxProps[]; form: (props: AlmBindingDefinitionFormChildrenProps) => React.ReactNode; help?: React.ReactNode; loadingAlmDefinitions: boolean; @@ -64,154 +58,99 @@ export interface AlmTabRendererProps { success: boolean; } -function renderListOfDefinitions(props: AlmTabRendererProps) { - const { - additionalColumnsHeaders, - additionalColumnsKeys, - additionalTableInfo, - alm, - definitions, - definitionStatus, - loadingProjectCount - } = props; - - if (VALIDATED_ALMS.includes(alm)) { - return ( - <> -
- -
- {definitions.map(def => ( - 1} - onCheck={props.onCheck} - onDelete={props.onDelete} - onEdit={props.onEdit} - status={definitionStatus[def.key]} - /> - ))} - - ); - } - - const mappedDefinitions = definitions.map(({ key, ...properties }) => { - const additionalColumns = additionalColumnsKeys.map(k => (properties as any)[k]); - return { - key, - additionalColumns - }; - }); - - return ( - - ); -} +const renderDefaultHelp = (alm: AlmKeys) => ( + + {translate('learn_more')} + + ) + }} + /> +); export default function AlmTabRenderer( props: AlmTabRendererProps ) { const { alm, - defaultBinding, definitions, + definitionStatus, editedDefinition, - features = [], form, loadingAlmDefinitions, loadingProjectCount, multipleAlmEnabled, optionalFields, - submitting, - success, - help = ( - - {translate('learn_more')} - - ) - }} - /> - ) + help = renderDefaultHelp(alm) } = props; - let definition: B | undefined; - let showEdit: boolean | undefined; - - if (!multipleAlmEnabled) { - definition = editedDefinition; - if (definition === undefined && definitions.length > 0) { - definition = definitions[0]; - } - showEdit = definition && editedDefinition === undefined; - } + const preventCreation = loadingProjectCount || (!multipleAlmEnabled && definitions.length > 0); + const creationTooltip = preventCreation ? ( + + {translate('settings.almintegration.create.tooltip.link')} + + ), + alm: translate('alm', alm) + }} + /> + ) : null; return (
- {multipleAlmEnabled ? ( - - {renderListOfDefinitions(props)} - - {editedDefinition && ( - - {form} - - )} - - ) : ( - - {form} - - )} - - {!VALIDATED_ALMS.includes(alm) && features.length > 0 && ( -
-

{translate('settings.almintegration.features')}

+ + {definitions.length === 0 && ( +

{translate('settings.almintegration.empty', alm)}

+ )} -
- {features.map((feature, i) => ( - - ))} -
+
0 ? 'spacer-bottom text-right' : 'big-spacer-top'}> + + +
- )} + {definitions.map(def => ( + 1} + onCheck={props.onCheck} + onDelete={props.onDelete} + onEdit={props.onEdit} + status={definitionStatus[def.key]} + /> + ))} + + {editedDefinition && ( + + {form} + + )} +
); } diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx index f727d695c2d..f6998962796 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx @@ -18,7 +18,6 @@ * 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 { createAzureConfiguration, updateAzureConfiguration } from '../../../../api/alm-settings'; import { AlmKeys, @@ -56,14 +55,6 @@ export default function AzureTab(props: AzureTabProps) { defaultBinding={{ key: '', personalAccessToken: '' }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.pr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.pr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - } - ]} form={childProps => } loadingAlmDefinitions={loadingAlmDefinitions} loadingProjectCount={loadingProjectCount} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx index 4fc261cfb92..fa0aa6c5950 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx @@ -18,10 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; import { Link } from 'react-router'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; +import { translate } from 'sonar-ui-common/helpers/l10n'; import { createBitbucketConfiguration, updateBitbucketConfiguration @@ -57,45 +55,11 @@ export default function BitbucketTab(props: BitbucketTabProps) { return (
- {translate('settings.almintegration.feature.alm_repo_import.title')} - ) - }} - /> - - } alm={AlmKeys.Bitbucket} createConfiguration={createBitbucketConfiguration} defaultBinding={{ key: '', url: '', personalAccessToken: '' }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.pr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.pr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - }, - { - name: translate('settings.almintegration.feature.alm_repo_import.title'), - active: definitions.length === 1, - description: translate('settings.almintegration.feature.alm_repo_import.description'), - inactiveReason: translateWithParameters( - 'settings.almintegration.feature.alm_repo_import.bitbucket.wrong_count_x', - definitions.length - ) - } - ]} form={childProps => } help={ <> diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx index a44d2e8813e..214f0b87286 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx @@ -18,10 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import WarningIcon from 'sonar-ui-common/components/icons/WarningIcon'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; import { createGithubConfiguration, updateGithubConfiguration } from '../../../../api/alm-settings'; import { AlmKeys, @@ -62,26 +58,6 @@ export default function GithubTab(props: GithubTabProps) { {branchesEnabled && ( <> - {translate('settings.almintegration.feature.alm_repo_import.title')} - ) - }} - /> - - } alm={AlmKeys.GitHub} createConfiguration={createGithubConfiguration} defaultBinding={{ @@ -94,45 +70,6 @@ export default function GithubTab(props: GithubTabProps) { }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.pr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.pr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - }, - { - name: translate('settings.almintegration.feature.alm_repo_import.title'), - active: - definitions.length === 1 && - !!definitions[0].clientId && - !!definitions[0].clientSecret, - description: translate( - 'settings.almintegration.feature.alm_repo_import.description' - ), - inactiveReason: - definitions.length === 1 ? ( - <> - - clientId, - clientSecret: clientSecret - }} - /> - - ) : ( - translateWithParameters( - 'settings.almintegration.feature.alm_repo_import.github.wrong_count_x', - definitions.length - ) - ) - } - ]} form={childProps => } loadingAlmDefinitions={loadingAlmDefinitions} loadingProjectCount={loadingProjectCount} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx index db7558480d0..552891d9358 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx @@ -18,9 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; import { createGitlabConfiguration, updateGitlabConfiguration } from '../../../../api/alm-settings'; import { AlmKeys, @@ -56,61 +53,16 @@ export default function GitlabTab(props: GitlabTabProps) { loadingProjectCount } = props; - const importFeatureEnabled = Boolean(definitions.length === 1 && definitions[0].url); - return (
{branchesEnabled && ( <> - {translate('settings.almintegration.feature.alm_repo_import.title')} - ) - }} - /> - - } alm={AlmKeys.GitLab} createConfiguration={createGitlabConfiguration} defaultBinding={{ key: '', personalAccessToken: '', url: '' }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.mr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.mr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - }, - { - name: translate('settings.almintegration.feature.alm_repo_import.title'), - active: importFeatureEnabled, - description: translate( - 'settings.almintegration.feature.alm_repo_import.description' - ), - inactiveReason: - definitions.length === 1 - ? translate( - 'settings.almintegration.feature.alm_repo_import.gitlab.requires_fields' - ) - : translateWithParameters( - 'settings.almintegration.feature.alm_repo_import.gitlab.wrong_count_x', - definitions.length - ) - } - ]} form={childProps => } loadingAlmDefinitions={loadingAlmDefinitions} loadingProjectCount={loadingProjectCount} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx index d8c9cbb93d4..89fe0fe5f77 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx @@ -21,44 +21,57 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockAlmSettingsBindingStatus, + mockAzureBindingDefinition, mockGithubBindingDefinition } from '../../../../../helpers/mocks/alm-settings'; +import { AlmKeys, AlmSettingsBindingStatusType } from '../../../../../types/alm-settings'; import AlmBindingDefinitionBox, { AlmBindingDefinitionBoxProps } from '../AlmBindingDefinitionBox'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot('default'); expect(shallowRender({ multipleDefinitions: true })).toMatchSnapshot('multiple definitions'); expect( - shallowRender({ status: mockAlmSettingsBindingStatus({ errorMessage: '', validating: false }) }) + shallowRender({ + status: mockAlmSettingsBindingStatus({ + type: AlmSettingsBindingStatusType.Success + }) + }) ).toMatchSnapshot('success'); expect( shallowRender({ status: mockAlmSettingsBindingStatus({ - errorMessage: 'Oops, something went wrong', - validating: false + failureMessage: 'Oops, something went wrong', + type: AlmSettingsBindingStatusType.Failure }) }) ).toMatchSnapshot('error'); expect( shallowRender({ - status: mockAlmSettingsBindingStatus({ alert: true, errorMessage: '', validating: false }) + status: mockAlmSettingsBindingStatus({ + alertSuccess: true, + type: AlmSettingsBindingStatusType.Success + }) }) ).toMatchSnapshot('success with alert'); + expect( shallowRender({ status: mockAlmSettingsBindingStatus({ - alert: true, - errorMessage: 'Oops, something went wrong', - validating: false + type: AlmSettingsBindingStatusType.Warning }) }) - ).toMatchSnapshot('error with alert'); + ).toMatchSnapshot('warning'); + + expect( + shallowRender({ alm: AlmKeys.Azure, definition: mockAzureBindingDefinition() }) + ).toMatchSnapshot('Azure DevOps'); }); function shallowRender(props: Partial = {}) { return shallow( { - expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender()).toMatchSnapshot('create'); - expect(shallowRender({ showInModal: true })).toMatchSnapshot('modal'); - expect( - shallowRender({ bindingDefinition: mockGithubBindingDefinition(), showInModal: true }) - ).toMatchSnapshot('modal edit'); + expect(shallowRender({ bindingDefinition: mockGithubBindingDefinition() })).toMatchSnapshot( + 'edit' + ); }); it('should reset if the props change', () => { diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx deleted file mode 100644 index 6774ed436d6..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { SubmitButton } from 'sonar-ui-common/components/controls/buttons'; -import { submit } from 'sonar-ui-common/helpers/testUtils'; -import AlmBindingDefinitionFormRenderer, { - AlmBindingDefinitionFormRendererProps -} from '../AlmBindingDefinitionFormRenderer'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect(shallowRender({ onCancel: jest.fn() })).toMatchSnapshot(); - expect(shallowRender({ onDelete: jest.fn() })).toMatchSnapshot(); - expect(shallowRender({ success: true })).toMatchSnapshot(); - expect(shallowRender({ loading: true })).toMatchSnapshot(); -}); - -it('should correctly block the form submission', () => { - const canSubmit = jest.fn(() => false); - const wrapper = shallowRender({ canSubmit, loading: false }); - - expect(canSubmit).toBeCalled(); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); - - wrapper.setProps({ canSubmit: jest.fn(), loading: true }); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); - - wrapper.setProps({ canSubmit: () => true, loading: false }); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(false); -}); - -it('should correctly submit the form', () => { - const onSubmit = jest.fn(); - const wrapper = shallowRender({ onSubmit }); - submit(wrapper.find('form')); - expect(onSubmit).toBeCalled(); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - {() => null} - - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionsTable-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionsTable-test.tsx deleted file mode 100644 index ab0455f10a9..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionsTable-test.tsx +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { AlmKeys } from '../../../../../types/alm-settings'; -import AlmBindingDefinitionsTable, { - AlmBindingDefinitionsTableProps -} from '../AlmBindingDefinitionsTable'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect( - shallowRender({ - additionalColumnsHeaders: ['additional1', 'additional2'], - alm: AlmKeys.GitHub, - definitions: [ - { key: 'definition1', additionalColumns: ['def1-v1', 'def1-v2'] }, - { key: 'definition2', additionalColumns: ['def2-v1', 'def2-v2'] } - ] - }) - ).toMatchSnapshot('additional columns'); - expect(shallowRender()).toMatchSnapshot('loading'); - expect(shallowRender({ alm: AlmKeys.GitLab })).toMatchSnapshot('title adjusts for GitLab'); -}); - -it('should correctly trigger create, delete, and edit', () => { - const onCreate = jest.fn(); - const onDelete = jest.fn(); - const onEdit = jest.fn(); - - const wrapper = shallowRender({ - additionalColumnsHeaders: [], - alm: AlmKeys.Bitbucket, - definitions: [{ key: 'defKey', additionalColumns: [] }], - onCreate, - onDelete, - onEdit - }); - - wrapper.find('Button').simulate('click'); - expect(onCreate).toBeCalled(); - - wrapper.find('DeleteButton').simulate('click'); - expect(onDelete).toBeCalledWith('defKey'); - - wrapper.find('ButtonIcon').simulate('click'); - expect(onEdit).toBeCalledWith('defKey'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx index fc05d4faaa6..2bb0d844580 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx @@ -26,7 +26,7 @@ import { getAlmDefinitions, validateAlmSettings } from '../../../../../api/alm-settings'; -import { AlmKeys } from '../../../../../types/alm-settings'; +import { AlmKeys, AlmSettingsBindingStatusType } from '../../../../../types/alm-settings'; import { AlmIntegration } from '../AlmIntegration'; jest.mock('../../../../../api/alm-settings', () => ({ @@ -99,38 +99,38 @@ it('should delete configuration', async () => { it('should validate a configuration', async () => { const definitionKey = 'validated-key'; - const errorMessage = 'an error occured'; + const failureMessage = 'an error occured'; const wrapper = shallowRender(); await waitAndUpdate(wrapper); (validateAlmSettings as jest.Mock) - .mockResolvedValueOnce(undefined) - .mockResolvedValueOnce(errorMessage) + .mockRejectedValueOnce(undefined) + .mockResolvedValueOnce(failureMessage) .mockResolvedValueOnce(''); await wrapper.instance().handleCheck(definitionKey); - expect(wrapper.state().definitionStatus[definitionKey]).toEqual( - expect.objectContaining({ - validating: true - }) - ); + expect(wrapper.state().definitionStatus[definitionKey]).toEqual({ + alertSuccess: true, + failureMessage: '', + type: AlmSettingsBindingStatusType.Warning + }); await wrapper.instance().handleCheck(definitionKey); expect(wrapper.state().definitionStatus[definitionKey]).toEqual({ - alert: true, - errorMessage, - validating: false + alertSuccess: true, + failureMessage, + type: AlmSettingsBindingStatusType.Failure }); await wrapper.instance().handleCheck(definitionKey); expect(wrapper.state().definitionStatus[definitionKey]).toEqual({ - alert: true, - errorMessage: '', - validating: false + alertSuccess: true, + failureMessage: '', + type: AlmSettingsBindingStatusType.Success }); }); diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationFeatureBox-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationFeatureBox-test.tsx deleted file mode 100644 index 7366117e6bb..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationFeatureBox-test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -import { shallow } from 'enzyme'; -import * as React from 'react'; -import AlmIntegrationFeatureBox, { - AlmIntegrationFeatureBoxProps -} from '../AlmIntegrationFeatureBox'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ active: false })).toMatchSnapshot('inactive'); - expect(shallowRender({ active: false, inactiveReason: "Bar is foo'd" })).toMatchSnapshot( - 'inactive, with reason' - ); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx index 08e55918d2d..3ee492b7694 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx @@ -42,22 +42,6 @@ it('should render correctly for multi-ALM binding', () => { expect(shallowRenderAzure({ editedDefinition: mockAzureBindingDefinition() })).toMatchSnapshot( 'editing a definition' ); - expect( - shallowRenderAzure({ - features: [ - { - active: true, - name: 'Foo', - description: 'Bar' - }, - { - active: false, - name: 'Baz', - description: 'Bim' - } - ] - }) - ).toMatchSnapshot('with features'); }); it('should render correctly for single-ALM binding', () => { @@ -108,8 +92,6 @@ function shallowRender( ) { return shallow( @@ -31,50 +31,34 @@ exports[`should render correctly: default 1`] = `

key

- - http://github.enterprise.com -
- - - settings.almintegration.checking_configuration -
- } - loading={true} +
-
-
+ settings.almintegration.feature.pr_decoration.title - -
-
- settings.almintegration.feature.alm_repo_import.title - -
-
-
+
+ - settings.almintegration.check_configuration - - + settings.almintegration.no_validation + +
`; -exports[`should render correctly: error 1`] = ` +exports[`should render correctly: default 1`] = `
@@ -109,46 +93,14 @@ exports[`should render correctly: error 1`] = ` http://github.enterprise.com
- - - settings.almintegration.checking_configuration - - } - loading={false} - > -
-
- settings.almintegration.feature.pr_decoration.title - -
-
- settings.almintegration.feature.alm_repo_import.title - -
-
- -
+ + settings.almintegration.checking_configuration `; -exports[`should render correctly: error with alert 1`] = ` +exports[`should render correctly: error 1`] = `
@@ -183,19 +135,11 @@ exports[`should render correctly: error with alert 1`] = ` http://github.enterprise.com
- - - settings.almintegration.checking_configuration - - } - loading={false} +
-
-
- settings.almintegration.feature.alm_repo_import.title - -
-
-
- +
+ - Oops, something went wrong - + + settings.almintegration.feature.alm_repo_import.title + + +
- - + Oops, something went wrong +
+
+
`; @@ -266,52 +216,10 @@ exports[`should render correctly: multiple definitions 1`] = ` http://github.enterprise.com - - - settings.almintegration.checking_configuration - - } - loading={true} - > -
-
- settings.almintegration.feature.pr_decoration.title - -
-
- settings.almintegration.feature.alm_repo_import.title -
- - settings.almintegration.feature.alm_repo_import.disabled - - -
-
-
- -
+ + settings.almintegration.checking_configuration `; @@ -350,19 +258,11 @@ exports[`should render correctly: success 1`] = ` http://github.enterprise.com - - - settings.almintegration.checking_configuration - - } - loading={false} +
-
-
- settings.almintegration.feature.alm_repo_import.title - -
+ +
+ + + settings.almintegration.feature.alm_repo_import.title + + +
- - +
+
+
`; @@ -424,19 +333,11 @@ exports[`should render correctly: success with alert 1`] = ` http://github.enterprise.com
- - - settings.almintegration.checking_configuration - - } - loading={false} +
-
-
- settings.almintegration.feature.alm_repo_import.title - -
-
-
- +
+ - settings.almintegration.configuration_valid - + + settings.almintegration.feature.alm_repo_import.title + + +
+
+
+ + settings.almintegration.configuration_valid + +
+ +
+`; + +exports[`should render correctly: warning 1`] = ` +
+
- + +
+
+

+ key +

+ + http://github.enterprise.com + +
+
+ + settings.almintegration.could_not_validate + +
+
`; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap index e489ff7cef5..525258ed31d 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap @@ -1,16 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render correctly: default 1`] = ` - -`; - -exports[`should render correctly: modal 1`] = ` +exports[`should render correctly: create 1`] = ` `; -exports[`should render correctly: modal edit 1`] = ` +exports[`should render correctly: edit 1`] = ` -
-
- -
- - settings.almintegration.form.save - -
-
-
- -`; - -exports[`should render correctly 2`] = ` -
-
-
- -
- - settings.almintegration.form.save - - - cancel - -
-
-
-
-`; - -exports[`should render correctly 3`] = ` -
-
-
- -
- - settings.almintegration.form.save - - -
-
-
-
-`; - -exports[`should render correctly 4`] = ` -
-
-
- -
- - settings.almintegration.form.save - - - - settings.state.saved - -
-
-
-
-`; - -exports[`should render correctly 5`] = ` -
-
-
- -
- - settings.almintegration.form.save - - -
-
-
-
-`; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionsTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionsTable-test.tsx.snap deleted file mode 100644 index 3f2d55a204c..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionsTable-test.tsx.snap +++ /dev/null @@ -1,304 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -
-

- settings.almintegration.table.title -

- -
- - - - - - - - - - - - - -
- settings.almintegration.table.column.name - - settings.almintegration.table.column.edit - - settings.almintegration.table.column.delete -
- settings.almintegration.table.empty.azure -
-
-`; - -exports[`should render correctly: additional columns 1`] = ` - -
-

- settings.almintegration.table.title -

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- settings.almintegration.table.column.name - - additional1 - - additional2 - - settings.almintegration.table.column.edit - - settings.almintegration.table.column.delete -
- definition1 - - def1-v1 - - def1-v2 - - - - - - -
- definition2 - - def2-v1 - - def2-v2 - - - - - - -
-
-`; - -exports[`should render correctly: loading 1`] = ` - -
-

- settings.almintegration.table.title -

- -
- - - - - - - - - - - - - -
- settings.almintegration.table.column.name - - settings.almintegration.table.column.edit - - settings.almintegration.table.column.delete -
- settings.almintegration.table.empty.azure -
-
-`; - -exports[`should render correctly: title adjusts for GitLab 1`] = ` - -
-

- settings.almintegration.table.title -

- -
- - - - - - - - - - - - - -
- settings.almintegration.table.column.name - - settings.almintegration.table.column.edit - - settings.almintegration.table.column.delete -
- settings.almintegration.table.empty.gitlab -
-
-`; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationFeatureBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationFeatureBox-test.tsx.snap deleted file mode 100644 index 16a177214ae..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationFeatureBox-test.tsx.snap +++ /dev/null @@ -1,97 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` -
- -
-

- Foo -

-
- Foo bar... -
-
- - settings.almintegration.feature.enabled - -
-
-
-`; - -exports[`should render correctly: inactive 1`] = ` -
- -
-

- Foo -

-
- Foo bar... -
-
- - settings.almintegration.feature.disabled - -
-
-
-`; - -exports[`should render correctly: inactive, with reason 1`] = ` -
- -
-

- Foo -

-
- Foo bar... -
-
- - Bar is foo'd - -
-
-
-`; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap index 68d1d8350fa..fc68bb972d1 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap @@ -2,8 +2,6 @@ exports[`should render correctly 1`] = ` - + + + + + @@ -51,7 +65,6 @@ exports[`should render correctly for multi-ALM binding: editing a definition 1`] isSecondInstance={true} onCancel={[MockFunction]} onSubmit={[MockFunction]} - showInModal={true} > @@ -66,19 +79,33 @@ exports[`should render correctly for multi-ALM binding: loaded 1`] = ` - + + + + + @@ -93,19 +120,33 @@ exports[`should render correctly for multi-ALM binding: loading ALM definitions - + + + + + @@ -120,19 +161,50 @@ exports[`should render correctly for multi-ALM binding: loading project count 1` - + + settings.almintegration.create.tooltip.link + , + } + } + /> + } + > + + + + @@ -147,19 +219,33 @@ exports[`should render correctly for multi-ALM binding: submitting 1`] = ` - + + + + + @@ -167,98 +253,61 @@ exports[`should render correctly for multi-ALM binding: submitting 1`] = ` `; -exports[`should render correctly for multi-ALM binding: with features 1`] = ` +exports[`should render correctly for single-ALM binding 1`] = `
- + + settings.almintegration.create.tooltip.link + , + } + } + /> + } + > + + +
+
-
-

- settings.almintegration.features -

-
- - -
-
- -`; - -exports[`should render correctly for single-ALM binding 1`] = ` -
- - learn_more - , - } - } - /> - } - hideKeyField={true} - loading={true} - onCancel={[MockFunction]} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - onSubmit={[MockFunction]} - readOnly={true} - success={false} - > - -
`; @@ -266,42 +315,57 @@ exports[`should render correctly for single-ALM binding 2`] = `
- - learn_more - , - } - } - /> - } - hideKeyField={true} - loading={true} - onCancel={[MockFunction]} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - onSubmit={[MockFunction]} - readOnly={true} - success={false} + - - +
+ + settings.almintegration.create.tooltip.link + , + } + } + /> + } + > + + +
+ +
`; @@ -309,42 +373,57 @@ exports[`should render correctly for single-ALM binding 3`] = `
- - learn_more - , - } - } - /> - } - hideKeyField={true} - loading={true} - onCancel={[MockFunction]} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - onSubmit={[MockFunction]} - readOnly={true} - success={false} + - - +
+ + settings.almintegration.create.tooltip.link + , + } + } + /> + } + > + + +
+ +
`; @@ -358,15 +437,21 @@ exports[`should render correctly with validation 1`] = `
- + +
+

+ settings.almintegration.empty.github +

- + +
@@ -455,15 +549,21 @@ exports[`should render correctly with validation: create a second 1`] = `
- + +
@@ -527,16 +626,26 @@ exports[`should render correctly with validation: empty 1`] = ` +

+ settings.almintegration.empty.github +

- + +
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap index 0ed28e44289..395e569599d 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap @@ -22,16 +22,6 @@ exports[`should render correctly 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.pr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.pr_decoration.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap index 6dc5847e249..2c9e37f15f9 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap @@ -5,34 +5,6 @@ exports[`should render correctly 1`] = ` className="bordered" > - - settings.almintegration.feature.alm_repo_import.title - , - } - } - /> - - } alm="bitbucket" createConfiguration={[Function]} defaultBinding={ @@ -52,22 +24,6 @@ exports[`should render correctly 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.pr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.pr_decoration.title", - }, - Object { - "active": true, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.bitbucket.wrong_count_x.1", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} help={ diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap index 0ab619e3f37..0f9cfaacda4 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap @@ -5,36 +5,6 @@ exports[`should render correctly: with branch support 1`] = ` className="bordered" > - - settings.almintegration.feature.alm_repo_import.title - , - } - } - /> - - } alm="github" createConfiguration={[Function]} defaultBinding={ @@ -60,40 +30,6 @@ exports[`should render correctly: with branch support 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.pr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.pr_decoration.title", - }, - Object { - "active": true, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": - - - clientId - , - "clientSecret": - clientSecret - , - } - } - /> - , - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap index 2ef3faa1a0d..52116b54658 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap @@ -5,34 +5,6 @@ exports[`should render correctly: with URL 1`] = ` className="bordered" > - - settings.almintegration.feature.alm_repo_import.title - , - } - } - /> - - } alm="gitlab" createConfiguration={[Function]} defaultBinding={ @@ -52,22 +24,6 @@ exports[`should render correctly: with URL 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.mr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.mr_decoration.title", - }, - Object { - "active": true, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.gitlab.requires_fields", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} @@ -96,34 +52,6 @@ exports[`should render correctly: with branch support 1`] = ` className="bordered" > - - settings.almintegration.feature.alm_repo_import.title - , - } - } - /> - - } alm="gitlab" createConfiguration={[Function]} defaultBinding={ @@ -142,22 +70,6 @@ exports[`should render correctly: with branch support 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.mr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.mr_decoration.title", - }, - Object { - "active": false, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.gitlab.requires_fields", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} @@ -186,34 +98,6 @@ exports[`should render correctly: with no definitions 1`] = ` className="bordered" > - - settings.almintegration.feature.alm_repo_import.title - , - } - } - /> - - } alm="gitlab" createConfiguration={[Function]} defaultBinding={ @@ -225,22 +109,6 @@ exports[`should render correctly: with no definitions 1`] = ` } definitionStatus={Object {}} definitions={Array []} - features={ - Array [ - Object { - "active": false, - "description": "settings.almintegration.feature.mr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.mr_decoration.title", - }, - Object { - "active": false, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.gitlab.wrong_count_x.0", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} diff --git a/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts b/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts index b2bd99f0432..b4a67f72610 100644 --- a/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts +++ b/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts @@ -20,6 +20,7 @@ import { AlmKeys, AlmSettingsBindingStatus, + AlmSettingsBindingStatusType, AlmSettingsInstance, AzureBindingDefinition, BitbucketBindingDefinition, @@ -135,9 +136,9 @@ export function mockAlmSettingsBindingStatus( overrides: Partial ): AlmSettingsBindingStatus { return { - alert: false, - errorMessage: '', - validating: true, + alertSuccess: false, + failureMessage: '', + type: AlmSettingsBindingStatusType.Validating, ...overrides }; } 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 8cc38476792..09284f3c8c3 100644 --- a/server/sonar-web/src/main/js/types/alm-settings.ts +++ b/server/sonar-web/src/main/js/types/alm-settings.ts @@ -111,7 +111,14 @@ export interface AlmSettingsBindingDefinitions { } export interface AlmSettingsBindingStatus { - alert: boolean; - errorMessage: string; - validating: boolean; + alertSuccess: boolean; + failureMessage: string; + type: AlmSettingsBindingStatusType; +} + +export enum AlmSettingsBindingStatusType { + Validating, + Success, + Failure, + Warning } diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 8272a5f5ef8..3ba74543794 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -355,7 +355,16 @@ Th=Th Fr=Fr Sa=Sa +#------------------------------------------------------------------------------ +# +# ALM +# +#------------------------------------------------------------------------------ +alm.azure=Azure Devops Server +alm.bitbucket=Bitbucket Server +alm.github=Github +alm.gitlab=GitLab #------------------------------------------------------------------------------ # @@ -1047,29 +1056,24 @@ settings.languages.select_a_language_placeholder=Select a language settings.almintegration.title=Integration configurations settings.almintegration.description=ALM integrations allow SonarQube to interact with your ALM. This enables things like authentication, or providing analysis details and a Quality Gate to your Pull Requests directly in your ALM provider's interface. -settings.almintegration.manage_instances=Manage instances settings.almintegration.azure.info=Accounts that will be used to decorate Pull Requests need Code: Read & Write permission. {link} settings.almintegration.github.info=You need to install a GitHub App with specific settings and permissions to enable Pull Request Decoration on your Organization or Repository. {link} settings.almintegration.gitlab.info=Accounts that will be used to decorate Merge Requests need comment permissions on projects. The personal key needs the API scope permission. {link} settings.almintegration.bitbucket.help_1=SonarQube needs a Personal Access Token to communicate with Bitbucket Server. This token will be used to decorate Pull Requests. settings.almintegration.bitbucket.help_2=The account used for integration needs write permission. settings.almintegration.bitbucket.help_3=We recommend to integrate with SonarQube using a Bitbucket Server Service Account. -settings.almintegration.table.title=ALM integration configurations -settings.almintegration.table.empty.azure=Create your first Azure DevOps configuration to enable Pull Request Decoration on your projects. -settings.almintegration.table.empty.bitbucket=Create your first Bitbucket configuration to enable Pull Request Decoration on your projects. -settings.almintegration.table.empty.github=Create your first GitHub configuration to enable Pull Request Decoration on your organization or repository. -settings.almintegration.table.empty.gitlab=Create your first GitLab configuration to enable Merge Request Decoration on your repository. -settings.almintegration.table.create=Create configuration -settings.almintegration.table.column.name=Name -settings.almintegration.table.column.bitbucket.url=Bitbucket Server URL -settings.almintegration.table.column.github.url=GitHub Enterprise or GitHub.com URL -settings.almintegration.table.column.gitlab.url=GitLab Self-Managed or GitLab.com URL -settings.almintegration.table.column.app_id=App ID -settings.almintegration.table.column.edit=Edit -settings.almintegration.table.column.delete=Delete +settings.almintegration.empty.azure=Create your first Azure DevOps configuration to start analyzing your repositories on SonarQube. +settings.almintegration.empty.bitbucket=Create your first Bitbucket configuration to start analyzing your repositories on SonarQube. +settings.almintegration.empty.github=Create your first GitHub configuration to start analyzing your repositories on SonarQube. +settings.almintegration.empty.gitlab=Create your first GitLab configuration to start analyzing your repositories on SonarQube. +settings.almintegration.create=Create configuration +settings.almintegration.create.tooltip=Upgrade to {link} to integrate with multiple {alm} instances. +settings.almintegration.create.tooltip.link=Enterprise Edition settings.almintegration.check_configuration=Check configuration settings.almintegration.checking_configuration=Checking configuration settings.almintegration.configuration_valid=Configuration valid +settings.almintegration.could_not_validate=Could not validate this configuration. +settings.almintegration.no_validation=Pull Request decoration is enabled. However, SonarQube doesn't currently validate Azure DevOps Server configurations. settings.almintegration.delete.header=Delete configuration settings.almintegration.delete.message=Are you sure you want to delete the {id} configuration? settings.almintegration.delete.info={0} projects will no longer get Pull Request Decorations. @@ -1101,10 +1105,6 @@ settings.almintegration.form.personal_access_token.azure.help=Token of the user settings.almintegration.form.personal_access_token.gitlab.help=Token of the user that will be used to decorate the Merge Requests. Needs API scope authorization. settings.almintegration.form.save=Save configuration settings.almintegration.form.cancel=Cancel -settings.almintegration.features=ALM integration features -settings.almintegration.feature.enabled=This feature is enabled -settings.almintegration.feature.disabled=This feature is currently disabled -settings.almintegration.feature.need_at_least_1_binding=You need to have at least 1 binding configured to use this feature settings.almintegration.feature.pr_decoration.title=Pull Request Decoration settings.almintegration.feature.pr_decoration.description=Add analysis and a Quality Gate to your Pull Requests directly in your ALM provider's interface. settings.almintegration.feature.mr_decoration.title=Merge Request Decoration @@ -1113,14 +1113,6 @@ settings.almintegration.feature.alm_repo_import.title=Import repositories from y settings.almintegration.feature.alm_repo_import.description=Select repositories from your ALM, and import them into SonarQube. settings.almintegration.feature.alm_repo_import.disabled=Disabled settings.almintegration.feature.alm_repo_import.help=This feature is disabled because you have 2 or more integration instances configured. -settings.almintegration.feature.alm_repo_import.disabled_if_multiple_bbs_instances=If you have multiple Bitbucket instances connected, you cannot add a project by importing it from a Bitbucket repository, and you'll have to add it manually. -settings.almintegration.feature.alm_repo_import.disabled_if_multiple_github_instances=If you have multiple GitHub instances connected, you cannot add a project by importing it from a GitHub repository, and you'll have to add it manually. -settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances=If you have multiple GitLab instances connected, you cannot add a project by importing it from a GitLab repository, and you'll have to add it manually. -settings.almintegration.feature.alm_repo_import.bitbucket.wrong_count_x=You must have exactly 1 Bitbucket Server instance configured in order to use this method. You currently have {0}. -settings.almintegration.feature.alm_repo_import.github.wrong_count_x=You must have exactly 1 GitHub instance configured in order to use this method. You currently have {0}. -settings.almintegration.feature.alm_repo_import.gitlab.wrong_count_x=You must have exactly 1 GitLab instance configured in order to use this method. You currently have {0}. -settings.almintegration.feature.alm_repo_import.gitlab.requires_fields=Your configured instance must be provided with its API URL. -settings.almintegration.feature.alm_repo_import.github.requires_fields=Your configured instance must be provided with the App's {clientId} and {clientSecret}. settings.pr_decoration.binding.category=Pull Request Decoration settings.pr_decoration.binding.no_bindings=This feature must first be enabled in the global settings. {link} -- 2.39.5