openreplay/frontend/app/components/Client/ManageUsers/ManageUsers.js
2021-12-04 02:19:16 +05:30

267 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { connect } from 'react-redux';
import cn from 'classnames';
import withPageTitle from 'HOCs/withPageTitle';
import {
IconButton, SlideModal, Input, Button, Loader,
NoContent, Popup, CopyButton, Dropdown } from 'UI';
import { init, save, edit, remove as deleteMember, fetchList, generateInviteLink } from 'Duck/member';
import { fetchList as fetchRoles } from 'Duck/roles';
import styles from './manageUsers.css';
import UserItem from './UserItem';
import { confirm } from 'UI/Confirmation';
import { toast } from 'react-toastify';
import BannerMessage from 'Shared/BannerMessage';
const PERMISSION_WARNING = 'You dont have the permissions to perform this action.';
const LIMIT_WARNING = 'You have reached users limit.';
@connect(state => ({
account: state.getIn([ 'user', 'account' ]),
members: state.getIn([ 'members', 'list' ]).filter(u => u.id),
member: state.getIn([ 'members', 'instance' ]),
errors: state.getIn([ 'members', 'saveRequest', 'errors' ]),
loading: state.getIn([ 'members', 'loading' ]),
saving: state.getIn([ 'members', 'saveRequest', 'loading' ]),
roles: state.getIn(['roles', 'list']).filter(r => !r.protected).map(r => ({ text: r.name, value: r.roleId })).toJS(),
isEnterprise: state.getIn([ 'user', 'client', 'edition' ]) === 'ee',
}), {
init,
save,
edit,
deleteMember,
fetchList,
generateInviteLink,
fetchRoles
})
@withPageTitle('Users - OpenReplay Preferences')
class ManageUsers extends React.PureComponent {
state = { showModal: false, remaining: this.props.account.limits.teamMember.remaining, invited: false }
// writeOption = (e, { name, value }) => this.props.edit({ [ name ]: value });
onChange = (e, { name, value }) => this.props.edit({ [ name ]: value });
onChangeCheckbox = ({ target: { checked, name } }) => this.props.edit({ [ name ]: checked });
setFocus = () => this.focusElement.focus();
closeModal = () => this.setState({ showModal: false });
componentWillMount = () => {
this.props.fetchList();
this.props.fetchRoles();
}
adminLabel = (user) => {
if (user.superAdmin) return 'Owner';
return user.admin ? 'Admin' : '';
};
editHandler = user => {
this.init(user)
}
deleteHandler = async (user) => {
if (await confirm({
header: 'Users',
confirmation: `Are you sure you want to remove this user?`
})) {
this.props.deleteMember(user.id).then(() => {
const { remaining } = this.state;
if (remaining <= 0) return;
this.setState({ remaining: remaining - 1 })
});
}
}
save = (e) => {
e.preventDefault();
this.props.save(this.props.member)
.then(() => {
const { errors } = this.props;
if (errors && errors.size > 0) {
errors.forEach(e => {
toast.error(e);
})
}
this.setState({ invited: true })
// this.closeModal()
});
}
formContent = () => {
const { member, account, isEnterprise, roles } = this.props;
return (
<div className={ styles.form }>
<form onSubmit={ this.save } >
<div className={ styles.formGroup }>
<label>{ 'Full Name' }</label>
<Input
ref={ (ref) => { this.focusElement = ref; } }
name="name"
value={ member.name }
onChange={ this.onChange }
className={ styles.input }
id="name-field"
/>
</div>
<div className={ styles.formGroup }>
<label>{ 'Email Address' }</label>
<Input
disabled={member.exists()}
name="email"
value={ member.email }
onChange={ this.onChange }
className={ styles.input }
/>
</div>
{ !account.smtp &&
<div className={cn("mb-4 p-2", styles.smtpMessage)}>
SMTP is not configured. Please follow (see <a className="link" href="https://docs.openreplay.com/configuration/configure-smtp" target="_blank">here</a> how to set it up). You can still add new users, but youd have to manually copy then send them the invitation link.
</div>
}
<div className={ styles.formGroup }>
<label className={ styles.checkbox }>
<input
name="admin"
type="checkbox"
value={ member.admin }
checked={ !!member.admin }
onChange={ this.onChangeCheckbox }
disabled={member.superAdmin}
/>
<span>{ 'Admin Privileges' }</span>
</label>
<div className={ styles.adminInfo }>{ 'Can manage Projects and team members.' }</div>
</div>
{ isEnterprise && (
<div className={ styles.formGroup }>
<label htmlFor="role">{ 'Role' }</label>
<Dropdown
placeholder="Role"
selection
options={ roles }
name="roleId"
value={ member.roleId }
onChange={ this.onChange }
/>
</div>
)}
</form>
<div className="flex items-center">
<div className="flex items-center mr-auto">
<Button
onClick={ this.save }
disabled={ !member.validate() }
loading={ this.props.saving }
primary
marginRight
>
{ member.exists() ? 'Update' : 'Invite' }
</Button>
<Button
data-hidden={ !member.exists() }
onClick={ this.closeModal }
outline
>
{ 'Cancel' }
</Button>
</div>
{ !member.joined && member.invitationLink &&
<CopyButton
content={member.invitationLink}
className="link"
btnText="Copy invite link"
/>
}
</div>
</div>
)
}
init = (v) => {
this.props.init(v);
this.setState({ showModal: true });
this.setFocus();
}
render() {
const {
members, loading, account, hideHeader = false
} = this.props;
const { showModal, remaining, invited } = this.state;
const isAdmin = account.admin || account.superAdmin;
const canAddUsers = isAdmin && remaining !== 0;
return (
<React.Fragment>
<Loader loading={ loading }>
<SlideModal
title="Invite People"
size="small"
isDisplayed={ showModal }
content={ this.formContent() }
onClose={ this.closeModal }
/>
<div className={ styles.wrapper }>
<div className={ cn(styles.tabHeader, 'flex items-center') }>
<div className="flex items-center mr-auto">
{ !hideHeader && <h3 className={ cn(styles.tabTitle, "text-2xl") }>{ (isAdmin ? 'Manage ' : '') + 'Users' }</h3> }
{ hideHeader && <h3 className={ cn(styles.tabTitle, "text-xl") }>{ `Team Size ${members.size}` }</h3>}
<Popup
trigger={
<div>
<IconButton
id="add-button"
disabled={ !canAddUsers }
circle
icon="plus"
outline
onClick={ () => this.init() }
/>
</div>
}
disabled={ canAddUsers }
content={ `${ !canAddUsers ? (!isAdmin ? PERMISSION_WARNING : LIMIT_WARNING) : 'Add team member' }` }
size="tiny"
inverted
position="top left"
/>
</div>
</div>
<NoContent
title="No users are available."
size="small"
show={ members.size === 0 }
icon
>
<div className={ styles.list }>
{
members.map(user => (
<UserItem
generateInviteLink={this.props.generateInviteLink}
key={ user.id }
user={ user }
adminLabel={ this.adminLabel(user) }
deleteHandler={ isAdmin && account.email !== user.email
? this.deleteHandler
: null
}
editHandler={ isAdmin ? this.editHandler : null }
/>
))
}
{ !members.size > 0 &&
<div>{ 'No Data.' }</div>
}
</div>
</NoContent>
</div>
</Loader>
</React.Fragment>
);
}
}
export default ManageUsers;