diff --git a/client/coral-admin/src/components/BanUserDialog.js b/client/coral-admin/src/components/BanUserDialog.js index b23d8f9d1..4f2296409 100644 --- a/client/coral-admin/src/components/BanUserDialog.js +++ b/client/coral-admin/src/components/BanUserDialog.js @@ -8,7 +8,14 @@ import I18n from 'coral-framework/modules/i18n/i18n'; import translations from '../translations'; const lang = new I18n(translations); -const BanUserDialog = ({open, handleClose, handleBanUser, user}) => ( +const onBanClick = (userId, commentId, handleBanUser, rejectComment, handleClose) => (e) => { + e.preventDefault(); + handleBanUser({userId}) + .then(handleClose) + .then(() => rejectComment({commentId})); +}; + +const BanUserDialog = ({open, handleClose, handleBanUser, rejectComment, user, commentId}) => ( ( - diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js index 2f43911b1..e53162992 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js @@ -21,12 +21,13 @@ import ModerationKeysModal from '../../components/ModerationKeysModal'; class ModerationContainer extends Component { state = { - selectedIndex: 0 + selectedIndex: 0, + sort: 'REVERSE_CHRONOLOGICAL' } componentWillMount() { const {toggleModal, singleView} = this.props; - + this.props.fetchSettings(); key('s', () => singleView()); key('shift+/', () => toggleModal(true)); @@ -74,6 +75,11 @@ class ModerationContainer extends Component { } } + selectSort = (sort) => { + this.setState({sort}); + this.props.modQueueResort(sort); + } + componentWillUnmount() { key.unbind('s'); key.unbind('shift+/'); @@ -92,7 +98,7 @@ class ModerationContainer extends Component { } render () { - const {data, moderation, settings, assets, modQueueResort, onClose, ...props} = this.props; + const {data, moderation, settings, assets, onClose, ...props} = this.props; const providedAssetId = this.props.params.id; const activeTab = this.props.route.path === ':id' ? 'premod' : this.props.route.path; @@ -115,6 +121,18 @@ class ModerationContainer extends Component { } const comments = data[activeTab]; + let activeTabCount; + switch(activeTab) { + case 'premod': + activeTabCount = data.premodCount; + break; + case 'flagged': + activeTabCount = data.flaggedCount; + break; + case 'rejected': + activeTabCount = data.rejectedCount; + break; + } return (
@@ -124,7 +142,8 @@ class ModerationContainer extends Component { premodCount={data.premodCount} rejectedCount={data.rejectedCount} flaggedCount={data.flaggedCount} - modQueueResort={modQueueResort} + selectSort={this.selectSort} + sort={this.state.sort} /> { +const ModerationQueue = ({comments, selectedIndex, commentCount, singleView, loadMore, activeTab, sort, ...props}) => { return (
    @@ -20,7 +21,7 @@ const ModerationQueue = ({comments, selectedIndex, singleView, ...props}) => { key={i} index={i} comment={comment} - commentType={props.activeTab} + commentType={activeTab} selected={i === selectedIndex} suspectWords={props.suspectWords} actions={actionsMap[status]} @@ -33,6 +34,14 @@ const ModerationQueue = ({comments, selectedIndex, singleView, ...props}) => { : {lang.t('modqueue.emptyqueue')} }
+
); }; diff --git a/client/coral-admin/src/containers/ModerationQueue/components/LoadMore.js b/client/coral-admin/src/containers/ModerationQueue/components/LoadMore.js new file mode 100644 index 000000000..f8d3f0ed4 --- /dev/null +++ b/client/coral-admin/src/containers/ModerationQueue/components/LoadMore.js @@ -0,0 +1,31 @@ +import React, {PropTypes} from 'react'; +import {Button} from 'coral-ui'; +import styles from './styles.css'; + +const LoadMore = ({comments, loadMore, sort, tab, assetId, showLoadMore}) => +
+ { + showLoadMore && + } +
; + +LoadMore.propTypes = { + comments: PropTypes.array.isRequired, + loadMore: PropTypes.func.isRequired, + sort: PropTypes.oneOf(['CHRONOLOGICAL', 'REVERSE_CHRONOLOGICAL']).isRequired, + tab: PropTypes.oneOf(['rejected', 'premod', 'flagged']).isRequired, + assetId: PropTypes.string, + showLoadMore: PropTypes.bool.isRequired +}; + +export default LoadMore; diff --git a/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js b/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js index f9b0c266f..b8160e21b 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js @@ -1,4 +1,4 @@ -import React, {PropTypes, Component} from 'react'; +import React, {PropTypes} from 'react'; import CommentCount from './CommentCount'; import styles from './styles.css'; import {SelectField, Option} from 'react-mdl-selectfield'; @@ -8,57 +8,45 @@ import {Link} from 'react-router'; const lang = new I18n(translations); -class ModerationMenu extends Component { - state = { - sort: 'REVERSE_CHRONOLOGICAL', - } - - static propTypes = { - premodCount: PropTypes.number.isRequired, - rejectedCount: PropTypes.number.isRequired, - flaggedCount: PropTypes.number.isRequired, - asset: PropTypes.shape({ - id: PropTypes.string - }) - } - - selectSort = (sort) => { - this.setState({sort}); - this.props.modQueueResort(sort); - } - - render() { - const {asset, premodCount, rejectedCount, flaggedCount} = this.props; - const premodPath = asset ? `/admin/moderate/premod/${asset.id}` : '/admin/moderate/premod'; - const rejectPath = asset ? `/admin/moderate/rejected/${asset.id}` : '/admin/moderate/rejected'; - const flagPath = asset ? `/admin/moderate/flagged/${asset.id}` : '/admin/moderate/flagged'; - return ( -
-
-
-
- - {lang.t('modqueue.premod')} - - - {lang.t('modqueue.rejected')} - - - {lang.t('modqueue.flagged')} - -
- this.selectSort(sort)}> - - - +const ModerationMenu = ({asset, premodCount, rejectedCount, flaggedCount, selectSort, sort}) => { + const premodPath = asset ? `/admin/moderate/premod/${asset.id}` : '/admin/moderate/premod'; + const rejectPath = asset ? `/admin/moderate/rejected/${asset.id}` : '/admin/moderate/rejected'; + const flagPath = asset ? `/admin/moderate/flagged/${asset.id}` : '/admin/moderate/flagged'; + return ( +
+
+
+
+ + {lang.t('modqueue.premod')} + + + {lang.t('modqueue.rejected')} + + + {lang.t('modqueue.flagged')} +
+ selectSort(sort)}> + + +
- ); - } -} +
+ ); +}; + +ModerationMenu.propTypes = { + premodCount: PropTypes.number.isRequired, + rejectedCount: PropTypes.number.isRequired, + flaggedCount: PropTypes.number.isRequired, + asset: PropTypes.shape({ + id: PropTypes.string + }) +}; export default ModerationMenu; diff --git a/client/coral-admin/src/containers/ModerationQueue/components/styles.css b/client/coral-admin/src/containers/ModerationQueue/components/styles.css index 627cde5e4..9576045de 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/styles.css +++ b/client/coral-admin/src/containers/ModerationQueue/components/styles.css @@ -394,3 +394,23 @@ span { cursor: pointer; } } + +.loadMoreContainer { + display: flex; + justify-content: center; + width: 100%; +}; + +.loadMore { + width: 100%; + text-align: center; + color: #FFF; + max-width: 660px; + margin-bottom: 30px; + background-color: #2376D8; + cursor: pointer; +} + +.loadMore:hover { + background-color: #4399FF; +} diff --git a/client/coral-admin/src/graphql/queries/index.js b/client/coral-admin/src/graphql/queries/index.js index c4a30ad44..13164bca2 100644 --- a/client/coral-admin/src/graphql/queries/index.js +++ b/client/coral-admin/src/graphql/queries/index.js @@ -1,6 +1,7 @@ import {graphql} from 'react-apollo'; import MOD_QUEUE_QUERY from './modQueueQuery.graphql'; +import MOD_QUEUE_LOAD_MORE from './loadMore.graphql'; import METRICS from './metricsQuery.graphql'; export const modQueueQuery = graphql(MOD_QUEUE_QUERY, { @@ -14,7 +15,8 @@ export const modQueueQuery = graphql(MOD_QUEUE_QUERY, { }, props: ({ownProps: {params: {id = null}}, data}) => ({ data, - modQueueResort: modQueueResort(id, data.fetchMore) + modQueueResort: modQueueResort(id, data.fetchMore), + loadMore: loadMore(data.fetchMore) }) }); @@ -30,6 +32,40 @@ export const getMetrics = graphql(METRICS, { } }); +export const loadMore = (fetchMore) => ({limit, cursor, sort, tab, asset_id}) => { + let statuses; + switch(tab) { + case 'premod': + statuses = ['PREMOD']; + break; + case 'flagged': + statuses = ['NONE', 'PREMOD']; + break; + case 'rejected': + statuses = ['REJECTED']; + break; + } + return fetchMore({ + query: MOD_QUEUE_LOAD_MORE, + variables: { + limit, + cursor, + sort, + statuses, + asset_id + }, + updateQuery: (oldData, {fetchMoreResult:{data:{comments}}}) => { + return { + ...oldData, + [tab]: [ + ...oldData[tab], + ...comments + ] + }; + } + }); +}; + export const modQueueResort = (id, fetchMore) => (sort) => { return fetchMore({ query: MOD_QUEUE_QUERY, diff --git a/client/coral-admin/src/graphql/queries/loadMore.graphql b/client/coral-admin/src/graphql/queries/loadMore.graphql new file mode 100644 index 000000000..56966a804 --- /dev/null +++ b/client/coral-admin/src/graphql/queries/loadMore.graphql @@ -0,0 +1,13 @@ +#import "../fragments/commentView.graphql" + +query LoadMoreModQueue($limit: Int = 10, $cursor: Date, $sort: SORT_ORDER, $asset_id: ID, $statuses:[COMMENT_STATUS!]) { + comments(query: {limit: $limit, cursor: $cursor, asset_id: $asset_id, statuses: $statuses, sort: $sort}) { + ...commentView + action_summaries { + count + ... on FlagActionSummary { + reason + } + } + } +}