From 219399a23153cc7f5e85b6c2b933478f530b8ec0 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Wed, 27 Sep 2017 22:50:45 +0700 Subject: [PATCH] Refactor ComemntDetail and implement ToxicDetail --- .../src/components/CommentDetail.css | 34 +++++++ .../src/components/CommentDetail.js | 32 +++++++ client/coral-admin/src/components/FlagBox.css | 93 +++++++------------ client/coral-admin/src/components/FlagBox.js | 65 +++++++------ .../routes/Moderation/components/Comment.js | 10 +- .../client/components/ToxicDetail.css | 11 +++ .../client/components/ToxicDetail.js | 46 +++++++++ .../client/containers/ToxicDetail.js | 21 +++++ .../client/containers/ToxicLabel.js | 7 +- .../client/index.js | 2 + .../client/utils.js | 4 + plugins/talk-plugin-toxic-comments/index.js | 2 + .../server/resolvers.js | 7 ++ .../server/typeDefs.graphql | 3 + 14 files changed, 235 insertions(+), 102 deletions(-) create mode 100644 client/coral-admin/src/components/CommentDetail.css create mode 100644 client/coral-admin/src/components/CommentDetail.js create mode 100644 plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.css create mode 100644 plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.js create mode 100644 plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js create mode 100644 plugins/talk-plugin-toxic-comments/client/utils.js create mode 100644 plugins/talk-plugin-toxic-comments/server/resolvers.js diff --git a/client/coral-admin/src/components/CommentDetail.css b/client/coral-admin/src/components/CommentDetail.css new file mode 100644 index 000000000..259d4e1c5 --- /dev/null +++ b/client/coral-admin/src/components/CommentDetail.css @@ -0,0 +1,34 @@ +.root { + margin-left: 16px; +} + +.headerContainer { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.header { + vertical-align: middle; + margin: 0; + font-weight: 500; + display: inline-block; + font-size: 12px; + line-height: 12px; + margin-right: 7px; +} + +.info { + font-size: 12px; +} + +.details { + padding: 0 20px 16px; + font-size: 12px; +} + +.icon { + vertical-align: middle; + font-size: 12px; + margin-right: 7px; +} diff --git a/client/coral-admin/src/components/CommentDetail.js b/client/coral-admin/src/components/CommentDetail.js new file mode 100644 index 000000000..2e1a89089 --- /dev/null +++ b/client/coral-admin/src/components/CommentDetail.js @@ -0,0 +1,32 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import styles from './CommentDetail.css'; +import {Icon} from 'coral-ui'; + +const CommentDetail = ({icon, header, info, children, className}) => { + return ( +
+
+ {icon && } +

{header}:

+
{info}
+
+ {children && +
+ {children} +
+ } +
+ ); +}; + +CommentDetail.propTypes = { + className: PropTypes.string, + header: PropTypes.node, + icon: PropTypes.string, + info: PropTypes.node, + children: PropTypes.node, +}; + +export default CommentDetail; diff --git a/client/coral-admin/src/components/FlagBox.css b/client/coral-admin/src/components/FlagBox.css index 232803203..b88f904b9 100644 --- a/client/coral-admin/src/components/FlagBox.css +++ b/client/coral-admin/src/components/FlagBox.css @@ -1,56 +1,42 @@ .flagBox { border-top: 1px solid rgba(66, 66, 66, 0.12); margin-top: 10px; - .container { - padding: 0 14px; - } + padding-top: 10px; +} - .detail { - padding: 0 20px 16px; - ul { - padding: 0; - list-style: none; - font-size: 12px; - font-weight: 500; - } - } +.info { + vertical-align: middle; + list-style: none; + display: inline-block; + padding: 0; + font-size: 12px; +} - .header { - position: relative; - .moreDetail { - float: right; - font-size: 12px; - font-weight: 500; - margin-right: 10px; - margin-top: 8px; - color: black; +.detail { + padding: 0; + list-style: none; + font-size: 12px; + font-weight: 500; +} - &:hover { - opacity: 0.9; - cursor: pointer; - } - } - i { - vertical-align: middle; - font-size: 12px; - } - ul { - vertical-align: middle; - list-style: none; - display: inline-block; - padding: 0; - margin-left: 10px; - font-size: 12px; - } - } +.subDetail { + padding: 0; + list-style: none; + font-size: 12px; + font-weight: normal; + color: #888; +} - h3 { - vertical-align: middle; - margin: 0; - font-weight: 500; - display: inline-block; - margin-left: 7px; - font-size: 12px; +.moreDetail { + position: absolute; + font-size: 12px; + font-weight: 500; + color: black; + right: 16px; + + &:hover { + opacity: 0.9; + cursor: pointer; } } @@ -59,15 +45,6 @@ margin-right: 10px; } -.subDetail { - font-weight: normal; - color: #888; - - span { - color: black; - } -} - .username { color: #393B44; text-decoration: none; @@ -77,7 +54,7 @@ border-radius: 2px; margin-left: -5px; transition: background-color 200ms ease; -&:hover { - background-color: #E0E0E0; - } + &:hover { + background-color: #E0E0E0; + } } diff --git a/client/coral-admin/src/components/FlagBox.js b/client/coral-admin/src/components/FlagBox.js index 05fd14128..44a302e52 100644 --- a/client/coral-admin/src/components/FlagBox.js +++ b/client/coral-admin/src/components/FlagBox.js @@ -1,8 +1,8 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {Icon} from 'coral-ui'; import styles from './FlagBox.css'; import t from 'coral-framework/services/i18n'; +import CommentDetail from './CommentDetail'; const shortReasons = { 'This comment is offensive': t('modqueue.offensive'), @@ -39,45 +39,42 @@ class FlagBox extends Component { return (
-
-
-

{t('community.flags')} ({actionSummaries.length}):

- - {showDetail ? t('modqueue.less_detail') : t('modqueue.more_detail')} -
+ }> {showDetail && ( -
-
    - {actionSummaries.map((summary, i) => { - - const actionList = actions.filter((a) => a.reason === summary.reason); - - return ( -
  • - {this.reasonMap(summary.reason)} ({summary.count}) - -
  • - ); - })} -
-
+
    + {actionSummaries.map((summary, i) => { + const actionList = actions.filter((a) => a.reason === summary.reason); + return ( +
  • + {this.reasonMap(summary.reason)} ({summary.count}) + +
  • + ); + })} +
)} -
+
); } diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index f72b0ef12..e19f34229 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -185,11 +185,6 @@ class Comment extends React.Component { - {flagActions && flagActions.length ? : null} + ); } diff --git a/plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.css b/plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.css new file mode 100644 index 000000000..cbf7ce8de --- /dev/null +++ b/plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.css @@ -0,0 +1,11 @@ +.info { + background-color: rgba(44, 44, 44, 0.89); + color: white; + padding: 2px 4px; + font-size: 0.8em; + margin-left: 6px; +} + +.toxic { + background-color: #d03235; +} diff --git a/plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.js b/plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.js new file mode 100644 index 000000000..de8a0337c --- /dev/null +++ b/plugins/talk-plugin-toxic-comments/client/components/ToxicDetail.js @@ -0,0 +1,46 @@ +import React from 'react'; +import CommentDetail from 'coral-admin/src/components/CommentDetail'; +import {isToxic} from '../utils'; +import styles from './ToxicDetail.css'; +import cn from 'classnames'; +import PropTypes from 'prop-types'; + +const getInfo = (toxicity, actions) => { + const toxic = isToxic(actions); + let text = 'Unlikely'; + if (toxicity > 0.8) { + text = 'Highly Likely'; + } + else if (toxicity >= 0.5) { + text = 'Possibly'; + } + else if (toxicity >= 0.7) { + text = 'Likely'; + } + + return ( +
+ {text} + + {Math.round(toxicity * 100)}% + +
+ ); +}; + +const ToxicLabel = ({comment: {actions, toxicity}}) => ( + +); + +ToxicLabel.propTypes = { + comment: PropTypes.shape({ + actions: PropTypes.array, + toxicity: PropTypes.toxicity, + }), +}; + +export default ToxicLabel; diff --git a/plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js b/plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js new file mode 100644 index 000000000..32b83fbb3 --- /dev/null +++ b/plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js @@ -0,0 +1,21 @@ +import {compose, gql} from 'react-apollo'; +import {withFragments, excludeIf} from 'plugin-api/beta/client/hocs'; +import ToxicDetail from '../components/ToxicDetail'; + +const enhance = compose( + withFragments({ + comment: gql` + fragment TalkToxicComments_ToxicDetail_Comment on Comment { + toxicity + actions { + __typename + ... on FlagAction { + reason + } + } + }`, + }), + excludeIf(({comment: {toxicity}}) => toxicity === null), +); + +export default enhance(ToxicDetail); diff --git a/plugins/talk-plugin-toxic-comments/client/containers/ToxicLabel.js b/plugins/talk-plugin-toxic-comments/client/containers/ToxicLabel.js index 0d2e9e14b..ee43f4a7e 100644 --- a/plugins/talk-plugin-toxic-comments/client/containers/ToxicLabel.js +++ b/plugins/talk-plugin-toxic-comments/client/containers/ToxicLabel.js @@ -1,15 +1,12 @@ import {compose, gql} from 'react-apollo'; import {withFragments, excludeIf} from 'plugin-api/beta/client/hocs'; import ToxicLabel from '../components/ToxicLabel'; - -function isToxic(actions) { - return actions.some((action) => action.__typename === 'FlagAction' && action.reason === 'TOXIC_COMMENT'); -} +import {isToxic} from '../utils'; const enhance = compose( withFragments({ comment: gql` - fragment TalkToxicComments_Comment on Comment { + fragment TalkToxicComments_ToxicLabel_Comment on Comment { actions { __typename ... on FlagAction { diff --git a/plugins/talk-plugin-toxic-comments/client/index.js b/plugins/talk-plugin-toxic-comments/client/index.js index 8a16b8dea..1db520891 100644 --- a/plugins/talk-plugin-toxic-comments/client/index.js +++ b/plugins/talk-plugin-toxic-comments/client/index.js @@ -1,11 +1,13 @@ import translations from './translations.yml'; import CheckToxicityHook from './containers/CheckToxicityHook'; import ToxicLabel from './containers/ToxicLabel'; +import ToxicDetail from './containers/ToxicDetail'; export default { translations, slots: { commentInputDetailArea: [CheckToxicityHook], adminCommentLabels: [ToxicLabel], + adminCommentDetailArea: [ToxicDetail], }, }; diff --git a/plugins/talk-plugin-toxic-comments/client/utils.js b/plugins/talk-plugin-toxic-comments/client/utils.js new file mode 100644 index 000000000..57bfd9633 --- /dev/null +++ b/plugins/talk-plugin-toxic-comments/client/utils.js @@ -0,0 +1,4 @@ +export function isToxic(actions) { + return actions.some((action) => action.__typename === 'FlagAction' && action.reason === 'TOXIC_COMMENT'); +} + diff --git a/plugins/talk-plugin-toxic-comments/index.js b/plugins/talk-plugin-toxic-comments/index.js index 0802a6c11..444cb94f5 100644 --- a/plugins/talk-plugin-toxic-comments/index.js +++ b/plugins/talk-plugin-toxic-comments/index.js @@ -1,8 +1,10 @@ const {readFileSync} = require('fs'); const path = require('path'); const hooks = require('./server/hooks'); +const resolvers = require('./server/resolvers'); module.exports = { typeDefs: readFileSync(path.join(__dirname, 'server/typeDefs.graphql'), 'utf8'), hooks, + resolvers, }; diff --git a/plugins/talk-plugin-toxic-comments/server/resolvers.js b/plugins/talk-plugin-toxic-comments/server/resolvers.js new file mode 100644 index 000000000..5af584b44 --- /dev/null +++ b/plugins/talk-plugin-toxic-comments/server/resolvers.js @@ -0,0 +1,7 @@ +const get = require('lodash/get'); + +module.exports = { + Comment: { + toxicity: (comment) => get(comment, 'metadata.perspective.SEVERE_TOXICITY.summaryScore'), + } +}; diff --git a/plugins/talk-plugin-toxic-comments/server/typeDefs.graphql b/plugins/talk-plugin-toxic-comments/server/typeDefs.graphql index b4dfc8345..c9e28fb9c 100644 --- a/plugins/talk-plugin-toxic-comments/server/typeDefs.graphql +++ b/plugins/talk-plugin-toxic-comments/server/typeDefs.graphql @@ -5,3 +5,6 @@ input CreateCommentInput { checkToxicity: Boolean } +type Comment { + toxicity: Float +}