aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-09-21 14:04:25 +0200
committerSonarTech <sonartech@sonarsource.com>2018-09-25 20:21:00 +0200
commitcd467657fc139c01074956aeca33bb57ac0b87bf (patch)
treeec9e14eba5f5831e038206126845dc5452404776
parent748c41c723cef0f11a0b90378773dafb3b51b4a0 (diff)
downloadsonarqube-cd467657fc139c01074956aeca33bb57ac0b87bf.tar.gz
sonarqube-cd467657fc139c01074956aeca33bb57ac0b87bf.zip
SONARCLOUD-120 update landing page of just created organization
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx11
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.css23
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.tsx71
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.tsx16
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationJustCreated-test.tsx49
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationPage-test.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationJustCreated-test.tsx.snap41
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/routes.ts7
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx18
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OnboardingModal-test.tsx.snap30
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/styles.css9
-rw-r--r--server/sonar-web/src/main/js/components/icons-components/Icon.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/icons-components/OnboardingAddMembersIcon.tsx44
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties2
15 files changed, 303 insertions, 28 deletions
diff --git a/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx b/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
index 78201f442d9..8e25b0e249b 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
@@ -88,6 +88,13 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
);
};
+ finishCreation = (key: string) => {
+ this.props.router.push({
+ pathname: getOrganizationUrl(key),
+ state: { justCreated: true }
+ });
+ };
+
handleOrganizationDetailsStepOpen = () => {
this.setState({ step: Step.OrganizationDetails });
};
@@ -99,13 +106,13 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
handlePaidPlanChoose = () => {
if (this.state.organization) {
- this.props.router.push(getOrganizationUrl(this.state.organization.key));
+ this.finishCreation(this.state.organization.key);
}
};
handleFreePlanChoose = () => {
return this.createOrganization().then(key => {
- this.props.router.push(getOrganizationUrl(key));
+ this.finishCreation(key);
});
};
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
index e466c12bb5c..6adb8f9d520 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
@@ -53,7 +53,10 @@ it('should render and create organization', async () => {
wrapper.find('PlanStep').prop<Function>('onFreePlanChoose')();
await waitAndUpdate(wrapper);
expect(createOrganization).toBeCalledWith(organization);
- expect(router.push).toBeCalledWith('/organizations/foo');
+ expect(router.push).toBeCalledWith({
+ pathname: '/organizations/foo',
+ state: { justCreated: true }
+ });
});
it('should preselect paid plan', async () => {
diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.css b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.css
new file mode 100644
index 00000000000..2405d972144
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.css
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.
+ */
+.organization-just-created {
+ margin: 120px auto 0;
+ width: 480px;
+}
diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.tsx b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.tsx
new file mode 100644
index 00000000000..c77fabe8c26
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationJustCreated.tsx
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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 { withRouter, WithRouterProps } from 'react-router';
+import { Organization } from '../../../app/types';
+import { Button } from '../../../components/ui/buttons';
+import OnboardingProjectIcon from '../../../components/icons-components/OnboardingProjectIcon';
+import OnboardingAddMembersIcon from '../../../components/icons-components/OnboardingAddMembersIcon';
+import { translate } from '../../../helpers/l10n';
+import '../../tutorials/styles.css';
+import './OrganizationJustCreated.css';
+
+interface Props {
+ organization: Organization;
+}
+
+export class OrganizationJustCreated extends React.PureComponent<Props & WithRouterProps> {
+ static contextTypes = {
+ openProjectOnboarding: () => null
+ };
+
+ handleNewProjectClick = () => {
+ this.context.openProjectOnboarding(this.props.organization.key);
+ };
+
+ handleAddMembersClick = () => {
+ const { organization } = this.props;
+ this.props.router.push(`/organizations/${organization.key}/members`);
+ };
+
+ render() {
+ return (
+ <div className="organization-just-created">
+ <h3 className="text-center">{translate('onboarding.create_organization.ready')}</h3>
+ <div className="onboarding-choices">
+ <Button className="onboarding-choice" onClick={this.handleNewProjectClick}>
+ <OnboardingProjectIcon className="big-spacer-bottom" />
+ <h6 className="onboarding-choice-name">
+ {translate('provisioning.create_new_project')}
+ </h6>
+ </Button>
+ <Button className="onboarding-choice" onClick={this.handleAddMembersClick}>
+ <OnboardingAddMembersIcon />
+ <h6 className="onboarding-choice-name">
+ {translate('organization.members.add.multiple')}
+ </h6>
+ </Button>
+ </div>
+ </div>
+ );
+ }
+}
+
+export default withRouter(OrganizationJustCreated);
diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.tsx b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.tsx
index a4581693d1b..5ae1a3503da 100644
--- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.tsx
+++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.tsx
@@ -20,6 +20,8 @@
import * as React from 'react';
import Helmet from 'react-helmet';
import { connect } from 'react-redux';
+import { Location } from 'history';
+import OrganizationJustCreated from './OrganizationJustCreated';
import OrganizationNavigation from '../navigation/OrganizationNavigation';
import { fetchOrganization } from '../actions';
import NotFound from '../../../app/components/NotFound';
@@ -34,7 +36,7 @@ import {
interface OwnProps {
children?: React.ReactNode;
- location: { pathname: string };
+ location: Location;
params: { organizationKey: string };
}
@@ -84,6 +86,16 @@ export class OrganizationPage extends React.PureComponent<Props, State> {
this.props.fetchOrganization(organizationKey).then(this.stopLoading, this.stopLoading);
};
+ renderChildren(organization: Organization) {
+ const { location } = this.props;
+ const justCreated = Boolean(location.state && location.state.justCreated);
+ return justCreated ? (
+ <OrganizationJustCreated organization={organization} />
+ ) : (
+ this.props.children
+ );
+ }
+
render() {
const { organization } = this.props;
@@ -105,7 +117,7 @@ export class OrganizationPage extends React.PureComponent<Props, State> {
organization={organization}
userOrganizations={this.props.userOrganizations}
/>
- {this.props.children}
+ {this.renderChildren(organization)}
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationJustCreated-test.tsx b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationJustCreated-test.tsx
new file mode 100644
index 00000000000..cc6298cd304
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationJustCreated-test.tsx
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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 { shallow } from 'enzyme';
+import { OrganizationJustCreated } from '../OrganizationJustCreated';
+import { Organization } from '../../../../app/types';
+import { click } from '../../../../helpers/testUtils';
+
+const organization: Organization = { key: 'foo', name: 'Foo' };
+
+it('should render', () => {
+ // @ts-ignore
+ expect(shallow(<OrganizationJustCreated organization={organization} />)).toMatchSnapshot();
+});
+
+it('should create new project', () => {
+ const openProjectOnboarding = jest.fn();
+ // @ts-ignore
+ const wrapper = shallow(<OrganizationJustCreated organization={organization} />, {
+ context: { openProjectOnboarding }
+ });
+ click(wrapper.find('Button').first());
+ expect(openProjectOnboarding).toBeCalledWith('foo');
+});
+
+it('should add members', () => {
+ const router = { push: jest.fn() };
+ // @ts-ignore
+ const wrapper = shallow(<OrganizationJustCreated organization={organization} router={router} />);
+ click(wrapper.find('Button').last());
+ expect(router.push).toBeCalledWith('/organizations/foo/members');
+});
diff --git a/server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationPage-test.tsx b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationPage-test.tsx
index 5bf896954b5..0f97587fa9d 100644
--- a/server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationPage-test.tsx
+++ b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationPage-test.tsx
@@ -19,6 +19,7 @@
*/
import * as React from 'react';
import { shallow } from 'enzyme';
+import { Location } from 'history';
import { OrganizationPage } from '../OrganizationPage';
const fetchOrganization = jest.fn().mockResolvedValue(undefined);
@@ -54,7 +55,7 @@ function getWrapper(props = {}) {
<OrganizationPage
currentUser={{ isLoggedIn: false }}
fetchOrganization={fetchOrganization}
- location={{ pathname: 'foo' }}
+ location={{ pathname: 'foo' } as Location}
params={{ organizationKey: 'foo' }}
userOrganizations={[]}
{...props}>
diff --git a/server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationJustCreated-test.tsx.snap b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationJustCreated-test.tsx.snap
new file mode 100644
index 00000000000..4a96855b821
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationJustCreated-test.tsx.snap
@@ -0,0 +1,41 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render 1`] = `
+<div
+ className="organization-just-created"
+>
+ <h3
+ className="text-center"
+ >
+ onboarding.create_organization.ready
+ </h3>
+ <div
+ className="onboarding-choices"
+ >
+ <Button
+ className="onboarding-choice"
+ onClick={[Function]}
+ >
+ <OnboardingProjectIcon
+ className="big-spacer-bottom"
+ />
+ <h6
+ className="onboarding-choice-name"
+ >
+ provisioning.create_new_project
+ </h6>
+ </Button>
+ <Button
+ className="onboarding-choice"
+ onClick={[Function]}
+ >
+ <OnboardingAddMembersIcon />
+ <h6
+ className="onboarding-choice-name"
+ >
+ organization.members.add.multiple
+ </h6>
+ </Button>
+ </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/organizations/routes.ts b/server/sonar-web/src/main/js/apps/organizations/routes.ts
index d78634091ec..e3279292d9c 100644
--- a/server/sonar-web/src/main/js/apps/organizations/routes.ts
+++ b/server/sonar-web/src/main/js/apps/organizations/routes.ts
@@ -34,8 +34,11 @@ const routes = [
{
indexRoute: {
onEnter(nextState: RouterState, replace: RedirectFunction) {
- const { params } = nextState;
- replace(`/organizations/${params.organizationKey}/projects`);
+ const { location, params } = nextState;
+ const justCreated = Boolean(location.state && location.state.justCreated);
+ if (!justCreated) {
+ replace(`/organizations/${params.organizationKey}/projects`);
+ }
}
}
},
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx
index 1ed6b84045e..b41edb8e99e 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx
+++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.tsx
@@ -68,18 +68,24 @@ export class OnboardingModal extends React.PureComponent<Props> {
</div>
<div className="modal-simple-body text-center onboarding-choices">
<Button className="onboarding-choice" onClick={this.props.onOpenProjectOnboarding}>
- <OnboardingProjectIcon />
- <span>{translate('onboarding.analyze_public_code')}</span>
+ <OnboardingProjectIcon className="big-spacer-bottom" />
+ <h6 className="onboarding-choice-name">
+ {translate('onboarding.analyze_public_code')}
+ </h6>
<p className="note">{translate('onboarding.analyze_public_code.note')}</p>
</Button>
<Button className="onboarding-choice" onClick={this.props.onOpenOrganizationOnboarding}>
- <OnboardingPrivateIcon />
- <span>{translate('onboarding.analyze_private_code')}</span>
+ <OnboardingPrivateIcon className="big-spacer-bottom" />
+ <h6 className="onboarding-choice-name">
+ {translate('onboarding.analyze_private_code')}
+ </h6>
<p className="note">{translate('onboarding.analyze_private_code.note')}</p>
</Button>
<Button className="onboarding-choice" onClick={this.props.onOpenTeamOnboarding}>
- <OnboardingTeamIcon />
- <span>{translate('onboarding.contribute_existing_project')}</span>
+ <OnboardingTeamIcon className="big-spacer-bottom" />
+ <h6 className="onboarding-choice-name">
+ {translate('onboarding.contribute_existing_project')}
+ </h6>
<p className="note">{translate('onboarding.contribute_existing_project.note')}</p>
</Button>
</div>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OnboardingModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OnboardingModal-test.tsx.snap
index 18b2f16f846..1b46fdaca66 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OnboardingModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OnboardingModal-test.tsx.snap
@@ -26,10 +26,14 @@ exports[`renders correctly 1`] = `
className="onboarding-choice"
onClick={[MockFunction]}
>
- <OnboardingProjectIcon />
- <span>
+ <OnboardingProjectIcon
+ className="big-spacer-bottom"
+ />
+ <h6
+ className="onboarding-choice-name"
+ >
onboarding.analyze_public_code
- </span>
+ </h6>
<p
className="note"
>
@@ -40,10 +44,14 @@ exports[`renders correctly 1`] = `
className="onboarding-choice"
onClick={[MockFunction]}
>
- <OnboardingPrivateIcon />
- <span>
+ <OnboardingPrivateIcon
+ className="big-spacer-bottom"
+ />
+ <h6
+ className="onboarding-choice-name"
+ >
onboarding.analyze_private_code
- </span>
+ </h6>
<p
className="note"
>
@@ -54,10 +62,14 @@ exports[`renders correctly 1`] = `
className="onboarding-choice"
onClick={[MockFunction]}
>
- <OnboardingTeamIcon />
- <span>
+ <OnboardingTeamIcon
+ className="big-spacer-bottom"
+ />
+ <h6
+ className="onboarding-choice-name"
+ >
onboarding.contribute_existing_project
- </span>
+ </h6>
<p
className="note"
>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/styles.css b/server/sonar-web/src/main/js/apps/tutorials/styles.css
index da2571a369d..e7cc5a727f6 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/styles.css
+++ b/server/sonar-web/src/main/js/apps/tutorials/styles.css
@@ -65,7 +65,7 @@
.onboarding-choice {
display: flex;
flex-direction: column;
- justify-content: flex-end;
+ justify-content: center;
padding: calc(2 * var(--gridSize));
width: 190px;
height: 190px;
@@ -78,12 +78,13 @@
.onboarding-choice svg {
color: var(--gray40);
- margin-bottom: calc(3 * var(--gridSize));
}
-.onboarding-choice span {
+.onboarding-choice-name {
+ padding-top: var(--gridSize);
+ padding-bottom: calc(0.5 * var(--gridSize));
+ color: inherit;
font-size: var(--mediumFontSize);
- margin-bottom: calc(var(--gridSize) / 2);
}
.onboarding-choice .note {
diff --git a/server/sonar-web/src/main/js/components/icons-components/Icon.tsx b/server/sonar-web/src/main/js/components/icons-components/Icon.tsx
index 25560e4eac8..5e2baa27f62 100644
--- a/server/sonar-web/src/main/js/components/icons-components/Icon.tsx
+++ b/server/sonar-web/src/main/js/components/icons-components/Icon.tsx
@@ -26,7 +26,7 @@ export interface IconProps {
}
interface Props {
- children: React.ReactElement<any>;
+ children: React.ReactNode;
className?: string;
size?: number;
style?: React.CSSProperties;
diff --git a/server/sonar-web/src/main/js/components/icons-components/OnboardingAddMembersIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/OnboardingAddMembersIcon.tsx
new file mode 100644
index 00000000000..5dcdff50549
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/icons-components/OnboardingAddMembersIcon.tsx
@@ -0,0 +1,44 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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 Icon, { IconProps } from './Icon';
+
+export default function OnboardingAddMembersIcon({
+ className,
+ fill = 'currentColor',
+ size = 64
+}: IconProps) {
+ return (
+ <Icon className={className} height={(size / 64) * 80} viewBox="0 0 64 80" width={size}>
+ <path
+ d="M49 34c0 9.389-7.611 17-17 17s-17-7.611-17-17 7.611-17 17-17 17 7.611 17 17z"
+ style={{ fill: 'none', stroke: fill, strokeWidth: 2 }}
+ />
+ <path
+ d="M36 32c0 2.2-1.8 4-4 4s-4-1.8-4-4v-1c0-2.2 1.8-4 4-4s4 1.8 4 4v1zm4 39a8 8 0 1 1-16 0 8 8 0 0 1 16 0z"
+ style={{ fill: 'none', stroke: fill, strokeWidth: 2 }}
+ />
+ <path
+ d="M33 70h2v2h-2v2h-2v-2h-2v-2h2v-2h2v2zm-5-14l-.072-.001c-1.521-.054-2.834-1.337-2.925-2.855L25 50h2c0 1.745-.532 3.91.952 3.999L28 54h8v.002l.072-.005c.506-.042.922-.489.928-1.003V50h2c0 1.024.011 2.048-.001 3.072-.054 1.518-1.337 2.834-2.855 2.925l-.072.002L36 56v8h-2v-7.982c-1.333.007-2.667.007-4 0V64h-2v-8zm-7 0H1V10 0h62v56H43v-2h18V10H3v44h18v2zm38-4H43v-2h14V14H7v36h14v2H5V12h54v40zm-19-9l1 .017c-.03 1.79-2.454 2.506-3.918 2.717-4.074.584-8.503.911-12.176-.477-.949-.358-1.887-1.119-1.906-2.24l.191-.017H23v-3.566l5.38-3.228.913-.913 1.414 1.414-1.087 1.087L25 40.566v2.438c.067 1.304 10.98 2.117 13.844.157.076-.052.152-.172.156-.178v-2.417l-4.62-2.772-1.087-1.087 1.414-1.414.913.913L41 39.434V43h-1zm14-4h-2v-2h2v2zm-42 0h-2v-2h2v2zm42-4h-2v-2h2v2zm-42 0h-2v-2h2v2zm42-4h-2v-2h2v2zm-42 0h-2v-2h2v2zm20.198-10.999c3.529.062 6.837 1.669 9.386 4.169l-1.289 1.539c-4.178-4.152-11.167-5.254-16.359-.228l-.231.228-1.41-1.418c2.633-2.617 6.031-4.313 9.903-4.29zM3 2v6h58V2H3zm56 4H17V4h42v2zM11 6H9V4h2v2zM7 6H5V4h2v2zm8 0h-2V4h2v2z"
+ style={{ fill, fillRule: 'nonzero' }}
+ />
+ </Icon>
+ );
+}
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 c63dff4130a..76f5cb99b84 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -2613,6 +2613,7 @@ organization.url.description=Url of the homepage of the organization.
organization.members.page=Members
organization.members.page.description=Add users to the organization and grant them permissions to work on the projects. See {link} documentation.
organization.members.add=Add a member
+organization.members.add.multiple=Add members
organization.members.x_groups={0} group(s)
organization.members.members=member(s)
organization.members.remove=Remove from organization's members
@@ -2722,6 +2723,7 @@ onboarding.create_organization.choose_plan=Choose a plan
onboarding.create_organization.choose_payment_method=Choose payment solution
onboarding.create_organization.enter_your_coupon=Enter your coupon
onboarding.create_organization.create_and_upgrade=Create Organization and Upgrade
+onboarding.create_organization.ready=All set! Your organization is now ready to go
onboarding.team.header=Join a team
onboarding.team.first_step=Well congrats, the first step is done!