]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14364 Enable project import in CE
authorJeremy Davis <jeremy.davis@sonarsource.com>
Thu, 28 Jan 2021 17:24:21 +0000 (18:24 +0100)
committersonartech <sonartech@sonarsource.com>
Thu, 4 Feb 2021 20:07:08 +0000 (20:07 +0000)
34 files changed:
server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx
server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap
server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenu.tsx
server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCreationMenu-test.tsx
server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PageHeader-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/CreationTooltip.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AzureTab-test.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTab-test.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/CreationTooltip-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GithubTab-test.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GitlabTab-test.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/CreationTooltip-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index d6105855b00f89299d0f32e3e2d4951cd3a9fd9f..c2bdfd909e2a86c4884f6faa3905f22070c41935 100644 (file)
@@ -37,7 +37,7 @@ import './style.css';
 import { CreateProjectModes } from './types';
 
 interface Props extends Pick<WithRouterProps, 'router' | 'location'> {
-  appState: Pick<T.AppState, 'branchesEnabled' | 'canAdmin'>;
+  appState: Pick<T.AppState, 'canAdmin'>;
   currentUser: T.LoggedInUser;
 }
 
@@ -60,13 +60,8 @@ export class CreateProjectPage extends React.PureComponent<Props, State> {
   };
 
   componentDidMount() {
-    const {
-      appState: { branchesEnabled }
-    } = this.props;
     this.mounted = true;
-    if (branchesEnabled) {
-      this.fetchAlmBindings();
-    }
+    this.fetchAlmBindings();
   }
 
   componentWillUnmount() {
@@ -192,10 +187,7 @@ export class CreateProjectPage extends React.PureComponent<Props, State> {
   }
 
   render() {
-    const {
-      appState: { branchesEnabled },
-      location
-    } = this.props;
+    const { location } = this.props;
     const mode: CreateProjectModes | undefined = location.query?.mode;
 
     return (
@@ -203,7 +195,7 @@ export class CreateProjectPage extends React.PureComponent<Props, State> {
         <Helmet title={translate('my_account.create_new.TRK')} titleTemplate="%s" />
         <A11ySkipTarget anchor="create_project_main" />
         <div className="page page-limited huge-spacer-bottom position-relative" id="create-project">
-          {this.renderForm(branchesEnabled ? mode : CreateProjectModes.Manual)}
+          {this.renderForm(mode)}
         </div>
       </>
     );
index 7f43cf60b592533ec3d323f3e57104f1854778f6..e59baf2bb09fb413da3b93d3b9dcc05c6964447f 100644 (file)
@@ -36,11 +36,6 @@ it('should render correctly', () => {
   expect(getAlmSettings).toBeCalled();
 });
 
-it('should render correctly if no branch support', () => {
-  expect(shallowRender({ appState: { branchesEnabled: false } })).toMatchSnapshot();
-  expect(getAlmSettings).not.toBeCalled();
-});
-
 it('should render correctly if the manual method is selected', () => {
   expect(
     shallowRender({
@@ -82,7 +77,7 @@ it('should render correctly if the GitLab method is selected', () => {
 function shallowRender(props: Partial<CreateProjectPage['props']> = {}) {
   return shallow<CreateProjectPage>(
     <CreateProjectPage
-      appState={{ branchesEnabled: true }}
+      appState={{}}
       currentUser={mockLoggedInUser()}
       location={mockLocation()}
       router={mockRouter()}
index 475b40c6b494d66953a98b15ba1410d7486a4f93..99f3a717d691d81dbcb781fbe908bbc0a0664ead 100644 (file)
@@ -31,28 +31,6 @@ exports[`should render correctly 1`] = `
 </Fragment>
 `;
 
-exports[`should render correctly if no branch support 1`] = `
-<Fragment>
-  <Helmet
-    defer={true}
-    encodeSpecialCharacters={true}
-    title="my_account.create_new.TRK"
-    titleTemplate="%s"
-  />
-  <A11ySkipTarget
-    anchor="create_project_main"
-  />
-  <div
-    className="page page-limited huge-spacer-bottom position-relative"
-    id="create-project"
-  >
-    <ManualProjectCreate
-      onProjectCreate={[Function]}
-    />
-  </div>
-</Fragment>
-`;
-
 exports[`should render correctly if the Azure method is selected 1`] = `
 <Fragment>
   <Helmet
index 9ead04d60cc0d0f369f5e79b0264021ce46c2fcb..4a406a6a36f46a652876991cfc9b62793842a575 100644 (file)
@@ -23,14 +23,12 @@ import Dropdown from 'sonar-ui-common/components/controls/Dropdown';
 import DropdownIcon from 'sonar-ui-common/components/icons/DropdownIcon';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import { getAlmSettings } from '../../../api/alm-settings';
-import { withAppState } from '../../../components/hoc/withAppState';
 import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
 import { hasGlobalPermission } from '../../../helpers/users';
 import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
 import ProjectCreationMenuItem from './ProjectCreationMenuItem';
 
 interface Props {
-  appState: Pick<T.AppState, 'branchesEnabled'>;
   className?: string;
   currentUser: T.LoggedInUser;
 }
@@ -71,18 +69,15 @@ export class ProjectCreationMenu extends React.PureComponent<Props, State> {
   };
 
   fetchAlmBindings = async () => {
-    const {
-      appState: { branchesEnabled },
-      currentUser
-    } = this.props;
+    const { currentUser } = this.props;
     const canCreateProject = hasGlobalPermission(currentUser, PROJECT_CREATION_PERMISSION);
 
     // getAlmSettings requires branchesEnabled
-    if (!canCreateProject || !branchesEnabled) {
+    if (!canCreateProject) {
       return;
     }
 
-    const almSettings = await getAlmSettings();
+    const almSettings: AlmSettingsInstance[] = await getAlmSettings().catch(() => []);
 
     // Import is only available if exactly one binding is configured
     const boundAlms = IMPORT_COMPATIBLE_ALMS.filter(key => {
@@ -129,4 +124,4 @@ export class ProjectCreationMenu extends React.PureComponent<Props, State> {
   }
 }
 
-export default withAppState(withCurrentUser(ProjectCreationMenu));
+export default withCurrentUser(ProjectCreationMenu);
index 51deead6bf2ede778175ac6f390884929afcaecb..5b2825de4b2132470aea0eeb94450740232277b5 100644 (file)
@@ -21,7 +21,7 @@ import { shallow } from 'enzyme';
 import * as React from 'react';
 import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
 import { getAlmSettings } from '../../../../api/alm-settings';
-import { mockAppState, mockLoggedInUser } from '../../../../helpers/testMocks';
+import { mockLoggedInUser } from '../../../../helpers/testMocks';
 import { AlmKeys } from '../../../../types/alm-settings';
 import { ProjectCreationMenu } from '../ProjectCreationMenu';
 
@@ -52,12 +52,6 @@ it('should not fetch alm bindings if user cannot create projects', async () => {
   expect(getAlmSettings).not.toBeCalled();
 });
 
-it('should not fetch alm bindings if branches are not enabled', async () => {
-  const wrapper = shallowRender({ appState: mockAppState({ branchesEnabled: false }) });
-  await waitAndUpdate(wrapper);
-  expect(getAlmSettings).not.toBeCalled();
-});
-
 it('should filter alm bindings appropriately', async () => {
   (getAlmSettings as jest.Mock).mockResolvedValueOnce([
     { alm: AlmKeys.Azure },
@@ -77,7 +71,6 @@ it('should filter alm bindings appropriately', async () => {
 function shallowRender(overrides: Partial<ProjectCreationMenu['props']> = {}) {
   return shallow<ProjectCreationMenu>(
     <ProjectCreationMenu
-      appState={mockAppState({ branchesEnabled: true })}
       currentUser={mockLoggedInUser({ permissions: { global: ['provisioning'] } })}
       {...overrides}
     />
index 2b6933ea8724c28744f4978a0f7aa784239d3fbc..7f5915cf34ff06d1488b551830bfb825931c85fb 100644 (file)
@@ -18,7 +18,7 @@ exports[`should render correctly 1`] = `
     <div
       className="display-flex-center"
     >
-      <Connect(withAppState(Connect(withCurrentUser(ProjectCreationMenu))))
+      <Connect(withCurrentUser(ProjectCreationMenu))
         className="little-spacer-right"
       />
       <Connect(withAppState(Connect(withCurrentUser(withRouter(ApplicationCreation)))))
@@ -96,7 +96,7 @@ exports[`should render correctly while loading 1`] = `
     <div
       className="display-flex-center"
     >
-      <Connect(withAppState(Connect(withCurrentUser(ProjectCreationMenu))))
+      <Connect(withCurrentUser(ProjectCreationMenu))
         className="little-spacer-right"
       />
       <Connect(withAppState(Connect(withCurrentUser(withRouter(ApplicationCreation)))))
@@ -174,7 +174,7 @@ exports[`should render disabled sorting options for visualizations 1`] = `
     <div
       className="display-flex-center"
     >
-      <Connect(withAppState(Connect(withCurrentUser(ProjectCreationMenu))))
+      <Connect(withCurrentUser(ProjectCreationMenu))
         className="little-spacer-right"
       />
       <Connect(withAppState(Connect(withCurrentUser(withRouter(ApplicationCreation)))))
index 813eef536d58564cfedfe551a858b43ebbc6e1e3..c83889511c9a5ba0edbf46a9fc945e6caf6e7877 100644 (file)
@@ -18,6 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
 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';
@@ -27,15 +28,18 @@ 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 { translate } from 'sonar-ui-common/helpers/l10n';
+import { getEdition, getEditionUrl } from '../../../../helpers/editions';
 import {
   AlmBindingDefinition,
   AlmKeys,
   AlmSettingsBindingStatus,
   AlmSettingsBindingStatusType
 } from '../../../../types/alm-settings';
+import { EditionKey } from '../../../../types/editions';
 
 export interface AlmBindingDefinitionBoxProps {
   alm: AlmKeys;
+  branchesEnabled: boolean;
   definition: AlmBindingDefinition;
   multipleDefinitions: boolean;
   onCheck: (definitionKey: string) => void;
@@ -55,6 +59,48 @@ const STATUS_ICON = {
   [AlmSettingsBindingStatusType.Success]: <AlertSuccessIcon className="spacer-left" />
 };
 
+function getPRDecorationFeatureStatus(
+  branchesEnabled: boolean,
+  type: AlmSettingsBindingStatusType.Success | AlmSettingsBindingStatusType.Failure
+) {
+  if (branchesEnabled) {
+    return STATUS_ICON[type];
+  }
+
+  return (
+    <div className="display-inline-flex-center">
+      <strong className="spacer-left">
+        {translate('settings.almintegration.feature.pr_decoration.disabled')}
+      </strong>
+      <HelpTooltip
+        className="little-spacer-left"
+        overlay={
+          <FormattedMessage
+            id="settings.almintegration.feature.pr_decoration.disabled.no_branches"
+            defaultMessage={translate(
+              'settings.almintegration.feature.pr_decoration.disabled.no_branches'
+            )}
+            values={{
+              link: (
+                <a
+                  href={getEditionUrl(getEdition(EditionKey.developer), {
+                    sourceEdition: EditionKey.community
+                  })}
+                  rel="noopener noreferrer"
+                  target="_blank">
+                  {translate(
+                    'settings.almintegration.feature.pr_decoration.disabled.no_branches.link'
+                  )}
+                </a>
+              )
+            }}
+          />
+        }
+      />
+    </div>
+  );
+}
+
 function getImportFeatureStatus(
   definition: AlmBindingDefinition,
   multipleDefinitions: boolean,
@@ -72,7 +118,9 @@ function getImportFeatureStatus(
         />
       </div>
     );
-  } else if (!definition.url) {
+  }
+
+  if (!definition.url) {
     return (
       <div className="display-inline-flex-center">
         <strong className="spacer-left">
@@ -84,13 +132,13 @@ function getImportFeatureStatus(
         />
       </div>
     );
-  } else {
-    return STATUS_ICON[type];
   }
+
+  return STATUS_ICON[type];
 }
 
 export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxProps) {
-  const { alm, definition, multipleDefinitions, status = DEFAULT_STATUS } = props;
+  const { alm, branchesEnabled, definition, multipleDefinitions, status = DEFAULT_STATUS } = props;
 
   const importFeatureTitle =
     alm === AlmKeys.GitLab
@@ -129,12 +177,12 @@ export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxPr
         <>
           {status.type !== AlmSettingsBindingStatusType.Warning && (
             <div className="display-flex-row spacer-bottom">
-              <Tooltip overlay={importFeatureDescription}>
-                <div className="huge-spacer-right">
-                  {importFeatureTitle}
-                  {STATUS_ICON[status.type]}
-                </div>
-              </Tooltip>
+              <div className="huge-spacer-right">
+                <Tooltip overlay={importFeatureDescription}>
+                  <span>{importFeatureTitle}</span>
+                </Tooltip>
+                {getPRDecorationFeatureStatus(branchesEnabled, status.type)}
+              </div>
               <div>
                 <Tooltip
                   overlay={translate(
index 796b2c3e81917d3597fa10644e904350ad694eb7..254cffa1d76e70cd33ac019505f25bf3edc3baf6 100644 (file)
@@ -101,14 +101,6 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
   };
 
   fetchPullRequestDecorationSetting = () => {
-    const {
-      appState: { branchesEnabled }
-    } = this.props;
-
-    if (!branchesEnabled) {
-      return Promise.resolve();
-    }
-
     this.setState({ loadingAlmDefinitions: true });
     return getAlmDefinitions()
       .then(definitions => {
index b13c8a9cfb1b5a5504c995299215faecef034e87..5f4bd44a36ef3224a86269db851af27f4f207e7e 100644 (file)
@@ -64,7 +64,8 @@ const tabs = [
         />
         GitHub
       </>
-    )
+    ),
+    requiresBranchesEnabled: false
   },
   {
     key: AlmKeys.Bitbucket,
@@ -79,7 +80,7 @@ const tabs = [
         Bitbucket Server
       </>
     ),
-    requiresBranchesEnabled: true
+    requiresBranchesEnabled: false
   },
   {
     key: AlmKeys.Azure,
@@ -94,7 +95,7 @@ const tabs = [
         Azure DevOps Server
       </>
     ),
-    requiresBranchesEnabled: true
+    requiresBranchesEnabled: false
   },
   {
     key: AlmKeys.GitLab,
@@ -108,7 +109,8 @@ const tabs = [
         />
         GitLab
       </>
-    )
+    ),
+    requiresBranchesEnabled: false
   }
 ];
 
@@ -143,6 +145,7 @@ export default function AlmIntegrationRenderer(props: AlmIntegrationRendererProp
 
       {currentAlm === AlmKeys.Azure && (
         <AzureTab
+          branchesEnabled={branchesEnabled}
           definitions={definitions.azure}
           definitionStatus={definitionStatus}
           loadingAlmDefinitions={loadingAlmDefinitions}
@@ -155,6 +158,7 @@ export default function AlmIntegrationRenderer(props: AlmIntegrationRendererProp
       )}
       {currentAlm === AlmKeys.Bitbucket && (
         <BitbucketTab
+          branchesEnabled={branchesEnabled}
           definitions={definitions.bitbucket}
           definitionStatus={definitionStatus}
           loadingAlmDefinitions={loadingAlmDefinitions}
index 315c138db24eaabe7d4e4402443f502518909226..95c680e8c5da0d411ba93fa215a3ef5169143d74 100644 (file)
@@ -28,6 +28,7 @@ import AlmTabRenderer from './AlmTabRenderer';
 
 interface Props<B> {
   alm: AlmKeys;
+  branchesEnabled: boolean;
   createConfiguration: (data: B) => Promise<void>;
   defaultBinding: B;
   definitions: B[];
@@ -109,6 +110,7 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo
   render() {
     const {
       alm,
+      branchesEnabled,
       defaultBinding,
       definitions,
       definitionStatus,
@@ -124,6 +126,7 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo
     return (
       <AlmTabRenderer
         alm={alm}
+        branchesEnabled={branchesEnabled}
         defaultBinding={defaultBinding}
         definitions={definitions}
         definitionStatus={definitionStatus}
index 9d2c43ae224ad572fc16ce174a00838a027d20e7..c7c1cbd5a7f5357f8f6990c5d4b9d0980aa34483 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
 import { Button } from 'sonar-ui-common/components/controls/buttons';
-import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
 import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
 import { translate } from 'sonar-ui-common/helpers/l10n';
-import { getEdition, getEditionUrl } from '../../../../helpers/editions';
 import {
   AlmBindingDefinition,
   AlmKeys,
   AlmSettingsBindingStatus
 } from '../../../../types/alm-settings';
-import { EditionKey } from '../../../../types/editions';
 import AlmBindingDefinitionBox from './AlmBindingDefinitionBox';
 import AlmBindingDefinitionForm, {
   AlmBindingDefinitionFormChildrenProps
 } from './AlmBindingDefinitionForm';
+import CreationTooltip from './CreationTooltip';
 
 export interface AlmTabRendererProps<B> {
   alm: AlmKeys;
+  branchesEnabled: boolean;
   definitionStatus: T.Dict<AlmSettingsBindingStatus>;
   editedDefinition?: B;
   defaultBinding: B;
@@ -62,6 +60,7 @@ export default function AlmTabRenderer<B extends AlmBindingDefinition>(
 ) {
   const {
     alm,
+    branchesEnabled,
     definitions,
     definitionStatus,
     editedDefinition,
@@ -74,25 +73,6 @@ export default function AlmTabRenderer<B extends AlmBindingDefinition>(
   } = props;
 
   const preventCreation = loadingProjectCount || (!multipleAlmEnabled && definitions.length > 0);
-  const creationTooltip = preventCreation ? (
-    <FormattedMessage
-      id="settings.almintegration.create.tooltip"
-      defaultMessage={translate('settings.almintegration.create.tooltip')}
-      values={{
-        link: (
-          <a
-            href={getEditionUrl(getEdition(EditionKey.enterprise), {
-              sourceEdition: EditionKey.developer
-            })}
-            rel="noopener noreferrer"
-            target="_blank">
-            {translate('settings.almintegration.create.tooltip.link')}
-          </a>
-        ),
-        alm: translate('alm', alm)
-      }}
-    />
-  ) : null;
 
   return (
     <div className="big-padded">
@@ -102,18 +82,19 @@ export default function AlmTabRenderer<B extends AlmBindingDefinition>(
         )}
 
         <div className={definitions.length > 0 ? 'spacer-bottom text-right' : 'big-spacer-top'}>
-          <Tooltip overlay={creationTooltip} mouseLeaveDelay={0.25}>
+          <CreationTooltip alm={alm} preventCreation={preventCreation}>
             <Button
               data-test="settings__alm-create"
               disabled={preventCreation}
               onClick={props.onCreate}>
               {translate('settings.almintegration.create')}
             </Button>
-          </Tooltip>
+          </CreationTooltip>
         </div>
         {definitions.map(def => (
           <AlmBindingDefinitionBox
             alm={alm}
+            branchesEnabled={branchesEnabled}
             definition={def}
             key={def.key}
             multipleDefinitions={definitions.length > 1}
index 4ffb60a04ae258b9abeab5157df5a1d917741c20..5be30a1be4b89d9709624a467063394d5f4075da 100644 (file)
@@ -32,6 +32,7 @@ import AlmTab from './AlmTab';
 import AzureForm from './AzureForm';
 
 export interface AzureTabProps {
+  branchesEnabled: boolean;
   definitions: AzureBindingDefinition[];
   definitionStatus: T.Dict<AlmSettingsBindingStatus>;
   loadingAlmDefinitions: boolean;
@@ -44,6 +45,7 @@ export interface AzureTabProps {
 
 export default function AzureTab(props: AzureTabProps) {
   const {
+    branchesEnabled,
     multipleAlmEnabled,
     definitions,
     definitionStatus,
@@ -55,6 +57,7 @@ export default function AzureTab(props: AzureTabProps) {
     <div className="bordered">
       <AlmTab
         alm={AlmKeys.Azure}
+        branchesEnabled={branchesEnabled}
         createConfiguration={createAzureConfiguration}
         defaultBinding={{ key: '', personalAccessToken: '', url: '' }}
         definitions={definitions}
index d975245ea619920af255bbfb00061e2563deabf2..1ea3352965b797b69385583b3ba7bfaccd1b76be 100644 (file)
@@ -34,6 +34,7 @@ import AlmTab from './AlmTab';
 import BitbucketForm from './BitbucketForm';
 
 export interface BitbucketTabProps {
+  branchesEnabled: boolean;
   definitions: BitbucketBindingDefinition[];
   definitionStatus: T.Dict<AlmSettingsBindingStatus>;
   loadingAlmDefinitions: boolean;
@@ -46,6 +47,7 @@ export interface BitbucketTabProps {
 
 export default function BitbucketTab(props: BitbucketTabProps) {
   const {
+    branchesEnabled,
     multipleAlmEnabled,
     definitions,
     definitionStatus,
@@ -57,6 +59,7 @@ export default function BitbucketTab(props: BitbucketTabProps) {
     <div className="bordered">
       <AlmTab
         alm={AlmKeys.Bitbucket}
+        branchesEnabled={branchesEnabled}
         createConfiguration={createBitbucketConfiguration}
         defaultBinding={{ key: '', url: '', personalAccessToken: '' }}
         definitions={definitions}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/CreationTooltip.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/CreationTooltip.tsx
new file mode 100644 (file)
index 0000000..bc9fcb2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { FormattedMessage } from 'react-intl';
+import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { withAppState } from '../../../../components/hoc/withAppState';
+import { getEdition, getEditionUrl } from '../../../../helpers/editions';
+import { AlmKeys } from '../../../../types/alm-settings';
+import { EditionKey } from '../../../../types/editions';
+
+export interface CreationTooltipProps {
+  alm: AlmKeys;
+  appState: T.AppState;
+  children: React.ReactElement<{}>;
+  preventCreation: boolean;
+}
+
+export function CreationTooltip(props: CreationTooltipProps) {
+  const {
+    alm,
+    appState: { edition },
+    children,
+    preventCreation
+  } = props;
+
+  const sourceEdition = edition ? EditionKey[edition] : undefined;
+
+  return (
+    <Tooltip
+      overlay={
+        preventCreation ? (
+          <FormattedMessage
+            id="settings.almintegration.create.tooltip"
+            defaultMessage={translate('settings.almintegration.create.tooltip')}
+            values={{
+              link: (
+                <a
+                  href={getEditionUrl(getEdition(EditionKey.enterprise), {
+                    sourceEdition
+                  })}
+                  rel="noopener noreferrer"
+                  target="_blank">
+                  {translate('settings.almintegration.create.tooltip.link')}
+                </a>
+              ),
+              alm: translate('alm', alm)
+            }}
+          />
+        ) : null
+      }
+      mouseLeaveDelay={0.25}>
+      {children}
+    </Tooltip>
+  );
+}
+
+export default withAppState(CreationTooltip);
index 7811a6eafb63335efcdf7d30f037643e44119e8c..5a2371242dab9a9107194bf197863d69b1f3a2b6 100644 (file)
@@ -59,47 +59,44 @@ export default function GithubTab(props: GithubTabProps) {
 
   return (
     <div className="bordered">
-      {branchesEnabled && (
-        <>
-          <AlmTab
-            alm={AlmKeys.GitHub}
-            createConfiguration={createGithubConfiguration}
-            defaultBinding={{
-              key: '',
-              appId: '',
-              clientId: '',
-              clientSecret: '',
-              url: '',
-              privateKey: ''
+      <AlmTab
+        alm={AlmKeys.GitHub}
+        branchesEnabled={branchesEnabled}
+        createConfiguration={createGithubConfiguration}
+        defaultBinding={{
+          key: '',
+          appId: '',
+          clientId: '',
+          clientSecret: '',
+          url: '',
+          privateKey: ''
+        }}
+        definitions={definitions}
+        definitionStatus={definitionStatus}
+        form={childProps => <GithubForm {...childProps} />}
+        help={
+          <FormattedMessage
+            defaultMessage={translate(`settings.almintegration.github.info`)}
+            id="settings.almintegration.github.info"
+            values={{
+              link: (
+                <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitHub]}>
+                  {translate('learn_more')}
+                </Link>
+              )
             }}
-            definitions={definitions}
-            definitionStatus={definitionStatus}
-            form={childProps => <GithubForm {...childProps} />}
-            help={
-              <FormattedMessage
-                defaultMessage={translate(`settings.almintegration.github.info`)}
-                id="settings.almintegration.github.info"
-                values={{
-                  link: (
-                    <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitHub]}>
-                      {translate('learn_more')}
-                    </Link>
-                  )
-                }}
-              />
-            }
-            loadingAlmDefinitions={loadingAlmDefinitions}
-            loadingProjectCount={loadingProjectCount}
-            multipleAlmEnabled={multipleAlmEnabled}
-            onCheck={props.onCheck}
-            onDelete={props.onDelete}
-            onUpdateDefinitions={props.onUpdateDefinitions}
-            updateConfiguration={updateGithubConfiguration}
           />
+        }
+        loadingAlmDefinitions={loadingAlmDefinitions}
+        loadingProjectCount={loadingProjectCount}
+        multipleAlmEnabled={multipleAlmEnabled}
+        onCheck={props.onCheck}
+        onDelete={props.onDelete}
+        onUpdateDefinitions={props.onUpdateDefinitions}
+        updateConfiguration={updateGithubConfiguration}
+      />
 
-          <div className="huge-spacer-top huge-spacer-bottom bordered-top" />
-        </>
-      )}
+      <div className="huge-spacer-top huge-spacer-bottom bordered-top" />
 
       <div className="big-padded">
         <CategoryDefinitionsList
index d973cae790fb9d52ecfc801ef83b4e207a209da4..993b6214b70e2feb21e2b5fabc1563b81a58bc71 100644 (file)
@@ -59,40 +59,37 @@ export default function GitlabTab(props: GitlabTabProps) {
 
   return (
     <div className="bordered">
-      {branchesEnabled && (
-        <>
-          <AlmTab
-            alm={AlmKeys.GitLab}
-            createConfiguration={createGitlabConfiguration}
-            defaultBinding={{ key: '', personalAccessToken: '', url: '' }}
-            definitions={definitions}
-            definitionStatus={definitionStatus}
-            form={childProps => <GitlabForm {...childProps} />}
-            help={
-              <FormattedMessage
-                defaultMessage={translate(`settings.almintegration.gitlab.info`)}
-                id="settings.almintegration.gitlab.info"
-                values={{
-                  link: (
-                    <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitLab]}>
-                      {translate('learn_more')}
-                    </Link>
-                  )
-                }}
-              />
-            }
-            loadingAlmDefinitions={loadingAlmDefinitions}
-            loadingProjectCount={loadingProjectCount}
-            multipleAlmEnabled={multipleAlmEnabled}
-            onCheck={props.onCheck}
-            onDelete={props.onDelete}
-            onUpdateDefinitions={props.onUpdateDefinitions}
-            updateConfiguration={updateGitlabConfiguration}
+      <AlmTab
+        alm={AlmKeys.GitLab}
+        branchesEnabled={branchesEnabled}
+        createConfiguration={createGitlabConfiguration}
+        defaultBinding={{ key: '', personalAccessToken: '', url: '' }}
+        definitions={definitions}
+        definitionStatus={definitionStatus}
+        form={childProps => <GitlabForm {...childProps} />}
+        help={
+          <FormattedMessage
+            defaultMessage={translate(`settings.almintegration.gitlab.info`)}
+            id="settings.almintegration.gitlab.info"
+            values={{
+              link: (
+                <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitLab]}>
+                  {translate('learn_more')}
+                </Link>
+              )
+            }}
           />
+        }
+        loadingAlmDefinitions={loadingAlmDefinitions}
+        loadingProjectCount={loadingProjectCount}
+        multipleAlmEnabled={multipleAlmEnabled}
+        onCheck={props.onCheck}
+        onDelete={props.onDelete}
+        onUpdateDefinitions={props.onUpdateDefinitions}
+        updateConfiguration={updateGitlabConfiguration}
+      />
 
-          <div className="huge-spacer-top huge-spacer-bottom bordered-top" />
-        </>
-      )}
+      <div className="huge-spacer-top huge-spacer-bottom bordered-top" />
 
       <div className="big-padded">
         <CategoryDefinitionsList
index 8eb973c85d20d0b47f967331a82eba2bf293455e..f122eb43c8f3574bd9b6c171dfb08a63a02d4cfd 100644 (file)
@@ -66,12 +66,23 @@ it('should render correctly', () => {
   expect(
     shallowRender({ alm: AlmKeys.Azure, definition: mockAzureBindingDefinition() })
   ).toMatchSnapshot('Azure DevOps');
+
+  expect(
+    shallowRender({
+      branchesEnabled: false,
+      status: mockAlmSettingsBindingStatus({
+        alertSuccess: true,
+        type: AlmSettingsBindingStatusType.Success
+      })
+    })
+  ).toMatchSnapshot('success with branches disabled');
 });
 
 function shallowRender(props: Partial<AlmBindingDefinitionBoxProps> = {}) {
   return shallow(
     <AlmBindingDefinitionBox
       alm={AlmKeys.GitHub}
+      branchesEnabled={true}
       definition={mockGithubBindingDefinition()}
       multipleDefinitions={false}
       onCheck={jest.fn()}
index c1f8fba85e0c4be623d958b2f63978b41bfc93c5..dbabfdadf5be0e11496bf8bf03e8ac2ac00bb490 100644 (file)
@@ -95,6 +95,7 @@ function shallowRender(props: Partial<AlmTab<AzureBindingDefinition>['props']> =
   return shallow<AlmTab<AzureBindingDefinition>>(
     <AlmTab
       alm={AlmKeys.Azure}
+      branchesEnabled={true}
       createConfiguration={jest.fn()}
       defaultBinding={DEFAULT_BINDING}
       definitions={[mockAzureBindingDefinition()]}
index 658024e7145548bd4d8a7d1dbb557a4b96409684..8e1f243485f171e8d58ae4acbfe5a30e6e2c0af0 100644 (file)
@@ -93,6 +93,7 @@ function shallowRender<B extends AlmBindingDefinition>(
   return shallow(
     <AlmTabRenderer
       alm={AlmKeys.Azure}
+      branchesEnabled={true}
       defaultBinding={{} as any}
       definitions={[]}
       definitionStatus={{}}
index fcfd7f6cdd9940f481eb45dda68db4fae8eb89e7..ab62239c83a68332fadc4d3c01a86b1af241b1cc 100644 (file)
@@ -29,6 +29,7 @@ it('should render correctly', () => {
 function shallowRender(props: Partial<AzureTabProps> = {}) {
   return shallow(
     <AzureTab
+      branchesEnabled={true}
       definitions={[mockAzureBindingDefinition()]}
       definitionStatus={{}}
       loadingAlmDefinitions={false}
index 6ab1e0cbe04b46d924fc274aa3e99d0eb21ffe5f..28551069145c19621968b87150f38aae6859fa67 100644 (file)
@@ -29,6 +29,7 @@ it('should render correctly', () => {
 function shallowRender(props: Partial<BitbucketTabProps> = {}) {
   return shallow(
     <BitbucketTab
+      branchesEnabled={true}
       definitions={[mockBitbucketBindingDefinition()]}
       definitionStatus={{}}
       loadingAlmDefinitions={false}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/CreationTooltip-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/CreationTooltip-test.tsx
new file mode 100644 (file)
index 0000000..746ba7e
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { mockAppState } from '../../../../../helpers/testMocks';
+import { AlmKeys } from '../../../../../types/alm-settings';
+import { EditionKey } from '../../../../../types/editions';
+import { CreationTooltip, CreationTooltipProps } from '../CreationTooltip';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+  expect(shallowRender({ preventCreation: false })).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<CreationTooltipProps> = {}) {
+  return shallow(
+    <CreationTooltip
+      alm={AlmKeys.Azure}
+      appState={mockAppState({ edition: EditionKey.community })}
+      preventCreation={true}
+      {...props}>
+      <span>Child</span>
+    </CreationTooltip>
+  );
+}
index 4ab684867355b04769b48026a88400f1856b9d7a..3785bb786081b7109737b3a8b0bcc8b6318cd2d9 100644 (file)
@@ -24,7 +24,6 @@ import GithubTab, { GithubTabProps } from '../GithubTab';
 
 it('should render correctly', () => {
   expect(shallowRender()).toMatchSnapshot('with branch support');
-  expect(shallowRender({ branchesEnabled: false })).toMatchSnapshot('without branch support');
 });
 
 function shallowRender(props: Partial<GithubTabProps> = {}) {
index 8ea03aa327d451a3875d4c9c720f608ead4b6499..a3a9b6e80a343ea1daa552fb857d206624028d59 100644 (file)
@@ -24,7 +24,6 @@ import GitlabTab, { GitlabTabProps } from '../GitlabTab';
 
 it('should render correctly', () => {
   expect(shallowRender()).toMatchSnapshot('with branch support');
-  expect(shallowRender({ branchesEnabled: false })).toMatchSnapshot('without branch support');
   expect(
     shallowRender({
       definitions: [mockGitlabBindingDefinition({ url: 'https://gitlab.com/api/v4' })]
index 5a3af1e526019f0764518812559c603522801ec0..07cd7a44076e0c0cabb580401d9c9da4803f9cbc 100644 (file)
@@ -119,18 +119,20 @@ exports[`should render correctly: error 1`] = `
   <div
     className="display-flex-row spacer-bottom"
   >
-    <Tooltip
-      overlay="settings.almintegration.feature.pr_decoration.description"
+    <div
+      className="huge-spacer-right"
     >
-      <div
-        className="huge-spacer-right"
+      <Tooltip
+        overlay="settings.almintegration.feature.pr_decoration.description"
       >
-        settings.almintegration.feature.pr_decoration.title
-        <AlertErrorIcon
-          className="spacer-left"
-        />
-      </div>
-    </Tooltip>
+        <span>
+          settings.almintegration.feature.pr_decoration.title
+        </span>
+      </Tooltip>
+      <AlertErrorIcon
+        className="spacer-left"
+      />
+    </div>
     <div>
       <Tooltip
         overlay="settings.almintegration.feature.alm_repo_import.description"
@@ -242,18 +244,20 @@ exports[`should render correctly: success 1`] = `
   <div
     className="display-flex-row spacer-bottom"
   >
-    <Tooltip
-      overlay="settings.almintegration.feature.pr_decoration.description"
+    <div
+      className="huge-spacer-right"
     >
-      <div
-        className="huge-spacer-right"
+      <Tooltip
+        overlay="settings.almintegration.feature.pr_decoration.description"
       >
-        settings.almintegration.feature.pr_decoration.title
-        <AlertSuccessIcon
-          className="spacer-left"
-        />
-      </div>
-    </Tooltip>
+        <span>
+          settings.almintegration.feature.pr_decoration.title
+        </span>
+      </Tooltip>
+      <AlertSuccessIcon
+        className="spacer-left"
+      />
+    </div>
     <div>
       <Tooltip
         overlay="settings.almintegration.feature.alm_repo_import.description"
@@ -317,18 +321,129 @@ exports[`should render correctly: success with alert 1`] = `
   <div
     className="display-flex-row spacer-bottom"
   >
-    <Tooltip
-      overlay="settings.almintegration.feature.pr_decoration.description"
+    <div
+      className="huge-spacer-right"
+    >
+      <Tooltip
+        overlay="settings.almintegration.feature.pr_decoration.description"
+      >
+        <span>
+          settings.almintegration.feature.pr_decoration.title
+        </span>
+      </Tooltip>
+      <AlertSuccessIcon
+        className="spacer-left"
+      />
+    </div>
+    <div>
+      <Tooltip
+        overlay="settings.almintegration.feature.alm_repo_import.description"
+      >
+        <span>
+          settings.almintegration.feature.alm_repo_import.title
+        </span>
+      </Tooltip>
+      <AlertSuccessIcon
+        className="spacer-left"
+      />
+    </div>
+  </div>
+  <div
+    className="width-50"
+  >
+    <Alert
+      variant="success"
+    >
+      settings.almintegration.configuration_valid
+    </Alert>
+  </div>
+  <Button
+    className="big-spacer-top"
+    onClick={[Function]}
+  >
+    settings.almintegration.check_configuration
+  </Button>
+</div>
+`;
+
+exports[`should render correctly: success with branches disabled 1`] = `
+<div
+  className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
+>
+  <div
+    className="actions pull-right"
+  >
+    <Button
+      onClick={[Function]}
+    >
+      <EditIcon
+        className="spacer-right"
+      />
+      edit
+    </Button>
+    <Button
+      className="button-red spacer-left"
+      onClick={[Function]}
+    >
+      <DeleteIcon
+        className="spacer-right"
+      />
+      delete
+    </Button>
+  </div>
+  <div
+    className="big-spacer-bottom"
+  >
+    <h3>
+      key
+    </h3>
+    <span>
+      http://github.enterprise.com
+    </span>
+  </div>
+  <div
+    className="display-flex-row spacer-bottom"
+  >
+    <div
+      className="huge-spacer-right"
     >
+      <Tooltip
+        overlay="settings.almintegration.feature.pr_decoration.description"
+      >
+        <span>
+          settings.almintegration.feature.pr_decoration.title
+        </span>
+      </Tooltip>
       <div
-        className="huge-spacer-right"
+        className="display-inline-flex-center"
       >
-        settings.almintegration.feature.pr_decoration.title
-        <AlertSuccessIcon
+        <strong
           className="spacer-left"
+        >
+          settings.almintegration.feature.pr_decoration.disabled
+        </strong>
+        <HelpTooltip
+          className="little-spacer-left"
+          overlay={
+            <FormattedMessage
+              defaultMessage="settings.almintegration.feature.pr_decoration.disabled.no_branches"
+              id="settings.almintegration.feature.pr_decoration.disabled.no_branches"
+              values={
+                Object {
+                  "link": <a
+                    href="https://redirect.sonarsource.com/editions/developer.html?sourceEdition=community"
+                    rel="noopener noreferrer"
+                    target="_blank"
+                  >
+                    settings.almintegration.feature.pr_decoration.disabled.no_branches.link
+                  </a>,
+                }
+              }
+            />
+          }
         />
       </div>
-    </Tooltip>
+    </div>
     <div>
       <Tooltip
         overlay="settings.almintegration.feature.alm_repo_import.description"
index 2a887a2e77ca9fac629131884c7075504873547b..f5f4acd52651aa4a04f420328cc1d62458294785 100644 (file)
@@ -32,6 +32,7 @@ exports[`should render correctly: azure 1`] = `
             />
             GitHub
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "bitbucket",
@@ -44,7 +45,7 @@ exports[`should render correctly: azure 1`] = `
             />
             Bitbucket Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "azure",
@@ -57,7 +58,7 @@ exports[`should render correctly: azure 1`] = `
             />
             Azure DevOps Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "gitlab",
@@ -70,11 +71,13 @@ exports[`should render correctly: azure 1`] = `
             />
             GitLab
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
       ]
     }
   />
   <AzureTab
+    branchesEnabled={true}
     definitionStatus={Object {}}
     definitions={Array []}
     loadingAlmDefinitions={false}
@@ -119,6 +122,7 @@ exports[`should render correctly: bitbucket 1`] = `
             />
             GitHub
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "bitbucket",
@@ -131,7 +135,7 @@ exports[`should render correctly: bitbucket 1`] = `
             />
             Bitbucket Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "azure",
@@ -144,7 +148,7 @@ exports[`should render correctly: bitbucket 1`] = `
             />
             Azure DevOps Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "gitlab",
@@ -157,11 +161,13 @@ exports[`should render correctly: bitbucket 1`] = `
             />
             GitLab
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
       ]
     }
   />
   <BitbucketTab
+    branchesEnabled={true}
     definitionStatus={Object {}}
     definitions={Array []}
     loadingAlmDefinitions={false}
@@ -206,6 +212,7 @@ exports[`should render correctly: default 1`] = `
             />
             GitHub
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "bitbucket",
@@ -218,7 +225,7 @@ exports[`should render correctly: default 1`] = `
             />
             Bitbucket Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "azure",
@@ -231,7 +238,7 @@ exports[`should render correctly: default 1`] = `
             />
             Azure DevOps Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "gitlab",
@@ -244,6 +251,7 @@ exports[`should render correctly: default 1`] = `
             />
             GitLab
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
       ]
     }
@@ -294,6 +302,7 @@ exports[`should render correctly: delete modal 1`] = `
             />
             GitHub
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "bitbucket",
@@ -306,7 +315,7 @@ exports[`should render correctly: delete modal 1`] = `
             />
             Bitbucket Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "azure",
@@ -319,7 +328,7 @@ exports[`should render correctly: delete modal 1`] = `
             />
             Azure DevOps Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "gitlab",
@@ -332,6 +341,7 @@ exports[`should render correctly: delete modal 1`] = `
             />
             GitLab
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
       ]
     }
@@ -387,6 +397,7 @@ exports[`should render correctly: gitlab 1`] = `
             />
             GitHub
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "bitbucket",
@@ -399,7 +410,7 @@ exports[`should render correctly: gitlab 1`] = `
             />
             Bitbucket Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "azure",
@@ -412,7 +423,7 @@ exports[`should render correctly: gitlab 1`] = `
             />
             Azure DevOps Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "gitlab",
@@ -425,6 +436,7 @@ exports[`should render correctly: gitlab 1`] = `
             />
             GitLab
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
       ]
     }
@@ -475,6 +487,7 @@ exports[`should render correctly: loading 1`] = `
             />
             GitHub
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "bitbucket",
@@ -487,7 +500,7 @@ exports[`should render correctly: loading 1`] = `
             />
             Bitbucket Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "azure",
@@ -500,7 +513,7 @@ exports[`should render correctly: loading 1`] = `
             />
             Azure DevOps Server
           </React.Fragment>,
-          "requiresBranchesEnabled": true,
+          "requiresBranchesEnabled": false,
         },
         Object {
           "key": "gitlab",
@@ -513,6 +526,7 @@ exports[`should render correctly: loading 1`] = `
             />
             GitLab
           </React.Fragment>,
+          "requiresBranchesEnabled": false,
         },
       ]
     }
index 9c8ed1fce1d7c7ee50f64a2d7ef88a922e7dd7a4..76720ff1334d15ea4f3a66c59c753c8f51a340b0 100644 (file)
@@ -3,6 +3,7 @@
 exports[`should render correctly 1`] = `
 <AlmTabRenderer
   alm="azure"
+  branchesEnabled={true}
   defaultBinding={
     Object {
       "key": "",
index 39b1c424c4493888205d63b23d8b4a860d9af8d1..816690de7ed74e5651a60420c399d657119247ff 100644 (file)
@@ -10,9 +10,9 @@ exports[`should render correctly for multi-ALM binding: editing a definition 1`]
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -21,10 +21,11 @@ exports[`should render correctly for multi-ALM binding: editing a definition 1`]
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -65,9 +66,9 @@ exports[`should render correctly for multi-ALM binding: loaded 1`] = `
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -76,10 +77,11 @@ exports[`should render correctly for multi-ALM binding: loaded 1`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -106,9 +108,9 @@ exports[`should render correctly for multi-ALM binding: loading ALM definitions
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -117,10 +119,11 @@ exports[`should render correctly for multi-ALM binding: loading ALM definitions
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -147,26 +150,9 @@ exports[`should render correctly for multi-ALM binding: loading project count 1`
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={
-          <FormattedMessage
-            defaultMessage="settings.almintegration.create.tooltip"
-            id="settings.almintegration.create.tooltip"
-            values={
-              Object {
-                "alm": "alm.azure",
-                "link": <a
-                  href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer"
-                  rel="noopener noreferrer"
-                  target="_blank"
-                >
-                  settings.almintegration.create.tooltip.link
-                </a>,
-              }
-            }
-          />
-        }
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={true}
       >
         <Button
           data-test="settings__alm-create"
@@ -175,10 +161,11 @@ exports[`should render correctly for multi-ALM binding: loading project count 1`
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -205,9 +192,9 @@ exports[`should render correctly for multi-ALM binding: submitting 1`] = `
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -216,10 +203,11 @@ exports[`should render correctly for multi-ALM binding: submitting 1`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -246,26 +234,9 @@ exports[`should render correctly for single-ALM binding 1`] = `
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={
-          <FormattedMessage
-            defaultMessage="settings.almintegration.create.tooltip"
-            id="settings.almintegration.create.tooltip"
-            values={
-              Object {
-                "alm": "alm.azure",
-                "link": <a
-                  href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer"
-                  rel="noopener noreferrer"
-                  target="_blank"
-                >
-                  settings.almintegration.create.tooltip.link
-                </a>,
-              }
-            }
-          />
-        }
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={true}
       >
         <Button
           data-test="settings__alm-create"
@@ -274,10 +245,11 @@ exports[`should render correctly for single-ALM binding 1`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -304,26 +276,9 @@ exports[`should render correctly for single-ALM binding 2`] = `
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={
-          <FormattedMessage
-            defaultMessage="settings.almintegration.create.tooltip"
-            id="settings.almintegration.create.tooltip"
-            values={
-              Object {
-                "alm": "alm.azure",
-                "link": <a
-                  href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer"
-                  rel="noopener noreferrer"
-                  target="_blank"
-                >
-                  settings.almintegration.create.tooltip.link
-                </a>,
-              }
-            }
-          />
-        }
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={true}
       >
         <Button
           data-test="settings__alm-create"
@@ -332,10 +287,11 @@ exports[`should render correctly for single-ALM binding 2`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -362,26 +318,9 @@ exports[`should render correctly for single-ALM binding 3`] = `
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={
-          <FormattedMessage
-            defaultMessage="settings.almintegration.create.tooltip"
-            id="settings.almintegration.create.tooltip"
-            values={
-              Object {
-                "alm": "alm.azure",
-                "link": <a
-                  href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer"
-                  rel="noopener noreferrer"
-                  target="_blank"
-                >
-                  settings.almintegration.create.tooltip.link
-                </a>,
-              }
-            }
-          />
-        }
+      <Connect(withAppState(CreationTooltip))
+        alm="azure"
+        preventCreation={true}
       >
         <Button
           data-test="settings__alm-create"
@@ -390,10 +329,11 @@ exports[`should render correctly for single-ALM binding 3`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="azure"
+      branchesEnabled={true}
       definition={
         Object {
           "key": "key",
@@ -420,9 +360,9 @@ exports[`should render correctly with validation 1`] = `
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="github"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -431,10 +371,11 @@ exports[`should render correctly with validation 1`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="github"
+      branchesEnabled={true}
       definition={
         Object {
           "appId": "123456",
@@ -470,9 +411,9 @@ exports[`should render correctly with validation: create a first 1`] = `
     <div
       className="big-spacer-top"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="github"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -481,7 +422,7 @@ exports[`should render correctly with validation: create a first 1`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionForm
       bindingDefinition={
@@ -515,9 +456,9 @@ exports[`should render correctly with validation: create a second 1`] = `
     <div
       className="spacer-bottom text-right"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="github"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -526,10 +467,11 @@ exports[`should render correctly with validation: create a second 1`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
     <AlmBindingDefinitionBox
       alm="github"
+      branchesEnabled={true}
       definition={
         Object {
           "appId": "123456",
@@ -583,9 +525,9 @@ exports[`should render correctly with validation: empty 1`] = `
     <div
       className="big-spacer-top"
     >
-      <Tooltip
-        mouseLeaveDelay={0.25}
-        overlay={null}
+      <Connect(withAppState(CreationTooltip))
+        alm="github"
+        preventCreation={false}
       >
         <Button
           data-test="settings__alm-create"
@@ -594,7 +536,7 @@ exports[`should render correctly with validation: empty 1`] = `
         >
           settings.almintegration.create
         </Button>
-      </Tooltip>
+      </Connect(withAppState(CreationTooltip))>
     </div>
   </DeferredSpinner>
 </div>
index 6740a5d328293f221331404a93b5559670461c0d..b282c81565436b0d3ebdd046130889bce9f686ca 100644 (file)
@@ -6,6 +6,7 @@ exports[`should render correctly 1`] = `
 >
   <AlmTab
     alm="azure"
+    branchesEnabled={true}
     createConfiguration={[Function]}
     defaultBinding={
       Object {
index a0b21c5d1fbf2553d280efa891ca4d664479c0b4..e7b2a23b1da3a2d9d077b13c570986cdf5ad0b8f 100644 (file)
@@ -6,6 +6,7 @@ exports[`should render correctly 1`] = `
 >
   <AlmTab
     alm="bitbucket"
+    branchesEnabled={true}
     createConfiguration={[Function]}
     defaultBinding={
       Object {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/CreationTooltip-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/CreationTooltip-test.tsx.snap
new file mode 100644 (file)
index 0000000..7892bc6
--- /dev/null
@@ -0,0 +1,40 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Tooltip
+  mouseLeaveDelay={0.25}
+  overlay={
+    <FormattedMessage
+      defaultMessage="settings.almintegration.create.tooltip"
+      id="settings.almintegration.create.tooltip"
+      values={
+        Object {
+          "alm": "alm.azure",
+          "link": <a
+            href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=community"
+            rel="noopener noreferrer"
+            target="_blank"
+          >
+            settings.almintegration.create.tooltip.link
+          </a>,
+        }
+      }
+    />
+  }
+>
+  <span>
+    Child
+  </span>
+</Tooltip>
+`;
+
+exports[`should render correctly 2`] = `
+<Tooltip
+  mouseLeaveDelay={0.25}
+  overlay={null}
+>
+  <span>
+    Child
+  </span>
+</Tooltip>
+`;
index e8575a5557135dc4484893e4c083690c2dc39686..7ad5b337f717d59d862e694ba9ee7aec6c6f03c8 100644 (file)
@@ -6,6 +6,7 @@ exports[`should render correctly: with branch support 1`] = `
 >
   <AlmTab
     alm="github"
+    branchesEnabled={true}
     createConfiguration={[Function]}
     defaultBinding={
       Object {
@@ -70,18 +71,3 @@ exports[`should render correctly: with branch support 1`] = `
   </div>
 </div>
 `;
-
-exports[`should render correctly: without branch support 1`] = `
-<div
-  className="bordered"
->
-  <div
-    className="big-padded"
-  >
-    <Connect(SubCategoryDefinitionsList)
-      category="almintegration"
-      subCategory="github"
-    />
-  </div>
-</div>
-`;
index d9e0818ec211d96cd9f183c95dea47c5827259a6..dfbd667ff1ceacea1119c047112c1b5f39a976f8 100644 (file)
@@ -6,6 +6,7 @@ exports[`should render correctly: with URL 1`] = `
 >
   <AlmTab
     alm="gitlab"
+    branchesEnabled={true}
     createConfiguration={[Function]}
     defaultBinding={
       Object {
@@ -71,6 +72,7 @@ exports[`should render correctly: with branch support 1`] = `
 >
   <AlmTab
     alm="gitlab"
+    branchesEnabled={true}
     createConfiguration={[Function]}
     defaultBinding={
       Object {
@@ -135,6 +137,7 @@ exports[`should render correctly: with no definitions 1`] = `
 >
   <AlmTab
     alm="gitlab"
+    branchesEnabled={true}
     createConfiguration={[Function]}
     defaultBinding={
       Object {
@@ -185,18 +188,3 @@ exports[`should render correctly: with no definitions 1`] = `
   </div>
 </div>
 `;
-
-exports[`should render correctly: without branch support 1`] = `
-<div
-  className="bordered"
->
-  <div
-    className="big-padded"
-  >
-    <Connect(SubCategoryDefinitionsList)
-      category="almintegration"
-      subCategory="gitlab"
-    />
-  </div>
-</div>
-`;
index 42a36e41c0fca6b300d31275efe1e0518e7995cf..e43c3e42cc59dc7119ccd9dbcc6ac31825f29d9c 100644 (file)
@@ -1126,6 +1126,9 @@ 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
 settings.almintegration.feature.mr_decoration.description=Add analysis and a Quality Gate to your Merge Requests directly in your ALM provider's interface.
+settings.almintegration.feature.pr_decoration.disabled=Disabled
+settings.almintegration.feature.pr_decoration.disabled.no_branches=Upgrade to {link} to enable this feature.
+settings.almintegration.feature.pr_decoration.disabled.no_branches.link=Developer Edition
 settings.almintegration.feature.alm_repo_import.title=Import repositories from your ALM
 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