From 39d8a5d01b8896e37b07d4a6978b758911f4d022 Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Mon, 5 Jun 2017 14:20:34 -0600 Subject: [PATCH 1/8] bulk operations on User Detail comments --- client/coral-admin/src/actions/moderation.js | 7 +++ .../coral-admin/src/constants/moderation.js | 2 + client/coral-admin/src/reducers/moderation.js | 7 ++- .../routes/Moderation/components/Comment.js | 21 ++++++++- .../Moderation/components/UserDetail.css | 26 ++++++++++- .../Moderation/components/UserDetail.js | 44 ++++++++++++++++--- .../routes/Moderation/components/styles.css | 13 +++--- .../Moderation/containers/UserDetail.js | 22 ++++++++-- 8 files changed, 126 insertions(+), 16 deletions(-) diff --git a/client/coral-admin/src/actions/moderation.js b/client/coral-admin/src/actions/moderation.js index 3f8d975df..de57a6102 100644 --- a/client/coral-admin/src/actions/moderation.js +++ b/client/coral-admin/src/actions/moderation.js @@ -42,3 +42,10 @@ export const changeUserDetailStatuses = (tab) => { } return {type: actions.CHANGE_USER_DETAIL_STATUSES, tab, statuses}; }; + +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/constants/moderation.js b/client/coral-admin/src/constants/moderation.js index aa8a51a24..a4d75c202 100644 --- a/client/coral-admin/src/constants/moderation.js +++ b/client/coral-admin/src/constants/moderation.js @@ -9,3 +9,5 @@ export const VIEW_USER_DETAIL = 'VIEW_USER_DETAIL'; export const HIDE_USER_DETAIL = 'HIDE_USER_DETAIL'; export const SET_SORT_ORDER = 'MODERATION_SET_SORT_ORDER'; 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'; diff --git a/client/coral-admin/src/reducers/moderation.js b/client/coral-admin/src/reducers/moderation.js index 4201ffb06..579800423 100644 --- a/client/coral-admin/src/reducers/moderation.js +++ b/client/coral-admin/src/reducers/moderation.js @@ -1,4 +1,4 @@ -import {fromJS, Map} from 'immutable'; +import {fromJS, Map, Set} from 'immutable'; import * as actions from '../constants/moderation'; const initialState = fromJS({ @@ -10,6 +10,7 @@ const initialState = fromJS({ userDetailId: null, userDetailActiveTab: 'all', userDetailStatuses: ['NONE', 'ACCEPTED', 'REJECTED', 'PREMOD'], + userDetailSelectedIds: new Set(), banDialog: false, shortcutsNoteVisible: window.localStorage.getItem('coral:shortcutsNote') || 'show', sortOrder: 'REVERSE_CHRONOLOGICAL', @@ -71,6 +72,10 @@ export default function moderation (state = initialState, action) { 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.SET_SORT_ORDER: return state.set('sortOrder', action.order); default : diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index 1bc2b50d7..edb474493 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -24,6 +24,8 @@ const Comment = ({ suspectWords, bannedWords, minimal, + selected, + toggleSelect, ...props }) => { const links = linkify.getMatches(comment.body); @@ -48,10 +50,17 @@ const Comment = ({ }) .concat(linkText); + let selectionStateCSS; + if (minimal) { + selectionStateCSS = selected ? styles.minimalSelection : ''; + } else { + selectionStateCSS = selected ? 'mdl-shadow--16dp' : 'mdl-shadow--2dp'; + } + return (
  • @@ -63,6 +72,15 @@ const Comment = ({ ) } + { + minimal && typeof selected === 'boolean' && typeof toggleSelect === 'function' && ( + toggleSelect(e.target.value, e.target.checked)} /> + ) + } {timeago(comment.created_at || Date.now() - props.index * 60 * 1000)} @@ -187,6 +205,7 @@ Comment.propTypes = { showBanUserDialog: PropTypes.func.isRequired, showSuspendUserDialog: PropTypes.func.isRequired, currentUserId: PropTypes.string.isRequired, + toggleSelect: PropTypes.func, comment: PropTypes.shape({ body: PropTypes.string.isRequired, action_summaries: PropTypes.array, diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.css b/client/coral-admin/src/routes/Moderation/components/UserDetail.css index 1119be8c4..d4b5f0db7 100644 --- a/client/coral-admin/src/routes/Moderation/components/UserDetail.css +++ b/client/coral-admin/src/routes/Moderation/components/UserDetail.css @@ -41,8 +41,11 @@ } .commentStatuses { - padding: 0; + padding: 10px 0 0 0; + margin: 0; + height: 52px; list-style: none; + box-sizing: border-box; li { display: inline-block; @@ -56,3 +59,24 @@ font-weight: bold; border-bottom: 3px solid #F36451; } + +.bulkActionGroup { + height: 52px; + background-color: #efefef; + + i { + margin-right: 0; + } + + .bulkAction { + display: inline-block; + width: 48px; + height: 48px; + transform: scale(.7); + min-width: 0; + } + + .bulkAction:last-child { + margin-left: -10px; + } +} diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.js b/client/coral-admin/src/routes/Moderation/components/UserDetail.js index c461220c8..97321c1d6 100644 --- a/client/coral-admin/src/routes/Moderation/components/UserDetail.js +++ b/client/coral-admin/src/routes/Moderation/components/UserDetail.js @@ -16,6 +16,9 @@ export default class UserDetail extends React.Component { showSuspendUserDialog: PropTypes.func.isRequired, acceptComment: PropTypes.func.isRequired, rejectComment: PropTypes.func.isRequired, + changeStatus: PropTypes.func.isRequired, + toggleSelect: PropTypes.func.isRequired, + bulkSetCommentStatus: PropTypes.func.isRequired, } copyPermalink = () => { @@ -44,9 +47,14 @@ export default class UserDetail extends React.Component { rejectedComments, comments: {nodes} }, - moderation: {userDetailActiveTab: tab}, + moderation: { + userDetailActiveTab: tab, + userDetailSelectedIds: selectedIds + }, bannedWords, suspectWords, + toggleSelect, + bulkSetCommentStatus, showBanUserDialog, showSuspendUserDialog, acceptComment, @@ -94,14 +102,38 @@ export default class UserDetail extends React.Component {

    {`${(rejectedPercent).toFixed(1)}%`}

    - + { + selectedIds.length === 0 + ? ( + + ) + : ( +
    + + + {`${selectedIds.length} comments selected`} +
    + ) + } +
    { nodes.map((comment, i) => { const status = comment.action_summaries ? 'FLAGGED' : comment.status; + const selected = selectedIds.indexOf(comment.id) !== -1; return ; diff --git a/client/coral-admin/src/routes/Moderation/components/styles.css b/client/coral-admin/src/routes/Moderation/components/styles.css index e7bea9430..d278e0ed1 100644 --- a/client/coral-admin/src/routes/Moderation/components/styles.css +++ b/client/coral-admin/src/routes/Moderation/components/styles.css @@ -185,10 +185,6 @@ span { padding: 0 14px; } - &:hover { - box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); - } - &:last-child { border-bottom: none; } @@ -291,7 +287,6 @@ span { @media (--big-viewport) { .listItem { - border: 1px solid #e0e0e0; margin-bottom: 30px; &:last-child { @@ -460,3 +455,11 @@ span { position: relative; } } + +.minimal { + margin: 0; +} + +.minimalSelection { + background-color: #ecf4ff; +} diff --git a/client/coral-admin/src/routes/Moderation/containers/UserDetail.js b/client/coral-admin/src/routes/Moderation/containers/UserDetail.js index 9afd10efb..5a0956161 100644 --- a/client/coral-admin/src/routes/Moderation/containers/UserDetail.js +++ b/client/coral-admin/src/routes/Moderation/containers/UserDetail.js @@ -6,7 +6,8 @@ import UserDetail from '../components/UserDetail'; import withQuery from 'coral-framework/hocs/withQuery'; import {getSlotsFragments} from 'coral-framework/helpers/plugins'; import {getDefinitionName} from 'coral-framework/utils'; -import {changeUserDetailStatuses} from 'coral-admin/src/actions/moderation'; +import {changeUserDetailStatuses, toggleSelectCommentInUserDetail} from 'coral-admin/src/actions/moderation'; +import {withSetCommentStatus} from 'coral-framework/graphql/mutations'; import Comment from './Comment'; const commentConnectionFragment = gql` @@ -31,12 +32,23 @@ class UserDetailContainer extends React.Component { hideUserDetail: PropTypes.func.isRequired } + // status can be 'ACCEPTED' or 'REJECTED' + bulkSetCommentStatus = (status) => { + this.props.moderation.userDetailSelectedIds.forEach((commentId) => { + this.props.setCommentStatus({commentId, status}); + }); + } + render () { if (!('user' in this.props.root)) { return null; } - return ; + return ; } } @@ -79,10 +91,14 @@ const mapStateToProps = (state) => ({ }); const mapDispatchToProps = (dispatch) => ({ - ...bindActionCreators({changeUserDetailStatuses}, dispatch) + ...bindActionCreators({ + changeUserDetailStatuses, + toggleSelectCommentInUserDetail + }, dispatch) }); export default compose( connect(mapStateToProps, mapDispatchToProps), withUserDetailQuery, + withSetCommentStatus, )(UserDetailContainer); From c4a41af33b1eccb21551f4c9f5cd03cb65b71b4f Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Mon, 5 Jun 2017 14:40:03 -0600 Subject: [PATCH 2/8] clear selected ids when panel is closed --- client/coral-admin/src/reducers/moderation.js | 4 +++- .../coral-admin/src/routes/Moderation/components/Comment.js | 1 + .../coral-admin/src/routes/Moderation/components/styles.css | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/client/coral-admin/src/reducers/moderation.js b/client/coral-admin/src/reducers/moderation.js index 579800423..7975e3e39 100644 --- a/client/coral-admin/src/reducers/moderation.js +++ b/client/coral-admin/src/reducers/moderation.js @@ -67,7 +67,9 @@ export default function moderation (state = initialState, action) { case actions.VIEW_USER_DETAIL: return state.set('userDetailId', action.userId); case actions.HIDE_USER_DETAIL: - return state.set('userDetailId', null); + return state + .set('userDetailId', null) + .update('userDetailSelectedIds', (set) => set.clear()); case actions.CHANGE_USER_DETAIL_STATUSES: return state .set('userDetailActiveTab', action.tab) diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index edb474493..9d1019b5e 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -75,6 +75,7 @@ const Comment = ({ { minimal && typeof selected === 'boolean' && typeof toggleSelect === 'function' && ( Date: Tue, 6 Jun 2017 12:52:26 -0600 Subject: [PATCH 3/8] reload and clear selections --- client/coral-admin/src/actions/moderation.js | 2 ++ client/coral-admin/src/constants/moderation.js | 1 + client/coral-admin/src/reducers/moderation.js | 2 ++ .../routes/Moderation/components/UserDetail.js | 18 ++++++++++++++---- .../routes/Moderation/containers/UserDetail.js | 16 +++++++++++++--- 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/client/coral-admin/src/actions/moderation.js b/client/coral-admin/src/actions/moderation.js index de57a6102..37e09590d 100644 --- a/client/coral-admin/src/actions/moderation.js +++ b/client/coral-admin/src/actions/moderation.js @@ -43,6 +43,8 @@ export const changeUserDetailStatuses = (tab) => { 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, diff --git a/client/coral-admin/src/constants/moderation.js b/client/coral-admin/src/constants/moderation.js index a4d75c202..374de616a 100644 --- a/client/coral-admin/src/constants/moderation.js +++ b/client/coral-admin/src/constants/moderation.js @@ -11,3 +11,4 @@ export const SET_SORT_ORDER = 'MODERATION_SET_SORT_ORDER'; 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/reducers/moderation.js b/client/coral-admin/src/reducers/moderation.js index 7975e3e39..1b95bdb90 100644 --- a/client/coral-admin/src/reducers/moderation.js +++ b/client/coral-admin/src/reducers/moderation.js @@ -70,6 +70,8 @@ export default function moderation (state = initialState, action) { 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) diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.js b/client/coral-admin/src/routes/Moderation/components/UserDetail.js index 97321c1d6..76bc100fc 100644 --- a/client/coral-admin/src/routes/Moderation/components/UserDetail.js +++ b/client/coral-admin/src/routes/Moderation/components/UserDetail.js @@ -39,6 +39,18 @@ export default class UserDetail extends React.Component { } } + rejectThenReload = (info) => { + this.props.rejectComment(info).then(() => { + this.props.data.refetch(); + }); + } + + acceptThenReload = (info) => { + this.props.acceptComment(info).then(() => { + this.props.data.refetch(); + }); + } + render () { const { root: { @@ -57,8 +69,6 @@ export default class UserDetail extends React.Component { bulkSetCommentStatus, showBanUserDialog, showSuspendUserDialog, - acceptComment, - rejectComment, hideUserDetail } = this.props; const localProfile = user.profiles.find((p) => p.provider === 'local'); @@ -145,8 +155,8 @@ export default class UserDetail extends React.Component { actions={actionsMap[status]} showBanUserDialog={showBanUserDialog} showSuspendUserDialog={showSuspendUserDialog} - acceptComment={acceptComment} - rejectComment={rejectComment} + acceptComment={this.acceptThenReload} + rejectComment={this.rejectThenReload} selected={selected} toggleSelect={toggleSelect} currentAsset={null} diff --git a/client/coral-admin/src/routes/Moderation/containers/UserDetail.js b/client/coral-admin/src/routes/Moderation/containers/UserDetail.js index 5a0956161..9604f27a0 100644 --- a/client/coral-admin/src/routes/Moderation/containers/UserDetail.js +++ b/client/coral-admin/src/routes/Moderation/containers/UserDetail.js @@ -6,7 +6,11 @@ import UserDetail from '../components/UserDetail'; import withQuery from 'coral-framework/hocs/withQuery'; import {getSlotsFragments} from 'coral-framework/helpers/plugins'; import {getDefinitionName} from 'coral-framework/utils'; -import {changeUserDetailStatuses, toggleSelectCommentInUserDetail} from 'coral-admin/src/actions/moderation'; +import { + changeUserDetailStatuses, + clearUserDetailSelections, + toggleSelectCommentInUserDetail +} from 'coral-admin/src/actions/moderation'; import {withSetCommentStatus} from 'coral-framework/graphql/mutations'; import Comment from './Comment'; @@ -34,8 +38,13 @@ class UserDetailContainer extends React.Component { // status can be 'ACCEPTED' or 'REJECTED' bulkSetCommentStatus = (status) => { - this.props.moderation.userDetailSelectedIds.forEach((commentId) => { - this.props.setCommentStatus({commentId, status}); + const changes = this.props.moderation.userDetailSelectedIds.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 }); } @@ -93,6 +102,7 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => ({ ...bindActionCreators({ changeUserDetailStatuses, + clearUserDetailSelections, toggleSelectCommentInUserDetail }, dispatch) }); From 4e19d5eecf73bb26d0798ca353ed8e4b85d469d6 Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Tue, 6 Jun 2017 13:11:31 -0600 Subject: [PATCH 4/8] don't have functions re-created every render --- .../Moderation/components/UserDetail.js | 30 ++++++++++--------- .../Moderation/containers/UserDetail.js | 11 ++++++- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.js b/client/coral-admin/src/routes/Moderation/components/UserDetail.js index 76bc100fc..0fb355486 100644 --- a/client/coral-admin/src/routes/Moderation/components/UserDetail.js +++ b/client/coral-admin/src/routes/Moderation/components/UserDetail.js @@ -18,7 +18,8 @@ export default class UserDetail extends React.Component { rejectComment: PropTypes.func.isRequired, changeStatus: PropTypes.func.isRequired, toggleSelect: PropTypes.func.isRequired, - bulkSetCommentStatus: PropTypes.func.isRequired, + bulkAccept: PropTypes.func.isRequired, + bulkReject: PropTypes.func.isRequired, } copyPermalink = () => { @@ -31,14 +32,6 @@ export default class UserDetail extends React.Component { } } - changeStatus = (tab) => { - if (tab === 'all') { - this.props.changeStatus('all'); - } else if (tab === 'rejected') { - this.props.changeStatus('rejected'); - } - } - rejectThenReload = (info) => { this.props.rejectComment(info).then(() => { this.props.data.refetch(); @@ -51,6 +44,14 @@ export default class UserDetail extends React.Component { }); } + showAll = () => { + this.props.changeStatus('all'); + } + + showRejected = () => { + this.props.changeStatus('rejected'); + } + render () { const { root: { @@ -66,7 +67,8 @@ export default class UserDetail extends React.Component { bannedWords, suspectWords, toggleSelect, - bulkSetCommentStatus, + bulkAccept, + bulkReject, showBanUserDialog, showSuspendUserDialog, hideUserDetail @@ -116,20 +118,20 @@ export default class UserDetail extends React.Component { selectedIds.length === 0 ? (
      -
    • All
    • -
    • Rejected
    • +
    • All
    • +
    • Rejected
    ) : (
    + {/* Edit Comment Timeframe */} + +
    {t('configure.edit_comment_timeframe_heading')}
    +

    + {t('configure.edit_comment_timeframe_text_pre')} +   + +   + {t('configure.edit_comment_timeframe_text_post')} +

    +
    Date: Tue, 6 Jun 2017 16:49:51 -0600 Subject: [PATCH 6/8] moved plugin to lazy load --- services/passport.js | 1 + services/users.js | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/services/passport.js b/services/passport.js index 03602cdb6..d42dfa295 100644 --- a/services/passport.js +++ b/services/passport.js @@ -40,6 +40,7 @@ const SetTokenForSafari = (req, res, token) => { if (browser.ios || browser.safari) { res.cookie('authorization', token, { httpOnly: true, + secure: process.env.NODE_ENV === 'production', expires: new Date(Date.now() + ms(JWT_EXPIRY)) }); } diff --git a/services/users.js b/services/users.js index 5c6440a0e..9bca10ea5 100644 --- a/services/users.js +++ b/services/users.js @@ -930,16 +930,21 @@ module.exports = class UsersService { // Extract all the tokenUserNotFound plugins so we can integrate with other // providers. -const tokenUserNotFoundHooks = require('./plugins') - .get('server', 'tokenUserNotFound') - .map(({plugin, tokenUserNotFound}) => { - debug(`added plugin '${plugin.name}' to tokenUserNotFound hooks`); +let tokenUserNotFoundHooks = null; - return tokenUserNotFound; - }); - -// Provide a function that +// Provide a function that can loop over the hooks and search for a provider +// can crack the token to a user. const lookupUserNotFound = async (token) => { + if (!Array.isArray(tokenUserNotFoundHooks)) { + tokenUserNotFoundHooks = require('./plugins') + .get('server', 'tokenUserNotFound') + .map(({plugin, tokenUserNotFound}) => { + debug(`added plugin '${plugin.name}' to tokenUserNotFound hooks`); + + return tokenUserNotFound; + }); + } + for (let hook of tokenUserNotFoundHooks) { let user = await hook(token); if (user !== null && typeof user !== 'undefined') { From ceb99cf20588bdc450d1b2822d219eb32f690384 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Wed, 7 Jun 2017 17:45:33 +0700 Subject: [PATCH 7/8] Better refetch detection --- client/coral-embed-stream/src/components/Comment.js | 1 + client/coral-embed-stream/src/reducers/embed.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 71117563d..228dd4c41 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -297,6 +297,7 @@ class Comment extends React.Component { } = this.props; const view = this.getVisibileReplies(); + const hasMoreComments = comment.replies && (comment.replies.hasNextPage || comment.replies.nodes.length > view.length); const replyCount = this.hasIgnoredReplies() ? '' : comment.replyCount; const flagSummary = getActionSummary('FlagActionSummary', comment); diff --git a/client/coral-embed-stream/src/reducers/embed.js b/client/coral-embed-stream/src/reducers/embed.js index 8ccf4cbbc..06073c54e 100644 --- a/client/coral-embed-stream/src/reducers/embed.js +++ b/client/coral-embed-stream/src/reducers/embed.js @@ -4,6 +4,7 @@ const initialState = { activeTab: 'stream', previousTab: '', refetching: false, + refetchRequestId: 0, }; export default function stream(state = initialState, action) { @@ -18,7 +19,8 @@ export default function stream(state = initialState, action) { if (action.queryString.indexOf('query CoralEmbedStream_Embed(') >= 0) { return { ...state, - refetching: action.isRefetch, + refetching: action.isRefetch ? true : state.refetching, + refetchRequestId: action.isRefetch ? action.requestId : state.refetchRequestId, }; } return state; @@ -26,7 +28,7 @@ export default function stream(state = initialState, action) { if (action.operationName === 'CoralEmbedStream_Embed') { return { ...state, - refetching: false, + refetching: action.requestId === state.refetchRequestId ? false : state.refetching, }; } return state; From 9f4df35c3ac41971c5644b62cb7b319b9e5c9f3b Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Wed, 7 Jun 2017 10:15:50 -0600 Subject: [PATCH 8/8] percents have to be multiplied by 100 --- .../coral-admin/src/routes/Moderation/components/UserDetail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.js b/client/coral-admin/src/routes/Moderation/components/UserDetail.js index 0fb355486..688ac75d0 100644 --- a/client/coral-admin/src/routes/Moderation/components/UserDetail.js +++ b/client/coral-admin/src/routes/Moderation/components/UserDetail.js @@ -80,7 +80,7 @@ export default class UserDetail extends React.Component { profile = localProfile.id; } - let rejectedPercent = rejectedComments / totalComments; + let rejectedPercent = (rejectedComments / totalComments) * 100; if (rejectedPercent === Infinity || isNaN(rejectedPercent)) { // if totalComments is 0, you're dividing by zero, which is naughty