/* * 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 { find, without } from 'lodash'; import { User } from '../../../app/types'; import Modal from '../../../components/controls/Modal'; import SelectList, { Filter } from '../../../components/SelectList/SelectList'; import { translate } from '../../../helpers/l10n'; import { getUserGroups, UserGroup } from '../../../api/users'; import { addUserToGroup, removeUserFromGroup } from '../../../api/user_groups'; interface Props { onClose: () => void; onUpdateUsers: () => void; user: User; } interface State { error: string; groups: UserGroup[]; selectedGroups: string[]; } export default class GroupsForm extends React.PureComponent<Props> { container?: HTMLDivElement | null; state: State = { error: '', groups: [], selectedGroups: [] }; componentDidMount() { this.handleSearch('', Filter.Selected); } handleSearch = (query: string, selected: Filter) => { return getUserGroups(this.props.user.login, undefined, query, selected).then(data => { this.setState({ groups: data.groups, selectedGroups: data.groups.filter(group => group.selected).map(group => group.name) }); }); }; handleSelect = (name: string) => { return addUserToGroup({ name, login: this.props.user.login }).then(() => { this.setState((state: State) => ({ selectedGroups: [...state.selectedGroups, name] })); }); }; handleUnselect = (name: string) => { return removeUserFromGroup({ name, login: this.props.user.login }).then(() => { this.setState((state: State) => ({ selectedGroups: without(state.selectedGroups, name) })); }); }; handleCloseClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.handleClose(); }; handleClose = () => { this.props.onUpdateUsers(); this.props.onClose(); }; renderElement = (name: string): React.ReactNode => { const group = find(this.state.groups, { name }); return ( <div className="select-list-list-item"> {group === undefined ? ( name ) : ( <> {group.name} <br /> <span className="note">{group.description}</span> </> )} </div> ); }; render() { const header = translate('users.update_groups'); return ( <Modal contentLabel={header} onRequestClose={this.handleClose}> <div className="modal-head"> <h2>{header}</h2> </div> <div className="modal-body"> {this.state.error !== '' && ( <div className="alert alert-danger"> <p>{this.state.error}</p> </div> )} <SelectList elements={this.state.groups.map(group => group.name)} onSearch={this.handleSearch} onSelect={this.handleSelect} onUnselect={this.handleUnselect} renderElement={this.renderElement} selectedElements={this.state.selectedGroups} /> </div> <footer className="modal-foot"> <a className="js-modal-close" href="#" onClick={this.handleCloseClick}> {translate('Done')} </a> </footer> </Modal> ); } }