Add RBAC to org views

This commit is contained in:
mabashian
2019-04-18 13:31:03 -04:00
parent 1509ef3e80
commit 5ae7cbb43a
14 changed files with 315 additions and 98 deletions

View File

@@ -62,8 +62,7 @@ class OrganizationsList extends Component {
loading: true,
results: [],
selected: [],
isModalOpen: false,
orgsToDelete: [],
isModalOpen: false
};
@@ -74,14 +73,16 @@ class OrganizationsList extends Component {
this.onSelectAll = this.onSelectAll.bind(this);
this.onSelect = this.onSelect.bind(this);
this.updateUrl = this.updateUrl.bind(this);
this.callOrganizations = this.callOrganizations.bind(this);
this.fetchOrganizations = this.fetchOrganizations.bind(this);
this.handleOrgDelete = this.handleOrgDelete.bind(this);
this.handleOpenOrgDeleteModal = this.handleOpenOrgDeleteModal.bind(this);
this.handleClearOrgsToDelete = this.handleClearOrgsToDelete.bind(this);
this.handleCloseOrgDeleteModal = this.handleCloseOrgDeleteModal.bind(this);
}
componentDidMount () {
const queryParams = this.getQueryParams();
this.callOrganizations();
this.fetchOrganizations(queryParams);
}
@@ -117,20 +118,20 @@ class OrganizationsList extends Component {
onSelectAll (isSelected) {
const { results } = this.state;
const selected = isSelected ? results.map(o => o.id) : [];
const selected = isSelected ? results : [];
this.setState({ selected });
}
onSelect (id) {
onSelect (row) {
const { selected } = this.state;
const isSelected = selected.includes(id);
const isSelected = selected.some(s => s.id === row.id);
if (isSelected) {
this.setState({ selected: selected.filter(s => s !== id) });
this.setState({ selected: selected.filter(s => s.id !== row.id) });
} else {
this.setState({ selected: selected.concat(id) });
this.setState({ selected: selected.concat(row) });
}
}
@@ -143,43 +144,35 @@ class OrganizationsList extends Component {
return Object.assign({}, this.defaultParams, searchParams, overrides);
}
handleClearOrgsToDelete () {
handleCloseOrgDeleteModal () {
this.setState({
isModalOpen: false,
orgsToDelete: []
isModalOpen: false
});
this.onSelectAll();
}
handleOpenOrgDeleteModal () {
const { results, selected } = this.state;
const { selected } = this.state;
const warningTitle = selected.length > 1 ? i18nMark('Delete Organization') : i18nMark('Delete Organizations');
const warningMsg = i18nMark('Are you sure you want to delete:');
const orgsToDelete = [];
results.forEach((result) => {
selected.forEach((selectedOrg) => {
if (result.id === selectedOrg) {
orgsToDelete.push({ name: result.name, id: selectedOrg });
}
});
});
this.setState({
orgsToDelete,
isModalOpen: true,
warningTitle,
warningMsg,
loading: false });
loading: false
});
}
async handleOrgDelete (event) {
const { orgsToDelete } = this.state;
async handleOrgDelete () {
const { selected } = this.state;
const { api, handleHttpError } = this.props;
let errorHandled;
try {
await Promise.all(orgsToDelete.map((org) => api.destroyOrganization(org.id)));
this.handleClearOrgsToDelete();
await Promise.all(selected.map((org) => api.destroyOrganization(org.id)));
this.setState({
isModalOpen: false,
selected: []
});
} catch (err) {
errorHandled = handleHttpError(err);
} finally {
@@ -188,7 +181,6 @@ class OrganizationsList extends Component {
this.fetchOrganizations(queryParams);
}
}
event.preventDefault();
}
updateUrl (queryParams) {
@@ -248,16 +240,35 @@ class OrganizationsList extends Component {
}
}
async callOrganizations () {
const { api } = this.props;
try {
const { data } = await api.callOrganizations();
const { actions } = data;
const stateToUpdate = {
canAdd: Object.prototype.hasOwnProperty.call(actions, 'POST')
};
this.setState(stateToUpdate);
} catch (err) {
this.setState({ error: true });
} finally {
this.setState({ loading: false });
}
}
render () {
const {
medium,
} = PageSectionVariants;
const {
canAdd,
count,
error,
loading,
noInitialResults,
orgsToDelete,
page,
pageCount,
page_size,
@@ -270,6 +281,12 @@ class OrganizationsList extends Component {
warningMsg,
} = this.state;
const { match } = this.props;
const disableDelete = (
selected.length === 0
|| selected.some(row => !row.summary_fields.user_capabilities.delete)
);
return (
<I18n>
{({ i18n }) => (
@@ -280,15 +297,15 @@ class OrganizationsList extends Component {
variant="danger"
title={warningTitle}
isOpen={isModalOpen}
onClose={this.handleClearOrgsToDelete}
onClose={this.handleCloseOrgDeleteModal}
actions={[
<Button variant="danger" key="delete" aria-label="confirm-delete" onClick={this.handleOrgDelete}>{i18n._(t`Delete`)}</Button>,
<Button variant="secondary" key="cancel" aria-label="cancel-delete" onClick={this.handleClearOrgsToDelete}>{i18n._(t`Cancel`)}</Button>
<Button variant="secondary" key="cancel" aria-label="cancel-delete" onClick={this.handleCloseOrgDeleteModal}>{i18n._(t`Cancel`)}</Button>
]}
>
{warningMsg}
<br />
{orgsToDelete.map((org) => (
{selected.map((org) => (
<span key={org.id}>
<strong>
{org.name}
@@ -321,9 +338,24 @@ class OrganizationsList extends Component {
onSort={this.onSort}
onSelectAll={this.onSelectAll}
onOpenDeleteModal={this.handleOpenOrgDeleteModal}
disableTrashCanIcon={selected.length === 0}
disableTrashCanIcon={disableDelete}
deleteTooltip={
selected.some(row => !row.summary_fields.user_capabilities.delete) ? (
<div>
<Trans>
You dont have permission to delete the following Organizations:
</Trans>
{selected.map(row => (
<div key={row.id}>
{row.name}
</div>
))}
</div>
) : undefined
}
showDelete
showSelectAll
showAdd={canAdd}
/>
<ul className="pf-c-data-list" aria-label={i18n._(t`Organizations List`)}>
{ results.map(o => (
@@ -334,8 +366,8 @@ class OrganizationsList extends Component {
detailUrl={`${match.url}/${o.id}`}
memberCount={o.summary_fields.related_field_counts.users}
teamCount={o.summary_fields.related_field_counts.teams}
isSelected={selected.includes(o.id)}
onSelect={() => this.onSelect(o.id, o.name)}
isSelected={selected.some(row => row.id === o.id)}
onSelect={() => this.onSelect(o)}
onOpenOrgDeleteModal={this.handleOpenOrgDeleteModal}
/>
))}