From: Jeremy Davis Date: Thu, 4 Jun 2020 07:35:00 +0000 (+0200) Subject: SONAR-13479 new creation menu X-Git-Tag: 8.4.0.35506~14 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=0f5ec7677c8ce61d568b78ead47a6d1279f796ba;p=sonarqube.git SONAR-13479 new creation menu --- diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavPlus.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavPlus.tsx index 2d3f41d9629..f94ebbb8574 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavPlus.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavPlus.tsx @@ -18,33 +18,46 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { Link, withRouter, WithRouterProps } from 'react-router'; import Dropdown from 'sonar-ui-common/components/controls/Dropdown'; import PlusIcon from 'sonar-ui-common/components/icons/PlusIcon'; import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getAlmSettings } from '../../../../api/alm-settings'; import { getComponentNavigation } from '../../../../api/nav'; import CreateFormShim from '../../../../apps/portfolio/components/CreateFormShim'; +import { Router, withRouter } from '../../../../components/hoc/withRouter'; import { getExtensionStart } from '../../../../helpers/extensions'; -import { isSonarCloud } from '../../../../helpers/system'; import { getPortfolioAdminUrl, getPortfolioUrl } from '../../../../helpers/urls'; import { hasGlobalPermission } from '../../../../helpers/users'; +import { AlmKeys } from '../../../../types/alm-settings'; +import { ComponentQualifier } from '../../../../types/component'; +import GlobalNavPlusMenu from './GlobalNavPlusMenu'; interface Props { appState: Pick; currentUser: T.LoggedInUser; + router: Router; } interface State { - createPortfolio: boolean; + boundAlms: Array; + creatingComponent?: ComponentQualifier; governanceReady: boolean; } -export class GlobalNavPlus extends React.PureComponent { +/* + * ALMs for which the import feature has been implemented + */ +const IMPORT_COMPATIBLE_ALMS = [AlmKeys.Bitbucket, AlmKeys.GitHub]; + +export class GlobalNavPlus extends React.PureComponent { mounted = false; - state: State = { createPortfolio: false, governanceReady: false }; + state: State = { boundAlms: [], governanceReady: false }; componentDidMount() { this.mounted = true; + + this.fetchAlmBindings(); + if (this.props.appState.qualifiers.includes('VW')) { getExtensionStart('governance/console').then( () => { @@ -61,26 +74,31 @@ export class GlobalNavPlus extends React.PureComponent) => { - event.preventDefault(); - this.props.router.push('/projects/create'); + closeComponentCreationForm = () => { + this.setState({ creatingComponent: undefined }); }; - openCreatePortfolioForm = () => { - this.setState({ createPortfolio: true }); - }; + fetchAlmBindings = async () => { + const almSettings = await getAlmSettings(); + + // Import is only available if exactly one binding is configured + const boundAlms = IMPORT_COMPATIBLE_ALMS.filter(key => { + const count = almSettings.filter(s => s.alm === key).length; + return count === 1; + }); - closeCreatePortfolioForm = () => { - this.setState({ createPortfolio: false }); + if (this.mounted) { + this.setState({ + boundAlms + }); + } }; - handleNewPortfolioClick = (event: React.MouseEvent) => { - event.preventDefault(); - event.currentTarget.blur(); - this.openCreatePortfolioForm(); + handleComponentCreationClick = (qualifier: ComponentQualifier) => { + this.setState({ creatingComponent: qualifier }); }; - handleCreatePortfolio = ({ key, qualifier }: { key: string; qualifier: string }) => { + handleComponentCreate = ({ key, qualifier }: { key: string; qualifier: ComponentQualifier }) => { return getComponentNavigation({ component: key }).then(data => { if ( data.configuration && @@ -93,104 +111,50 @@ export class GlobalNavPlus extends React.PureComponent - - {isSonarCloud() - ? translate('provisioning.analyze_new_project') - : translate('my_account.create_new.TRK')} - - - ); - } - - renderCreateOrganization(canCreateOrg: boolean) { - if (!canCreateOrg) { - return null; - } - - return ( -
  • - - {translate('my_account.create_new_organization')} - -
  • - ); - } - - renderCreatePortfolio(showGovernanceEntry: boolean, defaultQualifier?: string) { - const governanceInstalled = this.props.appState.qualifiers.includes('VW'); - if (!governanceInstalled || !showGovernanceEntry) { - return null; - } - - return ( -
  • - - {defaultQualifier - ? translate('my_account.create_new', defaultQualifier) - : translate('my_account.create_new_portfolio_application')} - -
  • - ); - } - render() { - const { currentUser } = this.props; - const canCreateApplication = hasGlobalPermission(currentUser, 'applicationcreator'); - const canCreateOrg = isSonarCloud(); - const canCreatePortfolio = hasGlobalPermission(currentUser, 'portfoliocreator'); - const canCreateProject = isSonarCloud() || hasGlobalPermission(currentUser, 'provisioning'); - - if (!canCreateProject && !canCreateApplication && !canCreatePortfolio && !canCreateOrg) { + const { appState, currentUser } = this.props; + const { boundAlms, governanceReady, creatingComponent } = this.state; + const governanceInstalled = appState.qualifiers.includes(ComponentQualifier.Portfolio); + const canCreateApplication = + governanceInstalled && hasGlobalPermission(currentUser, 'applicationcreator'); + const canCreatePortfolio = + governanceInstalled && hasGlobalPermission(currentUser, 'portfoliocreator'); + const canCreateProject = hasGlobalPermission(currentUser, 'provisioning'); + + if (!canCreateProject && !canCreateApplication && !canCreatePortfolio) { return null; } - let defaultQualifier: string | undefined; - if (!canCreateApplication) { - defaultQualifier = 'VW'; - } else if (!canCreatePortfolio) { - defaultQualifier = 'APP'; - } - return ( <> - {this.renderCreateProject(canCreateProject)} - {this.renderCreateOrganization(canCreateOrg)} - {this.renderCreatePortfolio( - canCreateApplication || canCreatePortfolio, - defaultQualifier - )} - + } tagName="li"> + title={translate('my_account.create_new_project_portfolio_or_application')}> - {this.state.governanceReady && this.state.createPortfolio && ( + {governanceReady && creatingComponent && ( )} @@ -198,4 +162,4 @@ export class GlobalNavPlus extends React.PureComponent(GlobalNavPlus); +export default withRouter(GlobalNavPlus); diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavPlusMenu.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavPlusMenu.tsx new file mode 100644 index 00000000000..b3891faebb5 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavPlusMenu.tsx @@ -0,0 +1,99 @@ +/* + * 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 { Link } from 'react-router'; +import { ButtonLink } from 'sonar-ui-common/components/controls/buttons'; +import ChevronsIcon from 'sonar-ui-common/components/icons/ChevronsIcon'; +import QualifierIcon from 'sonar-ui-common/components/icons/QualifierIcon'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; +import { ComponentQualifier } from '../../../../types/component'; + +export interface GlobalNavPlusMenuProps { + canCreateApplication: boolean; + canCreatePortfolio: boolean; + canCreateProject: boolean; + compatibleAlms: Array; + onComponentCreationClick: (componentQualifier: ComponentQualifier) => void; +} + +function renderCreateProjectOptions(compatibleAlms: Array) { + return [...compatibleAlms, 'manual'].map(alm => ( +
  • + + {alm === 'manual' ? ( + + ) : ( + {alm} + )} + {translate('my_account.add_project', alm)} + +
  • + )); +} + +function renderCreateComponent( + componentQualifier: ComponentQualifier, + onClick: (qualifier: ComponentQualifier) => void +) { + return ( +
  • + onClick(componentQualifier)}> + + {translate('my_account.create_new', componentQualifier)} + +
  • + ); +} + +export default function GlobalNavPlusMenu(props: GlobalNavPlusMenuProps) { + const { canCreateApplication, canCreatePortfolio, canCreateProject, compatibleAlms } = props; + + return ( +
      + {canCreateProject && ( + <> +
    • + {translate('my_account.add_project')} +
    • + {renderCreateProjectOptions(compatibleAlms)} + + )} + {(canCreateApplication || canCreatePortfolio) && ( + <> + {canCreateProject &&
    • } + {canCreatePortfolio && + renderCreateComponent(ComponentQualifier.Portfolio, props.onComponentCreationClick)} + {canCreateApplication && + renderCreateComponent(ComponentQualifier.Application, props.onComponentCreationClick)} + + )} +
    + ); +} diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavPlus-test.tsx b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavPlus-test.tsx index 4914ea8d02a..62efab3775a 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavPlus-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavPlus-test.tsx @@ -17,88 +17,105 @@ * 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, ShallowWrapper } from 'enzyme'; +import { shallow } from 'enzyme'; import * as React from 'react'; -import { click } from 'sonar-ui-common/helpers/testUtils'; -import { isSonarCloud } from '../../../../../helpers/system'; -import { mockRouter } from '../../../../../helpers/testMocks'; +import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; +import { getAlmSettings } from '../../../../../api/alm-settings'; +import { getComponentNavigation } from '../../../../../api/nav'; +import CreateFormShim from '../../../../../apps/portfolio/components/CreateFormShim'; +import { mockLoggedInUser, mockRouter } from '../../../../../helpers/testMocks'; +import { getPortfolioAdminUrl, getPortfolioUrl } from '../../../../../helpers/urls'; +import { AlmKeys } from '../../../../../types/alm-settings'; +import { ComponentQualifier } from '../../../../../types/component'; import { GlobalNavPlus } from '../GlobalNavPlus'; -jest.mock('../../../../../helpers/system', () => ({ - isSonarCloud: jest.fn() +const PROJECT_CREATION_RIGHT = 'provisioning'; +const APP_CREATION_RIGHT = 'applicationcreator'; +const PORTFOLIO_CREATION_RIGHT = 'portfoliocreator'; + +jest.mock('../../../../../api/alm-settings', () => ({ + getAlmSettings: jest.fn().mockResolvedValue([]) })); -beforeEach(() => { - (isSonarCloud as jest.Mock).mockReturnValue(false); -}); +jest.mock('../../../../../api/nav', () => ({ + getComponentNavigation: jest.fn().mockResolvedValue({}) +})); -it('render', () => { - const wrapper = getWrapper(); - expect(wrapper.find('Dropdown')).toMatchSnapshot(); -}); +jest.mock('../../../../../helpers/urls', () => ({ + getPortfolioUrl: jest.fn(), + getPortfolioAdminUrl: jest.fn() +})); -it('opens onboarding', () => { - const push = jest.fn(); - const wrapper = getOverlayWrapper(getWrapper({ router: mockRouter({ push }) })); - click(wrapper.find('.js-new-project')); - expect(push).toBeCalled(); -}); +it('should render correctly', () => { + expect(shallowRender().type()).toBeNull(); + expect( + shallowRender([APP_CREATION_RIGHT, PORTFOLIO_CREATION_RIGHT, PROJECT_CREATION_RIGHT]) + ).toMatchSnapshot('no governance'); -it('should display create new project link when user has permission only', () => { - expect(getWrapper({}, []).find('Dropdown').length).toEqual(0); + const wrapper = shallowRender( + [APP_CREATION_RIGHT, PORTFOLIO_CREATION_RIGHT, PROJECT_CREATION_RIGHT], + true + ); + wrapper.setState({ boundAlms: ['bitbucket'] }); + expect(wrapper).toMatchSnapshot('full rights and alms'); }); -it('should display create new organization on SonarCloud only', () => { - (isSonarCloud as jest.Mock).mockReturnValue(true); - expect(getOverlayWrapper(getWrapper())).toMatchSnapshot(); -}); +it('should load correctly', async () => { + (getAlmSettings as jest.Mock).mockResolvedValueOnce([ + { alm: AlmKeys.Azure, key: 'A1' }, + { alm: AlmKeys.Bitbucket, key: 'B1' }, + { alm: AlmKeys.GitHub, key: 'GH1' } + ]); -it('should display new organization and new project on SonarCloud', () => { - (isSonarCloud as jest.Mock).mockReturnValue(true); - expect(getOverlayWrapper(getWrapper({}, []))).toMatchSnapshot(); -}); + const wrapper = shallowRender(); -it('should display create portfolio and application', () => { - checkOpenCreatePortfolio(['applicationcreator', 'portfoliocreator'], undefined); + await waitAndUpdate(wrapper); + + expect(getAlmSettings).toBeCalled(); + expect(wrapper.state().boundAlms).toEqual([AlmKeys.Bitbucket, AlmKeys.GitHub]); }); -it('should display create portfolio', () => { - checkOpenCreatePortfolio(['portfoliocreator'], 'VW'); +it('should display component creation form', () => { + const wrapper = shallowRender([PORTFOLIO_CREATION_RIGHT], true); + + wrapper.instance().handleComponentCreationClick(ComponentQualifier.Portfolio); + wrapper.setState({ governanceReady: true }); + + expect(wrapper.find(CreateFormShim).exists()).toBe(true); }); -it('should display create application', () => { - checkOpenCreatePortfolio(['applicationcreator'], 'APP'); +describe('handleComponentCreate', () => { + (getComponentNavigation as jest.Mock) + .mockResolvedValueOnce({ + configuration: { extensions: [{ key: 'governance/console', name: 'governance' }] } + }) + .mockResolvedValueOnce({}); + + const portfolio = { key: 'portfolio', qualifier: ComponentQualifier.Portfolio }; + + const wrapper = shallowRender([], true); + + it('should redirect to admin', async () => { + wrapper.instance().handleComponentCreate(portfolio); + await waitAndUpdate(wrapper); + expect(getPortfolioAdminUrl).toBeCalledWith(portfolio.key, portfolio.qualifier); + expect(wrapper.state().creatingComponent).toBeUndefined(); + }); + + it('should redirect to dashboard', async () => { + wrapper.instance().handleComponentCreate(portfolio); + await waitAndUpdate(wrapper); + + expect(getPortfolioUrl).toBeCalledWith(portfolio.key); + }); }); -function getWrapper(props = {}, globalPermissions?: string[]) { - return shallow( - // @ts-ignore avoid passing everything from WithRouterProps +function shallowRender(permissions: string[] = [], enableGovernance = false) { + return shallow( ); } - -function getOverlayWrapper(wrapper: ShallowWrapper) { - return shallow(wrapper.find('Dropdown').prop('overlay')); -} - -function checkOpenCreatePortfolio(permissions: string[], defaultQualifier?: string) { - const wrapper = getWrapper({ appState: { qualifiers: ['VW'] } }, permissions); - wrapper.setState({ governanceReady: true }); - const overlayWrapper = getOverlayWrapper(wrapper); - expect(overlayWrapper.find('.js-new-portfolio')).toMatchSnapshot(); - - click(overlayWrapper.find('.js-new-portfolio')); - wrapper.update(); - expect(wrapper.find('CreateFormShim').exists()).toBe(true); - expect(wrapper.find('CreateFormShim').prop('defaultQualifier')).toBe(defaultQualifier); -} diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavPlusMenu-test.tsx b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavPlusMenu-test.tsx new file mode 100644 index 00000000000..4eb0f379c14 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavPlusMenu-test.tsx @@ -0,0 +1,76 @@ +/* + * 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 { ButtonLink } from 'sonar-ui-common/components/controls/buttons'; +import { AlmKeys } from '../../../../../types/alm-settings'; +import { ComponentQualifier } from '../../../../../types/component'; +import GlobalNavPlusMenu, { GlobalNavPlusMenuProps } from '../GlobalNavPlusMenu'; + +it('should render correctly', () => { + expect(shallowRender({ canCreateApplication: true })).toMatchSnapshot('app only'); + expect(shallowRender({ canCreatePortfolio: true })).toMatchSnapshot('portfolio only'); + expect(shallowRender({ canCreateProject: true })).toMatchSnapshot('project only'); + expect( + shallowRender({ canCreateProject: true, compatibleAlms: [AlmKeys.Bitbucket] }) + ).toMatchSnapshot('imports'); + expect( + shallowRender({ + canCreateApplication: true, + canCreatePortfolio: true, + canCreateProject: true, + compatibleAlms: [AlmKeys.Bitbucket] + }) + ).toMatchSnapshot('all'); +}); + +it('should trigger onClick', () => { + const onComponentCreationClick = jest.fn(); + const wrapper = shallowRender({ + canCreateApplication: true, + canCreatePortfolio: true, + onComponentCreationClick + }); + + // Portfolio + const portfolioButton = wrapper.find(ButtonLink).at(0); + portfolioButton.simulate('click'); + expect(onComponentCreationClick).toBeCalledWith(ComponentQualifier.Portfolio); + + onComponentCreationClick.mockClear(); + + // App + const appButton = wrapper.find(ButtonLink).at(1); + appButton.simulate('click'); + expect(onComponentCreationClick).toBeCalledWith(ComponentQualifier.Application); +}); + +function shallowRender(overrides: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavPlus-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavPlus-test.tsx.snap index 11427944e71..658c06d2ab9 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavPlus-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavPlus-test.tsx.snap @@ -1,112 +1,57 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`render 1`] = ` - -
  • - - my_account.create_new.TRK - -
  • - - } - tagName="li" -> - + + } + tagName="li" > - - -
    -`; - -exports[`should display create application 1`] = ` - - my_account.create_new.APP - -`; - -exports[`should display create new organization on SonarCloud only 1`] = ` - + + `; -exports[`should display create portfolio 1`] = ` - - my_account.create_new.VW - -`; - -exports[`should display create portfolio and application 1`] = ` - - my_account.create_new_portfolio_application - -`; - -exports[`should display new organization and new project on SonarCloud 1`] = ` - + + `; diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavPlusMenu-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavPlusMenu-test.tsx.snap new file mode 100644 index 00000000000..e10a9f2ac36 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavPlusMenu-test.tsx.snap @@ -0,0 +1,224 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: all 1`] = ` +
      +
    • + + my_account.add_project + +
    • +
    • + + bitbucket + my_account.add_project.bitbucket + +
    • +
    • + + + my_account.add_project.manual + +
    • +
    • +
    • + + + my_account.create_new.VW + +
    • +
    • + + + my_account.create_new.APP + +
    • +
    +`; + +exports[`should render correctly: app only 1`] = ` +
      +
    • + + + my_account.create_new.APP + +
    • +
    +`; + +exports[`should render correctly: imports 1`] = ` +
      +
    • + + my_account.add_project + +
    • +
    • + + bitbucket + my_account.add_project.bitbucket + +
    • +
    • + + + my_account.add_project.manual + +
    • +
    +`; + +exports[`should render correctly: portfolio only 1`] = ` +
      +
    • + + + my_account.create_new.VW + +
    • +
    +`; + +exports[`should render correctly: project only 1`] = ` +
      +
    • + + my_account.add_project + +
    • +
    • + + + my_account.add_project.manual + +
    • +
    +`; diff --git a/server/sonar-web/src/main/js/app/styles/components/menu.css b/server/sonar-web/src/main/js/app/styles/components/menu.css index 2062096a1de..64d39525208 100644 --- a/server/sonar-web/src/main/js/app/styles/components/menu.css +++ b/server/sonar-web/src/main/js/app/styles/components/menu.css @@ -37,6 +37,7 @@ .menu-item, .menu > li > a, +.menu > li > button, .menu > li > span { display: block; padding: 4px 16px; @@ -54,6 +55,12 @@ transition: none; } +.menu > li > button { + color: var(--baseFontColor); + text-align: left; + width: 100%; +} + .menu > li > a.rich-item { display: flex; align-items: center; @@ -82,7 +89,9 @@ } .menu > li > a:hover, -.menu > li > a:focus { +.menu > li > a:focus, +.menu > li > button:hover, +.menu > li > button:focus { text-decoration: none; color: var(--baseFontColor); background-color: var(--barBackgroundColor); diff --git a/server/sonar-web/src/main/js/app/styles/init/misc.css b/server/sonar-web/src/main/js/app/styles/init/misc.css index b05d35cd039..b987a065653 100644 --- a/server/sonar-web/src/main/js/app/styles/init/misc.css +++ b/server/sonar-web/src/main/js/app/styles/init/misc.css @@ -395,6 +395,11 @@ th.huge-spacer-right { align-items: center; } +.display-flex-justify-start { + display: flex !important; + justify-content: flex-start !important; +} + .display-flex-justify-center { display: flex !important; justify-content: center; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap index 6ba025c784e..fa7fa8fc11d 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap @@ -68,7 +68,7 @@ exports[`should render correctly: no projects 1`] = ` Object { "pathname": "/projects/create", "query": Object { - "mode": "bbs", + "mode": "bitbucket", "resetPat": 1, }, } diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap index ced072128a2..03b1ab6bdf0 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap @@ -263,7 +263,7 @@ exports[`should render correctly: no repos 1`] = ` Object { "pathname": "/projects/create", "query": Object { - "mode": "bbs", + "mode": "bitbucket", "resetPat": 1, }, } diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap index 05531913bb2..99b42043c24 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap @@ -81,7 +81,7 @@ exports[`should render correctly if the BBS method is selected 1`] = ` "key": "key", "pathname": "/path", "query": Object { - "mode": "bbs", + "mode": "bitbucket", }, "search": "", "state": Object {}, diff --git a/server/sonar-web/src/main/js/apps/create/project/types.ts b/server/sonar-web/src/main/js/apps/create/project/types.ts index b316a4e781a..d991cd60d3a 100644 --- a/server/sonar-web/src/main/js/apps/create/project/types.ts +++ b/server/sonar-web/src/main/js/apps/create/project/types.ts @@ -19,5 +19,5 @@ */ export enum CreateProjectModes { Manual = 'manual', - BitbucketServer = 'bbs' + BitbucketServer = 'bitbucket' } diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/CreateFormShim.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/CreateFormShim.tsx index 7dd89ec8cc2..96f9ab98e86 100644 --- a/server/sonar-web/src/main/js/apps/portfolio/components/CreateFormShim.tsx +++ b/server/sonar-web/src/main/js/apps/portfolio/components/CreateFormShim.tsx @@ -21,11 +21,12 @@ import * as React from 'react'; import * as theme from '../../../app/theme'; import { getCurrentL10nBundle } from '../../../helpers/l10n'; import { getBaseUrl } from '../../../helpers/system'; +import { ComponentQualifier } from '../../../types/component'; interface Props { defaultQualifier?: string; onClose: () => void; - onCreate: (portfolio: { key: string; qualifier: string }) => void; + onCreate: (portfolio: { key: string; qualifier: ComponentQualifier }) => void; } export default class CreateFormShim extends React.Component { 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 5aafe022028..03d6729ba44 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1787,12 +1787,14 @@ my_account.create_organization=Create Organization my_account.search_project=Search Project my_account.set_notifications_for=Search a project by name my_account.set_notifications_for.title=Add a project -my_account.create_new_portfolio_application=Create new portfolio / application my_account.create_new.TRK=Create new project -my_account.create_new.VW=Create new portfolio -my_account.create_new.APP=Create new application -my_account.create_new_organization=Create new organization -my_account.create_new_project_or_organization=Analyze new project or create new organization +my_account.create_new.VW=Create portfolio +my_account.create_new.APP=Create application +my_account.add_project=Add project +my_account.add_project.manual=Manually +my_account.add_project.github=GitHub +my_account.add_project.bitbucket=Bitbucket + my_account.create_new_project_portfolio_or_application=Analyze new project / Create new portfolio or application @@ -1801,7 +1803,6 @@ my_account.create_new_project_portfolio_or_application=Analyze new project / Cre # PROJECT PROVISIONING # #------------------------------------------------------------------------------ -provisioning.analyze_new_project=Analyze new project provisioning.no_analysis=No analysis has been performed since creation. The only available section is the configuration. provisioning.no_analysis.delete=Either you should retry analysis or simply {link}. provisioning.no_analysis.delete_project=delete the project