PreviousVersion = 'previous_version' | PreviousVersion = 'previous_version' | ||||
} | } | ||||
export interface Permission { | |||||
export interface PermissionDefinition { | |||||
key: string; | key: string; | ||||
name: string; | name: string; | ||||
description: string; | description: string; | ||||
} | } | ||||
export type PermissionDefinitions = Array<PermissionDefinition | PermissionDefinitionGroup>; | |||||
export interface PermissionDefinitionGroup { | |||||
category: string; | |||||
permissions: PermissionDefinition[]; | |||||
} | |||||
export interface PermissionGroup { | export interface PermissionGroup { | ||||
description?: string; | |||||
id?: string; | id?: string; | ||||
name: string; | name: string; | ||||
description?: string; | |||||
permissions: string[]; | permissions: string[]; | ||||
} | } | ||||
export interface PermissionUser { | export interface PermissionUser { | ||||
avatar?: string; | |||||
email?: string; | |||||
login: string; | login: string; | ||||
name: string; | name: string; | ||||
email?: string; | |||||
permissions: string[]; | permissions: string[]; | ||||
avatar?: string; | |||||
} | } | ||||
export interface PermissionTemplate { | export interface PermissionTemplate { |
import React from 'react'; | import React from 'react'; | ||||
import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||
import Helmet from 'react-helmet'; | import Helmet from 'react-helmet'; | ||||
import { debounce } from 'lodash'; | |||||
import TemplateHeader from './TemplateHeader'; | import TemplateHeader from './TemplateHeader'; | ||||
import TemplateDetails from './TemplateDetails'; | import TemplateDetails from './TemplateDetails'; | ||||
import HoldersList from '../../permissions/shared/components/HoldersList'; | import HoldersList from '../../permissions/shared/components/HoldersList'; | ||||
import SearchForm from '../../permissions/shared/components/SearchForm'; | import SearchForm from '../../permissions/shared/components/SearchForm'; | ||||
import { PERMISSIONS_ORDER_FOR_PROJECT } from '../../permissions/project/constants'; | |||||
import { | |||||
convertToPermissionDefinitions, | |||||
PERMISSIONS_ORDER_FOR_PROJECT_TEMPLATE | |||||
} from '../../permissions/utils'; | |||||
import * as api from '../../../api/permissions'; | import * as api from '../../../api/permissions'; | ||||
import { translate } from '../../../helpers/l10n'; | import { translate } from '../../../helpers/l10n'; | ||||
}; | }; | ||||
render() { | render() { | ||||
const permissions = PERMISSIONS_ORDER_FOR_PROJECT.map(p => ({ | |||||
key: p, | |||||
name: translate('projects_role', p), | |||||
description: translate('projects_role', p, 'desc') | |||||
})); | |||||
const permissions = convertToPermissionDefinitions( | |||||
PERMISSIONS_ORDER_FOR_PROJECT_TEMPLATE, | |||||
'projects_role' | |||||
); | |||||
const allUsers = [...this.state.users]; | const allUsers = [...this.state.users]; | ||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { connect } from 'react-redux'; | |||||
import SearchForm from '../../shared/components/SearchForm'; | import SearchForm from '../../shared/components/SearchForm'; | ||||
import HoldersList from '../../shared/components/HoldersList'; | import HoldersList from '../../shared/components/HoldersList'; | ||||
import { translate } from '../../../../helpers/l10n'; | |||||
import { Organization, Paging, PermissionGroup, PermissionUser } from '../../../../app/types'; | |||||
import ListFooter from '../../../../components/controls/ListFooter'; | import ListFooter from '../../../../components/controls/ListFooter'; | ||||
import { | |||||
AppState, | |||||
Organization, | |||||
Paging, | |||||
PermissionGroup, | |||||
PermissionUser | |||||
} from '../../../../app/types'; | |||||
import { | |||||
PERMISSIONS_ORDER_GLOBAL, | |||||
convertToPermissionDefinitions, | |||||
PERMISSIONS_ORDER_GLOBAL_GOV | |||||
} from '../../utils'; | |||||
import { Store, getAppState } from '../../../../store/rootReducer'; | |||||
const PERMISSIONS_ORDER = ['admin', 'profileadmin', 'gateadmin', 'scan', 'provisioning']; | |||||
interface StateProps { | |||||
appState: Pick<AppState, 'qualifiers'>; | |||||
} | |||||
interface Props { | |||||
interface OwnProps { | |||||
filter: string; | filter: string; | ||||
grantPermissionToGroup: (groupName: string, permission: string) => Promise<void>; | grantPermissionToGroup: (groupName: string, permission: string) => Promise<void>; | ||||
grantPermissionToUser: (login: string, permission: string) => Promise<void>; | grantPermissionToUser: (login: string, permission: string) => Promise<void>; | ||||
groups: PermissionGroup[]; | groups: PermissionGroup[]; | ||||
groupsPaging: Paging; | |||||
groupsPaging?: Paging; | |||||
loadHolders: () => void; | loadHolders: () => void; | ||||
loading?: boolean; | loading?: boolean; | ||||
onLoadMore: (usersPageIndex: number, groupsPageIndex: number) => void; | |||||
onLoadMore: () => void; | |||||
onFilter: (filter: string) => void; | onFilter: (filter: string) => void; | ||||
onSearch: (query: string) => void; | onSearch: (query: string) => void; | ||||
onSelectPermission: (permission: string) => void; | |||||
organization?: Organization; | organization?: Organization; | ||||
query: string; | query: string; | ||||
revokePermissionFromGroup: (groupName: string, permission: string) => Promise<void>; | revokePermissionFromGroup: (groupName: string, permission: string) => Promise<void>; | ||||
revokePermissionFromUser: (login: string, permission: string) => Promise<void>; | revokePermissionFromUser: (login: string, permission: string) => Promise<void>; | ||||
selectedPermission?: string; | |||||
users: PermissionUser[]; | users: PermissionUser[]; | ||||
usersPaging: Paging; | |||||
usersPaging?: Paging; | |||||
} | } | ||||
export default class AllHoldersList extends React.PureComponent<Props> { | |||||
type Props = StateProps & OwnProps; | |||||
export class AllHoldersList extends React.PureComponent<Props> { | |||||
handleToggleUser = (user: PermissionUser, permission: string) => { | handleToggleUser = (user: PermissionUser, permission: string) => { | ||||
const hasPermission = user.permissions.includes(permission); | const hasPermission = user.permissions.includes(permission); | ||||
if (hasPermission) { | if (hasPermission) { | ||||
} | } | ||||
}; | }; | ||||
handleLoadMore = () => { | |||||
this.props.onLoadMore( | |||||
this.props.usersPaging.pageIndex + 1, | |||||
this.props.groupsPaging.pageIndex + 1 | |||||
); | |||||
}; | |||||
render() { | render() { | ||||
const { filter, groups, groupsPaging, users, usersPaging } = this.props; | |||||
const l10nPrefix = this.props.organization ? 'organizations_permissions' : 'global_permissions'; | const l10nPrefix = this.props.organization ? 'organizations_permissions' : 'global_permissions'; | ||||
const permissions = PERMISSIONS_ORDER.map(p => ({ | |||||
key: p, | |||||
name: translate(l10nPrefix, p), | |||||
description: translate(l10nPrefix, p, 'desc') | |||||
})); | |||||
const governanceInstalled = this.props.appState.qualifiers.includes('VW'); | |||||
const permissions = convertToPermissionDefinitions( | |||||
governanceInstalled ? PERMISSIONS_ORDER_GLOBAL_GOV : PERMISSIONS_ORDER_GLOBAL, | |||||
l10nPrefix | |||||
); | |||||
const count = | |||||
(this.props.filter !== 'users' ? this.props.groups.length : 0) + | |||||
(this.props.filter !== 'groups' ? this.props.users.length : 0); | |||||
const total = | |||||
(this.props.filter !== 'users' ? this.props.groupsPaging.total : 0) + | |||||
(this.props.filter !== 'groups' ? this.props.usersPaging.total : 0); | |||||
let count = 0; | |||||
let total = 0; | |||||
if (filter !== 'users') { | |||||
count += groups.length; | |||||
total += groupsPaging ? groupsPaging.total : groups.length; | |||||
} | |||||
if (filter !== 'groups') { | |||||
count += users.length; | |||||
total += usersPaging ? usersPaging.total : users.length; | |||||
} | |||||
return ( | return ( | ||||
<> | <> | ||||
<HoldersList | <HoldersList | ||||
groups={this.props.groups} | groups={this.props.groups} | ||||
loading={this.props.loading} | loading={this.props.loading} | ||||
onSelectPermission={this.props.onSelectPermission} | |||||
onToggleGroup={this.handleToggleGroup} | onToggleGroup={this.handleToggleGroup} | ||||
onToggleUser={this.handleToggleUser} | onToggleUser={this.handleToggleUser} | ||||
permissions={permissions} | permissions={permissions} | ||||
selectedPermission={this.props.selectedPermission} | |||||
users={this.props.users}> | users={this.props.users}> | ||||
<SearchForm | <SearchForm | ||||
filter={this.props.filter} | filter={this.props.filter} | ||||
query={this.props.query} | query={this.props.query} | ||||
/> | /> | ||||
</HoldersList> | </HoldersList> | ||||
<ListFooter count={count} loadMore={this.handleLoadMore} total={total} /> | |||||
<ListFooter count={count} loadMore={this.props.onLoadMore} total={total} /> | |||||
</> | </> | ||||
); | ); | ||||
} | } | ||||
} | } | ||||
const mapStateToProps = (state: Store): StateProps => ({ | |||||
appState: getAppState(state) | |||||
}); | |||||
export default connect(mapStateToProps)(AllHoldersList); |
} | } | ||||
interface State { | interface State { | ||||
filter: string; | |||||
filter: 'all' | 'groups' | 'users'; | |||||
groups: PermissionGroup[]; | groups: PermissionGroup[]; | ||||
groupsPaging: Paging; | |||||
groupsPaging?: Paging; | |||||
loading: boolean; | loading: boolean; | ||||
query: string; | query: string; | ||||
selectedPermission?: string; | |||||
users: PermissionUser[]; | users: PermissionUser[]; | ||||
usersPaging: Paging; | |||||
usersPaging?: Paging; | |||||
} | } | ||||
export class App extends React.PureComponent<Props, State> { | export class App extends React.PureComponent<Props, State> { | ||||
this.state = { | this.state = { | ||||
filter: 'all', | filter: 'all', | ||||
groups: [], | groups: [], | ||||
groupsPaging: { pageIndex: 1, pageSize: 100, total: 0 }, | |||||
loading: true, | loading: true, | ||||
query: '', | query: '', | ||||
users: [], | |||||
usersPaging: { pageIndex: 1, pageSize: 100, total: 0 } | |||||
users: [] | |||||
}; | }; | ||||
} | } | ||||
loadUsersAndGroups = (userPage?: number, groupsPage?: number) => { | loadUsersAndGroups = (userPage?: number, groupsPage?: number) => { | ||||
const { organization } = this.props; | const { organization } = this.props; | ||||
const { filter, query, selectedPermission } = this.state; | |||||
const { filter, query } = this.state; | |||||
const getUsers = | |||||
const getUsers: Promise<{ paging?: Paging; users: PermissionUser[] }> = | |||||
filter !== 'groups' | filter !== 'groups' | ||||
? api.getGlobalPermissionsUsers({ | ? api.getGlobalPermissionsUsers({ | ||||
q: query || undefined, | q: query || undefined, | ||||
permission: selectedPermission, | |||||
organization: organization && organization.key, | organization: organization && organization.key, | ||||
p: userPage | p: userPage | ||||
}) | }) | ||||
: Promise.resolve({ | |||||
paging: { | |||||
pageIndex: 1, | |||||
pageSize: 100, | |||||
total: 0 | |||||
}, | |||||
users: [] | |||||
}); | |||||
: Promise.resolve({ paging: undefined, users: [] }); | |||||
const getGroups = | |||||
const getGroups: Promise<{ paging?: Paging; groups: PermissionGroup[] }> = | |||||
filter !== 'users' | filter !== 'users' | ||||
? api.getGlobalPermissionsGroups({ | ? api.getGlobalPermissionsGroups({ | ||||
q: query || undefined, | q: query || undefined, | ||||
permission: selectedPermission, | |||||
organization: organization && organization.key, | organization: organization && organization.key, | ||||
p: groupsPage | p: groupsPage | ||||
}) | }) | ||||
: Promise.resolve({ | |||||
paging: { pageIndex: 1, pageSize: 100, total: 0 }, | |||||
groups: [] | |||||
}); | |||||
: Promise.resolve({ paging: undefined, groups: [] }); | |||||
return Promise.all([getUsers, getGroups]); | return Promise.all([getUsers, getGroups]); | ||||
}; | }; | ||||
}; | }; | ||||
onLoadMore = () => { | onLoadMore = () => { | ||||
const { usersPaging, groupsPaging } = this.state; | |||||
this.setState({ loading: true }); | this.setState({ loading: true }); | ||||
return this.loadUsersAndGroups( | return this.loadUsersAndGroups( | ||||
this.state.usersPaging.pageIndex + 1, | |||||
this.state.groupsPaging.pageIndex + 1 | |||||
usersPaging ? usersPaging.pageIndex + 1 : 1, | |||||
groupsPaging ? groupsPaging.pageIndex + 1 : 1 | |||||
).then(([usersResponse, groupsResponse]) => { | ).then(([usersResponse, groupsResponse]) => { | ||||
if (this.mounted) { | if (this.mounted) { | ||||
this.setState(({ groups, users }) => ({ | this.setState(({ groups, users }) => ({ | ||||
}, this.stopLoading); | }, this.stopLoading); | ||||
}; | }; | ||||
onFilter = (filter: string) => { | |||||
onFilter = (filter: 'all' | 'groups' | 'users') => { | |||||
this.setState({ filter }, this.loadHolders); | this.setState({ filter }, this.loadHolders); | ||||
}; | }; | ||||
this.setState({ query }, this.loadHolders); | this.setState({ query }, this.loadHolders); | ||||
}; | }; | ||||
onSelectPermission = (permission: string) => { | |||||
this.setState( | |||||
({ selectedPermission }) => ({ | |||||
selectedPermission: selectedPermission !== permission ? permission : undefined | |||||
}), | |||||
this.loadHolders | |||||
); | |||||
}; | |||||
addPermissionToGroup = (groups: PermissionGroup[], group: string, permission: string) => { | addPermissionToGroup = (groups: PermissionGroup[], group: string, permission: string) => { | ||||
return groups.map( | return groups.map( | ||||
candidate => | candidate => | ||||
onFilter={this.onFilter} | onFilter={this.onFilter} | ||||
onLoadMore={this.onLoadMore} | onLoadMore={this.onLoadMore} | ||||
onSearch={this.onSearch} | onSearch={this.onSearch} | ||||
onSelectPermission={this.onSelectPermission} | |||||
query={this.state.query} | query={this.state.query} | ||||
revokePermissionFromGroup={this.revokePermissionFromGroup} | revokePermissionFromGroup={this.revokePermissionFromGroup} | ||||
revokePermissionFromUser={this.revokePermissionFromUser} | revokePermissionFromUser={this.revokePermissionFromUser} | ||||
selectedPermission={this.state.selectedPermission} | |||||
users={this.state.users} | users={this.state.users} | ||||
usersPaging={this.state.usersPaging} | usersPaging={this.state.usersPaging} | ||||
/> | /> |
import { without } from 'lodash'; | import { without } from 'lodash'; | ||||
import SearchForm from '../../shared/components/SearchForm'; | import SearchForm from '../../shared/components/SearchForm'; | ||||
import HoldersList from '../../shared/components/HoldersList'; | import HoldersList from '../../shared/components/HoldersList'; | ||||
import { translate } from '../../../../helpers/l10n'; | |||||
import { PERMISSIONS_ORDER_BY_QUALIFIER } from '../constants'; | |||||
import ListFooter from '../../../../components/controls/ListFooter'; | |||||
import { PERMISSIONS_ORDER_BY_QUALIFIER, convertToPermissionDefinitions } from '../../utils'; | |||||
import { | import { | ||||
Component, | Component, | ||||
Paging, | Paging, | ||||
PermissionUser, | PermissionUser, | ||||
Visibility | Visibility | ||||
} from '../../../../app/types'; | } from '../../../../app/types'; | ||||
import ListFooter from '../../../../components/controls/ListFooter'; | |||||
interface Props { | interface Props { | ||||
component: Component; | component: Component; | ||||
grantPermissionToGroup: (group: string, permission: string) => Promise<void>; | grantPermissionToGroup: (group: string, permission: string) => Promise<void>; | ||||
grantPermissionToUser: (user: string, permission: string) => Promise<void>; | grantPermissionToUser: (user: string, permission: string) => Promise<void>; | ||||
groups: PermissionGroup[]; | groups: PermissionGroup[]; | ||||
groupsPaging: Paging; | |||||
onLoadMore: (usersPageIndex: number, groupsPageIndex: number) => void; | |||||
groupsPaging?: Paging; | |||||
onLoadMore: () => void; | |||||
onFilterChange: (filter: string) => void; | onFilterChange: (filter: string) => void; | ||||
onPermissionSelect: (permissions?: string) => void; | onPermissionSelect: (permissions?: string) => void; | ||||
onQueryChange: (query: string) => void; | onQueryChange: (query: string) => void; | ||||
revokePermissionFromUser: (user: string, permission: string) => Promise<void>; | revokePermissionFromUser: (user: string, permission: string) => Promise<void>; | ||||
selectedPermission?: string; | selectedPermission?: string; | ||||
users: PermissionUser[]; | users: PermissionUser[]; | ||||
usersPaging: Paging; | |||||
usersPaging?: Paging; | |||||
visibility?: Visibility; | visibility?: Visibility; | ||||
} | } | ||||
this.props.onPermissionSelect(permission); | this.props.onPermissionSelect(permission); | ||||
}; | }; | ||||
handleLoadMore = () => { | |||||
this.props.onLoadMore( | |||||
this.props.usersPaging.pageIndex + 1, | |||||
this.props.groupsPaging.pageIndex + 1 | |||||
); | |||||
}; | |||||
render() { | render() { | ||||
const { filter, groups, groupsPaging, users, usersPaging } = this.props; | |||||
let order = PERMISSIONS_ORDER_BY_QUALIFIER[this.props.component.qualifier]; | let order = PERMISSIONS_ORDER_BY_QUALIFIER[this.props.component.qualifier]; | ||||
if (this.props.visibility === Visibility.Public) { | if (this.props.visibility === Visibility.Public) { | ||||
order = without(order, 'user', 'codeviewer'); | order = without(order, 'user', 'codeviewer'); | ||||
} | } | ||||
const permissions = convertToPermissionDefinitions(order, 'projects_role'); | |||||
const permissions = order.map(p => ({ | |||||
key: p, | |||||
name: translate('projects_role', p), | |||||
description: translate('projects_role', p, 'desc') | |||||
})); | |||||
const count = | |||||
(this.props.filter !== 'users' ? this.props.groups.length : 0) + | |||||
(this.props.filter !== 'groups' ? this.props.users.length : 0); | |||||
const total = | |||||
(this.props.filter !== 'users' ? this.props.groupsPaging.total : 0) + | |||||
(this.props.filter !== 'groups' ? this.props.usersPaging.total : 0); | |||||
let count = 0; | |||||
let total = 0; | |||||
if (filter !== 'users') { | |||||
count += groups.length; | |||||
total += groupsPaging ? groupsPaging.total : groups.length; | |||||
} | |||||
if (filter !== 'groups') { | |||||
count += users.length; | |||||
total += usersPaging ? usersPaging.total : users.length; | |||||
} | |||||
return ( | return ( | ||||
<> | <> | ||||
query={this.props.query} | query={this.props.query} | ||||
/> | /> | ||||
</HoldersList> | </HoldersList> | ||||
<ListFooter count={count} loadMore={this.handleLoadMore} total={total} /> | |||||
<ListFooter count={count} loadMore={this.props.onLoadMore} total={total} /> | |||||
</> | </> | ||||
); | ); | ||||
} | } |
disclaimer: boolean; | disclaimer: boolean; | ||||
filter: string; | filter: string; | ||||
groups: PermissionGroup[]; | groups: PermissionGroup[]; | ||||
groupsPaging: Paging; | |||||
groupsPaging?: Paging; | |||||
loading: boolean; | loading: boolean; | ||||
query: string; | query: string; | ||||
selectedPermission?: string; | selectedPermission?: string; | ||||
users: PermissionUser[]; | users: PermissionUser[]; | ||||
usersPaging: Paging; | |||||
usersPaging?: Paging; | |||||
} | } | ||||
export default class App extends React.PureComponent<Props, State> { | export default class App extends React.PureComponent<Props, State> { | ||||
disclaimer: false, | disclaimer: false, | ||||
filter: 'all', | filter: 'all', | ||||
groups: [], | groups: [], | ||||
groupsPaging: { pageIndex: 1, pageSize: 100, total: 0 }, | |||||
loading: true, | loading: true, | ||||
query: '', | query: '', | ||||
users: [], | |||||
usersPaging: { pageIndex: 1, pageSize: 100, total: 0 } | |||||
users: [] | |||||
}; | }; | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
loadHolders = (usersPageIndex?: number, groupsPageIndex?: number) => { | |||||
if (this.mounted) { | |||||
this.setState({ loading: true }); | |||||
const { component } = this.props; | |||||
const { filter, query, selectedPermission } = this.state; | |||||
const getUsers = | |||||
filter !== 'groups' | |||||
? api.getPermissionsUsersForComponent({ | |||||
projectKey: component.key, | |||||
q: query || undefined, | |||||
permission: selectedPermission, | |||||
organization: component.organization, | |||||
p: usersPageIndex | |||||
}) | |||||
: Promise.resolve({ | |||||
paging: { pageIndex: 1, pageSize: 100, total: 0 }, | |||||
users: [] | |||||
}); | |||||
loadUsersAndGroups = (userPage?: number, groupsPage?: number) => { | |||||
const { component } = this.props; | |||||
const { filter, query, selectedPermission } = this.state; | |||||
const getUsers: Promise<{ paging?: Paging; users: PermissionUser[] }> = | |||||
filter !== 'groups' | |||||
? api.getPermissionsUsersForComponent({ | |||||
projectKey: component.key, | |||||
q: query || undefined, | |||||
permission: selectedPermission, | |||||
organization: component.organization, | |||||
p: userPage | |||||
}) | |||||
: Promise.resolve({ paging: undefined, users: [] }); | |||||
const getGroups: Promise<{ paging?: Paging; groups: PermissionGroup[] }> = | |||||
filter !== 'users' | |||||
? api.getPermissionsGroupsForComponent({ | |||||
projectKey: component.key, | |||||
q: query || undefined, | |||||
permission: selectedPermission, | |||||
organization: component.organization, | |||||
p: groupsPage | |||||
}) | |||||
: Promise.resolve({ paging: undefined, groups: [] }); | |||||
return Promise.all([getUsers, getGroups]); | |||||
}; | |||||
const getGroups = | |||||
filter !== 'users' | |||||
? api.getPermissionsGroupsForComponent({ | |||||
projectKey: component.key, | |||||
q: query || undefined, | |||||
permission: selectedPermission, | |||||
organization: component.organization, | |||||
p: groupsPageIndex | |||||
}) | |||||
: Promise.resolve({ | |||||
paging: { pageIndex: 1, pageSize: 100, total: 0 }, | |||||
groups: [] | |||||
}); | |||||
loadHolders = () => { | |||||
this.setState({ loading: true }); | |||||
return this.loadUsersAndGroups().then(([usersResponse, groupsResponse]) => { | |||||
if (this.mounted) { | |||||
this.setState({ | |||||
groups: groupsResponse.groups, | |||||
groupsPaging: groupsResponse.paging, | |||||
loading: false, | |||||
users: usersResponse.users, | |||||
usersPaging: usersResponse.paging | |||||
}); | |||||
} | |||||
}, this.stopLoading); | |||||
}; | |||||
Promise.all([getUsers, getGroups]).then(responses => { | |||||
if (this.mounted) { | |||||
this.setState(state => ({ | |||||
loading: false, | |||||
groups: groupsPageIndex | |||||
? [...state.groups, ...responses[1].groups] | |||||
: responses[1].groups, | |||||
groupsPaging: responses[1].paging, | |||||
users: usersPageIndex ? [...state.users, ...responses[0].users] : responses[0].users, | |||||
usersPaging: responses[0].paging | |||||
})); | |||||
} | |||||
}, this.stopLoading); | |||||
} | |||||
onLoadMore = () => { | |||||
const { usersPaging, groupsPaging } = this.state; | |||||
this.setState({ loading: true }); | |||||
return this.loadUsersAndGroups( | |||||
usersPaging ? usersPaging.pageIndex + 1 : 1, | |||||
groupsPaging ? groupsPaging.pageIndex + 1 : 1 | |||||
).then(([usersResponse, groupsResponse]) => { | |||||
if (this.mounted) { | |||||
this.setState(({ groups, users }) => ({ | |||||
groups: [...groups, ...groupsResponse.groups], | |||||
groupsPaging: groupsResponse.paging, | |||||
loading: false, | |||||
users: [...users, ...usersResponse.users], | |||||
usersPaging: usersResponse.paging | |||||
})); | |||||
} | |||||
}, this.stopLoading); | |||||
}; | }; | ||||
handleFilterChange = (filter: string) => { | handleFilterChange = (filter: string) => { | ||||
} | } | ||||
}; | }; | ||||
handleLoadMore = (usersPageIndex: number, groupsPageIndex: number) => { | |||||
this.loadHolders(usersPageIndex, groupsPageIndex); | |||||
}; | |||||
render() { | render() { | ||||
const canTurnToPrivate = | const canTurnToPrivate = | ||||
this.props.component.configuration != null && | this.props.component.configuration != null && | ||||
groups={this.state.groups} | groups={this.state.groups} | ||||
groupsPaging={this.state.groupsPaging} | groupsPaging={this.state.groupsPaging} | ||||
onFilterChange={this.handleFilterChange} | onFilterChange={this.handleFilterChange} | ||||
onLoadMore={this.handleLoadMore} | |||||
onLoadMore={this.onLoadMore} | |||||
onPermissionSelect={this.handlePermissionSelect} | onPermissionSelect={this.handlePermissionSelect} | ||||
onQueryChange={this.handleQueryChange} | onQueryChange={this.handleQueryChange} | ||||
query={this.state.query} | query={this.state.query} |
/* | |||||
* 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. | |||||
*/ | |||||
export const PERMISSIONS_ORDER_FOR_PROJECT = [ | |||||
'user', | |||||
'codeviewer', | |||||
'issueadmin', | |||||
'securityhotspotadmin', | |||||
'admin', | |||||
'scan' | |||||
]; | |||||
export const PERMISSIONS_ORDER_FOR_VIEW = ['user', 'admin']; | |||||
export const PERMISSIONS_ORDER_FOR_DEV = ['user', 'admin']; | |||||
export const PERMISSIONS_ORDER_BY_QUALIFIER: { [index: string]: string[] } = { | |||||
TRK: PERMISSIONS_ORDER_FOR_PROJECT, | |||||
VW: PERMISSIONS_ORDER_FOR_VIEW, | |||||
SVW: PERMISSIONS_ORDER_FOR_VIEW, | |||||
APP: PERMISSIONS_ORDER_FOR_VIEW, | |||||
DEV: PERMISSIONS_ORDER_FOR_DEV | |||||
}; |
*/ | */ | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { without } from 'lodash'; | import { without } from 'lodash'; | ||||
import Checkbox from '../../../../components/controls/Checkbox'; | |||||
import PermissionCell from './PermissionCell'; | |||||
import GroupIcon from '../../../../components/icons-components/GroupIcon'; | import GroupIcon from '../../../../components/icons-components/GroupIcon'; | ||||
import { PermissionGroup } from '../../../../app/types'; | |||||
import { PermissionDefinitions, PermissionGroup } from '../../../../app/types'; | |||||
import { isPermissionDefinitionGroup } from '../../utils'; | |||||
interface Props { | interface Props { | ||||
group: PermissionGroup; | group: PermissionGroup; | ||||
permissions: string[]; | |||||
selectedPermission?: string; | |||||
permissionsOrder: string[]; | |||||
onToggle: (group: PermissionGroup, permission: string) => Promise<void>; | onToggle: (group: PermissionGroup, permission: string) => Promise<void>; | ||||
permissions: PermissionDefinitions; | |||||
selectedPermission?: string; | |||||
} | } | ||||
interface State { | interface State { | ||||
}; | }; | ||||
render() { | render() { | ||||
const { selectedPermission } = this.props; | |||||
const permissionCells = this.props.permissionsOrder.map(permission => ( | |||||
<td | |||||
className="text-center text-middle" | |||||
key={permission} | |||||
style={{ backgroundColor: permission === selectedPermission ? '#d9edf7' : 'transparent' }}> | |||||
<Checkbox | |||||
checked={this.props.permissions.includes(permission)} | |||||
disabled={this.state.loading.includes(permission)} | |||||
id={permission} | |||||
onCheck={this.handleCheck} | |||||
/> | |||||
</td> | |||||
)); | |||||
const { group } = this.props; | const { group } = this.props; | ||||
return ( | return ( | ||||
<tr> | <tr> | ||||
<td className="nowrap"> | |||||
<td className="nowrap text-middle"> | |||||
<div className="display-inline-block text-middle big-spacer-right"> | <div className="display-inline-block text-middle big-spacer-right"> | ||||
<GroupIcon /> | <GroupIcon /> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</td> | </td> | ||||
{permissionCells} | |||||
{this.props.permissions.map(permission => ( | |||||
<PermissionCell | |||||
key={isPermissionDefinitionGroup(permission) ? permission.category : permission.key} | |||||
loading={this.state.loading} | |||||
onCheck={this.handleCheck} | |||||
permission={permission} | |||||
permissionItem={group} | |||||
selectedPermission={this.props.selectedPermission} | |||||
/> | |||||
))} | |||||
</tr> | </tr> | ||||
); | ); | ||||
} | } |
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { groupBy } from 'lodash'; | |||||
import { partition, sortBy } from 'lodash'; | |||||
import UserHolder from './UserHolder'; | import UserHolder from './UserHolder'; | ||||
import GroupHolder from './GroupHolder'; | import GroupHolder from './GroupHolder'; | ||||
import PermissionHeader from './PermissionHeader'; | import PermissionHeader from './PermissionHeader'; | ||||
import { translate } from '../../../../helpers/l10n'; | import { translate } from '../../../../helpers/l10n'; | ||||
import { Permission, PermissionGroup, PermissionUser } from '../../../../app/types'; | |||||
import { PermissionGroup, PermissionUser, PermissionDefinitions } from '../../../../app/types'; | |||||
import { isPermissionDefinitionGroup } from '../../utils'; | |||||
interface Props { | interface Props { | ||||
loading?: boolean; | loading?: boolean; | ||||
groups: PermissionGroup[]; | groups: PermissionGroup[]; | ||||
onSelectPermission: (permission: string) => void; | |||||
onSelectPermission?: (permission: string) => void; | |||||
onToggleGroup: (group: PermissionGroup, permission: string) => Promise<void>; | onToggleGroup: (group: PermissionGroup, permission: string) => Promise<void>; | ||||
onToggleUser: (user: PermissionUser, permission: string) => Promise<void>; | onToggleUser: (user: PermissionUser, permission: string) => Promise<void>; | ||||
permissions: Permission[]; | |||||
permissions: PermissionDefinitions; | |||||
selectedPermission?: string; | selectedPermission?: string; | ||||
showPublicProjectsWarning?: boolean; | showPublicProjectsWarning?: boolean; | ||||
users: PermissionUser[]; | users: PermissionUser[]; | ||||
return (item as PermissionUser).login !== undefined; | return (item as PermissionUser).login !== undefined; | ||||
} | } | ||||
renderTableHeader() { | |||||
const { onSelectPermission, selectedPermission, showPublicProjectsWarning } = this.props; | |||||
const cells = this.props.permissions.map(p => ( | |||||
<PermissionHeader | |||||
key={p.key} | |||||
onSelectPermission={onSelectPermission} | |||||
permission={p} | |||||
selectedPermission={selectedPermission} | |||||
showPublicProjectsWarning={showPublicProjectsWarning} | |||||
/> | |||||
)); | |||||
return ( | |||||
<thead> | |||||
<tr> | |||||
<td className="nowrap bordered-bottom">{this.props.children}</td> | |||||
{cells} | |||||
</tr> | |||||
</thead> | |||||
); | |||||
} | |||||
renderEmpty() { | renderEmpty() { | ||||
const columns = this.props.permissions.length + 1; | const columns = this.props.permissions.length + 1; | ||||
return ( | return ( | ||||
); | ); | ||||
} | } | ||||
renderItem(item: PermissionUser | PermissionGroup, permissionsOrder: string[]) { | |||||
return this.isPermissionUser(item) | |||||
? this.renderUser(item, permissionsOrder) | |||||
: this.renderGroup(item, permissionsOrder); | |||||
} | |||||
renderUser(user: PermissionUser, permissionsOrder: string[]) { | |||||
return ( | |||||
renderItem(item: PermissionUser | PermissionGroup, permissions: PermissionDefinitions) { | |||||
return this.isPermissionUser(item) ? ( | |||||
<UserHolder | <UserHolder | ||||
key={'user-' + user.login} | |||||
key={'user-' + item.login} | |||||
onToggle={this.props.onToggleUser} | onToggle={this.props.onToggleUser} | ||||
permissions={user.permissions} | |||||
permissionsOrder={permissionsOrder} | |||||
permissions={permissions} | |||||
selectedPermission={this.props.selectedPermission} | selectedPermission={this.props.selectedPermission} | ||||
user={user} | |||||
user={item} | |||||
/> | /> | ||||
); | |||||
} | |||||
renderGroup(group: PermissionGroup, permissionsOrder: string[]) { | |||||
return ( | |||||
) : ( | |||||
<GroupHolder | <GroupHolder | ||||
group={group} | |||||
key={'group-' + group.id} | |||||
group={item} | |||||
key={'group-' + item.id} | |||||
onToggle={this.props.onToggleGroup} | onToggle={this.props.onToggleGroup} | ||||
permissions={group.permissions} | |||||
permissionsOrder={permissionsOrder} | |||||
permissions={permissions} | |||||
selectedPermission={this.props.selectedPermission} | selectedPermission={this.props.selectedPermission} | ||||
/> | /> | ||||
); | ); | ||||
} | } | ||||
render() { | render() { | ||||
const permissionsOrder = this.props.permissions.map(p => p.key); | |||||
const items = [...this.props.users, ...this.props.groups].sort((a, b) => { | |||||
return a.name < b.name ? -1 : 1; | |||||
const { permissions } = this.props; | |||||
const items = sortBy([...this.props.users, ...this.props.groups], item => { | |||||
if (this.isPermissionUser(item) && item.login === '<creator>') { | |||||
return 0; | |||||
} | |||||
return item.name; | |||||
}); | }); | ||||
const { true: itemWithPermissions = [], false: itemWithoutPermissions = [] } = groupBy( | |||||
const [itemWithPermissions, itemWithoutPermissions] = partition( | |||||
items, | items, | ||||
item => item.permissions.length > 0 | item => item.permissions.length > 0 | ||||
); | ); | ||||
return ( | return ( | ||||
<div className="boxed-group boxed-group-inner"> | <div className="boxed-group boxed-group-inner"> | ||||
<table className="data zebra permissions-table"> | <table className="data zebra permissions-table"> | ||||
{this.renderTableHeader()} | |||||
<thead> | |||||
<tr> | |||||
<td className="nowrap bordered-bottom">{this.props.children}</td> | |||||
{permissions.map(permission => ( | |||||
<PermissionHeader | |||||
key={ | |||||
isPermissionDefinitionGroup(permission) ? permission.category : permission.key | |||||
} | |||||
onSelectPermission={this.props.onSelectPermission} | |||||
permission={permission} | |||||
selectedPermission={this.props.selectedPermission} | |||||
showPublicProjectsWarning={this.props.showPublicProjectsWarning} | |||||
/> | |||||
))} | |||||
</tr> | |||||
</thead> | |||||
<tbody> | <tbody> | ||||
{items.length === 0 && !this.props.loading && this.renderEmpty()} | {items.length === 0 && !this.props.loading && this.renderEmpty()} | ||||
{itemWithPermissions.map(item => this.renderItem(item, permissionsOrder))} | |||||
{itemWithPermissions.map(item => this.renderItem(item, permissions))} | |||||
{itemWithPermissions.length > 0 && | {itemWithPermissions.length > 0 && | ||||
itemWithoutPermissions.length > 0 && ( | itemWithoutPermissions.length > 0 && ( | ||||
<> | <> | ||||
<tr> | <tr> | ||||
<td className="divider" colSpan={6} /> | |||||
<td className="divider" colSpan={20} /> | |||||
</tr> | </tr> | ||||
<tr /> {/* Keep correct zebra colors in the table */} | |||||
<tr /> | |||||
{/* Keep correct zebra colors in the table */} | |||||
</> | </> | ||||
)} | )} | ||||
{itemWithoutPermissions.map(item => this.renderItem(item, permissionsOrder))} | |||||
{itemWithoutPermissions.map(item => this.renderItem(item, permissions))} | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</div> | </div> |
/* | |||||
* 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 * as classNames from 'classnames'; | |||||
import { | |||||
PermissionDefinition, | |||||
PermissionDefinitionGroup, | |||||
PermissionGroup, | |||||
PermissionUser | |||||
} from '../../../../app/types'; | |||||
import { isPermissionDefinitionGroup } from '../../utils'; | |||||
import Checkbox from '../../../../components/controls/Checkbox'; | |||||
interface Props { | |||||
loading: string[]; | |||||
onCheck: (checked: boolean, permission?: string) => void; | |||||
permission: PermissionDefinition | PermissionDefinitionGroup; | |||||
permissionItem: PermissionGroup | PermissionUser; | |||||
selectedPermission?: string; | |||||
} | |||||
export default class PermissionCell extends React.PureComponent<Props> { | |||||
render() { | |||||
const { loading, onCheck, permission, permissionItem, selectedPermission } = this.props; | |||||
if (isPermissionDefinitionGroup(permission)) { | |||||
return ( | |||||
<td className="text-middle"> | |||||
{permission.permissions.map(permission => ( | |||||
<div key={permission.key}> | |||||
<Checkbox | |||||
checked={permissionItem.permissions.includes(permission.key)} | |||||
disabled={loading.includes(permission.key)} | |||||
id={permission.key} | |||||
onCheck={onCheck}> | |||||
<span className="little-spacer-left">{permission.name}</span> | |||||
</Checkbox> | |||||
</div> | |||||
))} | |||||
</td> | |||||
); | |||||
} else { | |||||
return ( | |||||
<td | |||||
className={classNames('permission-column text-center text-middle', { | |||||
selected: permission.key === selectedPermission | |||||
})}> | |||||
<Checkbox | |||||
checked={permissionItem.permissions.includes(permission.key)} | |||||
disabled={loading.includes(permission.key)} | |||||
id={permission.key} | |||||
onCheck={onCheck} | |||||
/> | |||||
</td> | |||||
); | |||||
} | |||||
} | |||||
} |
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import * as classNames from 'classnames'; | |||||
import HelpTooltip from '../../../../components/controls/HelpTooltip'; | import HelpTooltip from '../../../../components/controls/HelpTooltip'; | ||||
import InstanceMessage from '../../../../components/common/InstanceMessage'; | import InstanceMessage from '../../../../components/common/InstanceMessage'; | ||||
import Tooltip from '../../../../components/controls/Tooltip'; | |||||
import { translate, translateWithParameters } from '../../../../helpers/l10n'; | import { translate, translateWithParameters } from '../../../../helpers/l10n'; | ||||
import { Permission } from '../../../../app/types'; | |||||
import { PermissionDefinition, PermissionDefinitionGroup } from '../../../../app/types'; | |||||
import { isPermissionDefinitionGroup } from '../../utils'; | |||||
import Tooltip from '../../../../components/controls/Tooltip'; | |||||
interface Props { | interface Props { | ||||
onSelectPermission: (permission: string) => void; | |||||
permission: Permission; | |||||
onSelectPermission?: (permission: string) => void; | |||||
permission: PermissionDefinition | PermissionDefinitionGroup; | |||||
selectedPermission?: string; | selectedPermission?: string; | ||||
showPublicProjectsWarning?: boolean; | showPublicProjectsWarning?: boolean; | ||||
} | } | ||||
handlePermissionClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => { | handlePermissionClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => { | ||||
event.preventDefault(); | event.preventDefault(); | ||||
event.currentTarget.blur(); | event.currentTarget.blur(); | ||||
this.props.onSelectPermission(this.props.permission.key); | |||||
const { permission } = this.props; | |||||
if (this.props.onSelectPermission && !isPermissionDefinitionGroup(permission)) { | |||||
this.props.onSelectPermission(permission.key); | |||||
} | |||||
}; | }; | ||||
renderTooltip = (permission: Permission) => { | |||||
if (this.props.showPublicProjectsWarning && ['user', 'codeviewer'].includes(permission.key)) { | |||||
return ( | |||||
<div> | |||||
<InstanceMessage message={permission.description} /> | |||||
<div className="alert alert-warning spacer-top"> | |||||
{translate('projects_role.public_projects_warning')} | |||||
getTooltipOverlay = () => { | |||||
const { permission } = this.props; | |||||
if (isPermissionDefinitionGroup(permission)) { | |||||
return permission.permissions.map(permission => ( | |||||
<> | |||||
<b className="little-spacer-right">{permission.name}:</b> | |||||
<InstanceMessage key={permission.key} message={permission.description} /> | |||||
<br /> | |||||
</> | |||||
)); | |||||
} else { | |||||
if (this.props.showPublicProjectsWarning && ['user', 'codeviewer'].includes(permission.key)) { | |||||
return ( | |||||
<div> | |||||
<InstanceMessage message={permission.description} /> | |||||
<div className="alert alert-warning spacer-top"> | |||||
{translate('projects_role.public_projects_warning')} | |||||
</div> | |||||
</div> | </div> | ||||
</div> | |||||
); | |||||
); | |||||
} | |||||
return <InstanceMessage message={permission.description} />; | |||||
} | } | ||||
return <InstanceMessage message={permission.description} />; | |||||
}; | }; | ||||
render() { | render() { | ||||
const { permission, selectedPermission } = this.props; | |||||
const { onSelectPermission, permission } = this.props; | |||||
let name; | |||||
if (isPermissionDefinitionGroup(permission)) { | |||||
name = translate('global_permissions', permission.category); | |||||
} else { | |||||
name = onSelectPermission ? ( | |||||
<Tooltip | |||||
overlay={translateWithParameters( | |||||
'global_permissions.filter_by_x_permission', | |||||
permission.name | |||||
)}> | |||||
<a href="#" onClick={this.handlePermissionClick}> | |||||
{permission.name} | |||||
</a> | |||||
</Tooltip> | |||||
) : ( | |||||
permission.name | |||||
); | |||||
} | |||||
return ( | return ( | ||||
<th | <th | ||||
className="permission-column text-center" | |||||
style={{ | |||||
backgroundColor: permission.key === selectedPermission ? '#d9edf7' : 'transparent' | |||||
}}> | |||||
className={classNames('permission-column text-center text-middle', { | |||||
selected: | |||||
!isPermissionDefinitionGroup(permission) && | |||||
permission.key === this.props.selectedPermission | |||||
})}> | |||||
<div className="permission-column-inner"> | <div className="permission-column-inner"> | ||||
<Tooltip | |||||
overlay={translateWithParameters( | |||||
'global_permissions.filter_by_x_permission', | |||||
permission.name | |||||
)}> | |||||
<a className="text-middle" href="#" onClick={this.handlePermissionClick}> | |||||
{permission.name} | |||||
</a> | |||||
</Tooltip> | |||||
<HelpTooltip className="spacer-left" overlay={this.renderTooltip(permission)} /> | |||||
{name} | |||||
<HelpTooltip className="spacer-left" overlay={this.getTooltipOverlay()} /> | |||||
</div> | </div> | ||||
</th> | </th> | ||||
); | ); |
*/ | */ | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { without } from 'lodash'; | import { without } from 'lodash'; | ||||
import PermissionCell from './PermissionCell'; | |||||
import Avatar from '../../../../components/ui/Avatar'; | import Avatar from '../../../../components/ui/Avatar'; | ||||
import Checkbox from '../../../../components/controls/Checkbox'; | |||||
import { translate } from '../../../../helpers/l10n'; | import { translate } from '../../../../helpers/l10n'; | ||||
import { PermissionUser } from '../../../../app/types'; | |||||
import { PermissionDefinitions, PermissionUser } from '../../../../app/types'; | |||||
import { isPermissionDefinitionGroup } from '../../utils'; | |||||
interface Props { | interface Props { | ||||
user: PermissionUser; | |||||
permissions: string[]; | |||||
selectedPermission?: string; | |||||
permissionsOrder: string[]; | |||||
onToggle: (user: PermissionUser, permission: string) => Promise<void>; | onToggle: (user: PermissionUser, permission: string) => Promise<void>; | ||||
permissions: PermissionDefinitions; | |||||
selectedPermission?: string; | |||||
user: PermissionUser; | |||||
} | } | ||||
interface State { | interface State { | ||||
}; | }; | ||||
render() { | render() { | ||||
const { selectedPermission } = this.props; | |||||
const permissionCells = this.props.permissionsOrder.map(permission => ( | |||||
<td | |||||
className="text-center text-middle" | |||||
key={permission} | |||||
style={{ backgroundColor: permission === selectedPermission ? '#d9edf7' : 'transparent' }}> | |||||
<Checkbox | |||||
checked={this.props.permissions.includes(permission)} | |||||
disabled={this.state.loading.includes(permission)} | |||||
id={permission} | |||||
onCheck={this.handleCheck} | |||||
/> | |||||
</td> | |||||
const { user } = this.props; | |||||
const permissionCells = this.props.permissions.map(permission => ( | |||||
<PermissionCell | |||||
key={isPermissionDefinitionGroup(permission) ? permission.category : permission.key} | |||||
loading={this.state.loading} | |||||
onCheck={this.handleCheck} | |||||
permission={permission} | |||||
permissionItem={user} | |||||
selectedPermission={this.props.selectedPermission} | |||||
/> | |||||
)); | )); | ||||
const { user } = this.props; | |||||
if (user.login === '<creator>') { | if (user.login === '<creator>') { | ||||
return ( | return ( | ||||
<tr> | <tr> | ||||
<td className="nowrap"> | |||||
<td className="nowrap text-middle"> | |||||
<div className="display-inline-block text-middle"> | <div className="display-inline-block text-middle"> | ||||
<div> | <div> | ||||
<strong>{user.name}</strong> | <strong>{user.name}</strong> | ||||
return ( | return ( | ||||
<tr> | <tr> | ||||
<td className="nowrap"> | |||||
<td className="nowrap text-middle"> | |||||
<Avatar | <Avatar | ||||
className="text-middle big-spacer-right" | className="text-middle big-spacer-right" | ||||
hash={user.avatar} | hash={user.avatar} |
group={group} | group={group} | ||||
key="foo" | key="foo" | ||||
onToggle={jest.fn(() => Promise.resolve())} | onToggle={jest.fn(() => Promise.resolve())} | ||||
permissions={['bar']} | |||||
permissionsOrder={['bar', 'baz']} | |||||
permissions={[ | |||||
{ | |||||
category: 'admin', | |||||
permissions: [ | |||||
{ key: 'foo', name: 'Foo', description: '' }, | |||||
{ key: 'bar', name: 'Bar', description: '' } | |||||
] | |||||
}, | |||||
{ key: 'baz', name: 'Baz', description: '' } | |||||
]} | |||||
selectedPermission={'bar'} | selectedPermission={'bar'} | ||||
/> | /> | ||||
); | ); | ||||
it('should display checkboxes for permissions', () => { | |||||
it('should render correctly', () => { | |||||
expect(shallow(groupHolder)).toMatchSnapshot(); | expect(shallow(groupHolder)).toMatchSnapshot(); | ||||
}); | }); | ||||
it('should disabled checkboxes when waiting for promise to return', async () => { | |||||
it('should disabled PermissionCell checkboxes when waiting for promise to return', async () => { | |||||
const wrapper = shallow(groupHolder); | const wrapper = shallow(groupHolder); | ||||
expect(wrapper.state().loading).toEqual([]); | expect(wrapper.state().loading).toEqual([]); | ||||
(wrapper.instance() as GroupHolder).handleCheck(true, 'baz'); | (wrapper.instance() as GroupHolder).handleCheck(true, 'baz'); | ||||
wrapper.update(); | wrapper.update(); | ||||
expect(wrapper.state().loading).toEqual(['baz']); | expect(wrapper.state().loading).toEqual(['baz']); | ||||
expect(wrapper).toMatchSnapshot(); | |||||
(wrapper.instance() as GroupHolder).handleCheck(true, 'bar'); | (wrapper.instance() as GroupHolder).handleCheck(true, 'bar'); | ||||
wrapper.update(); | wrapper.update(); | ||||
expect(wrapper.state().loading).toEqual(['baz', 'bar']); | expect(wrapper.state().loading).toEqual(['baz', 'bar']); | ||||
expect(wrapper).toMatchSnapshot(); | |||||
await waitAndUpdate(wrapper); | await waitAndUpdate(wrapper); | ||||
expect(wrapper.state().loading).toEqual([]); | expect(wrapper.state().loading).toEqual([]); |
import { shallow } from 'enzyme'; | import { shallow } from 'enzyme'; | ||||
import HoldersList from '../HoldersList'; | import HoldersList from '../HoldersList'; | ||||
const permissions = [{ key: 'bar', name: 'bar', description: 'foo' }]; | |||||
const permissions = [ | |||||
{ key: 'foo', name: 'Foo', description: '' }, | |||||
{ | |||||
category: 'admin', | |||||
permissions: [ | |||||
{ key: 'bar', name: 'Bar', description: '' }, | |||||
{ key: 'baz', name: 'Baz', description: '' } | |||||
] | |||||
} | |||||
]; | |||||
const groups = [ | const groups = [ | ||||
{ id: 'foobar', name: 'Foobar', permissions: ['bar'] }, | { id: 'foobar', name: 'Foobar', permissions: ['bar'] }, |
/* | |||||
* 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 PermissionCell from '../PermissionCell'; | |||||
const permissionItem = { | |||||
id: 'foobar', | |||||
name: 'Foobar', | |||||
permissions: ['bar'] | |||||
}; | |||||
const permission = { key: 'baz', name: 'Baz', description: '' }; | |||||
const permissionGroup = { | |||||
category: 'admin', | |||||
permissions: [ | |||||
{ key: 'foo', name: 'Foo', description: '' }, | |||||
{ key: 'bar', name: 'Bar', description: '' } | |||||
] | |||||
}; | |||||
it('should display unchecked checkbox', () => { | |||||
expect( | |||||
shallow( | |||||
<PermissionCell | |||||
loading={[]} | |||||
onCheck={jest.fn()} | |||||
permission={permission} | |||||
permissionItem={permissionItem} | |||||
/> | |||||
) | |||||
).toMatchSnapshot(); | |||||
}); | |||||
it('should display multiple checkboxes with one checked', () => { | |||||
expect( | |||||
shallow( | |||||
<PermissionCell | |||||
loading={[]} | |||||
onCheck={jest.fn()} | |||||
permission={permissionGroup} | |||||
permissionItem={permissionItem} | |||||
/> | |||||
) | |||||
).toMatchSnapshot(); | |||||
}); | |||||
it('should display disabled checkbox', () => { | |||||
expect( | |||||
shallow( | |||||
<PermissionCell | |||||
loading={['baz']} | |||||
onCheck={jest.fn()} | |||||
permission={permission} | |||||
permissionItem={permissionItem} | |||||
/> | |||||
) | |||||
).toMatchSnapshot(); | |||||
}); | |||||
it('should display selected checkbox', () => { | |||||
expect( | |||||
shallow( | |||||
<PermissionCell | |||||
loading={[]} | |||||
onCheck={jest.fn()} | |||||
permission={permission} | |||||
permissionItem={permissionItem} | |||||
selectedPermission="baz" | |||||
/> | |||||
) | |||||
).toMatchSnapshot(); | |||||
}); |
<UserHolder | <UserHolder | ||||
key="foo" | key="foo" | ||||
onToggle={jest.fn(() => Promise.resolve())} | onToggle={jest.fn(() => Promise.resolve())} | ||||
permissions={['bar']} | |||||
permissionsOrder={['bar', 'baz']} | |||||
permissions={[ | |||||
{ | |||||
category: 'admin', | |||||
permissions: [ | |||||
{ key: 'foo', name: 'Foo', description: '' }, | |||||
{ key: 'bar', name: 'Bar', description: '' } | |||||
] | |||||
}, | |||||
{ key: 'baz', name: 'Baz', description: '' } | |||||
]} | |||||
selectedPermission={'bar'} | selectedPermission={'bar'} | ||||
user={user} | user={user} | ||||
/> | /> | ||||
); | ); | ||||
it('should display checkboxes for permissions', () => { | |||||
it('should render correctly', () => { | |||||
expect(shallow(userHolder)).toMatchSnapshot(); | expect(shallow(userHolder)).toMatchSnapshot(); | ||||
}); | }); | ||||
it('should disabled checkboxes when waiting for promise to return', async () => { | |||||
it('should disabled PermissionCell checkboxes when waiting for promise to return', async () => { | |||||
const wrapper = shallow(userHolder); | const wrapper = shallow(userHolder); | ||||
expect(wrapper.state().loading).toEqual([]); | expect(wrapper.state().loading).toEqual([]); | ||||
(wrapper.instance() as UserHolder).handleCheck(true, 'baz'); | (wrapper.instance() as UserHolder).handleCheck(true, 'baz'); | ||||
wrapper.update(); | wrapper.update(); | ||||
expect(wrapper.state().loading).toEqual(['baz']); | expect(wrapper.state().loading).toEqual(['baz']); | ||||
expect(wrapper).toMatchSnapshot(); | |||||
(wrapper.instance() as UserHolder).handleCheck(true, 'bar'); | (wrapper.instance() as UserHolder).handleCheck(true, 'bar'); | ||||
wrapper.update(); | wrapper.update(); | ||||
expect(wrapper.state().loading).toEqual(['baz', 'bar']); | expect(wrapper.state().loading).toEqual(['baz', 'bar']); | ||||
expect(wrapper).toMatchSnapshot(); | |||||
await waitAndUpdate(wrapper); | await waitAndUpdate(wrapper); | ||||
expect(wrapper.state().loading).toEqual([]); | expect(wrapper.state().loading).toEqual([]); |
// Jest Snapshot v1, https://goo.gl/fbAQLP | // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
exports[`should disabled checkboxes when waiting for promise to return 1`] = ` | |||||
exports[`should render correctly 1`] = ` | |||||
<tr> | <tr> | ||||
<td | <td | ||||
className="nowrap" | |||||
className="nowrap text-middle" | |||||
> | > | ||||
<div | <div | ||||
className="display-inline-block text-middle big-spacer-right" | className="display-inline-block text-middle big-spacer-right" | ||||
/> | /> | ||||
</div> | </div> | ||||
</td> | </td> | ||||
<td | |||||
className="text-center text-middle" | |||||
key="bar" | |||||
style={ | |||||
<PermissionCell | |||||
key="admin" | |||||
loading={Array []} | |||||
onCheck={[Function]} | |||||
permission={ | |||||
Object { | Object { | ||||
"backgroundColor": "#d9edf7", | |||||
} | |||||
} | |||||
> | |||||
<Checkbox | |||||
checked={true} | |||||
disabled={false} | |||||
id="bar" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="baz" | |||||
style={ | |||||
Object { | |||||
"backgroundColor": "transparent", | |||||
} | |||||
} | |||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={true} | |||||
id="baz" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
</tr> | |||||
`; | |||||
exports[`should disabled checkboxes when waiting for promise to return 2`] = ` | |||||
<tr> | |||||
<td | |||||
className="nowrap" | |||||
> | |||||
<div | |||||
className="display-inline-block text-middle big-spacer-right" | |||||
> | |||||
<GroupIcon /> | |||||
</div> | |||||
<div | |||||
className="display-inline-block text-middle" | |||||
> | |||||
<div> | |||||
<strong> | |||||
Foobar | |||||
</strong> | |||||
</div> | |||||
<div | |||||
className="little-spacer-top" | |||||
style={ | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | Object { | ||||
"whiteSpace": "normal", | |||||
} | |||||
} | |||||
/> | |||||
</div> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="bar" | |||||
style={ | |||||
Object { | |||||
"backgroundColor": "#d9edf7", | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
], | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={true} | |||||
disabled={true} | |||||
id="bar" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="baz" | |||||
style={ | |||||
permissionItem={ | |||||
Object { | Object { | ||||
"backgroundColor": "transparent", | |||||
"id": "foobar", | |||||
"name": "Foobar", | |||||
"permissions": Array [ | |||||
"bar", | |||||
], | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={true} | |||||
id="baz" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
</tr> | |||||
`; | |||||
exports[`should display checkboxes for permissions 1`] = ` | |||||
<tr> | |||||
<td | |||||
className="nowrap" | |||||
> | |||||
<div | |||||
className="display-inline-block text-middle big-spacer-right" | |||||
> | |||||
<GroupIcon /> | |||||
</div> | |||||
<div | |||||
className="display-inline-block text-middle" | |||||
> | |||||
<div> | |||||
<strong> | |||||
Foobar | |||||
</strong> | |||||
</div> | |||||
<div | |||||
className="little-spacer-top" | |||||
style={ | |||||
Object { | |||||
"whiteSpace": "normal", | |||||
} | |||||
} | |||||
/> | |||||
</div> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="bar" | |||||
style={ | |||||
selectedPermission="bar" | |||||
/> | |||||
<PermissionCell | |||||
key="baz" | |||||
loading={Array []} | |||||
onCheck={[Function]} | |||||
permission={ | |||||
Object { | Object { | ||||
"backgroundColor": "#d9edf7", | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={true} | |||||
disabled={false} | |||||
id="bar" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="baz" | |||||
style={ | |||||
permissionItem={ | |||||
Object { | Object { | ||||
"backgroundColor": "transparent", | |||||
"id": "foobar", | |||||
"name": "Foobar", | |||||
"permissions": Array [ | |||||
"bar", | |||||
], | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={false} | |||||
id="baz" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
selectedPermission="bar" | |||||
/> | |||||
</tr> | </tr> | ||||
`; | `; |
className="nowrap bordered-bottom" | className="nowrap bordered-bottom" | ||||
/> | /> | ||||
<PermissionHeader | <PermissionHeader | ||||
key="bar" | |||||
key="foo" | |||||
onSelectPermission={[MockFunction]} | onSelectPermission={[MockFunction]} | ||||
permission={ | permission={ | ||||
Object { | Object { | ||||
"description": "foo", | |||||
"key": "bar", | |||||
"name": "bar", | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
} | |||||
} | |||||
selectedPermission="bar" | |||||
/> | |||||
<PermissionHeader | |||||
key="admin" | |||||
onSelectPermission={[MockFunction]} | |||||
permission={ | |||||
Object { | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
}, | |||||
], | |||||
} | } | ||||
} | } | ||||
selectedPermission="bar" | selectedPermission="bar" | ||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
<tbody> | <tbody> | ||||
<GroupHolder | |||||
group={ | |||||
Object { | |||||
"id": "barbaz", | |||||
"name": "Barbaz", | |||||
"permissions": Array [ | |||||
"bar", | |||||
], | |||||
} | |||||
} | |||||
key="group-barbaz" | |||||
onToggle={[MockFunction]} | |||||
permissions={ | |||||
Array [ | |||||
"bar", | |||||
] | |||||
} | |||||
permissionsOrder={ | |||||
Array [ | |||||
"bar", | |||||
] | |||||
} | |||||
selectedPermission="bar" | |||||
/> | |||||
<UserHolder | <UserHolder | ||||
key="user-barbaz" | key="user-barbaz" | ||||
onToggle={[MockFunction]} | onToggle={[MockFunction]} | ||||
permissions={ | permissions={ | ||||
Array [ | Array [ | ||||
"bar", | |||||
] | |||||
} | |||||
permissionsOrder={ | |||||
Array [ | |||||
"bar", | |||||
Object { | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
}, | |||||
], | |||||
}, | |||||
] | ] | ||||
} | } | ||||
selectedPermission="bar" | selectedPermission="bar" | ||||
<GroupHolder | <GroupHolder | ||||
group={ | group={ | ||||
Object { | Object { | ||||
"id": "foobar", | |||||
"name": "Foobar", | |||||
"id": "barbaz", | |||||
"name": "Barbaz", | |||||
"permissions": Array [ | "permissions": Array [ | ||||
"bar", | "bar", | ||||
], | ], | ||||
} | } | ||||
} | } | ||||
key="group-foobar" | |||||
key="group-barbaz" | |||||
onToggle={[MockFunction]} | onToggle={[MockFunction]} | ||||
permissions={ | permissions={ | ||||
Array [ | Array [ | ||||
"bar", | |||||
] | |||||
} | |||||
permissionsOrder={ | |||||
Array [ | |||||
"bar", | |||||
Object { | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
}, | |||||
], | |||||
}, | |||||
] | ] | ||||
} | } | ||||
selectedPermission="bar" | selectedPermission="bar" | ||||
onToggle={[MockFunction]} | onToggle={[MockFunction]} | ||||
permissions={ | permissions={ | ||||
Array [ | Array [ | ||||
"bar", | |||||
] | |||||
} | |||||
permissionsOrder={ | |||||
Array [ | |||||
"bar", | |||||
Object { | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
}, | |||||
], | |||||
}, | |||||
] | ] | ||||
} | } | ||||
selectedPermission="bar" | selectedPermission="bar" | ||||
} | } | ||||
} | } | ||||
/> | /> | ||||
<tr> | |||||
<td | |||||
className="divider" | |||||
colSpan={6} | |||||
/> | |||||
</tr> | |||||
<GroupHolder | |||||
group={ | |||||
Object { | |||||
"id": "foobar", | |||||
"name": "Foobar", | |||||
"permissions": Array [ | |||||
"bar", | |||||
], | |||||
} | |||||
} | |||||
key="group-foobar" | |||||
onToggle={[MockFunction]} | |||||
permissions={ | |||||
Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
}, | |||||
], | |||||
}, | |||||
] | |||||
} | |||||
selectedPermission="bar" | |||||
/> | |||||
<React.Fragment> | |||||
<tr> | |||||
<td | |||||
className="divider" | |||||
colSpan={20} | |||||
/> | |||||
</tr> | |||||
<tr /> | |||||
</React.Fragment> | |||||
<GroupHolder | <GroupHolder | ||||
group={ | group={ | ||||
Object { | Object { | ||||
} | } | ||||
key="group-abc" | key="group-abc" | ||||
onToggle={[MockFunction]} | onToggle={[MockFunction]} | ||||
permissions={Array []} | |||||
permissionsOrder={ | |||||
permissions={ | |||||
Array [ | Array [ | ||||
"bar", | |||||
Object { | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
}, | |||||
], | |||||
}, | |||||
] | ] | ||||
} | } | ||||
selectedPermission="bar" | selectedPermission="bar" | ||||
<UserHolder | <UserHolder | ||||
key="user-bcd" | key="user-bcd" | ||||
onToggle={[MockFunction]} | onToggle={[MockFunction]} | ||||
permissions={Array []} | |||||
permissionsOrder={ | |||||
permissions={ | |||||
Array [ | Array [ | ||||
"bar", | |||||
Object { | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
}, | |||||
], | |||||
}, | |||||
] | ] | ||||
} | } | ||||
selectedPermission="bar" | selectedPermission="bar" |
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||||
exports[`should display disabled checkbox 1`] = ` | |||||
<td | |||||
className="permission-column text-center text-middle" | |||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={true} | |||||
id="baz" | |||||
onCheck={[MockFunction]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
`; | |||||
exports[`should display multiple checkboxes with one checked 1`] = ` | |||||
<td | |||||
className="text-middle" | |||||
> | |||||
<div | |||||
key="foo" | |||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={false} | |||||
id="foo" | |||||
onCheck={[MockFunction]} | |||||
thirdState={false} | |||||
> | |||||
<span | |||||
className="little-spacer-left" | |||||
> | |||||
Foo | |||||
</span> | |||||
</Checkbox> | |||||
</div> | |||||
<div | |||||
key="bar" | |||||
> | |||||
<Checkbox | |||||
checked={true} | |||||
disabled={false} | |||||
id="bar" | |||||
onCheck={[MockFunction]} | |||||
thirdState={false} | |||||
> | |||||
<span | |||||
className="little-spacer-left" | |||||
> | |||||
Bar | |||||
</span> | |||||
</Checkbox> | |||||
</div> | |||||
</td> | |||||
`; | |||||
exports[`should display selected checkbox 1`] = ` | |||||
<td | |||||
className="permission-column text-center text-middle selected" | |||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={false} | |||||
id="baz" | |||||
onCheck={[MockFunction]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
`; | |||||
exports[`should display unchecked checkbox 1`] = ` | |||||
<td | |||||
className="permission-column text-center text-middle" | |||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={false} | |||||
id="baz" | |||||
onCheck={[MockFunction]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
`; |
// Jest Snapshot v1, https://goo.gl/fbAQLP | // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
exports[`should disabled checkboxes when waiting for promise to return 1`] = ` | |||||
exports[`should render correctly 1`] = ` | |||||
<tr> | <tr> | ||||
<td | <td | ||||
className="nowrap" | |||||
className="nowrap text-middle" | |||||
> | > | ||||
<Connect(Avatar) | <Connect(Avatar) | ||||
className="text-middle big-spacer-right" | className="text-middle big-spacer-right" | ||||
/> | /> | ||||
</div> | </div> | ||||
</td> | </td> | ||||
<td | |||||
className="text-center text-middle" | |||||
key="bar" | |||||
style={ | |||||
<PermissionCell | |||||
key="admin" | |||||
loading={Array []} | |||||
onCheck={[Function]} | |||||
permission={ | |||||
Object { | Object { | ||||
"backgroundColor": "#d9edf7", | |||||
"category": "admin", | |||||
"permissions": Array [ | |||||
Object { | |||||
"description": "", | |||||
"key": "foo", | |||||
"name": "Foo", | |||||
}, | |||||
Object { | |||||
"description": "", | |||||
"key": "bar", | |||||
"name": "Bar", | |||||
}, | |||||
], | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={true} | |||||
disabled={false} | |||||
id="bar" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="baz" | |||||
style={ | |||||
permissionItem={ | |||||
Object { | Object { | ||||
"backgroundColor": "transparent", | |||||
"login": "john doe", | |||||
"name": "John Doe", | |||||
"permissions": Array [ | |||||
"bar", | |||||
], | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={true} | |||||
id="baz" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
</tr> | |||||
`; | |||||
exports[`should disabled checkboxes when waiting for promise to return 2`] = ` | |||||
<tr> | |||||
<td | |||||
className="nowrap" | |||||
> | |||||
<Connect(Avatar) | |||||
className="text-middle big-spacer-right" | |||||
name="John Doe" | |||||
size={36} | |||||
/> | |||||
<div | |||||
className="display-inline-block text-middle" | |||||
> | |||||
<div> | |||||
<strong> | |||||
John Doe | |||||
</strong> | |||||
<span | |||||
className="note spacer-left" | |||||
> | |||||
john doe | |||||
</span> | |||||
</div> | |||||
<div | |||||
className="little-spacer-top" | |||||
/> | |||||
</div> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="bar" | |||||
style={ | |||||
Object { | |||||
"backgroundColor": "#d9edf7", | |||||
} | |||||
} | |||||
> | |||||
<Checkbox | |||||
checked={true} | |||||
disabled={true} | |||||
id="bar" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
selectedPermission="bar" | |||||
/> | |||||
<PermissionCell | |||||
key="baz" | key="baz" | ||||
style={ | |||||
loading={Array []} | |||||
onCheck={[Function]} | |||||
permission={ | |||||
Object { | Object { | ||||
"backgroundColor": "transparent", | |||||
"description": "", | |||||
"key": "baz", | |||||
"name": "Baz", | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={true} | |||||
id="baz" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
</tr> | |||||
`; | |||||
exports[`should display checkboxes for permissions 1`] = ` | |||||
<tr> | |||||
<td | |||||
className="nowrap" | |||||
> | |||||
<Connect(Avatar) | |||||
className="text-middle big-spacer-right" | |||||
name="John Doe" | |||||
size={36} | |||||
/> | |||||
<div | |||||
className="display-inline-block text-middle" | |||||
> | |||||
<div> | |||||
<strong> | |||||
John Doe | |||||
</strong> | |||||
<span | |||||
className="note spacer-left" | |||||
> | |||||
john doe | |||||
</span> | |||||
</div> | |||||
<div | |||||
className="little-spacer-top" | |||||
/> | |||||
</div> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="bar" | |||||
style={ | |||||
permissionItem={ | |||||
Object { | Object { | ||||
"backgroundColor": "#d9edf7", | |||||
"login": "john doe", | |||||
"name": "John Doe", | |||||
"permissions": Array [ | |||||
"bar", | |||||
], | |||||
} | } | ||||
} | } | ||||
> | |||||
<Checkbox | |||||
checked={true} | |||||
disabled={false} | |||||
id="bar" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
<td | |||||
className="text-center text-middle" | |||||
key="baz" | |||||
style={ | |||||
Object { | |||||
"backgroundColor": "transparent", | |||||
} | |||||
} | |||||
> | |||||
<Checkbox | |||||
checked={false} | |||||
disabled={false} | |||||
id="baz" | |||||
onCheck={[Function]} | |||||
thirdState={false} | |||||
/> | |||||
</td> | |||||
selectedPermission="bar" | |||||
/> | |||||
</tr> | </tr> | ||||
`; | `; |
* along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
.permissions-table > tbody > tr > td { | |||||
border-bottom: 10px solid #fff !important; | |||||
} | |||||
.permissions-table .permission-column { | |||||
width: 1px; | |||||
.permissions-table .permission-column.selected { | |||||
background-color: #d9edf7; | |||||
} | } | ||||
.permissions-table .permission-column-inner { | .permissions-table .permission-column-inner { | ||||
display: inline-block; | |||||
width: 100px; | width: 100px; | ||||
} | } | ||||
.permissions-table .divider { | .permissions-table .divider { | ||||
background: #e6e6e6; | |||||
border-bottom: 20px solid #fff !important; | |||||
border-top: 20px solid #fff !important; | |||||
background: #fff; | |||||
padding: 16px 0; | |||||
} | |||||
.permissions-table .divider::after { | |||||
display: block; | |||||
content: ''; | |||||
background: var(--barBorderColor); | |||||
height: 1px; | height: 1px; | ||||
padding: 0; | |||||
width: 100%; | |||||
} | } |
/* | |||||
* 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 { translate } from '../../helpers/l10n'; | |||||
import { PermissionDefinition, PermissionDefinitionGroup } from '../../app/types'; | |||||
export const PERMISSIONS_ORDER_FOR_PROJECT_TEMPLATE = [ | |||||
'user', | |||||
'codeviewer', | |||||
'issueadmin', | |||||
'securityhotspotadmin', | |||||
'admin', | |||||
'scan' | |||||
]; | |||||
export const PERMISSIONS_ORDER_GLOBAL = [ | |||||
'admin', | |||||
{ category: 'administer', permissions: ['gateadmin', 'profileadmin'] }, | |||||
'scan', | |||||
{ category: 'creator', permissions: ['provisioning'] } | |||||
]; | |||||
export const PERMISSIONS_ORDER_GLOBAL_GOV = [ | |||||
'admin', | |||||
{ category: 'administer', permissions: ['gateadmin', 'profileadmin'] }, | |||||
'scan', | |||||
{ category: 'creator', permissions: ['provisioning', 'applicationcreator', 'portfoliocreator'] } | |||||
]; | |||||
export const PERMISSIONS_ORDER_FOR_VIEW = ['user', 'admin']; | |||||
export const PERMISSIONS_ORDER_FOR_DEV = ['user', 'admin']; | |||||
export const PERMISSIONS_ORDER_BY_QUALIFIER: { [index: string]: string[] } = { | |||||
TRK: PERMISSIONS_ORDER_FOR_PROJECT_TEMPLATE, | |||||
VW: PERMISSIONS_ORDER_FOR_VIEW, | |||||
SVW: PERMISSIONS_ORDER_FOR_VIEW, | |||||
APP: PERMISSIONS_ORDER_FOR_VIEW, | |||||
DEV: PERMISSIONS_ORDER_FOR_DEV | |||||
}; | |||||
function convertToPermissionDefinition(permission: string, l10nPrefix: string) { | |||||
return { | |||||
key: permission, | |||||
name: translate(l10nPrefix, permission), | |||||
description: translate(l10nPrefix, permission, 'desc') | |||||
}; | |||||
} | |||||
export function convertToPermissionDefinitions( | |||||
permissions: Array<string | { category: string; permissions: string[] }>, | |||||
l10nPrefix: string | |||||
): Array<PermissionDefinition | PermissionDefinitionGroup> { | |||||
return permissions.map(permission => { | |||||
if (typeof permission === 'object') { | |||||
return { | |||||
category: permission.category, | |||||
permissions: permission.permissions.map(permission => | |||||
convertToPermissionDefinition(permission, l10nPrefix) | |||||
) | |||||
}; | |||||
} | |||||
return convertToPermissionDefinition(permission, l10nPrefix); | |||||
}); | |||||
} | |||||
export function isPermissionDefinitionGroup( | |||||
permission?: PermissionDefinition | PermissionDefinitionGroup | |||||
): permission is PermissionDefinitionGroup { | |||||
return Boolean(permission && (permission as PermissionDefinitionGroup).category); | |||||
} |
global_permissions.permission=Permission | global_permissions.permission=Permission | ||||
global_permissions.users=Users | global_permissions.users=Users | ||||
global_permissions.groups=Groups | global_permissions.groups=Groups | ||||
global_permissions.administer=Administer | |||||
global_permissions.creator=Create | |||||
global_permissions.admin=Administer System | global_permissions.admin=Administer System | ||||
global_permissions.admin.desc=Ability to perform all administration functions for the instance. | global_permissions.admin.desc=Ability to perform all administration functions for the instance. | ||||
global_permissions.profileadmin=Administer Quality Profiles | |||||
global_permissions.profileadmin=Quality Profiles | |||||
global_permissions.profileadmin.desc=Ability to perform any action on quality profiles. | global_permissions.profileadmin.desc=Ability to perform any action on quality profiles. | ||||
global_permissions.gateadmin=Administer Quality Gates | |||||
global_permissions.gateadmin=Quality Gates | |||||
global_permissions.gateadmin.desc=Ability to perform any action on quality gates. | global_permissions.gateadmin.desc=Ability to perform any action on quality gates. | ||||
global_permissions.scan=Execute Analysis | global_permissions.scan=Execute Analysis | ||||
global_permissions.scan.desc=Ability to get all settings required to perform an analysis (including the secured settings like passwords) and to push analysis results to the {instance} server. | global_permissions.scan.desc=Ability to get all settings required to perform an analysis (including the secured settings like passwords) and to push analysis results to the {instance} server. | ||||
global_permissions.provisioning=Create Projects | |||||
global_permissions.provisioning=Projects | |||||
global_permissions.provisioning.desc=Ability to initialize a project so its settings can be configured before the first analysis. | global_permissions.provisioning.desc=Ability to initialize a project so its settings can be configured before the first analysis. | ||||
global_permissions.filter_by_x_permission=Filter by "{0}" permission | global_permissions.filter_by_x_permission=Filter by "{0}" permission | ||||
global_permissions.restore_access=Restore Access | global_permissions.restore_access=Restore Access | ||||
global_permissions.restore_access.message=You will receive {browse} and {administer} permissions on the project. Do you want to continue? | global_permissions.restore_access.message=You will receive {browse} and {administer} permissions on the project. Do you want to continue? | ||||
global_permissions.applicationcreator=Applications | |||||
global_permissions.applicationcreator.desc=Ability to create an application. | |||||
global_permissions.portfoliocreator=Portfolios | |||||
global_permissions.portfoliocreator.desc=Ability to create a portfolio. | |||||
#------------------------------------------------------------------------------ | #------------------------------------------------------------------------------ | ||||
# | # |