diff --git a/client/coral-admin/src/actions/moderation.js b/client/coral-admin/src/actions/moderation.js index 1c803d87d..5136db4c3 100644 --- a/client/coral-admin/src/actions/moderation.js +++ b/client/coral-admin/src/actions/moderation.js @@ -15,33 +15,11 @@ export const hideShortcutsNote = () => { return {type: actions.HIDE_SHORTCUTS_NOTE}; }; -export const viewUserDetail = (userId) => ({type: actions.VIEW_USER_DETAIL, userId}); -export const hideUserDetail = () => ({type: actions.HIDE_USER_DETAIL}); - export const setSortOrder = (order) => ({ type: actions.SET_SORT_ORDER, order }); -export const changeUserDetailStatuses = (tab) => { - let statuses; - if (tab === 'all') { - statuses = ['NONE', 'ACCEPTED', 'REJECTED', 'PREMOD']; - } else if (tab === 'rejected') { - statuses = ['REJECTED']; - } - return {type: actions.CHANGE_USER_DETAIL_STATUSES, tab, statuses}; -}; - -export const clearUserDetailSelections = () => ({type: actions.CLEAR_USER_DETAIL_SELECTIONS}); - -export const toggleSelectCommentInUserDetail = (id, active) => { - return { - type: active ? actions.SELECT_USER_DETAIL_COMMENT : actions.UNSELECT_USER_DETAIL_COMMENT, - id - }; -}; - export const toggleStorySearch = (active) => ({ type: active ? actions.SHOW_STORY_SEARCH : actions.HIDE_STORY_SEARCH }); diff --git a/client/coral-admin/src/actions/userDetail.js b/client/coral-admin/src/actions/userDetail.js new file mode 100644 index 000000000..f6d0d563e --- /dev/null +++ b/client/coral-admin/src/actions/userDetail.js @@ -0,0 +1,24 @@ +import * as actions from 'constants/moderation'; + +export const viewUserDetail = (userId) => ({type: actions.VIEW_USER_DETAIL, userId}); +export const hideUserDetail = () => ({type: actions.HIDE_USER_DETAIL}); + +export const changeUserDetailStatuses = (tab) => { + let statuses; + if (tab === 'all') { + statuses = ['NONE', 'ACCEPTED', 'REJECTED', 'PREMOD']; + } else if (tab === 'rejected') { + statuses = ['REJECTED']; + } + return {type: actions.CHANGE_USER_DETAIL_STATUSES, tab, statuses}; +}; + +export const clearUserDetailSelections = () => ({type: actions.CLEAR_USER_DETAIL_SELECTIONS}); + +export const toggleSelectCommentInUserDetail = (id, active) => { + return { + type: active ? actions.SELECT_USER_DETAIL_COMMENT : actions.UNSELECT_USER_DETAIL_COMMENT, + id + }; +}; + diff --git a/client/coral-admin/src/components/ActionButton.js b/client/coral-admin/src/components/ActionButton.js index e084d8e7a..3dbac206b 100644 --- a/client/coral-admin/src/components/ActionButton.js +++ b/client/coral-admin/src/components/ActionButton.js @@ -1,7 +1,7 @@ import React, {PropTypes} from 'react'; import styles from './ModerationList.css'; import {Button} from 'coral-ui'; -import {menuActionsMap} from '../routes/Moderation/helpers/moderationQueueActionsMap'; +import {menuActionsMap} from '../utils/moderationQueueActionsMap'; import t from 'coral-framework/services/i18n'; diff --git a/client/coral-admin/src/routes/Moderation/components/ButtonCopyToClipboard.js b/client/coral-admin/src/components/ButtonCopyToClipboard.js similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/ButtonCopyToClipboard.js rename to client/coral-admin/src/components/ButtonCopyToClipboard.js diff --git a/client/coral-admin/src/components/CommentAnimatedEdit.css b/client/coral-admin/src/components/CommentAnimatedEdit.css new file mode 100644 index 000000000..83be36c11 --- /dev/null +++ b/client/coral-admin/src/components/CommentAnimatedEdit.css @@ -0,0 +1,24 @@ +.bodyLeave { + position: absolute; + width: 100%; + top: 0; + background-color: white; + opacity: 1.0; + transition: background 400ms, opacity 800ms 1600ms; + pointer-events: none; +} + +.bodyLeaveActive { + opacity: 0; + background-color: rgba(255,255,0, 0.2); +} + +.bodyEnter { + opacity: 0; + pointer-events: none; +} + +.bodyEnterActive { + opacity: 1.0; + transition: opacity 800ms 2400ms; +} diff --git a/client/coral-admin/src/routes/Moderation/components/CommentAnimatedEdit.js b/client/coral-admin/src/components/CommentAnimatedEdit.js similarity index 93% rename from client/coral-admin/src/routes/Moderation/components/CommentAnimatedEdit.js rename to client/coral-admin/src/components/CommentAnimatedEdit.js index d8ffa5339..141dc12cc 100644 --- a/client/coral-admin/src/routes/Moderation/components/CommentAnimatedEdit.js +++ b/client/coral-admin/src/components/CommentAnimatedEdit.js @@ -1,7 +1,7 @@ import React from 'react'; import {murmur3} from 'murmurhash-js'; import {CSSTransitionGroup} from 'react-transition-group'; -import styles from './styles.css'; +import styles from './CommentAnimatedEdit.css'; export default ({children, body}) => { return ( diff --git a/client/coral-admin/src/routes/Moderation/components/CommentType.css b/client/coral-admin/src/components/CommentType.css similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/CommentType.css rename to client/coral-admin/src/components/CommentType.css diff --git a/client/coral-admin/src/routes/Moderation/components/CommentType.js b/client/coral-admin/src/components/CommentType.js similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/CommentType.js rename to client/coral-admin/src/components/CommentType.js diff --git a/client/coral-admin/src/routes/Moderation/components/FlagBox.css b/client/coral-admin/src/components/FlagBox.css similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/FlagBox.css rename to client/coral-admin/src/components/FlagBox.css diff --git a/client/coral-admin/src/routes/Moderation/components/FlagBox.js b/client/coral-admin/src/components/FlagBox.js similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/FlagBox.js rename to client/coral-admin/src/components/FlagBox.js diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.css b/client/coral-admin/src/components/UserDetail.css similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/UserDetail.css rename to client/coral-admin/src/components/UserDetail.css diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.js b/client/coral-admin/src/components/UserDetail.js similarity index 91% rename from client/coral-admin/src/routes/Moderation/components/UserDetail.js rename to client/coral-admin/src/components/UserDetail.js index 2a4ecf28e..a7051b0ec 100644 --- a/client/coral-admin/src/routes/Moderation/components/UserDetail.js +++ b/client/coral-admin/src/components/UserDetail.js @@ -1,10 +1,10 @@ import React, {PropTypes} from 'react'; import Comment from './UserDetailComment'; import styles from './UserDetail.css'; -import {Button, Drawer} from 'coral-ui'; +import {Button, Drawer, Spinner} from 'coral-ui'; import {Slot} from 'coral-framework/components'; import ButtonCopyToClipboard from './ButtonCopyToClipboard'; -import {actionsMap} from '../helpers/moderationQueueActionsMap'; +import {actionsMap} from '../utils/moderationQueueActionsMap'; import ClickOutside from 'coral-framework/components/ClickOutside'; export default class UserDetail extends React.Component { @@ -43,7 +43,17 @@ export default class UserDetail extends React.Component { this.props.changeStatus('rejected'); } - render () { + renderLoading() { + return ( + + + + + + ); + } + + renderLoaded() { const { root: { user, @@ -61,6 +71,7 @@ export default class UserDetail extends React.Component { hideUserDetail, viewUserDetail, } = this.props; + const localProfile = user.profiles.find((p) => p.provider === 'local'); let profile; @@ -160,4 +171,11 @@ export default class UserDetail extends React.Component { ); } + + render () { + if (this.props.loading) { + return this.renderLoading(); + } + return this.renderLoaded(); + } } diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetailComment.css b/client/coral-admin/src/components/UserDetailComment.css similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/UserDetailComment.css rename to client/coral-admin/src/components/UserDetailComment.css diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetailComment.js b/client/coral-admin/src/components/UserDetailComment.js similarity index 100% rename from client/coral-admin/src/routes/Moderation/components/UserDetailComment.js rename to client/coral-admin/src/components/UserDetailComment.js diff --git a/client/coral-admin/src/constants/userDetail.js b/client/coral-admin/src/constants/userDetail.js new file mode 100644 index 000000000..b68efb5ea --- /dev/null +++ b/client/coral-admin/src/constants/userDetail.js @@ -0,0 +1,7 @@ +export const VIEW_USER_DETAIL = 'VIEW_USER_DETAIL'; +export const HIDE_USER_DETAIL = 'HIDE_USER_DETAIL'; +export const CHANGE_USER_DETAIL_STATUSES = 'CHANGE_USER_DETAIL_STATUSES'; +export const SELECT_USER_DETAIL_COMMENT = 'SELECT_USER_DETAIL_COMMENT'; +export const UNSELECT_USER_DETAIL_COMMENT = 'UNSELECT_USER_DETAIL_COMMENT'; +export const CLEAR_USER_DETAIL_SELECTIONS = 'CLEAR_USER_DETAIL_SELECTIONS'; + diff --git a/client/coral-admin/src/containers/Layout.js b/client/coral-admin/src/containers/Layout.js index dacf768c0..8b119fb72 100644 --- a/client/coral-admin/src/containers/Layout.js +++ b/client/coral-admin/src/containers/Layout.js @@ -10,6 +10,7 @@ import SuspendUserDialog from './SuspendUserDialog'; import {toggleModal as toggleShortcutModal} from '../actions/moderation'; import {checkLogin, handleLogin, requestPasswordReset} from '../actions/auth'; import {can} from 'coral-framework/services/perms'; +import UserDetail from 'coral-admin/src/containers/UserDetail'; class LayoutContainer extends Component { componentWillMount() { @@ -57,6 +58,7 @@ class LayoutContainer extends Component { > + {this.props.children} ); diff --git a/client/coral-admin/src/containers/UserDetail.js b/client/coral-admin/src/containers/UserDetail.js index 6b476b861..84a7bc3be 100644 --- a/client/coral-admin/src/containers/UserDetail.js +++ b/client/coral-admin/src/containers/UserDetail.js @@ -1,4 +1,4 @@ -import React, {PropTypes} from 'react'; +import React from 'react'; import {compose, gql} from 'react-apollo'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; @@ -6,23 +6,25 @@ import UserDetail from '../components/UserDetail'; import withQuery from 'coral-framework/hocs/withQuery'; import {getDefinitionName, getSlotFragmentSpreads} from 'coral-framework/utils'; import { + viewUserDetail, + hideUserDetail, changeUserDetailStatuses, clearUserDetailSelections, - toggleSelectCommentInUserDetail -} from 'coral-admin/src/actions/moderation'; + toggleSelectCommentInUserDetail, +} from 'coral-admin/src/actions/userDetail'; import {withSetCommentStatus} from 'coral-framework/graphql/mutations'; -import Comment from './Comment'; +import UserDetailComment from './UserDetailComment'; const commentConnectionFragment = gql` fragment CoralAdmin_Moderation_CommentConnection on CommentConnection { nodes { - ...${getDefinitionName(Comment.fragments.comment)} + ...${getDefinitionName(UserDetailComment.fragments.comment)} } hasNextPage startCursor endCursor } - ${Comment.fragments.comment} + ${UserDetailComment.fragments.comment} `; const slots = [ @@ -30,14 +32,10 @@ const slots = [ ]; class UserDetailContainer extends React.Component { - static propTypes = { - id: PropTypes.string.isRequired, - hideUserDetail: PropTypes.func.isRequired - } // status can be 'ACCEPTED' or 'REJECTED' bulkSetCommentStatus = (status) => { - const changes = this.props.moderation.userDetailSelectedIds.map((commentId) => { + const changes = this.props.selectedIds.map((commentId) => { return this.props.setCommentStatus({commentId, status}); }); @@ -55,16 +53,29 @@ class UserDetailContainer extends React.Component { this.bulkSetCommentStatus('ACCEPTED'); } + acceptComment = ({commentId}) => { + return this.props.setCommentStatus({commentId, status: 'ACCEPTED'}); + } + + rejectComment = ({commentId}) => { + return this.props.setCommentStatus({commentId, status: 'REJECTED'}); + } + render () { - if (!('user' in this.props.root)) { + if (!this.props.id) { return null; } + const loading = !('user' in this.props.root) || this.props.root.user.id !== this.props.id; + return ; } } @@ -93,22 +104,30 @@ export const withUserDetailQuery = withQuery(gql` } ${commentConnectionFragment} `, { - options: ({id, moderation: {userDetailStatuses: statuses}}) => { + options: ({id, statuses}) => { return { variables: {author_id: id, statuses} }; - } + }, + skip: (ownProps) => !ownProps.id, }); const mapStateToProps = (state) => ({ - moderation: state.moderation.toJS() + id: state.userDetail.userDetailId, + selectedIds: state.userDetail.userDetailSelectedIds, + statuses: state.userDetail.userDetailStatuses, + activeTab: state.userDetail.userDetailActiveTab, + bannedWords: state.settings.toJS().wordlist.banned, + suspectWords: state.settings.toJS().wordlist.suspect, }); const mapDispatchToProps = (dispatch) => ({ ...bindActionCreators({ changeUserDetailStatuses, clearUserDetailSelections, - toggleSelectCommentInUserDetail + toggleSelectCommentInUserDetail, + viewUserDetail, + hideUserDetail, }, dispatch) }); diff --git a/client/coral-admin/src/routes/Moderation/containers/UserDetailComment.js b/client/coral-admin/src/containers/UserDetailComment.js similarity index 100% rename from client/coral-admin/src/routes/Moderation/containers/UserDetailComment.js rename to client/coral-admin/src/containers/UserDetailComment.js diff --git a/client/coral-admin/src/reducers/index.js b/client/coral-admin/src/reducers/index.js index f94b50817..b329675a4 100644 --- a/client/coral-admin/src/reducers/index.js +++ b/client/coral-admin/src/reducers/index.js @@ -7,11 +7,13 @@ import install from './install'; import config from './config'; import banUserDialog from './banUserDialog'; import suspendUserDialog from './suspendUserDialog'; +import userDetail from './userDetail'; export default { auth, banUserDialog, suspendUserDialog, + userDetail, assets, settings, community, diff --git a/client/coral-admin/src/reducers/moderation.js b/client/coral-admin/src/reducers/moderation.js index a2c8975ff..a0cba1f5f 100644 --- a/client/coral-admin/src/reducers/moderation.js +++ b/client/coral-admin/src/reducers/moderation.js @@ -1,13 +1,9 @@ -import {fromJS, Set} from 'immutable'; +import {fromJS} from 'immutable'; import * as actions from '../constants/moderation'; const initialState = fromJS({ singleView: false, modalOpen: false, - userDetailId: null, - userDetailActiveTab: 'all', - userDetailStatuses: ['NONE', 'ACCEPTED', 'REJECTED', 'PREMOD'], - userDetailSelectedIds: new Set(), storySearchVisible: false, storySearchString: '', shortcutsNoteVisible: window.localStorage.getItem('coral:shortcutsNote') || 'show', @@ -18,9 +14,6 @@ export default function moderation (state = initialState, action) { switch (action.type) { case actions.MODERATION_CLEAR_STATE: return initialState; - case actions.SET_ACTIVE_TAB: - return state - .set('activeTab', action.activeTab); case actions.TOGGLE_MODAL: return state .set('modalOpen', action.open); @@ -30,22 +23,6 @@ export default function moderation (state = initialState, action) { case actions.HIDE_SHORTCUTS_NOTE: return state .set('shortcutsNoteVisible', 'hide'); - case actions.VIEW_USER_DETAIL: - return state.set('userDetailId', action.userId); - case actions.HIDE_USER_DETAIL: - return state - .set('userDetailId', null) - .update('userDetailSelectedIds', (set) => set.clear()); - case actions.CLEAR_USER_DETAIL_SELECTIONS: - return state.update('userDetailSelectedIds', (set) => set.clear()); - case actions.CHANGE_USER_DETAIL_STATUSES: - return state - .set('userDetailActiveTab', action.tab) - .set('userDetailStatuses', action.statuses); - case actions.SELECT_USER_DETAIL_COMMENT: - return state.update('userDetailSelectedIds', (set) => set.add(action.id)); - case actions.UNSELECT_USER_DETAIL_COMMENT: - return state.update('userDetailSelectedIds', (set) => set.delete(action.id)); case actions.SHOW_STORY_SEARCH: return state.set('storySearchVisible', true); case actions.HIDE_STORY_SEARCH: diff --git a/client/coral-admin/src/reducers/userDetail.js b/client/coral-admin/src/reducers/userDetail.js new file mode 100644 index 000000000..bb7bed441 --- /dev/null +++ b/client/coral-admin/src/reducers/userDetail.js @@ -0,0 +1,47 @@ +import * as actions from '../constants/userDetail'; + +const initialState = { + userDetailId: null, + userDetailActiveTab: 'all', + userDetailStatuses: ['NONE', 'ACCEPTED', 'REJECTED', 'PREMOD'], + userDetailSelectedIds: [], +}; + +export default function banUserDialog(state = initialState, action) { + switch (action.type) { + case actions.VIEW_USER_DETAIL: + return { + ...state, + userDetailId: action.userId, + }; + case actions.HIDE_USER_DETAIL: + return { + ...state, + userDetailId: null, + userDetailSelectedIds: [], + }; + case actions.CLEAR_USER_DETAIL_SELECTIONS: + return { + ...state, + userDetailSelectedIds: [], + }; + case actions.CHANGE_USER_DETAIL_STATUSES: + return { + ...state, + userDetailActiveTab: action.tab, + userDetailStatuses: action.statuses, + }; + case actions.SELECT_USER_DETAIL_COMMENT: + return { + ...state, + userDetailSelectedIds: [...state.userDetailSelectedIds, action.id], + }; + case actions.UNSELECT_USER_DETAIL_COMMENT: + return { + ...state, + userDetailSelectedIds: state.userDetailSelectedIds.filter((id) => id !== action.id), + }; + default: + return state; + } +} diff --git a/client/coral-admin/src/routes/Community/components/ActionButton.js b/client/coral-admin/src/routes/Community/components/ActionButton.js index b0b68b063..09af420f6 100644 --- a/client/coral-admin/src/routes/Community/components/ActionButton.js +++ b/client/coral-admin/src/routes/Community/components/ActionButton.js @@ -1,7 +1,7 @@ import React from 'react'; import styles from './Community.css'; import {Button} from 'coral-ui'; -import {menuActionsMap} from '../../Moderation/helpers/moderationQueueActionsMap'; +import {menuActionsMap} from '../../../utils/moderationQueueActionsMap'; import t from 'coral-framework/services/i18n'; diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index 07e168ab7..e37fa887c 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -2,10 +2,10 @@ import React, {PropTypes} from 'react'; import {Link} from 'react-router'; import {Icon} from 'coral-ui'; -import FlagBox from './FlagBox'; +import FlagBox from 'coral-admin/src/components/FlagBox'; import styles from './styles.css'; -import CommentType from './CommentType'; -import CommentAnimatedEdit from './CommentAnimatedEdit'; +import CommentType from 'coral-admin/src/components/CommentType'; +import CommentAnimatedEdit from 'coral-admin/src/components/CommentAnimatedEdit'; import Slot from 'coral-framework/components/Slot'; import {getActionSummary} from 'coral-framework/utils'; import ActionButton from 'coral-admin/src/components/ActionButton'; diff --git a/client/coral-admin/src/routes/Moderation/components/Moderation.js b/client/coral-admin/src/routes/Moderation/components/Moderation.js index 75f613cc9..d9822724d 100644 --- a/client/coral-admin/src/routes/Moderation/components/Moderation.js +++ b/client/coral-admin/src/routes/Moderation/components/Moderation.js @@ -6,7 +6,6 @@ import ModerationQueue from './ModerationQueue'; import ModerationMenu from './ModerationMenu'; import ModerationHeader from './ModerationHeader'; import ModerationKeysModal from '../../../components/ModerationKeysModal'; -import UserDetail from '../containers/UserDetail'; import StorySearch from '../containers/StorySearch'; export default class Moderation extends Component { @@ -173,12 +172,6 @@ export default class Moderation extends Component { open={moderation.modalOpen} onClose={this.onClose}/> - {moderation.userDetailId && ( - - )} - ({ toggleStorySearch, showSuspendUserDialog, viewUserDetail, - hideUserDetail, setSortOrder, storySearchChange, clearState diff --git a/client/coral-admin/src/routes/Moderation/containers/UserDetail.js b/client/coral-admin/src/routes/Moderation/containers/UserDetail.js deleted file mode 100644 index 16f0916d3..000000000 --- a/client/coral-admin/src/routes/Moderation/containers/UserDetail.js +++ /dev/null @@ -1,135 +0,0 @@ -import React, {PropTypes} from 'react'; -import {compose, gql} from 'react-apollo'; -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import UserDetail from '../components/UserDetail'; -import withQuery from 'coral-framework/hocs/withQuery'; -import {getDefinitionName, getSlotFragmentSpreads} from 'coral-framework/utils'; -import {viewUserDetail, hideUserDetail} from 'actions/moderation'; -import { - changeUserDetailStatuses, - clearUserDetailSelections, - toggleSelectCommentInUserDetail, -} from 'coral-admin/src/actions/moderation'; -import {withSetCommentStatus} from 'coral-framework/graphql/mutations'; -import UserDetailComment from './UserDetailComment'; - -const commentConnectionFragment = gql` - fragment CoralAdmin_Moderation_CommentConnection on CommentConnection { - nodes { - ...${getDefinitionName(UserDetailComment.fragments.comment)} - } - hasNextPage - startCursor - endCursor - } - ${UserDetailComment.fragments.comment} -`; - -const slots = [ - 'userProfile', -]; - -class UserDetailContainer extends React.Component { - static propTypes = { - id: PropTypes.string.isRequired, - } - - // status can be 'ACCEPTED' or 'REJECTED' - bulkSetCommentStatus = (status) => { - const changes = this.props.selectedIds.map((commentId) => { - return this.props.setCommentStatus({commentId, status}); - }); - - Promise.all(changes).then(() => { - this.props.data.refetch(); // some comments may have moved out of this tab - this.props.clearUserDetailSelections(); // un-select everything - }); - } - - bulkReject = () => { - this.bulkSetCommentStatus('REJECTED'); - } - - bulkAccept = () => { - this.bulkSetCommentStatus('ACCEPTED'); - } - - acceptComment = ({commentId}) => { - return this.props.setCommentStatus({commentId, status: 'ACCEPTED'}); - } - - rejectComment = ({commentId}) => { - return this.props.setCommentStatus({commentId, status: 'REJECTED'}); - } - - render () { - if (!('user' in this.props.root)) { - return null; - } - - return ; - } -} - -export const withUserDetailQuery = withQuery(gql` - query CoralAdmin_UserDetail($author_id: ID!, $statuses: [COMMENT_STATUS!]) { - user(id: $author_id) { - id - username - created_at - profiles { - id - provider - } - ${getSlotFragmentSpreads(slots, 'user')} - } - totalComments: commentCount(query: {author_id: $author_id}) - rejectedComments: commentCount(query: {author_id: $author_id, statuses: [REJECTED]}) - comments: comments(query: { - author_id: $author_id, - statuses: $statuses - }) { - ...CoralAdmin_Moderation_CommentConnection - } - ${getSlotFragmentSpreads(slots, 'root')} - } - ${commentConnectionFragment} -`, { - options: ({id, statuses}) => { - return { - variables: {author_id: id, statuses} - }; - } -}); - -const mapStateToProps = (state) => ({ - selectedIds: state.moderation.toJS().userDetailSelectedIds, - statuses: state.moderation.toJS().userDetailStatuses, - activeTab: state.moderation.toJS().userDetailActiveTab, - bannedWords: state.settings.toJS().wordlist.banned, - suspectWords: state.settings.toJS().wordlist.suspect, -}); - -const mapDispatchToProps = (dispatch) => ({ - ...bindActionCreators({ - changeUserDetailStatuses, - clearUserDetailSelections, - toggleSelectCommentInUserDetail, - viewUserDetail, - hideUserDetail, - }, dispatch) -}); - -export default compose( - connect(mapStateToProps, mapDispatchToProps), - withUserDetailQuery, - withSetCommentStatus, -)(UserDetailContainer); diff --git a/client/coral-admin/src/routes/Moderation/helpers/moderationQueueActionsMap.js b/client/coral-admin/src/utils/moderationQueueActionsMap.js similarity index 100% rename from client/coral-admin/src/routes/Moderation/helpers/moderationQueueActionsMap.js rename to client/coral-admin/src/utils/moderationQueueActionsMap.js