import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import { DataList, DataListItem, DataListCell, Text, TextContent, TextVariants, Chip, Button } from '@patternfly/react-core'; import { PlusIcon, } from '@patternfly/react-icons'; import { I18n, i18nMark } from '@lingui/react'; import { t, Trans } from '@lingui/macro'; import { Link, withRouter } from 'react-router-dom'; import { withNetwork } from '../../../contexts/Network'; import AlertModal from '../../../components/AlertModal'; import Pagination from '../../../components/Pagination'; import DataListToolbar from '../../../components/DataListToolbar'; import AddResourceRole from '../../../components/AddRole/AddResourceRole'; import { parseQueryString, } from '../../../util/qs'; const userRolesWrapperStyle = { display: 'flex', flexWrap: 'wrap', }; const detailWrapperStyle = { display: 'grid', gridTemplateColumns: 'minmax(70px, max-content) minmax(60px, max-content)', }; const detailLabelStyle = { fontWeight: '700', lineHeight: '24px', marginRight: '20px', }; const detailValueStyle = { lineHeight: '28px', overflow: 'visible', }; const Detail = ({ label, value, url, customStyles }) => { let detail = null; if (value) { detail = ( {url ? ( {label} ) : ({label} )} {value} ); } return detail; }; const UserName = ({ value, url }) => { let username = null; if (value) { username = ( {url ? ( {value} ) : ({value} )} ); } return username; }; class OrganizationAccessList extends React.Component { columns = [ { name: i18nMark('Name'), key: 'first_name', isSortable: true }, { name: i18nMark('Username'), key: 'username', isSortable: true }, { name: i18nMark('Last Name'), key: 'last_name', isSortable: true }, ]; defaultParams = { page: 1, page_size: 5, order_by: 'first_name', }; constructor (props) { super(props); const { page, page_size } = this.getQueryParams(); this.state = { page, page_size, count: 0, sortOrder: 'ascending', sortedColumnKey: 'username', showWarning: false, warningTitle: '', warningMsg: '', deleteType: '', deleteRoleId: null, deleteResourceId: null, results: [], isModalOpen: false }; this.fetchOrgAccessList = this.fetchOrgAccessList.bind(this); this.onSetPage = this.onSetPage.bind(this); this.onSort = this.onSort.bind(this); this.getQueryParams = this.getQueryParams.bind(this); this.removeAccessRole = this.removeAccessRole.bind(this); this.handleWarning = this.handleWarning.bind(this); this.hideWarning = this.hideWarning.bind(this); this.confirmDelete = this.confirmDelete.bind(this); this.handleModalToggle = this.handleModalToggle.bind(this); this.handleSuccessfulRoleAdd = this.handleSuccessfulRoleAdd.bind(this); } componentDidMount () { const queryParams = this.getQueryParams(); try { this.fetchOrgAccessList(queryParams); } catch (error) { this.setState({ error }); } } onSetPage (pageNumber, pageSize) { const { sortOrder, sortedColumnKey } = this.state; const page = parseInt(pageNumber, 10); const page_size = parseInt(pageSize, 10); let order_by = sortedColumnKey; // Preserve sort order when paginating if (sortOrder === 'descending') { order_by = `-${order_by}`; } const queryParams = this.getQueryParams({ page, page_size, order_by }); this.fetchOrgAccessList(queryParams); } onSort (sortedColumnKey, sortOrder) { const { page_size } = this.state; let order_by = sortedColumnKey; if (sortOrder === 'descending') { order_by = `-${order_by}`; } const queryParams = this.getQueryParams({ order_by, page_size }); this.fetchOrgAccessList(queryParams); } getQueryParams (overrides = {}) { const { history } = this.props; const { search } = history.location; const searchParams = parseQueryString(search.substring(1)); return Object.assign({}, this.defaultParams, searchParams, overrides); } async fetchOrgAccessList (queryParams) { const { match, getAccessList } = this.props; const { page, page_size, order_by } = queryParams; let sortOrder = 'ascending'; let sortedColumnKey = order_by; if (order_by.startsWith('-')) { sortOrder = 'descending'; sortedColumnKey = order_by.substring(1); } try { const { data: { count = 0, results = [] } } = await getAccessList(match.params.id, queryParams); const pageCount = Math.ceil(count / page_size); const stateToUpdate = { count, page, pageCount, page_size, sortOrder, sortedColumnKey, results, }; results.forEach((result) => { // Separate out roles into user roles or team roles // based on whether or not a team_id attribute is present const teamRoles = []; const userRoles = []; Object.values(result.summary_fields).forEach(field => { if (field.length > 0) { field.forEach(item => { const { role } = item; if (role.team_id) { teamRoles.push(role); } else { userRoles.push(role); } }); } }); result.teamRoles = teamRoles; result.userRoles = userRoles; }); this.setState(stateToUpdate); } catch (error) { this.setState({ error }); } } async removeAccessRole (roleId, resourceId, type) { const { removeRole, handleHttpError } = this.props; const url = `/api/v2/${type}/${resourceId}/roles/`; try { await removeRole(url, roleId); const queryParams = this.getQueryParams(); await this.fetchOrgAccessList(queryParams); this.setState({ showWarning: false }); } catch (error) { handleHttpError(error) || this.setState({ error }); } } handleWarning (roleName, roleId, resourceName, resourceId, type) { let warningTitle; let warningMsg; if (type === 'users') { warningTitle = i18nMark('Remove User Access'); warningMsg = ( Are you sure you want to remove {` ${roleName} `} access from {` ${resourceName}`} ? ); } if (type === 'teams') { warningTitle = i18nMark('Remove Team Access'); warningMsg = ( Are you sure you want to remove {` ${roleName} `} access from {` ${resourceName}`} ? Doing so affects all members of the team.

If you only want to remove access for this particular user, please remove them from the team.
); } this.setState({ showWarning: true, warningMsg, warningTitle, deleteType: type, deleteRoleId: roleId, deleteResourceId: resourceId }); } handleSuccessfulRoleAdd () { this.handleModalToggle(); const queryParams = this.getQueryParams(); try { this.fetchOrgAccessList(queryParams); } catch (error) { this.setState({ error }); } } handleModalToggle () { this.setState((prevState) => ({ isModalOpen: !prevState.isModalOpen, })); } hideWarning () { this.setState({ showWarning: false }); } confirmDelete () { const { deleteType, deleteResourceId, deleteRoleId } = this.state; this.removeAccessRole(deleteRoleId, deleteResourceId, deleteType); } render () { const { results, error, count, page_size, pageCount, page, sortedColumnKey, sortOrder, warningMsg, warningTitle, showWarning, isModalOpen } = this.state; const { api, organization } = this.props; return ( {({ i18n }) => ( {!error && results.length <= 0 && (

Loading...

// TODO: replace with proper loading state )} {error && results.length <= 0 && (
{error.message}
{error.response && (
{error.response.data.detail}
)}
// TODO: replace with proper error handling )} {results.length > 0 && ( { }} onSort={this.onSort} add={( {isModalOpen && ( )} )} /> {showWarning && ( {i18n._(t`Delete`)}, ]} > {warningMsg} )} {results.map(result => ( {result.first_name || result.last_name ? ( ) : ( null )} {result.userRoles.length > 0 && (
    {i18n._(t`User Roles`)} {result.userRoles.map(role => ( this.handleWarning(role.name, role.id, result.username, result.id, 'users')} > {role.name} ))}
)} {result.teamRoles.length > 0 && (
    {i18n._(t`Team Roles`)} {result.teamRoles.map(role => ( this.handleWarning(role.name, role.id, role.team_name, role.team_id, 'teams')} > {role.name} ))}
)}
))}
)}
)}
); } } OrganizationAccessList.propTypes = { getAccessList: PropTypes.func.isRequired, removeRole: PropTypes.func.isRequired }; export { OrganizationAccessList as _OrganizationAccessList }; export default withRouter(withNetwork(OrganizationAccessList));