import React from 'react'; import cn from 'classnames'; import PropTypes from 'prop-types'; import capitalize from 'lodash/capitalize'; import styles from './UserDetail.css'; import UserHistory from './UserHistory'; import { Slot } from 'coral-framework/components'; import UserDetailCommentList from '../components/UserDetailCommentList'; import { isSuspended, isUsernameRejected, isUsernameChanged, isBanned, getKarma, } from 'coral-framework/utils/user'; import ButtonCopyToClipboard from './ButtonCopyToClipboard'; import ClickOutside from 'coral-framework/components/ClickOutside'; import { Icon, Drawer, Spinner, TabBar, Tab, TabContent, TabPane, } from 'coral-ui'; import ActionsMenu from 'coral-admin/src/components/ActionsMenu'; import ActionsMenuItem from 'coral-admin/src/components/ActionsMenuItem'; import UserInfoTooltip from './UserInfoTooltip'; import KarmaTooltip from './KarmaTooltip'; import t from 'coral-framework/services/i18n'; import { humanizeNumber } from 'coral-framework/helpers/numbers'; /** * getUserStatusArray * returns an array of active status(es) * i.e if suspension is active, it returns suspension */ function getUserStatusArray(user) { const statusMap = { suspended: isSuspended, banned: isBanned, usernameRejected: isUsernameRejected, usernameChanged: isUsernameChanged, }; return Object.keys(statusMap).filter(k => statusMap[k](user)); } class UserDetail extends React.Component { changeTab = tab => { this.props.changeTab(tab); }; showSuspenUserDialog = () => this.props.showSuspendUserDialog({ userId: this.props.root.user.id, username: this.props.root.user.username, }); showBanUserDialog = () => this.props.showBanUserDialog({ userId: this.props.root.user.id, username: this.props.root.user.username, }); showRejectUsernameDialog = () => this.props.showRejectUsernameDialog({ userId: this.props.root.user.id, username: this.props.root.user.username, }); renderLoading() { return ( ); } renderError() { return ( {this.props.data.error.message} ); } getActionMenuLabel(user) { const userStatusArr = getUserStatusArray(user); const count = userStatusArr.length; if (count > 1) { return `Status (${count})`; } else { const activeStatus = userStatusArr[0]; switch (activeStatus) { case 'suspended': return t('user_detail.suspended'); case 'banned': return t('user_detail.banned'); case 'usernameRejected': return ( {t('user_detail.username')} {` `} ); case 'usernameChanged': return ( {t('user_detail.username')} {` `} ); default: return activeStatus; } } } goToReportedUsernames = () => { const { router } = this.props; router.push('/admin/community/flagged'); }; renderLoaded() { const { root, root: { me, user, totalComments, rejectedComments, settings: { karmaThresholds }, }, activeTab, selectedCommentIds, toggleSelect, hideUserDetail, viewUserDetail, loadMore, toggleSelectAll, unbanUser, unsuspendUser, modal, acceptComment, rejectComment, bulkAccept, bulkReject, } = this.props; // if totalComments is 0, you're dividing by zero let rejectedPercent = rejectedComments / totalComments * 100; if (rejectedPercent === Infinity || isNaN(rejectedPercent)) { rejectedPercent = 0; } const banned = isBanned(user); const suspended = isSuspended(user); const usernameRejected = isUsernameRejected(user); const usernameChanged = isUsernameChanged(user); const slotPassthrough = { root, user, }; return ( {user.username} {user.id && ( {suspended ? ( unsuspendUser({ id: user.id })}> {t('user_detail.remove_suspension')} ) : ( {t('user_detail.suspend')} )} {banned ? ( unbanUser({ id: user.id })}> {t('user_detail.remove_ban')} ) : ( {t('user_detail.ban')} )} {usernameChanged && ( {t('user_detail.username_needs_approval')} {` `} )} {usernameRejected && !usernameChanged ? ( {t('user_detail.username_rejected')} ) : ( {t('user_detail.reject_username')} )} )} {(banned || suspended) && ( )} {t('user_detail.member_since')}: {new Date(user.created_at).toLocaleString()} {t('user_detail.email')}: {user.email}{' '} {user.profiles.map(({ provider, id }) => ( {capitalize(provider)} {t('user_detail.id')}: {id}{' '} ))} {t('user_detail.total_comments')} {totalComments} {t('user_detail.reject_rate')} {rejectedPercent.toFixed(1)}% {t('user_detail.karma')} {humanizeNumber(user.reliable.commenterKarma)} {t('user_detail.all')} {t('user_detail.rejected')} {t('user_detail.user_history')} ); } render() { if (this.props.data.error) { return this.renderError(); } if (this.props.loading) { return this.renderLoading(); } return this.renderLoaded(); } } UserDetail.propTypes = { router: PropTypes.object.isRequired, userId: PropTypes.string.isRequired, hideUserDetail: PropTypes.func.isRequired, root: PropTypes.object.isRequired, acceptComment: PropTypes.func.isRequired, rejectComment: PropTypes.func.isRequired, changeTab: PropTypes.func.isRequired, toggleSelect: PropTypes.func.isRequired, bulkAccept: PropTypes.func.isRequired, bulkReject: PropTypes.func.isRequired, toggleSelectAll: PropTypes.func.isRequired, loading: PropTypes.bool.isRequired, data: PropTypes.object, activeTab: PropTypes.string.isRequired, selectedCommentIds: PropTypes.array.isRequired, viewUserDetail: PropTypes.any.isRequired, loadMore: PropTypes.any.isRequired, showRejectUsernameDialog: PropTypes.func, showSuspendUserDialog: PropTypes.func, showBanUserDialog: PropTypes.func, unbanUser: PropTypes.func.isRequired, unsuspendUser: PropTypes.func.isRequired, modal: PropTypes.bool, rejectUsername: PropTypes.func.isRequired, }; export default UserDetail;