awx/src/components/AddRole/AddResourceRole.jsx
Jake McDermott e72f0bcfd4
update content loading and error handling
unwind error handling

use auth cookie as source of truth, fetch config only when authenticated
2019-06-14 13:00:37 -04:00

248 lines
6.8 KiB
JavaScript

import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Wizard } from '@patternfly/react-core';
import SelectResourceStep from './SelectResourceStep';
import SelectRoleStep from './SelectRoleStep';
import SelectableCard from './SelectableCard';
import { TeamsAPI, UsersAPI } from '../../api';
const readUsers = async (queryParams) => UsersAPI.read(
Object.assign(queryParams, { is_superuser: false })
);
const readTeams = async (queryParams) => TeamsAPI.read(queryParams);
class AddResourceRole extends React.Component {
constructor (props) {
super(props);
this.state = {
selectedResource: null,
selectedResourceRows: [],
selectedRoleRows: [],
currentStepId: 1,
};
this.handleResourceCheckboxClick = this.handleResourceCheckboxClick.bind(this);
this.handleResourceSelect = this.handleResourceSelect.bind(this);
this.handleRoleCheckboxClick = this.handleRoleCheckboxClick.bind(this);
this.handleWizardNext = this.handleWizardNext.bind(this);
this.handleWizardSave = this.handleWizardSave.bind(this);
}
handleResourceCheckboxClick (user) {
const { selectedResourceRows } = this.state;
const selectedIndex = selectedResourceRows
.findIndex(selectedRow => selectedRow.id === user.id);
if (selectedIndex > -1) {
selectedResourceRows.splice(selectedIndex, 1);
this.setState({ selectedResourceRows });
} else {
this.setState(prevState => ({
selectedResourceRows: [...prevState.selectedResourceRows, user]
}));
}
}
handleRoleCheckboxClick (role) {
const { selectedRoleRows } = this.state;
const selectedIndex = selectedRoleRows
.findIndex(selectedRow => selectedRow.id === role.id);
if (selectedIndex > -1) {
selectedRoleRows.splice(selectedIndex, 1);
this.setState({ selectedRoleRows });
} else {
this.setState(prevState => ({
selectedRoleRows: [...prevState.selectedRoleRows, role]
}));
}
}
handleResourceSelect (resourceType) {
this.setState({
selectedResource: resourceType,
selectedResourceRows: [],
selectedRoleRows: []
});
}
handleWizardNext (step) {
this.setState({
currentStepId: step.id,
});
}
async handleWizardSave () {
const {
onSave
} = this.props;
const {
selectedResourceRows,
selectedRoleRows,
selectedResource
} = this.state;
try {
const roleRequests = [];
for (let i = 0; i < selectedResourceRows.length; i++) {
for (let j = 0; j < selectedRoleRows.length; j++) {
if (selectedResource === 'users') {
roleRequests.push(
UsersAPI.associateRole(selectedResourceRows[i].id, selectedRoleRows[j].id)
);
} else if (selectedResource === 'teams') {
roleRequests.push(
TeamsAPI.associateRole(selectedResourceRows[i].id, selectedRoleRows[j].id)
);
}
}
}
await Promise.all(roleRequests);
onSave();
} catch (err) {
// TODO: handle this error
}
}
render () {
const {
selectedResource,
selectedResourceRows,
selectedRoleRows,
currentStepId,
} = this.state;
const {
onClose,
roles,
i18n
} = this.props;
const userColumns = [
{ name: i18n._(t`Username`), key: 'username', isSortable: true }
];
const teamColumns = [
{ name: i18n._(t`Name`), key: 'name', isSortable: true }
];
let wizardTitle = '';
switch (selectedResource) {
case 'users':
wizardTitle = i18n._(t`Add User Roles`);
break;
case 'teams':
wizardTitle = i18n._(t`Add Team Roles`);
break;
default:
wizardTitle = i18n._(t`Add Roles`);
}
const steps = [
{
id: 1,
name: i18n._(t`Select Users Or Teams`),
component: (
<div style={{ display: 'flex' }}>
<SelectableCard
isSelected={selectedResource === 'users'}
label={i18n._(t`Users`)}
onClick={() => this.handleResourceSelect('users')}
/>
<SelectableCard
isSelected={selectedResource === 'teams'}
label={i18n._(t`Teams`)}
onClick={() => this.handleResourceSelect('teams')}
/>
</div>
),
enableNext: selectedResource !== null
},
{
id: 2,
name: i18n._(t`Select items from list`),
component: (
<Fragment>
{selectedResource === 'users' && (
<SelectResourceStep
columns={userColumns}
displayKey="username"
onRowClick={this.handleResourceCheckboxClick}
onSearch={readUsers}
selectedLabel={i18n._(t`Selected`)}
selectedResourceRows={selectedResourceRows}
sortedColumnKey="username"
itemName="user"
/>
)}
{selectedResource === 'teams' && (
<SelectResourceStep
columns={teamColumns}
onRowClick={this.handleResourceCheckboxClick}
onSearch={readTeams}
selectedLabel={i18n._(t`Selected`)}
selectedResourceRows={selectedResourceRows}
itemName="team"
/>
)}
</Fragment>
),
enableNext: selectedResourceRows.length > 0
},
{
id: 3,
name: i18n._(t`Apply roles`),
component: (
<SelectRoleStep
onRolesClick={this.handleRoleCheckboxClick}
roles={roles}
selectedListKey={selectedResource === 'users' ? 'username' : 'name'}
selectedListLabel={i18n._(t`Selected`)}
selectedResourceRows={selectedResourceRows}
selectedRoleRows={selectedRoleRows}
/>
),
nextButtonText: i18n._(t`Save`),
enableNext: selectedRoleRows.length > 0
}
];
const currentStep = steps.find(step => step.id === currentStepId);
// TODO: somehow internationalize steps and currentStep.nextButtonText
return (
<Wizard
style={{ overflow: 'scroll' }}
isOpen
onNext={this.handleWizardNext}
onClose={onClose}
onSave={this.handleWizardSave}
steps={steps}
title={wizardTitle}
nextButtonText={currentStep.nextButtonText || undefined}
/>
);
}
}
AddResourceRole.propTypes = {
onClose: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
roles: PropTypes.shape()
};
AddResourceRole.defaultProps = {
roles: {}
};
export { AddResourceRole as _AddResourceRole };
export default withI18n()(AddResourceRole);