diff --git a/client/coral-admin/src/AppRouter.js b/client/coral-admin/src/AppRouter.js index 5827f0a21..4b3ea0f0b 100644 --- a/client/coral-admin/src/AppRouter.js +++ b/client/coral-admin/src/AppRouter.js @@ -1,5 +1,5 @@ import React from 'react'; -import {Router, Route, IndexRedirect, Redirect} from 'react-router'; +import {Router, Route, IndexRedirect, IndexRoute} from 'react-router'; import {history} from 'coral-framework/helpers/router'; import Configure from 'routes/Configure'; @@ -15,7 +15,7 @@ const routes = (
- + @@ -35,10 +35,15 @@ const routes = ( {/* Moderation Routes */} + + - + + + + @@ -47,11 +52,12 @@ const routes = ( - + - - + + +
diff --git a/client/coral-admin/src/components/UserDetailComment.js b/client/coral-admin/src/components/UserDetailComment.js index 1ec181214..9b4936847 100644 --- a/client/coral-admin/src/components/UserDetailComment.js +++ b/client/coral-admin/src/components/UserDetailComment.js @@ -60,7 +60,7 @@ class UserDetailComment extends React.Component {
Story: {comment.asset.title} - {{t('modqueue.moderate')}} + {{t('modqueue.moderate')}}
diff --git a/client/coral-admin/src/graphql/utils.js b/client/coral-admin/src/graphql/utils.js index 331fd876a..f729cc0ea 100644 --- a/client/coral-admin/src/graphql/utils.js +++ b/client/coral-admin/src/graphql/utils.js @@ -1,7 +1,7 @@ import update from 'immutability-helper'; import * as notification from 'coral-admin/src/services/notification'; -const queues = ['all', 'premod', 'flagged', 'accepted', 'rejected']; +const queues = ['all', 'premod', 'reported', 'approved', 'rejected', 'new']; const limit = 10; const ascending = (a, b) => { @@ -64,23 +64,35 @@ function addCommentToQueue(root, queue, comment, sort) { return update(root, changes); } +/** + * getCommentQueues determines in which queues a comment should be placed. + */ function getCommentQueues(comment) { const queues = ['all']; - if (comment.status === 'ACCEPTED') { - queues.push('accepted'); - } - else if (comment.status === 'REJECTED') { + const isFlagged = comment.actions && comment.actions.some((a) => a.__typename === 'FlagAction'); + + switch(comment.status) { + case 'ACCEPTED': + queues.push('approved'); + break; + case 'REJECTED': queues.push('rejected'); - } - else if (comment.status === 'PREMOD') { + break; + case 'PREMOD': queues.push('premod'); + queues.push('new'); + if (isFlagged) { + queues.push('reported'); + } + break; + case 'NONE': + queues.push('new'); + if (isFlagged) { + queues.push('reported'); + } + break; } - if ( - ['NONE', 'PREMOD'].indexOf(comment.status) >= 0 - && comment.actions && comment.actions.some((a) => a.__typename === 'FlagAction') - ) { - queues.push('flagged'); - } + return queues; } @@ -98,6 +110,7 @@ function getCommentQueues(comment) { */ export function handleCommentChange(root, comment, sort, notify) { let next = root; + const nextQueues = getCommentQueues(comment); let notificationShown = false; diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index e37fa887c..fd5579952 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -100,7 +100,7 @@ class Comment extends React.Component {
Story: {comment.asset.title} {!props.currentAsset && - {t('modqueue.moderate')}} + {t('modqueue.moderate')}}
diff --git a/client/coral-admin/src/routes/Moderation/components/Moderation.js b/client/coral-admin/src/routes/Moderation/components/Moderation.js index d9822724d..a69100f9d 100644 --- a/client/coral-admin/src/routes/Moderation/components/Moderation.js +++ b/client/coral-admin/src/routes/Moderation/components/Moderation.js @@ -58,8 +58,7 @@ export default class Moderation extends Component { } getComments = () => { - const {root, route} = this.props; - const activeTab = route.path === ':id' ? 'premod' : route.path; + const {root, activeTab} = this.props; return root[activeTab].nodes; } @@ -101,25 +100,28 @@ export default class Moderation extends Component { } render () { - - const {root, moderation, settings, viewUserDetail, hideUserDetail, activeTab, ...props} = this.props; + const {root, moderation, settings, viewUserDetail, hideUserDetail, activeTab, getModPath, premodEnabled, ...props} = this.props; const assetId = this.props.params.id; const {asset} = root; const comments = root[activeTab]; + let activeTabCount; switch(activeTab) { case 'all': activeTabCount = root.allCount; break; - case 'accepted': - activeTabCount = root.acceptedCount; + case 'new': + activeTabCount = root.newCount; + break; + case 'approved': + activeTabCount = root.approvedCount; break; case 'premod': activeTabCount = root.premodCount; break; - case 'flagged': - activeTabCount = root.flaggedCount; + case 'reported': + activeTabCount = root.reportedCount; break; case 'rejected': activeTabCount = root.rejectedCount; @@ -137,12 +139,16 @@ export default class Moderation extends Component { { - - function getPath (type) { - return asset ? `/admin/moderate/${type}/${asset.id}` : `/admin/moderate/${type}`; - } - +const ModerationMenu = ({ + asset = {}, + allCount, + approvedCount, + premodCount, + newCount, + rejectedCount, + reportedCount, + selectSort, + sort, + premodEnabled, + getModPath, + activeTab +}) => { return (
+ + { + premodEnabled ? ( + + {t('modqueue.premod')} + + ) : ( + + {t('modqueue.new')} + + ) + } + - {t('modqueue.all')} + {t('modqueue.reported')} - {t('modqueue.premod')} + {t('modqueue.approved')} - {t('modqueue.flagged')} - - - {t('modqueue.approved')} - - {t('modqueue.rejected')} + + {t('modqueue.all')} +
{ ? : assets.map((story, i) => { const storyOpen = story.closedAt === null || new Date(story.closedAt) > new Date(); + return Error
; @@ -209,10 +224,12 @@ class ModerationContainer extends Component { return ; } } @@ -304,7 +321,14 @@ const withModQueueQuery = withQuery(gql` }) { ...CoralAdmin_Moderation_CommentConnection } - accepted: comments(query: { + new: comments(query: { + statuses: [NONE, PREMOD], + asset_id: $asset_id, + sort: $sort + }) { + ...CoralAdmin_Moderation_CommentConnection + } + approved: comments(query: { statuses: [ACCEPTED], asset_id: $asset_id, sort: $sort @@ -318,7 +342,7 @@ const withModQueueQuery = withQuery(gql` }) { ...CoralAdmin_Moderation_CommentConnection } - flagged: comments(query: { + reported: comments(query: { action_type: FLAG, asset_id: $asset_id, statuses: [NONE, PREMOD], @@ -337,11 +361,18 @@ const withModQueueQuery = withQuery(gql` id title url + settings { + moderation + } } allCount: commentCount(query: { asset_id: $asset_id }) - acceptedCount: commentCount(query: { + newCount: commentCount(query: { + statuses: [NONE, PREMOD], + asset_id: $asset_id + }) + approvedCount: commentCount(query: { statuses: [ACCEPTED], asset_id: $asset_id }) @@ -353,13 +384,14 @@ const withModQueueQuery = withQuery(gql` statuses: [REJECTED], asset_id: $asset_id }) - flaggedCount: commentCount(query: { + reportedCount: commentCount(query: { action_type: FLAG, asset_id: $asset_id, statuses: [NONE, PREMOD] }) settings { organizationName + moderation } } ${commentConnectionFragment} @@ -380,7 +412,11 @@ const withQueueCountPolling = withQuery(gql` allCount: commentCount(query: { asset_id: $asset_id }) - acceptedCount: commentCount(query: { + newCount: commentCount(query: { + statuses: [NONE, PREMOD], + asset_id: $asset_id + }) + approvedCount: commentCount(query: { statuses: [ACCEPTED], asset_id: $asset_id }) @@ -392,7 +428,7 @@ const withQueueCountPolling = withQuery(gql` statuses: [REJECTED], asset_id: $asset_id }) - flaggedCount: commentCount(query: { + reportedCount: commentCount(query: { action_type: FLAG, asset_id: $asset_id, statuses: [NONE, PREMOD] diff --git a/client/coral-admin/src/routes/Moderation/containers/StorySearch.js b/client/coral-admin/src/routes/Moderation/containers/StorySearch.js index d5a0ad243..4175479e6 100644 --- a/client/coral-admin/src/routes/Moderation/containers/StorySearch.js +++ b/client/coral-admin/src/routes/Moderation/containers/StorySearch.js @@ -59,13 +59,13 @@ class StorySearchContainer extends React.Component { goToStory = (id) => { const {router} = this.props; - router.push(`/admin/moderate/all/${id}`); + router.push(`/admin/moderate/${id}`); this.clearAndCloseSearch(); } goToModerateAll = () => { const {router} = this.props; - router.push('/admin/moderate/all'); + router.push('/admin/moderate'); this.clearAndCloseSearch(); } diff --git a/client/coral-admin/src/utils/index.js b/client/coral-admin/src/utils/index.js new file mode 100644 index 000000000..14084ff77 --- /dev/null +++ b/client/coral-admin/src/utils/index.js @@ -0,0 +1,4 @@ +export const isPremod = (mod) => mod === 'PRE'; + +export const getModPath = (type = 'all', assetId) => + assetId ? `/admin/moderate/${type}/${assetId}` : `/admin/moderate/${type}`; diff --git a/client/coral-framework/components/Popup.js b/client/coral-framework/components/Popup.js index b9393a36d..1fe3408ea 100644 --- a/client/coral-framework/components/Popup.js +++ b/client/coral-framework/components/Popup.js @@ -42,14 +42,14 @@ export default class Popup extends Component { this.onUnload(); const interval = setInterval(() => { - if (this.ref.onload === null) { + if (this.ref && this.ref.onload === null) { this.setCallbacks(); clearInterval(interval); } }, 50); this.detectCloseInterval = setInterval(() => { - if (this.ref.closed) { + if (!this.ref || this.ref.closed) { clearInterval(this.detectCloseInterval); this.onClose(); } diff --git a/client/talk-plugin-moderation/ModerationLink.js b/client/talk-plugin-moderation/ModerationLink.js index 7239cc793..020b8c345 100644 --- a/client/talk-plugin-moderation/ModerationLink.js +++ b/client/talk-plugin-moderation/ModerationLink.js @@ -5,7 +5,7 @@ import t from 'coral-framework/services/i18n'; const ModerationLink = (props) => props.isAdmin ? ( diff --git a/locales/en.yml b/locales/en.yml index af985b593..54d5315d5 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -262,6 +262,7 @@ en: dont_like_username: "Don't like username" empty_queue: "No more comments to moderate! You're all caught up. Go have some ☕️" flagged: flagged + reported: reported impersonating: Impersonating less_detail: "Less detail" likes: likes @@ -269,6 +270,7 @@ en: mod_faster: "Moderate faster with keyboard shortcuts" moderate: "Moderate →" more_detail: "More detail" + new: New newest_first: "Newest First" navigation: Navigation next_comment: "Go to the next comment" diff --git a/locales/es.yml b/locales/es.yml index 963723e9e..8c3e7927b 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -261,6 +261,7 @@ es: mod_faster: "Moderar más rápido con atajos de teclado" moderate: "Moderar →" more_detail: "Más detalles" + new: Nuevo newest_first: "Primero el más nuevo" navigation: Navegación next_comment: "Ir al siguiente comentario" diff --git a/plugins/talk-plugin-featured-comments/client/components/Tag.js b/plugins/talk-plugin-featured-comments/client/components/Tag.js index ee2d13b19..c912c61b1 100644 --- a/plugins/talk-plugin-featured-comments/client/components/Tag.js +++ b/plugins/talk-plugin-featured-comments/client/components/Tag.js @@ -15,7 +15,7 @@ export default class Tag extends React.Component { } - showTooltip = e => { + showTooltip = (e) => { e.preventDefault(); this.setState({ tooltip: true