2019-02-27 19:44:22 +08:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
|
|
|
import { gettext, siteRoot, orgID, username } from '../../utils/constants';
|
|
|
|
import { seafileAPI } from '../../utils/seafile-api';
|
2019-07-16 10:01:09 +08:00
|
|
|
import { Utils } from '../../utils/utils';
|
|
|
|
import toaster from '../../components/toast';
|
2023-11-24 18:21:46 +08:00
|
|
|
import Selector from '../../components/single-selector';
|
2019-02-27 19:44:22 +08:00
|
|
|
|
|
|
|
const propTypes = {
|
2019-05-05 18:29:06 +08:00
|
|
|
user: PropTypes.object,
|
2019-02-27 19:44:22 +08:00
|
|
|
currentTab: PropTypes.string,
|
|
|
|
toggleRevokeAdmin: PropTypes.func,
|
|
|
|
isItemFreezed: PropTypes.bool.isRequired,
|
|
|
|
toggleDelete: PropTypes.func.isRequired,
|
|
|
|
onFreezedItem: PropTypes.func.isRequired,
|
|
|
|
onUnfreezedItem: PropTypes.func.isRequired,
|
2023-11-24 18:21:46 +08:00
|
|
|
toggleItemFreezed: PropTypes.func.isRequired,
|
2023-09-13 08:40:50 +08:00
|
|
|
changeStatus: PropTypes.func.isRequired,
|
2019-02-27 19:44:22 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class UserItem extends React.Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
highlight: false,
|
|
|
|
showMenu: false,
|
|
|
|
isItemMenuShow: false
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
onMouseEnter = () => {
|
|
|
|
if (!this.props.isItemFreezed) {
|
|
|
|
this.setState({
|
|
|
|
showMenu: true,
|
|
|
|
highlight: true,
|
|
|
|
});
|
|
|
|
}
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2019-02-27 19:44:22 +08:00
|
|
|
|
|
|
|
onMouseLeave = () => {
|
|
|
|
if (!this.props.isItemFreezed) {
|
|
|
|
this.setState({
|
|
|
|
showMenu: false,
|
|
|
|
highlight: false
|
|
|
|
});
|
|
|
|
}
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2019-02-27 19:44:22 +08:00
|
|
|
|
|
|
|
toggleDelete = () => {
|
|
|
|
const email = this.props.user.email;
|
2023-09-19 14:42:15 +08:00
|
|
|
const username = this.props.user.name;
|
|
|
|
this.props.toggleDelete(email, username);
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2020-11-02 13:56:35 +08:00
|
|
|
|
2019-02-27 19:44:22 +08:00
|
|
|
toggleResetPW = () => {
|
2020-09-17 14:48:29 +08:00
|
|
|
const { email, name } = this.props.user;
|
2019-07-31 14:43:11 +08:00
|
|
|
toaster.success(gettext('Resetting user\'s password, please wait for a moment.'));
|
2019-08-12 11:00:45 +08:00
|
|
|
seafileAPI.orgAdminResetOrgUserPassword(orgID, email).then(res => {
|
2019-02-27 19:44:22 +08:00
|
|
|
let msg;
|
|
|
|
msg = gettext('Successfully reset password to %(passwd)s for user %(user)s.');
|
|
|
|
msg = msg.replace('%(passwd)s', res.data.new_password);
|
2020-09-17 14:48:29 +08:00
|
|
|
msg = msg.replace('%(user)s', name);
|
2019-07-31 14:43:11 +08:00
|
|
|
toaster.success(msg, {
|
|
|
|
duration: 15
|
|
|
|
});
|
2019-07-16 10:01:09 +08:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
2019-02-27 19:44:22 +08:00
|
|
|
});
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2019-02-27 19:44:22 +08:00
|
|
|
|
|
|
|
toggleRevokeAdmin = () => {
|
|
|
|
const email = this.props.user.email;
|
|
|
|
this.props.toggleRevokeAdmin(email);
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2019-02-27 19:44:22 +08:00
|
|
|
|
2023-11-24 18:21:46 +08:00
|
|
|
changeStatus = (statusOption) => {
|
|
|
|
const isActive = statusOption.value == 'active';
|
2022-10-19 19:08:02 +08:00
|
|
|
if (isActive) {
|
|
|
|
toaster.notify(gettext('It may take some time, please wait.'));
|
2019-02-27 19:44:22 +08:00
|
|
|
}
|
2022-10-19 19:08:02 +08:00
|
|
|
this.props.changeStatus(this.props.user.email, isActive);
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2019-02-27 19:44:22 +08:00
|
|
|
|
|
|
|
onDropdownToggleClick = (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
this.toggleOperationMenu(e);
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2019-02-27 19:44:22 +08:00
|
|
|
|
|
|
|
toggleOperationMenu = (e) => {
|
|
|
|
e.stopPropagation();
|
|
|
|
this.setState(
|
|
|
|
{isItemMenuShow: !this.state.isItemMenuShow }, () => {
|
|
|
|
if (this.state.isItemMenuShow) {
|
|
|
|
this.props.onFreezedItem();
|
|
|
|
} else {
|
|
|
|
this.setState({
|
|
|
|
highlight: false,
|
|
|
|
showMenu: false,
|
|
|
|
});
|
|
|
|
this.props.onUnfreezedItem();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2019-02-27 19:44:22 +08:00
|
|
|
|
2020-09-24 16:53:55 +08:00
|
|
|
getQuotaTotal = (data) => {
|
|
|
|
switch (data) {
|
|
|
|
case -1: // failed to fetch quota
|
|
|
|
return gettext('Failed');
|
|
|
|
case -2:
|
|
|
|
return '--';
|
|
|
|
default: // data > 0
|
|
|
|
return Utils.formatSize({bytes: data});
|
|
|
|
}
|
2023-09-13 08:40:50 +08:00
|
|
|
};
|
2020-09-24 16:53:55 +08:00
|
|
|
|
2023-11-24 18:21:46 +08:00
|
|
|
translateStatus = (status) => {
|
|
|
|
switch (status) {
|
|
|
|
case 'active':
|
|
|
|
return gettext('Active');
|
|
|
|
case 'inactive':
|
|
|
|
return gettext('Inactive');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-02-27 19:44:22 +08:00
|
|
|
render() {
|
2023-11-24 18:21:46 +08:00
|
|
|
const { highlight } = this.state;
|
2019-02-27 19:44:22 +08:00
|
|
|
let { user, currentTab } = this.props;
|
|
|
|
let href = siteRoot + 'org/useradmin/info/' + encodeURIComponent(user.email) + '/';
|
|
|
|
let isOperationMenuShow = (user.email !== username) && this.state.showMenu;
|
2023-11-24 18:21:46 +08:00
|
|
|
|
|
|
|
// for 'user status'
|
|
|
|
const curStatus = user.is_active ? 'active' : 'inactive';
|
|
|
|
this.statusOptions = ['active', 'inactive'].map(item => {
|
|
|
|
return {
|
|
|
|
value: item,
|
|
|
|
text: this.translateStatus(item),
|
|
|
|
isSelected: item == curStatus
|
|
|
|
};
|
|
|
|
});
|
|
|
|
const currentSelectedStatusOption = this.statusOptions.filter(item => item.isSelected)[0];
|
|
|
|
|
2019-02-27 19:44:22 +08:00
|
|
|
return (
|
|
|
|
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
|
|
|
<td>
|
2020-04-27 14:46:41 +08:00
|
|
|
<a href={href}>{user.name}</a>
|
2019-02-27 19:44:22 +08:00
|
|
|
</td>
|
|
|
|
<td>
|
2023-11-24 18:21:46 +08:00
|
|
|
<Selector
|
|
|
|
isDropdownToggleShown={highlight}
|
|
|
|
currentSelectedOption={currentSelectedStatusOption}
|
|
|
|
options={this.statusOptions}
|
|
|
|
selectOption={this.changeStatus}
|
|
|
|
toggleItemFreezed={this.props.toggleItemFreezed}
|
2019-02-27 19:44:22 +08:00
|
|
|
/>
|
|
|
|
</td>
|
2020-09-24 16:53:55 +08:00
|
|
|
<td>{`${Utils.formatSize({bytes: user.quota_usage})} / ${this.getQuotaTotal(user.quota_total)}`}</td>
|
2020-04-27 14:46:41 +08:00
|
|
|
<td>
|
|
|
|
{user.ctime} /
|
|
|
|
<br />
|
|
|
|
{user.last_login ? user.last_login : '--'}
|
|
|
|
</td>
|
2019-02-27 19:44:22 +08:00
|
|
|
<td className="text-center cursor-pointer">
|
|
|
|
{isOperationMenuShow && (
|
|
|
|
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
|
|
|
<DropdownToggle
|
|
|
|
tag="a"
|
2019-03-11 10:34:40 +08:00
|
|
|
className="attr-action-icon fas fa-ellipsis-v"
|
2024-01-03 18:08:24 +08:00
|
|
|
title={gettext('More operations')}
|
|
|
|
aria-label={gettext('More operations')}
|
2019-02-27 19:44:22 +08:00
|
|
|
data-toggle="dropdown"
|
|
|
|
aria-expanded={this.state.isItemMenuShow}
|
|
|
|
onClick={this.onDropdownToggleClick}
|
|
|
|
/>
|
|
|
|
<DropdownMenu>
|
|
|
|
<DropdownItem onClick={this.toggleDelete}>{gettext('Delete')}</DropdownItem>
|
|
|
|
<DropdownItem onClick={this.toggleResetPW}>{gettext('ResetPwd')}</DropdownItem>
|
|
|
|
{currentTab == 'admins' && <DropdownItem onClick={this.toggleRevokeAdmin}>{gettext('Revoke Admin')}</DropdownItem>}
|
|
|
|
</DropdownMenu>
|
|
|
|
</Dropdown>
|
|
|
|
)}
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UserItem.propTypes = propTypes;
|
|
|
|
|
|
|
|
export default UserItem;
|