From: Grégoire Aubert Date: Wed, 29 Nov 2017 13:27:13 +0000 (+0100) Subject: Rewrite part of the permissions app to Typescript X-Git-Tag: 7.0-RC1~155 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ab2a5de55004f8ac50a99fae9840da26ce125088;p=sonarqube.git Rewrite part of the permissions app to Typescript --- diff --git a/server/sonar-web/src/main/js/api/permissions.ts b/server/sonar-web/src/main/js/api/permissions.ts index 8d2cf3e5596..39d77276f02 100644 --- a/server/sonar-web/src/main/js/api/permissions.ts +++ b/server/sonar-web/src/main/js/api/permissions.ts @@ -178,12 +178,20 @@ export function removeProjectCreatorFromTemplate( return post('/api/permissions/remove_project_creator_from_template', { templateId, permission }); } +export interface PermissionUser { + login: string; + name: string; + email?: string; + permissions: string[]; + avatar?: string; +} + export function getPermissionsUsersForComponent( projectKey: string, query?: string, permission?: string, organization?: string -): Promise { +): Promise { const data: RequestData = { projectKey, ps: PAGE_SIZE }; if (query) { data.q = query; @@ -197,12 +205,19 @@ export function getPermissionsUsersForComponent( return getJSON('/api/permissions/users', data).then(r => r.users); } +export interface PermissionGroup { + id: string; + name: string; + description?: string; + permissions: string[]; +} + export function getPermissionsGroupsForComponent( projectKey: string, query: string = '', permission?: string, organization?: string -): Promise { +): Promise { const data: RequestData = { projectKey, ps: PAGE_SIZE }; if (query) { data.q = query; @@ -220,7 +235,7 @@ export function getGlobalPermissionsUsers( query?: string, permission?: string, organization?: string -): Promise { +): Promise { const data: RequestData = { ps: PAGE_SIZE }; if (query) { data.q = query; @@ -238,7 +253,7 @@ export function getGlobalPermissionsGroups( query?: string, permission?: string, organization?: string -): Promise { +): Promise { const data: RequestData = { ps: PAGE_SIZE }; if (query) { data.q = query; diff --git a/server/sonar-web/src/main/js/app/types.ts b/server/sonar-web/src/main/js/app/types.ts index f18764601e4..a180856c47a 100644 --- a/server/sonar-web/src/main/js/app/types.ts +++ b/server/sonar-web/src/main/js/app/types.ts @@ -108,7 +108,7 @@ export interface Metric { } export interface Organization { - adminPages?: Array<{ key: string; name: string }>; + adminPages?: { key: string; name: string }[]; avatar?: string; canAdmin?: boolean; canDelete?: boolean; @@ -118,8 +118,8 @@ export interface Organization { isDefault?: boolean; key: string; name: string; - pages?: Array<{ key: string; name: string }>; - projectVisibility: string; + pages?: { key: string; name: string }[]; + projectVisibility: Visibility; url?: string; } diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js deleted file mode 100644 index cab087b3e55..00000000000 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import { connect } from 'react-redux'; -import GlobalPermissionsApp from '../../permissions/global/components/App'; -import { getOrganizationByKey } from '../../../store/rootReducer'; -/*:: import type { Organization } from '../../../store/organizations/duck'; */ - -/*:: -type Props = { - organization: Organization -}; -*/ - -function OrganizationPermissions(props /*: Props */) { - return ; -} - -const mapStateToProps = (state, ownProps) => ({ - organization: getOrganizationByKey(state, ownProps.params.organizationKey) -}); - -export default connect(mapStateToProps)(OrganizationPermissions); diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.tsx b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.tsx new file mode 100644 index 00000000000..b2136ea2f35 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.tsx @@ -0,0 +1,38 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 { connect } from 'react-redux'; +import GlobalPermissionsApp from '../../permissions/global/components/App'; +import { getOrganizationByKey } from '../../../store/rootReducer'; +import { Organization } from '../../../app/types'; + +interface Props { + organization: Organization; +} + +function OrganizationPermissions({ organization }: Props) { + return ; +} + +const mapStateToProps = (state: any, ownProps: any) => ({ + organization: getOrganizationByKey(state, ownProps.params.organizationKey) +}); + +export default connect(mapStateToProps)(OrganizationPermissions); diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js deleted file mode 100644 index 507d43bbfb0..00000000000 --- a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js +++ /dev/null @@ -1,241 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import { Link } from 'react-router'; -import classNames from 'classnames'; -import * as theme from '../../../app/theme'; -import { translate } from '../../../helpers/l10n'; -import ContextNavBar from '../../../components/nav/ContextNavBar'; -import NavBarTabs from '../../../components/nav/NavBarTabs'; -import OrganizationAvatar from '../../../components/common/OrganizationAvatar'; -import { getQualityGatesUrl } from '../../../helpers/urls'; -/*:: import type { Organization } from '../../../store/organizations/duck'; */ - -const ADMIN_PATHS = [ - 'edit', - 'groups', - 'delete', - 'permissions', - 'permission_templates', - 'projects_management' -]; - -export default class OrganizationNavigation extends React.PureComponent { - /*:: props: { - location: { pathname: string }, - organization: Organization - }; -*/ - - renderAdministration(adminActive /*: boolean */) { - const { organization } = this.props; - - return ( -
  • - - {translate('layout.settings')}  - -
      - {this.renderAdminExtensions()} -
    • - - {translate('user_groups.page')} - -
    • -
    • - - {translate('permissions.page')} - -
    • -
    • - - {translate('permission_templates')} - -
    • -
    • - - {translate('projects_management')} - -
    • -
    • - - {translate('edit')} - -
    • - {organization.canDelete && ( -
    • - - {translate('delete')} - -
    • - )} -
    -
  • - ); - } - - renderAdminExtensions() { - const extensions = this.props.organization.adminPages || []; - return extensions.map(this.renderExtension); - } - - renderExtension = (extension /*: { key: string, name: string } */) => { - const { organization } = this.props; - const pathname = `/organizations/${organization.key}/extension/${extension.key}`; - return ( -
  • - - {extension.name} - -
  • - ); - }; - - renderExtensions(moreActive /*: boolean */) { - const extensions = this.props.organization.pages || []; - if (extensions.length > 0) { - return ( -
  • - - {translate('more')}  - -
      {extensions.map(this.renderExtension)}
    -
  • - ); - } else { - return null; - } - } - - render() { - const { organization, location } = this.props; - - const isHomeActive = - location.pathname === `organizations/${organization.key}/projects` || - location.pathname === `organizations/${organization.key}/projects/favorite`; - - const adminPathsWithExtensions = (organization.adminPages || []) - .map(e => `extension/${e.key}`) - .concat(ADMIN_PATHS); - - const adminActive = adminPathsWithExtensions.some(path => - location.pathname.endsWith(`organizations/${organization.key}/${path}`) - ); - const moreActive = !adminActive && location.pathname.includes('/extension/'); - - return ( - -
    -

    - - - {organization.name} - -

    - {organization.description != null && ( -
    -

    - {organization.description} -

    -
    - )} -
    - -
    -
    - {translate('organization.key')}: {organization.key} -
    - {organization.url != null && ( - - )} -
    - - -
  • - - {translate('projects.page')} - -
  • -
  • - - {translate('issues.page')} - -
  • -
  • - - {translate('quality_profiles.page')} - -
  • -
  • - - {translate('coding_rules.page')} - -
  • -
  • - - {translate('quality_gates.page')} - -
  • -
  • - - {translate('organization.members.page')} - -
  • - {this.renderExtensions(moreActive)} - {organization.canAdmin && this.renderAdministration(adminActive)} -
    -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.tsx b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.tsx new file mode 100644 index 00000000000..4cffcc47d80 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.tsx @@ -0,0 +1,239 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 * as classNames from 'classnames'; +import { Link } from 'react-router'; +import * as theme from '../../../app/theme'; +import { translate } from '../../../helpers/l10n'; +import ContextNavBar from '../../../components/nav/ContextNavBar'; +import NavBarTabs from '../../../components/nav/NavBarTabs'; +import OrganizationAvatar from '../../../components/common/OrganizationAvatar'; +import { getQualityGatesUrl } from '../../../helpers/urls'; +import { Extension, Organization } from '../../../app/types'; + +const ADMIN_PATHS = [ + 'edit', + 'groups', + 'delete', + 'permissions', + 'permission_templates', + 'projects_management' +]; + +interface Props { + location: { pathname: string }; + organization: Organization; +} + +export default class OrganizationNavigation extends React.PureComponent { + renderAdministration(adminActive: boolean) { + const { organization } = this.props; + + return ( +
  • + + {translate('layout.settings')}  + +
      + {this.renderAdminExtensions()} +
    • + + {translate('user_groups.page')} + +
    • +
    • + + {translate('permissions.page')} + +
    • +
    • + + {translate('permission_templates')} + +
    • +
    • + + {translate('projects_management')} + +
    • +
    • + + {translate('edit')} + +
    • + {organization.canDelete && ( +
    • + + {translate('delete')} + +
    • + )} +
    +
  • + ); + } + + renderAdminExtensions() { + const extensions = this.props.organization.adminPages || []; + return extensions.map(this.renderExtension); + } + + renderExtension = (extension: Extension) => { + const { organization } = this.props; + const pathname = `/organizations/${organization.key}/extension/${extension.key}`; + return ( +
  • + + {extension.name} + +
  • + ); + }; + + renderExtensions(moreActive: boolean) { + const extensions = this.props.organization.pages || []; + if (extensions.length > 0) { + return ( +
  • + + {translate('more')}  + +
      {extensions.map(this.renderExtension)}
    +
  • + ); + } else { + return null; + } + } + + render() { + const { organization, location } = this.props; + + const isHomeActive = + location.pathname === `organizations/${organization.key}/projects` || + location.pathname === `organizations/${organization.key}/projects/favorite`; + + const adminPathsWithExtensions = (organization.adminPages || []) + .map(e => `extension/${e.key}`) + .concat(ADMIN_PATHS); + + const adminActive = adminPathsWithExtensions.some(path => + location.pathname.endsWith(`organizations/${organization.key}/${path}`) + ); + const moreActive = !adminActive && location.pathname.includes('/extension/'); + + return ( + +
    +

    + + + {organization.name} + +

    + {organization.description != null && ( +
    +

    + {organization.description} +

    +
    + )} +
    + +
    +
    + {translate('organization.key')}: {organization.key} +
    + {organization.url != null && ( + + )} +
    + + +
  • + + {translate('projects.page')} + +
  • +
  • + + {translate('issues.page')} + +
  • +
  • + + {translate('quality_profiles.page')} + +
  • +
  • + + {translate('coding_rules.page')} + +
  • +
  • + + {translate('quality_gates.page')} + +
  • +
  • + + {translate('organization.members.page')} + +
  • + {this.renderExtensions(moreActive)} + {organization.canAdmin && this.renderAdministration(adminActive)} +
    +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/OrganizationNavigation-test.js b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/OrganizationNavigation-test.js deleted file mode 100644 index 3f337c032d5..00000000000 --- a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/OrganizationNavigation-test.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import { shallow } from 'enzyme'; -import OrganizationNavigation from '../OrganizationNavigation'; - -jest.mock('../../../issues/utils', () => ({ - isMySet: () => false -})); - -it('regular user', () => { - const organization = { key: 'foo', name: 'Foo', canAdmin: false, canDelete: false }; - expect( - shallow( - - ) - ).toMatchSnapshot(); -}); - -it('admin', () => { - const organization = { key: 'foo', name: 'Foo', canAdmin: true, canDelete: true }; - expect( - shallow( - - ) - ).toMatchSnapshot(); -}); - -it('undeletable org', () => { - const organization = { key: 'foo', name: 'Foo', canAdmin: true, canDelete: false }; - expect( - shallow( - - ) - ).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/OrganizationNavigation-test.tsx b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/OrganizationNavigation-test.tsx new file mode 100644 index 00000000000..e4884f83545 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/OrganizationNavigation-test.tsx @@ -0,0 +1,61 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 OrganizationNavigation from '../OrganizationNavigation'; +import { Visibility } from '../../../../app/types'; + +jest.mock('../../../issues/utils', () => ({ + isMySet: () => false +})); + +const organization = { + key: 'foo', + name: 'Foo', + canAdmin: false, + canDelete: false, + projectVisibility: Visibility.Public +}; + +it('regular user', () => { + expect(getWrapper()).toMatchSnapshot(); +}); + +it('admin', () => { + expect( + getWrapper({ organization: { ...organization, canAdmin: true, canDelete: true } }) + ).toMatchSnapshot(); +}); + +it('undeletable org', () => { + expect( + getWrapper({ organization: { ...organization, canAdmin: true, canDelete: false } }) + ).toMatchSnapshot(); +}); + +function getWrapper(props = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap deleted file mode 100644 index 66184bbc5d4..00000000000 --- a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap +++ /dev/null @@ -1,520 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`admin 1`] = ` - -
    -

    - - - Foo - -

    -
    -
    -
    - - organization.key - : - - - foo -
    -
    - -
  • - - projects.page - -
  • -
  • - - issues.page - -
  • -
  • - - quality_profiles.page - -
  • -
  • - - coding_rules.page - -
  • -
  • - - quality_gates.page - -
  • -
  • - - organization.members.page - -
  • -
  • - - layout.settings -   - - -
      -
    • - - user_groups.page - -
    • -
    • - - permissions.page - -
    • -
    • - - permission_templates - -
    • -
    • - - projects_management - -
    • -
    • - - edit - -
    • -
    • - - delete - -
    • -
    -
  • -
    -
    -`; - -exports[`regular user 1`] = ` - -
    -

    - - - Foo - -

    -
    -
    -
    - - organization.key - : - - - foo -
    -
    - -
  • - - projects.page - -
  • -
  • - - issues.page - -
  • -
  • - - quality_profiles.page - -
  • -
  • - - coding_rules.page - -
  • -
  • - - quality_gates.page - -
  • -
  • - - organization.members.page - -
  • -
    -
    -`; - -exports[`undeletable org 1`] = ` - -
    -

    - - - Foo - -

    -
    -
    -
    - - organization.key - : - - - foo -
    -
    - -
  • - - projects.page - -
  • -
  • - - issues.page - -
  • -
  • - - quality_profiles.page - -
  • -
  • - - coding_rules.page - -
  • -
  • - - quality_gates.page - -
  • -
  • - - organization.members.page - -
  • -
  • - - layout.settings -   - - -
      -
    • - - user_groups.page - -
    • -
    • - - permissions.page - -
    • -
    • - - permission_templates - -
    • -
    • - - projects_management - -
    • -
    • - - edit - -
    • -
    -
  • -
    -
    -`; diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.tsx.snap b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.tsx.snap new file mode 100644 index 00000000000..66184bbc5d4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.tsx.snap @@ -0,0 +1,520 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`admin 1`] = ` + +
    +

    + + + Foo + +

    +
    +
    +
    + + organization.key + : + + + foo +
    +
    + +
  • + + projects.page + +
  • +
  • + + issues.page + +
  • +
  • + + quality_profiles.page + +
  • +
  • + + coding_rules.page + +
  • +
  • + + quality_gates.page + +
  • +
  • + + organization.members.page + +
  • +
  • + + layout.settings +   + + +
      +
    • + + user_groups.page + +
    • +
    • + + permissions.page + +
    • +
    • + + permission_templates + +
    • +
    • + + projects_management + +
    • +
    • + + edit + +
    • +
    • + + delete + +
    • +
    +
  • +
    +
    +`; + +exports[`regular user 1`] = ` + +
    +

    + + + Foo + +

    +
    +
    +
    + + organization.key + : + + + foo +
    +
    + +
  • + + projects.page + +
  • +
  • + + issues.page + +
  • +
  • + + quality_profiles.page + +
  • +
  • + + coding_rules.page + +
  • +
  • + + quality_gates.page + +
  • +
  • + + organization.members.page + +
  • +
    +
    +`; + +exports[`undeletable org 1`] = ` + +
    +

    + + + Foo + +

    +
    +
    +
    + + organization.key + : + + + foo +
    +
    + +
  • + + projects.page + +
  • +
  • + + issues.page + +
  • +
  • + + quality_profiles.page + +
  • +
  • + + coding_rules.page + +
  • +
  • + + quality_gates.page + +
  • +
  • + + organization.members.page + +
  • +
  • + + layout.settings +   + + +
      +
    • + + user_groups.page + +
    • +
    • + + permissions.page + +
    • +
    • + + permission_templates + +
    • +
    • + + projects_management + +
    • +
    • + + edit + +
    • +
    +
  • +
    +
    +`; diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js deleted file mode 100644 index f340d7e27c1..00000000000 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js +++ /dev/null @@ -1,139 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import { connect } from 'react-redux'; -import SearchForm from '../../shared/components/SearchForm'; -import HoldersList from '../../shared/components/HoldersList'; -import { - loadHolders, - grantToUser, - revokeFromUser, - grantToGroup, - revokeFromGroup, - updateFilter, - updateQuery, - selectPermission -} from '../store/actions'; -import { translate } from '../../../../helpers/l10n'; -import { - getPermissionsAppUsers, - getPermissionsAppGroups, - getPermissionsAppQuery, - getPermissionsAppFilter, - getPermissionsAppSelectedPermission -} from '../../../../store/rootReducer'; - -const PERMISSIONS_ORDER = ['admin', 'profileadmin', 'gateadmin', 'scan', 'provisioning']; - -const PERMISSIONS_FOR_CUSTOM_ORG = ['admin', 'profileadmin', 'scan', 'provisioning']; - -class AllHoldersList extends React.PureComponent { - componentDidMount() { - this.props.loadHolders(); - } - - handleToggleUser(user, permission) { - const hasPermission = user.permissions.includes(permission); - - if (hasPermission) { - this.props.revokePermissionFromUser(user.login, permission); - } else { - this.props.grantPermissionToUser(user.login, permission); - } - } - - handleToggleGroup(group, permission) { - const hasPermission = group.permissions.includes(permission); - - if (hasPermission) { - this.props.revokePermissionFromGroup(group.name, permission); - } else { - this.props.grantPermissionToGroup(group.name, permission); - } - } - - render() { - const order = - this.props.organization && !this.props.organization.isDefault - ? PERMISSIONS_FOR_CUSTOM_ORG - : PERMISSIONS_ORDER; - - const l10nPrefix = this.props.organization ? 'organizations_permissions' : 'global_permissions'; - - const permissions = order.map(p => ({ - key: p, - name: translate(l10nPrefix, p), - description: translate(l10nPrefix, p, 'desc') - })); - - return ( - - - - ); - } -} - -const mapStateToProps = state => ({ - users: getPermissionsAppUsers(state), - groups: getPermissionsAppGroups(state), - query: getPermissionsAppQuery(state), - filter: getPermissionsAppFilter(state), - selectedPermission: getPermissionsAppSelectedPermission(state) -}); - -/*:: -type OwnProps = { - organization?: { key: string } -}; -*/ - -const mapDispatchToProps = (dispatch /*: Function */, ownProps /*: OwnProps */) => { - const organizationKey = ownProps.organization ? ownProps.organization.key : undefined; - return { - loadHolders: () => dispatch(loadHolders(organizationKey)), - onSearch: query => dispatch(updateQuery(query, organizationKey)), - onFilter: filter => dispatch(updateFilter(filter, organizationKey)), - onSelectPermission: permission => dispatch(selectPermission(permission, organizationKey)), - grantPermissionToUser: (login, permission) => - dispatch(grantToUser(login, permission, organizationKey)), - revokePermissionFromUser: (login, permission) => - dispatch(revokeFromUser(login, permission, organizationKey)), - grantPermissionToGroup: (groupName, permission) => - dispatch(grantToGroup(groupName, permission, organizationKey)), - revokePermissionFromGroup: (groupName, permission) => - dispatch(revokeFromGroup(groupName, permission, organizationKey)) - }; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(AllHoldersList); diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.tsx b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.tsx new file mode 100644 index 00000000000..b9ee74940d0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.tsx @@ -0,0 +1,104 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 SearchForm from '../../shared/components/SearchForm'; +import HoldersList from '../../shared/components/HoldersList'; +import { translate } from '../../../../helpers/l10n'; +import { Organization } from '../../../../app/types'; +import { PermissionUser, PermissionGroup } from '../../../../api/permissions'; + +const PERMISSIONS_ORDER = ['admin', 'profileadmin', 'gateadmin', 'scan', 'provisioning']; +const PERMISSIONS_FOR_CUSTOM_ORG = ['admin', 'profileadmin', 'scan', 'provisioning']; + +interface Props { + filter: string; + grantPermissionToGroup: (groupName: string, permission: string) => void; + grantPermissionToUser: (login: string, permission: string) => void; + groups: PermissionGroup[]; + loadHolders: () => void; + onFilter: (filter: string) => void; + onSearch: (query: string) => void; + onSelectPermission: (permission: string) => void; + organization?: Organization; + query: string; + revokePermissionFromGroup: (groupName: string, permission: string) => void; + revokePermissionFromUser: (login: string, permission: string) => void; + selectedPermission?: string; + users: PermissionUser[]; +} + +export default class AllHoldersList extends React.PureComponent { + componentDidMount() { + this.props.loadHolders(); + } + + handleToggleUser = (user: PermissionUser, permission: string) => { + const hasPermission = user.permissions.includes(permission); + + if (hasPermission) { + this.props.revokePermissionFromUser(user.login, permission); + } else { + this.props.grantPermissionToUser(user.login, permission); + } + }; + + handleToggleGroup = (group: PermissionGroup, permission: string) => { + const hasPermission = group.permissions.includes(permission); + + if (hasPermission) { + this.props.revokePermissionFromGroup(group.name, permission); + } else { + this.props.grantPermissionToGroup(group.name, permission); + } + }; + + render() { + const order = + this.props.organization && !this.props.organization.isDefault + ? PERMISSIONS_FOR_CUSTOM_ORG + : PERMISSIONS_ORDER; + + const l10nPrefix = this.props.organization ? 'organizations_permissions' : 'global_permissions'; + + const permissions = order.map(p => ({ + key: p, + name: translate(l10nPrefix, p), + description: translate(l10nPrefix, p, 'desc') + })); + + return ( + + + + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersListContainer.tsx b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersListContainer.tsx new file mode 100644 index 00000000000..bb0647549eb --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersListContainer.tsx @@ -0,0 +1,95 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 { connect } from 'react-redux'; +import { + loadHolders, + grantToUser, + revokeFromUser, + grantToGroup, + revokeFromGroup, + updateFilter, + updateQuery, + selectPermission +} from '../store/actions'; +import { + getPermissionsAppUsers, + getPermissionsAppGroups, + getPermissionsAppQuery, + getPermissionsAppFilter, + getPermissionsAppSelectedPermission +} from '../../../../store/rootReducer'; +import AllHoldersList from './AllHoldersList'; +import { Organization } from '../../../../app/types'; +import { PermissionUser, PermissionGroup } from '../../../../api/permissions'; + +interface OwnProps { + organization?: Organization; +} + +interface StateToProps { + filter: string; + groups: PermissionGroup[]; + query: string; + selectedPermission?: string; + users: PermissionUser[]; +} + +interface DispatchToProps { + grantPermissionToGroup: (groupName: string, permission: string) => void; + grantPermissionToUser: (login: string, permission: string) => void; + loadHolders: () => void; + onFilter: (filter: string) => void; + onSearch: (query: string) => void; + onSelectPermission: (permission: string) => void; + revokePermissionFromGroup: (groupName: string, permission: string) => void; + revokePermissionFromUser: (login: string, permission: string) => void; +} + +const mapStateToProps = (state: any) => ({ + filter: getPermissionsAppFilter(state), + groups: getPermissionsAppGroups(state), + query: getPermissionsAppQuery(state), + selectedPermission: getPermissionsAppSelectedPermission(state), + users: getPermissionsAppUsers(state) +}); + +const mapDispatchToProps = (dispatch: Function, ownProps: OwnProps) => { + const organizationKey = ownProps.organization ? ownProps.organization.key : undefined; + return { + grantPermissionToGroup: (groupName: string, permission: string) => + dispatch(grantToGroup(groupName, permission, organizationKey)), + grantPermissionToUser: (login: string, permission: string) => + dispatch(grantToUser(login, permission, organizationKey)), + loadHolders: () => dispatch(loadHolders(organizationKey)), + onFilter: (filter: string) => dispatch(updateFilter(filter, organizationKey)), + onSearch: (query: string) => dispatch(updateQuery(query, organizationKey)), + onSelectPermission: (permission: string) => + dispatch(selectPermission(permission, organizationKey)), + revokePermissionFromGroup: (groupName: string, permission: string) => + dispatch(revokeFromGroup(groupName, permission, organizationKey)), + revokePermissionFromUser: (login: string, permission: string) => + dispatch(revokeFromUser(login, permission, organizationKey)) + }; +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(AllHoldersList); diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js b/server/sonar-web/src/main/js/apps/permissions/global/components/App.js deleted file mode 100644 index 4b7ea9f15e1..00000000000 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import Helmet from 'react-helmet'; -import PageHeader from './PageHeader'; -import AllHoldersList from './AllHoldersList'; -import PageError from '../../shared/components/PageError'; -import { translate } from '../../../../helpers/l10n'; -import '../../styles.css'; - -export default function App(props /*: { organization?: {} } */) { - return ( -
    - - - - -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/App.tsx b/server/sonar-web/src/main/js/apps/permissions/global/components/App.tsx new file mode 100644 index 00000000000..fdd4aec3dcf --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/App.tsx @@ -0,0 +1,42 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Helmet from 'react-helmet'; +import PageHeader from './PageHeader'; +import AllHoldersListContainer from './AllHoldersListContainer'; +import PageError from '../../shared/components/PageError'; +import { translate } from '../../../../helpers/l10n'; +import { Organization } from '../../../../app/types'; +import '../../styles.css'; + +interface Props { + organization?: Organization; +} + +export default function App({ organization }: Props) { + return ( +
    + + + + +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.js deleted file mode 100644 index 12a9c2af1ba..00000000000 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import PropTypes from 'prop-types'; -import GroupIcon from '../../../../components/icons-components/GroupIcon'; - -export default class GroupHolder extends React.PureComponent { - static propTypes = { - group: PropTypes.object.isRequired, - permissions: PropTypes.array.isRequired, - selectedPermission: PropTypes.string, - permissionsOrder: PropTypes.array.isRequired, - onToggle: PropTypes.func.isRequired - }; - - handleClick(permission, e) { - e.preventDefault(); - e.target.blur(); - this.props.onToggle(this.props.group, permission); - } - - render() { - const { selectedPermission } = this.props; - const permissionCells = this.props.permissionsOrder.map(p => ( - - - - )); - - const { group } = this.props; - - return ( - - -
    - -
    -
    -
    - {group.name} -
    -
    - {group.description} -
    -
    - - {permissionCells} - - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.tsx b/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.tsx new file mode 100644 index 00000000000..3fc076c002e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.tsx @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Checkbox from '../../../../components/controls/Checkbox'; +import GroupIcon from '../../../../components/icons-components/GroupIcon'; +import { PermissionGroup } from '../../../../api/permissions'; + +interface Props { + group: PermissionGroup; + permissions: string[]; + selectedPermission?: string; + permissionsOrder: string[]; + onToggle: (group: PermissionGroup, permission: string) => void; +} + +export default class GroupHolder extends React.PureComponent { + handleCheck = (_checked: boolean, permission?: string) => + permission && this.props.onToggle(this.props.group, permission); + + render() { + const { selectedPermission } = this.props; + const permissionCells = this.props.permissionsOrder.map(permission => ( + + + + )); + + const { group } = this.props; + + return ( + + +
    + +
    +
    +
    + {group.name} +
    +
    + {group.description} +
    +
    + + {permissionCells} + + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.js deleted file mode 100644 index da8bc9aa11f..00000000000 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.js +++ /dev/null @@ -1,137 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import PropTypes from 'prop-types'; -import UserHolder from './UserHolder'; -import GroupHolder from './GroupHolder'; -import Tooltip from '../../../../components/controls/Tooltip'; -import { translate, translateWithParameters } from '../../../../helpers/l10n'; - -export default class HoldersList extends React.PureComponent { - static propTypes = { - permissions: PropTypes.array.isRequired, - users: PropTypes.array.isRequired, - groups: PropTypes.array.isRequired, - selectedPermission: PropTypes.string, - showPublicProjectsWarning: PropTypes.bool, - onSelectPermission: PropTypes.func.isRequired, - onToggleUser: PropTypes.func.isRequired, - onToggleGroup: PropTypes.func.isRequired - }; - - static defaultProps = { - showPublicProjectsWarning: false - }; - - handlePermissionClick = event => { - event.preventDefault(); - event.currentTarget.blur(); - this.props.onSelectPermission(event.currentTarget.dataset.key); - }; - - renderTooltip = permission => - this.props.showPublicProjectsWarning && - (permission.key === 'user' || permission.key === 'codeviewer') ? ( -
    - {permission.description} -
    - {translate('projects_role.public_projects_warning')} -
    -
    - ) : ( - permission.description - ); - - renderTableHeader() { - const { selectedPermission } = this.props; - const cells = this.props.permissions.map(p => ( - -
    - - - {p.name} - - - - - -
    - - )); - return ( - - - {this.props.children} - {cells} - - - ); - } - - renderEmpty() { - const columns = this.props.permissions.length + 1; - return ( - - {translate('no_results_search')} - - ); - } - - render() { - const users = this.props.users.map(user => ( - - )); - - const groups = this.props.groups.map(group => ( - - )); - - return ( - - {this.renderTableHeader()} - - {users.length === 0 && groups.length === 0 && this.renderEmpty()} - {users} - {groups} - -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.tsx b/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.tsx new file mode 100644 index 00000000000..189351ba346 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.tsx @@ -0,0 +1,105 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 UserHolder from './UserHolder'; +import GroupHolder from './GroupHolder'; +import PermissionHeader, { Permission } from './PermissionHeader'; +import { PermissionUser, PermissionGroup } from '../../../../api/permissions'; +import { translate } from '../../../../helpers/l10n'; + +interface Props { + permissions: Permission[]; + users: PermissionUser[]; + groups: PermissionGroup[]; + selectedPermission?: string; + showPublicProjectsWarning?: boolean; + onSelectPermission: (permission: string) => void; + onToggleUser: (user: PermissionUser, permission: string) => void; + onToggleGroup: (group: PermissionGroup, permission: string) => void; +} + +export default class HoldersList extends React.PureComponent { + renderTableHeader() { + const { onSelectPermission, selectedPermission, showPublicProjectsWarning } = this.props; + const cells = this.props.permissions.map(p => ( + + )); + return ( + + + {this.props.children} + {cells} + + + ); + } + + renderEmpty() { + const columns = this.props.permissions.length + 1; + return ( + + {translate('no_results_search')} + + ); + } + + render() { + const permissionsOrder = this.props.permissions.map(p => p.key); + + const users = this.props.users.map(user => ( + + )); + + const groups = this.props.groups.map(group => ( + + )); + + return ( + + {this.renderTableHeader()} + + {users.length === 0 && groups.length === 0 && this.renderEmpty()} + {users} + {groups} + +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.js deleted file mode 100644 index e3d6266d94b..00000000000 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { getPermissionsAppError } from '../../../../store/rootReducer'; - -class PageError extends React.PureComponent { - static propTypes = { - message: PropTypes.string - }; - - render() { - const { message } = this.props; - - if (!message) { - return null; - } - - return
    {message}
    ; - } -} - -const mapStateToProps = state => ({ - message: getPermissionsAppError(state) -}); - -export default connect(mapStateToProps)(PageError); diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.tsx b/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.tsx new file mode 100644 index 00000000000..4f3878329c3 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.tsx @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 { connect } from 'react-redux'; +import { getPermissionsAppError } from '../../../../store/rootReducer'; + +interface Props { + message: string; +} + +function PageError({ message }: Props) { + if (!message) { + return null; + } + + return
    {message}
    ; +} + +const mapStateToProps = (state: any) => ({ + message: getPermissionsAppError(state) +}); + +export default connect(mapStateToProps)(PageError); diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx b/server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx new file mode 100644 index 00000000000..96d9e40d1c2 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx @@ -0,0 +1,87 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Tooltip from '../../../../components/controls/Tooltip'; +import { translate, translateWithParameters } from '../../../../helpers/l10n'; + +export interface Permission { + key: string; + name: string; + description: string; +} + +interface Props { + onSelectPermission: (permission: string) => void; + permission: Permission; + selectedPermission?: string; + showPublicProjectsWarning?: boolean; +} + +export default class PermissionHeader extends React.PureComponent { + static defaultProps = { + showPublicProjectsWarning: false + }; + + handlePermissionClick = (event: React.SyntheticEvent) => { + event.preventDefault(); + event.currentTarget.blur(); + this.props.onSelectPermission(this.props.permission.key); + }; + + renderTooltip = (permission: Permission) => { + if (this.props.showPublicProjectsWarning && ['user', 'codeviewer'].includes(permission.key)) { + return ( +
    + {permission.description} +
    + {translate('projects_role.public_projects_warning')} +
    +
    + ); + } + return permission.description; + }; + + render() { + const { permission, selectedPermission } = this.props; + return ( + + + + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.js deleted file mode 100644 index b680b491fbd..00000000000 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import PropTypes from 'prop-types'; -import RadioToggle from '../../../../components/controls/RadioToggle'; -import SearchBox from '../../../../components/controls/SearchBox'; -import { translate, translateWithParameters } from '../../../../helpers/l10n'; - -export default function SearchForm(props) { - const filterOptions = [ - { value: 'all', label: translate('all') }, - { value: 'users', label: translate('users.page') }, - { value: 'groups', label: translate('user_groups.page') } - ]; - - return ( -
    - - -
    - -
    -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.tsx b/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.tsx new file mode 100644 index 00000000000..903d3be562d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.tsx @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 RadioToggle from '../../../../components/controls/RadioToggle'; +import SearchBox from '../../../../components/controls/SearchBox'; +import { translate } from '../../../../helpers/l10n'; + +interface Props { + filter: string; + onFilter: (value: string) => void; + onSearch: (value: string) => void; + query: string; +} + +export default function SearchForm(props: Props) { + const filterOptions = [ + { value: 'all', label: translate('all') }, + { value: 'users', label: translate('users.page') }, + { value: 'groups', label: translate('user_groups.page') } + ]; + + return ( +
    + + +
    + +
    +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.js deleted file mode 100644 index d0b97ae588b..00000000000 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import PropTypes from 'prop-types'; -import Avatar from '../../../../components/ui/Avatar'; -import { translate } from '../../../../helpers/l10n'; - -export default class UserHolder extends React.PureComponent { - static propTypes = { - user: PropTypes.object.isRequired, - permissions: PropTypes.array.isRequired, - selectedPermission: PropTypes.string, - permissionsOrder: PropTypes.array.isRequired, - onToggle: PropTypes.func.isRequired - }; - - handleClick(permission, e) { - e.preventDefault(); - e.target.blur(); - this.props.onToggle(this.props.user, permission); - } - - render() { - const { selectedPermission } = this.props; - const permissionCells = this.props.permissionsOrder.map(p => ( - - - - )); - - const { user } = this.props; - - const isCreator = user.login === ''; - - return ( - - - {!isCreator && ( - - )} -
    -
    - {user.name} - {!isCreator && {user.login}} -
    - {!isCreator &&
    {user.email}
    } - {isCreator && ( -
    - {translate('permission_templates.project_creators.explanation')} -
    - )} -
    - - {permissionCells} - - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.tsx b/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.tsx new file mode 100644 index 00000000000..068c98f67af --- /dev/null +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.tsx @@ -0,0 +1,93 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Avatar from '../../../../components/ui/Avatar'; +import Checkbox from '../../../../components/controls/Checkbox'; +import { PermissionUser } from '../../../../api/permissions'; +import { translate } from '../../../../helpers/l10n'; + +interface Props { + user: PermissionUser; + permissions: string[]; + selectedPermission?: string; + permissionsOrder: string[]; + onToggle: (user: PermissionUser, permission: string) => void; +} + +export default class UserHolder extends React.PureComponent { + handleCheck = (_checked: boolean, permission?: string) => + permission && this.props.onToggle(this.props.user, permission); + + render() { + const { selectedPermission } = this.props; + const permissionCells = this.props.permissionsOrder.map(permission => ( + + + + )); + + const { user } = this.props; + if (user.login === '') { + return ( + + +
    +
    + {user.name} +
    +
    + {translate('permission_templates.project_creators.explanation')} +
    +
    + + {permissionCells} + + ); + } + + return ( + + + +
    +
    + {user.name} + {user.login} +
    +
    {user.email}
    +
    + + {permissionCells} + + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx index 00014d3b253..e17f7697ac1 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx @@ -21,6 +21,7 @@ import * as React from 'react'; import { mount } from 'enzyme'; import App, { Props } from '../App'; +import { Visibility } from '../../../app/types'; jest.mock('react-dom'); @@ -42,7 +43,7 @@ jest.mock('../../../api/components', () => ({ getComponents: jest.fn() })); const getComponents = require('../../../api/components').getComponents as jest.Mock; -const organization = { key: 'org', name: 'org', projectVisibility: 'public' }; +const organization = { key: 'org', name: 'org', projectVisibility: Visibility.Public }; const defaultSearchParameters = { organization: 'org', diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ChangeVisibilityForm-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ChangeVisibilityForm-test.tsx index 61dce6dbfe4..4d3505afd22 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ChangeVisibilityForm-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ChangeVisibilityForm-test.tsx @@ -21,12 +21,13 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import ChangeVisibilityForm, { Props } from '../ChangeVisibilityForm'; import { click } from '../../../helpers/testUtils'; +import { Visibility } from '../../../app/types'; const organization = { canUpdateProjectsVisibilityToPrivate: true, key: 'org', name: 'org', - projectVisibility: 'public' + projectVisibility: Visibility.Public }; it('renders disabled', () => { diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/CreateProjectForm-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/CreateProjectForm-test.tsx index c514345b78a..2682a771619 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/CreateProjectForm-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/CreateProjectForm-test.tsx @@ -28,10 +28,11 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import CreateProjectForm from '../CreateProjectForm'; import { change, submit, click } from '../../../helpers/testUtils'; +import { Visibility } from '../../../app/types'; const createProject = require('../../../api/components').createProject as jest.Mock; -const organization = { key: 'org', name: 'org', projectVisibility: 'public' }; +const organization = { key: 'org', name: 'org', projectVisibility: Visibility.Public }; it('creates project', async () => { const wrapper = shallow( diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx index b7cb62ab9a4..7d5b637949b 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx @@ -23,7 +23,7 @@ import Header, { Props } from '../Header'; import { Visibility } from '../../../app/types'; import { click } from '../../../helpers/testUtils'; -const organization = { key: 'org', name: 'org', projectVisibility: 'public' }; +const organization = { key: 'org', name: 'org', projectVisibility: Visibility.Public }; it('renders', () => { expect(shallowRender()).toMatchSnapshot(); diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx index 824c6ab2a5e..71cf3dcbe80 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx @@ -21,8 +21,9 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import Search, { Props } from '../Search'; import { click } from '../../../helpers/testUtils'; +import { Visibility } from '../../../app/types'; -const organization = { key: 'org', name: 'org', projectVisibility: 'public' }; +const organization = { key: 'org', name: 'org', projectVisibility: Visibility.Public }; it('renders', () => { expect(shallowRender()).toMatchSnapshot();