diff --git a/client/coral-admin/src/components/ActionButton.js b/client/coral-admin/src/components/ActionButton.js index ae75b829e..3651ee939 100644 --- a/client/coral-admin/src/components/ActionButton.js +++ b/client/coral-admin/src/components/ActionButton.js @@ -3,9 +3,8 @@ import styles from './ModerationList.css'; import {Button} from 'coral-ui'; import {menuActionsMap} from '../containers/ModerationQueue/helpers/moderationQueueActionsMap'; -const ActionButton = ({type = '', status, ...props}) => { +const ActionButton = ({type = '', active, ...props}) => { const typeName = type.toLowerCase(); - const active = ((type === 'REJECT' && status === 'REJECTED') || (type === 'APPROVE' && status === 'ACCEPTED')); let text = menuActionsMap[type].text; if (text === 'Approve' && active) { @@ -25,7 +24,7 @@ const ActionButton = ({type = '', status, ...props}) => { }; ActionButton.propTypes = { - status: PropTypes.string + active: PropTypes.bool }; export default ActionButton; diff --git a/client/coral-admin/src/containers/Dashboard/FlagWidget.js b/client/coral-admin/src/containers/Dashboard/FlagWidget.js index 92de6c4d2..ea72cddc6 100644 --- a/client/coral-admin/src/containers/Dashboard/FlagWidget.js +++ b/client/coral-admin/src/containers/Dashboard/FlagWidget.js @@ -21,7 +21,7 @@ const FlagWidget = ({assets}) => { ? assets.map(asset => { let flagSummary = null; if (asset.action_summaries) { - flagSummary = asset.action_summaries.find(s => s.type === 'FlagAssetActionSummary'); + flagSummary = asset.action_summaries.find(s => s.__typename === 'FlagAssetActionSummary'); } return ( diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js index eb59f369e..7a3aab909 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js @@ -5,7 +5,7 @@ import key from 'keymaster'; import isEqual from 'lodash/isEqual'; import styles from './components/styles.css'; -import {modQueueQuery} from '../../graphql/queries'; +import {modQueueQuery, getQueueCounts} from '../../graphql/queries'; import {banUser, setCommentStatus} from '../../graphql/mutations'; import {fetchSettings} from 'actions/settings'; @@ -220,6 +220,7 @@ const mapDispatchToProps = dispatch => ({ export default compose( connect(mapStateToProps, mapDispatchToProps), setCommentStatus, + getQueueCounts, modQueueQuery, banUser )(ModerationContainer); diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js index f986b947b..c4bf0f85c 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js @@ -9,51 +9,67 @@ import translations from 'coral-admin/src/translations'; import LoadMore from './components/LoadMore'; const lang = new I18n(translations); -const ModerationQueue = ({comments, selectedIndex, commentCount, singleView, loadMore, activeTab, sort, ...props}) => { - return ( -
- - -
- ); -}; +class ModerationQueue extends React.Component { -ModerationQueue.propTypes = { - bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired, - suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired, - currentAsset: PropTypes.object, - showBanUserDialog: PropTypes.func.isRequired, - rejectComment: PropTypes.func.isRequired, - acceptComment: PropTypes.func.isRequired, - comments: PropTypes.array.isRequired -}; + static propTypes = { + bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired, + suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired, + currentAsset: PropTypes.object, + showBanUserDialog: PropTypes.func.isRequired, + rejectComment: PropTypes.func.isRequired, + acceptComment: PropTypes.func.isRequired, + comments: PropTypes.array.isRequired + } + + componentDidUpdate (prev) { + const {loadMore, comments, commentCount, sort, activeTab: tab, assetId: asset_id} = this.props; + + // if the user just moderated the last (visible) comment + // AND there are more comments available on the server, + // go ahead and load more comments + if (prev.comments.length > 0 && comments.length === 0 && commentCount > 0) { + loadMore({sort, tab, asset_id}); + } + } + + render () { + const {comments, selectedIndex, commentCount, singleView, loadMore, activeTab, sort, ...props} = this.props; + + return ( +
+ + +
+ ); + } +} export default ModerationQueue; diff --git a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js index 0fdf435bd..e5afd9726 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js @@ -66,15 +66,17 @@ const Comment = ({actions = [], comment, ...props}) => {
{links ? Contains Link : null}
- {actions.map((action, i) => - props.acceptComment({commentId: comment.id})} - rejectComment={() => props.rejectComment({commentId: comment.id})} - /> - )} + {actions.map((action, i) => { + const active = (action === 'REJECT' && comment.status === 'REJECTED') || + (action === 'APPROVE' && comment.status === 'ACCEPTED'); + return props.acceptComment({commentId: comment.id})} + rejectComment={() => props.rejectComment({commentId: comment.id})} />; + })}
diff --git a/client/coral-admin/src/containers/ModerationQueue/components/LoadMore.js b/client/coral-admin/src/containers/ModerationQueue/components/LoadMore.js index f16635486..c90d3cd14 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/LoadMore.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/LoadMore.js @@ -7,13 +7,16 @@ const LoadMore = ({comments, loadMore, sort, tab, assetId, showLoadMore}) => { showLoadMore && } diff --git a/client/coral-admin/src/graphql/fragments/assetMetricsView.graphql b/client/coral-admin/src/graphql/fragments/assetMetricsView.graphql index c77fbc32b..726194143 100644 --- a/client/coral-admin/src/graphql/fragments/assetMetricsView.graphql +++ b/client/coral-admin/src/graphql/fragments/assetMetricsView.graphql @@ -6,7 +6,6 @@ fragment metrics on Asset { created_at commentCount action_summaries { - type: __typename actionCount actionableItemCount } diff --git a/client/coral-admin/src/graphql/mutations/index.js b/client/coral-admin/src/graphql/mutations/index.js index 4d62201d1..6b21c8421 100644 --- a/client/coral-admin/src/graphql/mutations/index.js +++ b/client/coral-admin/src/graphql/mutations/index.js @@ -44,6 +44,7 @@ export const suspendUser = graphql(SUSPEND_USER, { }) }); +const views = ['all', 'premod', 'flagged', 'accepted', 'rejected']; export const setCommentStatus = graphql(SET_COMMENT_STATUS, { props: ({mutate}) => ({ acceptComment: ({commentId}) => { @@ -54,7 +55,9 @@ export const setCommentStatus = graphql(SET_COMMENT_STATUS, { }, updateQueries: { ModQueue: (oldData) => { - const comment = oldData.all.find(c => c.id === commentId); + const comment = views.reduce((comment, view) => { + return comment ? comment : oldData[view].find(c => c.id === commentId); + }, null); let accepted; let acceptedCount = oldData.acceptedCount; @@ -76,10 +79,10 @@ export const setCommentStatus = graphql(SET_COMMENT_STATUS, { return { ...oldData, - premodCount, - flaggedCount, - acceptedCount, - rejectedCount, + premodCount: Math.max(0, premodCount), + flaggedCount: Math.max(0, flaggedCount), + acceptedCount: Math.max(0, acceptedCount), + rejectedCount: Math.max(0, rejectedCount), premod, flagged, accepted, @@ -97,7 +100,9 @@ export const setCommentStatus = graphql(SET_COMMENT_STATUS, { }, updateQueries: { ModQueue: (oldData) => { - const comment = oldData.all.find(c => c.id === commentId); + const comment = views.reduce((comment, view) => { + return comment ? comment : oldData[view].find(c => c.id === commentId); + }, null); let rejected; let rejectedCount = oldData.rejectedCount; @@ -119,10 +124,10 @@ export const setCommentStatus = graphql(SET_COMMENT_STATUS, { return { ...oldData, - premodCount, - flaggedCount, - acceptedCount, - rejectedCount, + premodCount: Math.max(0, premodCount), + flaggedCount: Math.max(0, flaggedCount), + acceptedCount: Math.max(0, acceptedCount), + rejectedCount: Math.max(0, rejectedCount), premod, flagged, accepted, diff --git a/client/coral-admin/src/graphql/queries/getQueueCounts.graphql b/client/coral-admin/src/graphql/queries/getQueueCounts.graphql new file mode 100644 index 000000000..4a7c00d87 --- /dev/null +++ b/client/coral-admin/src/graphql/queries/getQueueCounts.graphql @@ -0,0 +1,22 @@ +query Counts ($asset_id: ID) { + allCount: commentCount(query: { + asset_id: $asset_id + }) + acceptedCount: commentCount(query: { + statuses: [ACCEPTED], + asset_id: $asset_id + }) + premodCount: commentCount(query: { + statuses: [PREMOD], + asset_id: $asset_id + }) + rejectedCount: commentCount(query: { + statuses: [REJECTED], + asset_id: $asset_id + }) + flaggedCount: commentCount(query: { + action_type: FLAG, + asset_id: $asset_id, + statuses: [NONE, PREMOD] + }) +} diff --git a/client/coral-admin/src/graphql/queries/index.js b/client/coral-admin/src/graphql/queries/index.js index 68e5ae252..f26c8464e 100644 --- a/client/coral-admin/src/graphql/queries/index.js +++ b/client/coral-admin/src/graphql/queries/index.js @@ -4,6 +4,7 @@ import MOD_QUEUE_QUERY from './modQueueQuery.graphql'; import MOD_QUEUE_LOAD_MORE from './loadMore.graphql'; import MOD_USER_FLAGGED_QUERY from './modUserFlaggedQuery.graphql'; import METRICS from './metricsQuery.graphql'; +import GET_QUEUE_COUNTS from './getQueueCounts.graphql'; export const modQueueQuery = graphql(MOD_QUEUE_QUERY, { options: ({params: {id = null}}) => { @@ -93,3 +94,14 @@ export const modQueueResort = (id, fetchMore) => (sort) => { updateQuery: (oldData, {fetchMoreResult:{data}}) => data }); }; + +export const getQueueCounts = graphql(GET_QUEUE_COUNTS, { + options: ({params: {id = null}}) => { + return { + pollInterval: 5000, + variables: { + asset_id: id + } + }; + } +}); diff --git a/client/coral-admin/src/services/fragmentMatcher.js b/client/coral-admin/src/services/fragmentMatcher.js index bf167cd1e..531708f31 100644 --- a/client/coral-admin/src/services/fragmentMatcher.js +++ b/client/coral-admin/src/services/fragmentMatcher.js @@ -36,6 +36,7 @@ const fm = new IntrospectionFragmentMatcher({ kind: 'INTERFACE', name: 'Action', possibleTypes: [ + {name: 'DefaultAction'}, {name: 'FlagAction'}, {name: 'DontAgreeAction'} ], @@ -44,6 +45,7 @@ const fm = new IntrospectionFragmentMatcher({ kind: 'INTERFACE', name: 'ActionSummary', possibleTypes: [ + {name: 'DefaultActionSummary'}, {name: 'FlagActionSummary'}, {name: 'DontAgreeActionSummary'} ], diff --git a/test/server/graph/loaders/metrics.js b/test/server/graph/loaders/metrics.js index 75eadaff8..a24c18f79 100644 --- a/test/server/graph/loaders/metrics.js +++ b/test/server/graph/loaders/metrics.js @@ -70,7 +70,6 @@ describe('graph.loaders.Metrics', () => { fragment metrics on Asset { id action_summaries { - type: __typename actionCount actionableItemCount }