From: Stas Vilchik Date: Tue, 28 Nov 2017 14:56:44 +0000 (+0100) Subject: SONAR-9000 display all organizations a user is a member of X-Git-Tag: 7.0-RC1~270 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d1157c4101390a94167aebad27d054c93e0d66f4;p=sonarqube.git SONAR-9000 display all organizations a user is a member of --- diff --git a/server/sonar-web/src/main/js/api/organizations.ts b/server/sonar-web/src/main/js/api/organizations.ts index 408f6b65cb2..f2ffd3f6fe7 100644 --- a/server/sonar-web/src/main/js/api/organizations.ts +++ b/server/sonar-web/src/main/js/api/organizations.ts @@ -20,11 +20,17 @@ import { getJSON, post, postJSON, RequestData } from '../helpers/request'; import throwGlobalError from '../app/utils/throwGlobalError'; +interface GetOrganizationsParameters { + organizations?: string; + member?: boolean; +} + interface GetOrganizationsResponse { organizations: Array<{ avatar?: string; description?: string; guarded: boolean; + isAdmin: boolean; key: string; name: string; url?: string; @@ -36,20 +42,14 @@ interface GetOrganizationsResponse { }; } -export function getOrganizations(organizations?: string[]): Promise { - const data: RequestData = {}; - if (organizations) { - Object.assign(data, { organizations: organizations.join() }); - } +export function getOrganizations( + data: GetOrganizationsParameters +): Promise { return getJSON('/api/organizations/search', data); } -export function getMyOrganizations(): Promise { - return getJSON('/api/organizations/search_my_organizations').then(r => r.organizations); -} - export function getOrganization(key: string): Promise { - return getOrganizations([key]) + return getOrganizations({ organizations: key }) .then(r => r.organizations.find((o: any) => o.key === key)) .catch(throwGlobalError); } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js index 761cff9cde4..cb70ab05709 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js @@ -44,7 +44,7 @@ type Props = { currentUser: CurrentUser, fetchMyOrganizations: () => Promise<*>, location: Object, - organizations: Array<{ key: string, name: string }>, + organizations: Array<{ isAdmin: bool, key: string, name: string }>, router: { push: string => void } }; */ @@ -157,9 +157,17 @@ export default class GlobalNavUser extends React.PureComponent { {hasOrganizations && sortBy(organizations, org => org.name.toLowerCase()).map(organization => (
  • - - - {organization.name} + +
    + + {organization.name} +
    + {organization.isAdmin && ( + {translate('admin')} + )}
  • ))} diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavUser-test.js.snap b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavUser-test.js.snap index d603a20a60f..fb7c3c4e59e 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavUser-test.js.snap +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavUser-test.js.snap @@ -201,6 +201,7 @@ exports[`should render the users organizations 1`] = ` key="bar" > - - - bar - +
    + + + bar + +
  • - - - Foo - +
    + + + Foo + +
  • - - - MyOrg - +
    + + + MyOrg + +
  • {organization.name} + {organization.isAdmin && ( + {translate('admin')} + )} {!!organization.description && ( diff --git a/server/sonar-web/src/main/js/apps/account/organizations/actions.js b/server/sonar-web/src/main/js/apps/account/organizations/actions.js index da353d90380..38f30b159b0 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/actions.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/actions.js @@ -17,20 +17,14 @@ * 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 api from '../../../api/organizations'; +import { getOrganizations } from '../../../api/organizations'; import { receiveMyOrganizations } from '../../../store/organizations/duck'; import { getValues } from '../../../api/settings'; import { receiveValues } from '../../settings/store/values/actions'; export const fetchMyOrganizations = () => dispatch => { - return api.getMyOrganizations().then(keys => { - if (keys.length > 0) { - return api.getOrganizations(keys).then(({ organizations }) => { - return dispatch(receiveMyOrganizations(organizations)); - }); - } else { - return dispatch(receiveMyOrganizations([])); - } + return getOrganizations({ member: true }).then(({ organizations }) => { + return dispatch(receiveMyOrganizations(organizations)); }); }; diff --git a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js index c7c6608573f..d3af96718f6 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js +++ b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js @@ -41,7 +41,7 @@ const fetchIssueOrganizations = issues => dispatch => { } const organizationKeys = uniq(issues.map(issue => issue.organization)); - return getOrganizations(organizationKeys).then( + return getOrganizations({ organizations: organizationKeys.join() }).then( response => dispatch(receiveOrganizations(response.organizations)), throwGlobalError ); diff --git a/server/sonar-web/src/main/js/apps/projects/utils.ts b/server/sonar-web/src/main/js/apps/projects/utils.ts index 7ad9dd4e7c0..daa94d94a4d 100644 --- a/server/sonar-web/src/main/js/apps/projects/utils.ts +++ b/server/sonar-web/src/main/js/apps/projects/utils.ts @@ -270,7 +270,7 @@ function fetchProjectOrganizations(projects: Array<{ organization: string }>) { } const organizations = uniq(projects.map(project => project.organization)); - return getOrganizations(organizations).then(r => r.organizations); + return getOrganizations({ organizations: organizations.join() }).then(r => r.organizations); } function mapFacetValues(values: Array<{ val: string; count: number }>) { diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js index e5b5c49ed82..4db0fec476c 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js @@ -23,7 +23,7 @@ import classNames from 'classnames'; import { sortBy } from 'lodash'; import Step from './Step'; import NewOrganizationForm from './NewOrganizationForm'; -import { getMyOrganizations } from '../../../api/organizations'; +import { getOrganizations } from '../../../api/organizations'; import Select from '../../../components/controls/Select'; import { translate } from '../../../helpers/l10n'; @@ -68,13 +68,15 @@ export default class OrganizationStep extends React.PureComponent { } fetchOrganizations = () => { - getMyOrganizations().then( - organizations => { + getOrganizations({ member: true }).then( + ({ organizations }) => { if (this.mounted) { + const organizationKeys = organizations.map(o => o.key); // best guess: if there is only one organization, then it is personal // otherwise, we can't guess, let's display them all as just "existing organizations" - const personalOrganization = organizations.length === 1 ? organizations[0] : undefined; - const existingOrganizations = organizations.length > 1 ? sortBy(organizations) : []; + const personalOrganization = + organizationKeys.length === 1 ? organizationKeys[0] : undefined; + const existingOrganizations = organizationKeys.length > 1 ? sortBy(organizationKeys) : []; const selection = personalOrganization ? 'personal' : existingOrganizations.length > 0 ? 'existing' : 'new'; diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/OrganizationStep-test.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/OrganizationStep-test.js index 6bc5530cd54..be9c2542a87 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/OrganizationStep-test.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/OrganizationStep-test.js @@ -22,16 +22,18 @@ import React from 'react'; import { mount } from 'enzyme'; import OrganizationStep from '../OrganizationStep'; import { click } from '../../../../helpers/testUtils'; -import { getMyOrganizations } from '../../../../api/organizations'; +import { getOrganizations } from '../../../../api/organizations'; jest.mock('../../../../api/organizations', () => ({ - getMyOrganizations: jest.fn(() => Promise.resolve(['user', 'another'])) + getOrganizations: jest.fn(() => + Promise.resolve({ organizations: [{ key: 'user' }, { key: 'another' }] }) + ) })); const currentUser = { isLoggedIn: true, login: 'user' }; beforeEach(() => { - getMyOrganizations.mockClear(); + getOrganizations.mockClear(); }); // FIXME diff --git a/server/sonar-web/src/main/js/store/organizations/duck.js b/server/sonar-web/src/main/js/store/organizations/duck.js index 77ebd43e2f3..4b4023f97ce 100644 --- a/server/sonar-web/src/main/js/store/organizations/duck.js +++ b/server/sonar-web/src/main/js/store/organizations/duck.js @@ -30,6 +30,7 @@ export type Organization = { canProvisionProjects?: boolean, canUpdateProjectsVisibilityToPrivate?: boolean, description?: string, + isAdmin: bool, key: string, name: string, pages?: Array<{ key: string, name: string }>, diff --git a/server/sonar-web/src/main/js/store/rootActions.js b/server/sonar-web/src/main/js/store/rootActions.js index 3775e1d0391..00836bfe58e 100644 --- a/server/sonar-web/src/main/js/store/rootActions.js +++ b/server/sonar-web/src/main/js/store/rootActions.js @@ -45,7 +45,7 @@ export const fetchMetrics = () => dispatch => getAllMetrics().then(metrics => dispatch(receiveMetrics(metrics)), onFail(dispatch)); export const fetchOrganizations = (organizations /*: Array | void */) => dispatch => - getOrganizations(organizations).then( + getOrganizations({ organizations: organizations && organizations.join() }).then( r => dispatch(receiveOrganizations(r.organizations)), onFail(dispatch) ); 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 32946f38725..cc182652392 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -8,6 +8,7 @@ action=Action actions=Actions active=Active add_verb=Add +admin=Admin apply=Apply all=All and=And