export type PeriodMode = 'days' | 'date' | 'version' | 'previous_analysis' | 'previous_version'; | export type PeriodMode = 'days' | 'date' | 'version' | 'previous_analysis' | 'previous_version'; | ||||
export interface Permission { | |||||
description: string; | |||||
key: string; | |||||
name: string; | |||||
} | |||||
export interface PermissionDefinition { | export interface PermissionDefinition { | ||||
key: string; | key: string; | ||||
name: string; | name: string; |
* 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. | ||||
*/ | */ | ||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import * as React from 'react'; | |||||
import { Location } from 'history'; | |||||
import Home from './Home'; | import Home from './Home'; | ||||
import Template from './Template'; | import Template from './Template'; | ||||
import OrganizationHelmet from '../../../components/common/OrganizationHelmet'; | import OrganizationHelmet from '../../../components/common/OrganizationHelmet'; | ||||
import { translate } from '../../../helpers/l10n'; | import { translate } from '../../../helpers/l10n'; | ||||
import '../../permissions/styles.css'; | import '../../permissions/styles.css'; | ||||
export default class App extends React.PureComponent { | |||||
static propTypes = { | |||||
location: PropTypes.object.isRequired, | |||||
organization: PropTypes.object, | |||||
topQualifiers: PropTypes.array.isRequired | |||||
}; | |||||
interface Props { | |||||
location: Location; | |||||
organization: T.Organization | undefined; | |||||
topQualifiers: string[]; | |||||
} | |||||
state = { | |||||
interface State { | |||||
ready: boolean; | |||||
permissions: T.Permission[]; | |||||
permissionTemplates: T.PermissionTemplate[]; | |||||
} | |||||
export default class App extends React.PureComponent<Props, State> { | |||||
mounted = false; | |||||
state: State = { | |||||
ready: false, | ready: false, | ||||
permissions: [], | permissions: [], | ||||
permissionTemplates: [] | permissionTemplates: [] | ||||
mergePermissionsToTemplates(r.permissionTemplates, permissions), | mergePermissionsToTemplates(r.permissionTemplates, permissions), | ||||
r.defaultTemplates | r.defaultTemplates | ||||
); | ); | ||||
this.setState({ | |||||
ready: true, | |||||
permissionTemplates, | |||||
permissions | |||||
}); | |||||
this.setState({ ready: true, permissionTemplates, permissions }); | |||||
} | } | ||||
}); | }); | ||||
}; | }; | ||||
renderTemplate(id) { | |||||
renderTemplate(id: string) { | |||||
if (!this.state.ready) { | if (!this.state.ready) { | ||||
return null; | return null; | ||||
} | } | ||||
const template = this.state.permissionTemplates.find(t => t.id === id); | const template = this.state.permissionTemplates.find(t => t.id === id); | ||||
if (!template) { | |||||
return null; | |||||
} | |||||
return ( | return ( | ||||
<Template | <Template | ||||
organization={this.props.organization} | organization={this.props.organization} | ||||
return ( | return ( | ||||
<Home | <Home | ||||
organization={this.props.organization} | organization={this.props.organization} | ||||
permissions={this.state.permissions} | |||||
permissionTemplates={this.state.permissionTemplates} | permissionTemplates={this.state.permissionTemplates} | ||||
permissions={this.state.permissions} | |||||
ready={this.state.ready} | ready={this.state.ready} | ||||
refresh={this.requestPermissions} | refresh={this.requestPermissions} | ||||
topQualifiers={this.props.topQualifiers} | topQualifiers={this.props.topQualifiers} |
import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||
import App from './App'; | import App from './App'; | ||||
import forSingleOrganization from '../../organizations/forSingleOrganization'; | import forSingleOrganization from '../../organizations/forSingleOrganization'; | ||||
import { getAppState } from '../../../store/rootReducer'; | |||||
import { getAppState, Store } from '../../../store/rootReducer'; | |||||
const mapStateToProps = state => ({ topQualifiers: getAppState(state).qualifiers }); | |||||
const mapStateToProps = (state: Store) => ({ topQualifiers: getAppState(state).qualifiers }); | |||||
export default forSingleOrganization(connect(mapStateToProps)(App)); | export default forSingleOrganization(connect(mapStateToProps)(App)); |
* 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. | ||||
*/ | */ | ||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import * as React from 'react'; | |||||
import { sortBy } from 'lodash'; | import { sortBy } from 'lodash'; | ||||
import { translate, translateWithParameters } from '../../../helpers/l10n'; | import { translate, translateWithParameters } from '../../../helpers/l10n'; | ||||
import { PermissionTemplateType } from '../propTypes'; | |||||
export default class Defaults extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
permissionTemplate: PermissionTemplateType.isRequired | |||||
}; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
template: T.PermissionTemplate; | |||||
} | |||||
render() { | |||||
const qualifiersToDisplay = | |||||
this.props.organization && !this.props.organization.isDefault | |||||
? ['TRK'] | |||||
: this.props.permissionTemplate.defaultFor; | |||||
export default function Defaults({ organization, template }: Props) { | |||||
const qualifiersToDisplay = | |||||
organization && !organization.isDefault ? ['TRK'] : template.defaultFor; | |||||
const qualifiers = sortBy(qualifiersToDisplay) | |||||
.map(qualifier => translate('qualifiers', qualifier)) | |||||
.join(', '); | |||||
const qualifiers = sortBy(qualifiersToDisplay) | |||||
.map(qualifier => translate('qualifiers', qualifier)) | |||||
.join(', '); | |||||
return ( | |||||
<div> | |||||
<span className="badge spacer-right"> | |||||
{translateWithParameters('permission_template.default_for', qualifiers)} | |||||
</span> | |||||
</div> | |||||
); | |||||
} | |||||
return ( | |||||
<div> | |||||
<span className="badge spacer-right"> | |||||
{translateWithParameters('permission_template.default_for', qualifiers)} | |||||
</span> | |||||
</div> | |||||
); | |||||
} | } |
* 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. | ||||
*/ | */ | ||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import * as React from 'react'; | |||||
import Helmet from 'react-helmet'; | import Helmet from 'react-helmet'; | ||||
import Header from './Header'; | import Header from './Header'; | ||||
import List from './List'; | import List from './List'; | ||||
import { translate } from '../../../helpers/l10n'; | import { translate } from '../../../helpers/l10n'; | ||||
export default class Home extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
topQualifiers: PropTypes.array.isRequired, | |||||
permissions: PropTypes.array.isRequired, | |||||
permissionTemplates: PropTypes.array.isRequired, | |||||
ready: PropTypes.bool.isRequired, | |||||
refresh: PropTypes.func.isRequired | |||||
}; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
permissionTemplates: T.PermissionTemplate[]; | |||||
permissions: T.Permission[]; | |||||
ready: boolean; | |||||
refresh: () => Promise<void>; | |||||
topQualifiers: string[]; | |||||
} | |||||
render() { | |||||
return ( | |||||
<div className="page page-limited"> | |||||
<Helmet title={translate('permission_templates.page')} /> | |||||
export default function Home(props: Props) { | |||||
return ( | |||||
<div className="page page-limited"> | |||||
<Helmet title={translate('permission_templates.page')} /> | |||||
<Header | |||||
organization={this.props.organization} | |||||
ready={this.props.ready} | |||||
refresh={this.props.refresh} | |||||
/> | |||||
<Header organization={props.organization} ready={props.ready} refresh={props.refresh} /> | |||||
<List | |||||
organization={this.props.organization} | |||||
permissions={this.props.permissions} | |||||
permissionTemplates={this.props.permissionTemplates} | |||||
refresh={this.props.refresh} | |||||
topQualifiers={this.props.topQualifiers} | |||||
/> | |||||
</div> | |||||
); | |||||
} | |||||
<List | |||||
organization={props.organization} | |||||
permissionTemplates={props.permissionTemplates} | |||||
permissions={props.permissions} | |||||
refresh={props.refresh} | |||||
topQualifiers={props.topQualifiers} | |||||
/> | |||||
</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 React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import ListHeader from './ListHeader'; | |||||
import ListItem from './ListItem'; | |||||
import { PermissionTemplateType, CallbackType } from '../propTypes'; | |||||
export default class List extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
permissionTemplates: PropTypes.arrayOf(PermissionTemplateType).isRequired, | |||||
permissions: PropTypes.array.isRequired, | |||||
topQualifiers: PropTypes.array.isRequired, | |||||
refresh: CallbackType | |||||
}; | |||||
render() { | |||||
const permissionTemplates = this.props.permissionTemplates.map(p => ( | |||||
<ListItem | |||||
key={p.id} | |||||
organization={this.props.organization} | |||||
permissionTemplate={p} | |||||
refresh={this.props.refresh} | |||||
topQualifiers={this.props.topQualifiers} | |||||
/> | |||||
)); | |||||
return ( | |||||
<div className="boxed-group boxed-group-inner"> | |||||
<table className="data zebra permissions-table" id="permission-templates"> | |||||
<ListHeader organization={this.props.organization} permissions={this.props.permissions} /> | |||||
<tbody>{permissionTemplates}</tbody> | |||||
</table> | |||||
</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 ListHeader from './ListHeader'; | |||||
import ListItem from './ListItem'; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
permissionTemplates: T.PermissionTemplate[]; | |||||
permissions: T.Permission[]; | |||||
refresh: () => Promise<void>; | |||||
topQualifiers: string[]; | |||||
} | |||||
export default function List(props: Props) { | |||||
const permissionTemplates = props.permissionTemplates.map(p => ( | |||||
<ListItem | |||||
key={p.id} | |||||
organization={props.organization} | |||||
refresh={props.refresh} | |||||
template={p} | |||||
topQualifiers={props.topQualifiers} | |||||
/> | |||||
)); | |||||
return ( | |||||
<div className="boxed-group boxed-group-inner"> | |||||
<table className="data zebra permissions-table" id="permission-templates"> | |||||
<ListHeader organization={props.organization} permissions={props.permissions} /> | |||||
<tbody>{permissionTemplates}</tbody> | |||||
</table> | |||||
</div> | |||||
); | |||||
} |
* 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. | ||||
*/ | */ | ||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import * as React from 'react'; | |||||
import HelpTooltip from '../../../components/controls/HelpTooltip'; | import HelpTooltip from '../../../components/controls/HelpTooltip'; | ||||
import { translate } from '../../../helpers/l10n'; | import { translate } from '../../../helpers/l10n'; | ||||
import InstanceMessage from '../../../components/common/InstanceMessage'; | import InstanceMessage from '../../../components/common/InstanceMessage'; | ||||
import { Alert } from '../../../components/ui/Alert'; | import { Alert } from '../../../components/ui/Alert'; | ||||
export default class ListHeader extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
permissions: PropTypes.array.isRequired | |||||
}; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
permissions: T.Permission[]; | |||||
} | |||||
renderTooltip = permission => | |||||
permission.key === 'user' || permission.key === 'codeviewer' ? ( | |||||
export default class ListHeader extends React.PureComponent<Props> { | |||||
renderTooltip(permission: T.Permission) { | |||||
return permission.key === 'user' || permission.key === 'codeviewer' ? ( | |||||
<div> | <div> | ||||
<InstanceMessage message={translate('projects_role', permission.key, 'desc')} /> | <InstanceMessage message={translate('projects_role', permission.key, 'desc')} /> | ||||
<Alert className="spacer-top" variant="warning"> | <Alert className="spacer-top" variant="warning"> | ||||
) : ( | ) : ( | ||||
<InstanceMessage message={translate('projects_role', permission.key, 'desc')} /> | <InstanceMessage message={translate('projects_role', permission.key, 'desc')} /> | ||||
); | ); | ||||
} | |||||
render() { | render() { | ||||
const cells = this.props.permissions.map(permission => ( | const cells = this.props.permissions.map(permission => ( |
/* | |||||
* 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 React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import NameCell from './NameCell'; | |||||
import PermissionCell from './PermissionCell'; | |||||
import ActionsCell from './ActionsCell'; | |||||
import { PermissionTemplateType, CallbackType } from '../propTypes'; | |||||
export default class ListItem extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
permissionTemplate: PermissionTemplateType.isRequired, | |||||
topQualifiers: PropTypes.array.isRequired, | |||||
refresh: CallbackType | |||||
}; | |||||
render() { | |||||
const permissions = this.props.permissionTemplate.permissions.map(p => ( | |||||
<PermissionCell key={p.key} permission={p} /> | |||||
)); | |||||
return ( | |||||
<tr data-id={this.props.permissionTemplate.id} data-name={this.props.permissionTemplate.name}> | |||||
<NameCell | |||||
organization={this.props.organization} | |||||
permissionTemplate={this.props.permissionTemplate} | |||||
topQualifiers={this.props.topQualifiers} | |||||
/> | |||||
{permissions} | |||||
<td className="nowrap thin text-right"> | |||||
<ActionsCell | |||||
organization={this.props.organization} | |||||
permissionTemplate={this.props.permissionTemplate} | |||||
refresh={this.props.refresh} | |||||
topQualifiers={this.props.topQualifiers} | |||||
/> | |||||
</td> | |||||
</tr> | |||||
); | |||||
} | |||||
} |
/* | |||||
* 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 NameCell from './NameCell'; | |||||
import PermissionCell from './PermissionCell'; | |||||
import ActionsCell from './ActionsCell'; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
refresh: () => Promise<void>; | |||||
template: T.PermissionTemplate; | |||||
topQualifiers: string[]; | |||||
} | |||||
export default function ListItem(props: Props) { | |||||
const permissions = props.template.permissions.map(p => ( | |||||
<PermissionCell key={p.key} permission={p} /> | |||||
)); | |||||
return ( | |||||
<tr data-id={props.template.id} data-name={props.template.name}> | |||||
<NameCell organization={props.organization} template={props.template} /> | |||||
{permissions} | |||||
<td className="nowrap thin text-right"> | |||||
<ActionsCell | |||||
organization={props.organization} | |||||
permissionTemplate={props.template} | |||||
refresh={props.refresh} | |||||
topQualifiers={props.topQualifiers} | |||||
/> | |||||
</td> | |||||
</tr> | |||||
); | |||||
} |
/* | |||||
* 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 React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import { Link } from 'react-router'; | |||||
import Defaults from './Defaults'; | |||||
import { PermissionTemplateType } from '../propTypes'; | |||||
export default class NameCell extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
permissionTemplate: PermissionTemplateType.isRequired | |||||
}; | |||||
render() { | |||||
const { permissionTemplate: t, organization } = this.props; | |||||
const pathname = organization | |||||
? `/organizations/${organization.key}/permission_templates` | |||||
: '/permission_templates'; | |||||
return ( | |||||
<td> | |||||
<Link to={{ pathname, query: { id: t.id } }}> | |||||
<strong className="js-name">{t.name}</strong> | |||||
</Link> | |||||
{t.defaultFor.length > 0 && ( | |||||
<div className="spacer-top js-defaults"> | |||||
<Defaults | |||||
organization={organization} | |||||
permissionTemplate={this.props.permissionTemplate} | |||||
/> | |||||
</div> | |||||
)} | |||||
{!!t.description && <div className="spacer-top js-description">{t.description}</div>} | |||||
{!!t.projectKeyPattern && ( | |||||
<div className="spacer-top js-project-key-pattern"> | |||||
Project Key Pattern: <code>{t.projectKeyPattern}</code> | |||||
</div> | |||||
)} | |||||
</td> | |||||
); | |||||
} | |||||
} |
/* | |||||
* 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 { Link } from 'react-router'; | |||||
import Defaults from './Defaults'; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
template: T.PermissionTemplate; | |||||
} | |||||
export default function NameCell({ template, organization }: Props) { | |||||
const pathname = organization | |||||
? `/organizations/${organization.key}/permission_templates` | |||||
: '/permission_templates'; | |||||
return ( | |||||
<td> | |||||
<Link to={{ pathname, query: { id: template.id } }}> | |||||
<strong className="js-name">{template.name}</strong> | |||||
</Link> | |||||
{template.defaultFor.length > 0 && ( | |||||
<div className="spacer-top js-defaults"> | |||||
<Defaults organization={organization} template={template} /> | |||||
</div> | |||||
)} | |||||
{!!template.description && ( | |||||
<div className="spacer-top js-description">{template.description}</div> | |||||
)} | |||||
{!!template.projectKeyPattern && ( | |||||
<div className="spacer-top js-project-key-pattern"> | |||||
Project Key Pattern: <code>{template.projectKeyPattern}</code> | |||||
</div> | |||||
)} | |||||
</td> | |||||
); | |||||
} |
/* | |||||
* 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 React from 'react'; | |||||
import { PermissionType } from '../propTypes'; | |||||
import HelpTooltip from '../../../components/controls/HelpTooltip'; | |||||
import { translate } from '../../../helpers/l10n'; | |||||
import { isSonarCloud } from '../../../helpers/system'; | |||||
export default class PermissionCell extends React.PureComponent { | |||||
static propTypes = { | |||||
permission: PermissionType.isRequired | |||||
}; | |||||
render() { | |||||
const { permission: p } = this.props; | |||||
return ( | |||||
<td className="permission-column" data-permission={p.key}> | |||||
<div className="permission-column-inner"> | |||||
<ul> | |||||
{p.withProjectCreator && ( | |||||
<li className="little-spacer-bottom display-flex-center"> | |||||
{translate('permission_templates.project_creators')} | |||||
<HelpTooltip | |||||
className="little-spacer-left" | |||||
overlay={translate( | |||||
isSonarCloud() | |||||
? 'permission_templates.project_creators.explanation.sonarcloud' | |||||
: 'permission_templates.project_creators.explanation' | |||||
)} | |||||
/> | |||||
</li> | |||||
)} | |||||
<li className="little-spacer-bottom"> | |||||
<strong>{p.usersCount}</strong> | |||||
{' user(s)'} | |||||
</li> | |||||
<li> | |||||
<strong>{p.groupsCount}</strong> | |||||
{' group(s)'} | |||||
</li> | |||||
</ul> | |||||
</div> | |||||
</td> | |||||
); | |||||
} | |||||
} |
/* | |||||
* 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 HelpTooltip from '../../../components/controls/HelpTooltip'; | |||||
import { translate } from '../../../helpers/l10n'; | |||||
import { isSonarCloud } from '../../../helpers/system'; | |||||
interface Props { | |||||
permission: { | |||||
key: string; | |||||
usersCount: number; | |||||
groupsCount: number; | |||||
withProjectCreator?: boolean; | |||||
}; | |||||
} | |||||
export default function PermissionCell({ permission: p }: Props) { | |||||
return ( | |||||
<td className="permission-column" data-permission={p.key}> | |||||
<div className="permission-column-inner"> | |||||
<ul> | |||||
{p.withProjectCreator && ( | |||||
<li className="little-spacer-bottom display-flex-center"> | |||||
{translate('permission_templates.project_creators')} | |||||
<HelpTooltip | |||||
className="little-spacer-left" | |||||
overlay={translate( | |||||
isSonarCloud() | |||||
? 'permission_templates.project_creators.explanation.sonarcloud' | |||||
: 'permission_templates.project_creators.explanation' | |||||
)} | |||||
/> | |||||
</li> | |||||
)} | |||||
<li className="little-spacer-bottom"> | |||||
<strong>{p.usersCount}</strong> | |||||
{' user(s)'} | |||||
</li> | |||||
<li> | |||||
<strong>{p.groupsCount}</strong> | |||||
{' group(s)'} | |||||
</li> | |||||
</ul> | |||||
</div> | |||||
</td> | |||||
); | |||||
} |
* 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. | ||||
*/ | */ | ||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import * as React from 'react'; | |||||
import Helmet from 'react-helmet'; | import Helmet from 'react-helmet'; | ||||
import TemplateHeader from './TemplateHeader'; | import TemplateHeader from './TemplateHeader'; | ||||
import TemplateDetails from './TemplateDetails'; | import TemplateDetails from './TemplateDetails'; | ||||
import * as api from '../../../api/permissions'; | import * as api from '../../../api/permissions'; | ||||
import { translate } from '../../../helpers/l10n'; | import { translate } from '../../../helpers/l10n'; | ||||
export default class Template extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
template: PropTypes.object.isRequired, | |||||
refresh: PropTypes.func.isRequired, | |||||
topQualifiers: PropTypes.array.isRequired | |||||
}; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
refresh: () => void; | |||||
template: T.PermissionTemplate; | |||||
topQualifiers: string[]; | |||||
} | |||||
state = { | |||||
loading: false, | |||||
users: [], | |||||
interface State { | |||||
filter: string; | |||||
groups: T.PermissionGroup[]; | |||||
loading: boolean; | |||||
query: string; | |||||
selectedPermission?: string; | |||||
users: T.PermissionUser[]; | |||||
} | |||||
export default class Template extends React.PureComponent<Props, State> { | |||||
mounted = false; | |||||
state: State = { | |||||
filter: 'all', | |||||
groups: [], | groups: [], | ||||
loading: false, | |||||
query: '', | query: '', | ||||
filter: 'all', | |||||
selectedPermission: null | |||||
users: [] | |||||
}; | }; | ||||
componentDidMount() { | componentDidMount() { | ||||
this.mounted = false; | this.mounted = false; | ||||
} | } | ||||
requestHolders = realQuery => { | |||||
requestHolders = (realQuery?: string) => { | |||||
this.setState({ loading: true }); | this.setState({ loading: true }); | ||||
const { template } = this.props; | const { template } = this.props; | ||||
}); | }); | ||||
}; | }; | ||||
handleToggleUser = (user, permission) => { | |||||
handleToggleUser = (user: T.PermissionUser, permission: string) => { | |||||
if (user.login === '<creator>') { | if (user.login === '<creator>') { | ||||
return this.handleToggleProjectCreator(user, permission); | return this.handleToggleProjectCreator(user, permission); | ||||
} | } | ||||
const { template, organization } = this.props; | const { template, organization } = this.props; | ||||
const hasPermission = user.permissions.includes(permission); | const hasPermission = user.permissions.includes(permission); | ||||
const data = { | |||||
const data: { templateId: string; login: string; permission: string; organization?: string } = { | |||||
templateId: template.id, | templateId: template.id, | ||||
login: user.login, | login: user.login, | ||||
permission | permission | ||||
return request.then(() => this.requestHolders()).then(this.props.refresh); | return request.then(() => this.requestHolders()).then(this.props.refresh); | ||||
}; | }; | ||||
handleToggleProjectCreator = (user, permission) => { | |||||
handleToggleProjectCreator = (user: T.PermissionUser, permission: string) => { | |||||
const { template } = this.props; | const { template } = this.props; | ||||
const hasPermission = user.permissions.includes(permission); | const hasPermission = user.permissions.includes(permission); | ||||
const request = hasPermission | const request = hasPermission | ||||
return request.then(() => this.requestHolders()).then(this.props.refresh); | return request.then(() => this.requestHolders()).then(this.props.refresh); | ||||
}; | }; | ||||
handleToggleGroup = (group, permission) => { | |||||
handleToggleGroup = (group: T.PermissionGroup, permission: string) => { | |||||
const { template, organization } = this.props; | const { template, organization } = this.props; | ||||
const hasPermission = group.permissions.includes(permission); | const hasPermission = group.permissions.includes(permission); | ||||
const data = { | const data = { | ||||
return request.then(() => this.requestHolders()).then(this.props.refresh); | return request.then(() => this.requestHolders()).then(this.props.refresh); | ||||
}; | }; | ||||
handleSearch = query => { | |||||
handleSearch = (query: string) => { | |||||
this.setState({ query }); | this.setState({ query }); | ||||
this.requestHolders(query); | this.requestHolders(query); | ||||
}; | }; | ||||
handleFilter = filter => { | |||||
handleFilter = (filter: string) => { | |||||
this.setState({ filter }, this.requestHolders); | this.setState({ filter }, this.requestHolders); | ||||
}; | }; | ||||
handleSelectPermission = selectedPermission => { | |||||
handleSelectPermission = (selectedPermission: string) => { | |||||
if (selectedPermission === this.state.selectedPermission) { | if (selectedPermission === this.state.selectedPermission) { | ||||
this.setState({ selectedPermission: null }, this.requestHolders); | |||||
this.setState({ selectedPermission: undefined }, this.requestHolders); | |||||
} else { | } else { | ||||
this.setState({ selectedPermission }, this.requestHolders); | this.setState({ selectedPermission }, this.requestHolders); | ||||
} | } | ||||
}; | }; | ||||
shouldDisplayCreator = creatorPermissions => { | |||||
shouldDisplayCreator = (creatorPermissions: string[]) => { | |||||
const { filter, query, selectedPermission } = this.state; | const { filter, query, selectedPermission } = this.state; | ||||
const CREATOR_NAME = translate('permission_templates.project_creators'); | const CREATOR_NAME = translate('permission_templates.project_creators'); | ||||
const matchQuery = !query || CREATOR_NAME.toLocaleLowerCase().includes(query.toLowerCase()); | const matchQuery = !query || CREATOR_NAME.toLocaleLowerCase().includes(query.toLowerCase()); | ||||
const matchPermission = | const matchPermission = | ||||
selectedPermission == null || creatorPermissions.includes(selectedPermission); | |||||
selectedPermission === undefined || creatorPermissions.includes(selectedPermission); | |||||
return !isFiltered && matchQuery && matchPermission; | return !isFiltered && matchQuery && matchPermission; | ||||
}; | }; |
/* | |||||
* 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 React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import Defaults from './Defaults'; | |||||
export default class TemplateDetails extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
template: PropTypes.object.isRequired | |||||
}; | |||||
render() { | |||||
const { template } = this.props; | |||||
return ( | |||||
<div className="big-spacer-bottom"> | |||||
{template.defaultFor.length > 0 && ( | |||||
<div className="spacer-top js-defaults"> | |||||
<Defaults organization={this.props.organization} permissionTemplate={template} /> | |||||
</div> | |||||
)} | |||||
{!!template.description && ( | |||||
<div className="spacer-top js-description">{template.description}</div> | |||||
)} | |||||
{!!template.projectKeyPattern && ( | |||||
<div className="spacer-top js-project-key-pattern"> | |||||
Project Key Pattern: <code>{template.projectKeyPattern}</code> | |||||
</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 Defaults from './Defaults'; | |||||
interface Props { | |||||
organization: T.Organization | undefined; | |||||
template: T.PermissionTemplate; | |||||
} | |||||
export default function TemplateDetails({ organization, template }: Props) { | |||||
return ( | |||||
<div className="big-spacer-bottom"> | |||||
{template.defaultFor.length > 0 && ( | |||||
<div className="spacer-top js-defaults"> | |||||
<Defaults organization={organization} template={template} /> | |||||
</div> | |||||
)} | |||||
{!!template.description && ( | |||||
<div className="spacer-top js-description">{template.description}</div> | |||||
)} | |||||
{!!template.projectKeyPattern && ( | |||||
<div className="spacer-top js-project-key-pattern"> | |||||
Project Key Pattern: <code>{template.projectKeyPattern}</code> | |||||
</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 React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import { Link } from 'react-router'; | |||||
import ActionsCell from './ActionsCell'; | |||||
import { translate } from '../../../helpers/l10n'; | |||||
export default class TemplateHeader extends React.PureComponent { | |||||
static propTypes = { | |||||
organization: PropTypes.object, | |||||
template: PropTypes.object.isRequired, | |||||
loading: PropTypes.bool.isRequired, | |||||
refresh: PropTypes.func.isRequired, | |||||
topQualifiers: PropTypes.array.isRequired | |||||
}; | |||||
render() { | |||||
const { template, organization } = this.props; | |||||
const pathname = organization | |||||
? `/organizations/${organization.key}/permission_templates` | |||||
: '/permission_templates'; | |||||
return ( | |||||
<header className="page-header" id="project-permissions-header"> | |||||
<div className="note spacer-bottom"> | |||||
<Link className="text-muted" to={pathname}> | |||||
{translate('permission_templates.page')} | |||||
</Link> | |||||
</div> | |||||
<h1 className="page-title">{template.name}</h1> | |||||
{this.props.loading && <i className="spinner" />} | |||||
<div className="pull-right"> | |||||
<ActionsCell | |||||
fromDetails={true} | |||||
organization={this.props.organization} | |||||
permissionTemplate={this.props.template} | |||||
refresh={this.props.refresh} | |||||
topQualifiers={this.props.topQualifiers} | |||||
/> | |||||
</div> | |||||
</header> | |||||
); | |||||
} | |||||
} |
/* | |||||
* 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 { Link } from 'react-router'; | |||||
import ActionsCell from './ActionsCell'; | |||||
import { translate } from '../../../helpers/l10n'; | |||||
interface Props { | |||||
loading: boolean; | |||||
organization: T.Organization | undefined; | |||||
refresh: () => void; | |||||
template: T.PermissionTemplate; | |||||
topQualifiers: string[]; | |||||
} | |||||
export default function TemplateHeader(props: Props) { | |||||
const { template, organization } = props; | |||||
const pathname = organization | |||||
? `/organizations/${organization.key}/permission_templates` | |||||
: '/permission_templates'; | |||||
return ( | |||||
<header className="page-header" id="project-permissions-header"> | |||||
<div className="note spacer-bottom"> | |||||
<Link className="text-muted" to={pathname}> | |||||
{translate('permission_templates.page')} | |||||
</Link> | |||||
</div> | |||||
<h1 className="page-title">{template.name}</h1> | |||||
{props.loading && <i className="spinner" />} | |||||
<div className="pull-right"> | |||||
<ActionsCell | |||||
fromDetails={true} | |||||
organization={organization} | |||||
permissionTemplate={template} | |||||
refresh={props.refresh} | |||||
topQualifiers={props.topQualifiers} | |||||
/> | |||||
</div> | |||||
</header> | |||||
); | |||||
} |
* 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. | ||||
*/ | */ | ||||
import * as React from 'react'; | |||||
import { shallow } from 'enzyme'; | import { shallow } from 'enzyme'; | ||||
import React from 'react'; | |||||
import Defaults from '../Defaults'; | import Defaults from '../Defaults'; | ||||
const SAMPLE = { | |||||
const SAMPLE: T.PermissionTemplate = { | |||||
createdAt: '2018-01-01', | |||||
defaultFor: [], | |||||
id: 'id', | id: 'id', | ||||
name: 'name', | name: 'name', | ||||
permissions: [] | permissions: [] | ||||
it('should render one qualifier', () => { | it('should render one qualifier', () => { | ||||
const sample = { ...SAMPLE, defaultFor: ['DEV'] }; | const sample = { ...SAMPLE, defaultFor: ['DEV'] }; | ||||
const output = shallow(<Defaults permissionTemplate={sample} />); | |||||
const output = shallow(<Defaults organization={undefined} template={sample} />); | |||||
expect(output).toMatchSnapshot(); | expect(output).toMatchSnapshot(); | ||||
}); | }); | ||||
it('should render several qualifiers', () => { | it('should render several qualifiers', () => { | ||||
const sample = { ...SAMPLE, defaultFor: ['TRK', 'VW'] }; | const sample = { ...SAMPLE, defaultFor: ['TRK', 'VW'] }; | ||||
const output = shallow(<Defaults permissionTemplate={sample} />); | |||||
const output = shallow(<Defaults organization={undefined} template={sample} />); | |||||
expect(output).toMatchSnapshot(); | expect(output).toMatchSnapshot(); | ||||
}); | }); | ||||
it('should render several qualifiers for default organization', () => { | it('should render several qualifiers for default organization', () => { | ||||
const sample = { ...SAMPLE, defaultFor: ['TRK', 'VW'] }; | const sample = { ...SAMPLE, defaultFor: ['TRK', 'VW'] }; | ||||
const organization = { isDefault: true }; | |||||
const output = shallow(<Defaults organization={organization} permissionTemplate={sample} />); | |||||
const organization: T.Organization = { isDefault: true, key: 'org', name: 'org' }; | |||||
const output = shallow(<Defaults organization={organization} template={sample} />); | |||||
expect(output).toMatchSnapshot(); | expect(output).toMatchSnapshot(); | ||||
}); | }); | ||||
it('should render only projects for custom organization', () => { | it('should render only projects for custom organization', () => { | ||||
const sample = { ...SAMPLE, defaultFor: ['TRK', 'VW'] }; | const sample = { ...SAMPLE, defaultFor: ['TRK', 'VW'] }; | ||||
const organization = { isDefault: false }; | |||||
const output = shallow(<Defaults organization={organization} permissionTemplate={sample} />); | |||||
const organization: T.Organization = { isDefault: false, key: 'org', name: 'org' }; | |||||
const output = shallow(<Defaults organization={organization} template={sample} />); | |||||
expect(output).toMatchSnapshot(); | expect(output).toMatchSnapshot(); | ||||
}); | }); |
'scan' | 'scan' | ||||
]; | ]; | ||||
/** | |||||
* Sort list of permissions based on predefined order | |||||
* @param {Array} permissions | |||||
* @returns {Array} | |||||
*/ | |||||
export function sortPermissions(permissions) { | |||||
export function sortPermissions(permissions: T.Permission[]) { | |||||
return sortBy(permissions, p => PERMISSIONS_ORDER.indexOf(p.key)); | return sortBy(permissions, p => PERMISSIONS_ORDER.indexOf(p.key)); | ||||
} | } | ||||
/** | |||||
* Populate permissions' details in the list of permission templates | |||||
* @param {Array} permissionTemplates | |||||
* @param {Array} basePermissions | |||||
* @returns {Array} | |||||
*/ | |||||
export function mergePermissionsToTemplates(permissionTemplates, basePermissions) { | |||||
export function mergePermissionsToTemplates( | |||||
permissionTemplates: T.PermissionTemplate[], | |||||
basePermissions: T.Permission[] | |||||
): T.PermissionTemplate[] { | |||||
return permissionTemplates.map(permissionTemplate => { | return permissionTemplates.map(permissionTemplate => { | ||||
// it's important to keep the order of the permission template's permissions | // it's important to keep the order of the permission template's permissions | ||||
// the same as the order of base permissions | // the same as the order of base permissions | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* Mark default templates | |||||
* @param {Array} permissionTemplates | |||||
* @param {Array} defaultTemplates | |||||
* @returns {Array} | |||||
*/ | |||||
export function mergeDefaultsToTemplates(permissionTemplates, defaultTemplates = []) { | |||||
export function mergeDefaultsToTemplates( | |||||
permissionTemplates: T.PermissionTemplate[], | |||||
defaultTemplates: Array<{ templateId: string; qualifier: string }> = [] | |||||
): T.PermissionTemplate[] { | |||||
return permissionTemplates.map(permissionTemplate => { | return permissionTemplates.map(permissionTemplate => { | ||||
const defaultFor = []; | |||||
const defaultFor: string[] = []; | |||||
defaultTemplates.forEach(defaultTemplate => { | defaultTemplates.forEach(defaultTemplate => { | ||||
if (defaultTemplate.templateId === permissionTemplate.id) { | if (defaultTemplate.templateId === permissionTemplate.id) { |