diff --git a/.eslintignore b/.eslintignore
index fc0214dd2..22cf3d4b8 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -26,5 +26,6 @@ plugins/*
!plugins/talk-plugin-toxic-comments
!plugins/talk-plugin-remember-sort
!plugins/talk-plugin-deep-reply-count
+!plugins/talk-plugin-flag-details
node_modules
diff --git a/.gitignore b/.gitignore
index bcc7c89b1..e253c5904 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,5 +43,6 @@ plugins/*
!plugins/talk-plugin-toxic-comments
!plugins/talk-plugin-remember-sort
!plugins/talk-plugin-deep-reply-count
+!plugins/talk-plugin-flag-details
**/node_modules/*
diff --git a/client/coral-admin/src/components/ActionButton.css b/client/coral-admin/src/components/ActionButton.css
deleted file mode 100644
index 226006c6b..000000000
--- a/client/coral-admin/src/components/ActionButton.css
+++ /dev/null
@@ -1,24 +0,0 @@
-.actionButton {
- transform: scale(.8);
- margin: 0;
-}
-
-.minimal {
- width: 45px;
- min-width: 0;
-}
-
-.approve__active {
- box-shadow: none;
- color: white;
- background-color: #519954;
- cursor: not-allowed;
-}
-
-.reject__active, .rejected__active {
- color: white;
- background-color: #D03235;
- box-shadow: none;
- cursor: not-allowed;
-}
-
diff --git a/client/coral-admin/src/components/ActionButton.js b/client/coral-admin/src/components/ActionButton.js
deleted file mode 100644
index 77456b939..000000000
--- a/client/coral-admin/src/components/ActionButton.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import styles from './ActionButton.css';
-import {Button} from 'coral-ui';
-import {menuActionsMap} from '../utils/moderationQueueActionsMap';
-
-import t from 'coral-framework/services/i18n';
-
-const ActionButton = ({type = '', active, ...props}) => {
- const typeName = type.toLowerCase();
- let text = menuActionsMap[type].text;
-
- if (text === 'approve' && active) {
- text = 'approved';
- } else if (text === 'reject' && active) {
- text = 'rejected';
- }
-
- return (
-
- );
-};
-
-ActionButton.propTypes = {
- active: PropTypes.bool,
- type: PropTypes.oneOf(['APPROVE', 'REJECT']),
- minimal: PropTypes.bool,
- acceptComment: PropTypes.func,
- rejectComment: PropTypes.func,
-};
-
-export default ActionButton;
diff --git a/client/coral-admin/src/components/ApproveButton.css b/client/coral-admin/src/components/ApproveButton.css
new file mode 100644
index 000000000..4c42cc233
--- /dev/null
+++ b/client/coral-admin/src/components/ApproveButton.css
@@ -0,0 +1,44 @@
+.root {
+ display: block;
+ color: #519954;
+ border: solid 2px rgba(81, 153, 84, 0.75);
+ background: white;
+ padding: 10px 12px;
+ box-sizing: border-box;
+ vertical-align: middle;
+ line-height: 24px;
+ font-size: 17px;
+ height: 47px;
+ border-radius: 3px;
+ text-transform: capitalize;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
+ width: 129px;
+ transform: scale(.8);
+ margin: 0;
+
+ &:hover {
+ box-shadow: none;
+ color: white;
+ background-color: #519954;
+ cursor: pointer;
+ }
+}
+
+.active {
+ box-shadow: none;
+ color: white;
+ background-color: #519954;
+
+ &:hover {
+ cursor: not-allowed;
+ }
+}
+
+.minimal {
+ width: 45px;
+ min-width: 0;
+}
+
+.icon {
+ margin-right: 5px;
+}
diff --git a/client/coral-admin/src/components/ApproveButton.js b/client/coral-admin/src/components/ApproveButton.js
new file mode 100644
index 000000000..151a5ca29
--- /dev/null
+++ b/client/coral-admin/src/components/ApproveButton.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import cn from 'classnames';
+import styles from './ApproveButton.css';
+import {Icon} from 'coral-ui';
+
+import t from 'coral-framework/services/i18n';
+
+const ApproveButton = ({active, minimal, onClick}) => {
+ const text = active ? t('modqueue.approved') : t('modqueue.approve');
+ return (
+
+ );
+};
+
+ApproveButton.propTypes = {
+ active: PropTypes.bool,
+ minimal: PropTypes.bool,
+ onClick: PropTypes.func,
+};
+
+export default ApproveButton;
+
diff --git a/client/coral-admin/src/components/CommentDetails.js b/client/coral-admin/src/components/CommentDetails.js
index 9d9c26813..d984ce0c1 100644
--- a/client/coral-admin/src/components/CommentDetails.js
+++ b/client/coral-admin/src/components/CommentDetails.js
@@ -2,7 +2,7 @@ import React, {Component} from 'react';
import PropTypes from 'prop-types';
import styles from './CommentDetails.css';
import t from 'coral-framework/services/i18n';
-import FlagDetails from './FlagDetails';
+import Slot from 'coral-framework/components/Slot';
class CommentDetails extends Component {
state = {
@@ -23,15 +23,20 @@ class CommentDetails extends Component {
}
render() {
- const {actions, viewUserDetail} = this.props;
+ const {data, root, comment} = this.props;
const {showDetail} = this.state;
+ const queryData = {
+ root,
+ comment,
+ };
return (
@@ -40,11 +45,9 @@ class CommentDetails extends Component {
}
CommentDetails.propTypes = {
- actions: PropTypes.arrayOf(PropTypes.shape({
- message: PropTypes.string,
- user: PropTypes.shape({username: PropTypes.string})
- })).isRequired,
- viewUserDetail: PropTypes.func.isRequired,
+ data: PropTypes.object.isRequired,
+ root: PropTypes.object.isRequired,
+ comment: PropTypes.object.isRequired,
};
export default CommentDetails;
diff --git a/client/coral-admin/src/components/RejectButton.css b/client/coral-admin/src/components/RejectButton.css
new file mode 100644
index 000000000..a06cf5f43
--- /dev/null
+++ b/client/coral-admin/src/components/RejectButton.css
@@ -0,0 +1,44 @@
+.root {
+ display: block;
+ color: #D03235;
+ border: solid 1px #D03235;
+ background: white;
+ padding: 10px 11px;
+ box-sizing: border-box;
+ vertical-align: middle;
+ line-height: 24px;
+ font-size: 17px;
+ height: 47px;
+ border-radius: 3px;
+ text-transform: capitalize;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
+ width: 129px;
+ transform: scale(.8);
+ margin: 0;
+
+ &:hover {
+ color: white;
+ background-color: #D03235;
+ box-shadow: none;
+ cursor: pointer;
+ }
+}
+
+.active {
+ color: white;
+ background-color: #D03235;
+ box-shadow: none;
+
+ &:hover {
+ cursor: not-allowed;
+ }
+}
+
+.minimal {
+ width: 45px;
+ min-width: 0;
+}
+
+.icon {
+ margin-right: 5px;
+}
diff --git a/client/coral-admin/src/components/RejectButton.js b/client/coral-admin/src/components/RejectButton.js
new file mode 100644
index 000000000..e01102dc3
--- /dev/null
+++ b/client/coral-admin/src/components/RejectButton.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import cn from 'classnames';
+import styles from './RejectButton.css';
+import {Icon} from 'coral-ui';
+
+import t from 'coral-framework/services/i18n';
+
+const RejectButton = ({active, minimal, onClick}) => {
+ const text = active ? t('modqueue.rejected') : t('modqueue.reject');
+ return (
+
+ );
+};
+
+RejectButton.propTypes = {
+ active: PropTypes.bool,
+ minimal: PropTypes.bool,
+ onClick: PropTypes.func,
+};
+
+export default RejectButton;
+
diff --git a/client/coral-admin/src/components/UserDetail.js b/client/coral-admin/src/components/UserDetail.js
index b6b239057..a5955af45 100644
--- a/client/coral-admin/src/components/UserDetail.js
+++ b/client/coral-admin/src/components/UserDetail.js
@@ -5,7 +5,6 @@ import styles from './UserDetail.css';
import {Icon, Button, Drawer, Spinner} from 'coral-ui';
import {Slot} from 'coral-framework/components';
import ButtonCopyToClipboard from './ButtonCopyToClipboard';
-import {actionsMap} from '../utils/moderationQueueActionsMap';
import ClickOutside from 'coral-framework/components/ClickOutside';
import LoadMore from '../components/LoadMore';
import cn from 'classnames';
@@ -70,6 +69,7 @@ export default class UserDetail extends React.Component {
renderLoaded() {
const {
+ data,
root,
root: {
user,
@@ -177,15 +177,15 @@ export default class UserDetail extends React.Component {
{
nodes.map((comment) => {
- const status = comment.action_summaries ? 'FLAGGED' : comment.status;
const selected = selectedCommentIds.indexOf(comment.id) !== -1;
return
(this.props.comment.status === 'ACCEPTED'
+ ? null
+ : this.props.acceptComment({commentId: this.props.comment.id})
+ );
+
+ reject = () => (this.props.comment.status === 'REJECTED'
+ ? null
+ : this.props.rejectComment({commentId: this.props.comment.id})
+ );
+
render() {
const {
- actions = [],
comment,
- viewUserDetail,
suspectWords,
bannedWords,
selected,
toggleSelect,
className,
- user,
- ...props
+ data,
} = this.props;
- const flagActions = comment.actions && comment.actions.filter((a) => a.__typename === 'FlagAction');
-
return (
- {actions.map((action, i) => {
- const active =
- (action === 'REJECT' && comment.status === 'REJECTED') ||
- (action === 'APPROVE' && comment.status === 'ACCEPTED');
- return (
-
- (comment.status === 'ACCEPTED'
- ? null
- : props.acceptComment({commentId: comment.id}))}
- rejectComment={() =>
- (comment.status === 'REJECTED'
- ? null
- : props.rejectComment({commentId: comment.id}))}
- />
- );
- })}
+
+
- {flagActions && flagActions.length
- ?
- : null}
+
);
}
@@ -135,6 +127,8 @@ UserDetailComment.propTypes = {
bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired,
toggleSelect: PropTypes.func,
comment: PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ status: PropTypes.string.isRequired,
body: PropTypes.string.isRequired,
actions: PropTypes.array,
created_at: PropTypes.string.isRequired,
diff --git a/client/coral-admin/src/containers/CommentDetails.js b/client/coral-admin/src/containers/CommentDetails.js
new file mode 100644
index 000000000..a72a8eee4
--- /dev/null
+++ b/client/coral-admin/src/containers/CommentDetails.js
@@ -0,0 +1,23 @@
+import {gql} from 'react-apollo';
+import CommentDetails from '../components/CommentDetails';
+import {getSlotFragmentSpreads} from 'coral-framework/utils';
+import withFragments from 'coral-framework/hocs/withFragments';
+
+const slots = [
+ 'adminCommentDetailArea',
+];
+
+export default withFragments({
+ root: gql`
+ fragment CoralAdmin_CommentDetails_root on RootQuery {
+ __typename
+ ${getSlotFragmentSpreads(slots, 'root')}
+ }
+ `,
+ comment: gql`
+ fragment CoralAdmin_CommentDetails_comment on Comment {
+ __typename
+ ${getSlotFragmentSpreads(slots, 'comment')}
+ }
+ `
+})(CommentDetails);
diff --git a/client/coral-admin/src/containers/CommentLabels.js b/client/coral-admin/src/containers/CommentLabels.js
index af6a0d963..1942d1ad0 100644
--- a/client/coral-admin/src/containers/CommentLabels.js
+++ b/client/coral-admin/src/containers/CommentLabels.js
@@ -8,6 +8,12 @@ const slots = [
];
export default withFragments({
+ root: gql`
+ fragment CoralAdmin_CommentLabels_root on RootQuery {
+ __typename
+ ${getSlotFragmentSpreads(slots, 'root')}
+ }
+ `,
comment: gql`
fragment CoralAdmin_CommentLabels_comment on Comment {
hasParent
diff --git a/client/coral-admin/src/containers/UserDetail.js b/client/coral-admin/src/containers/UserDetail.js
index 5effb2b84..2ae842b1d 100644
--- a/client/coral-admin/src/containers/UserDetail.js
+++ b/client/coral-admin/src/containers/UserDetail.js
@@ -160,8 +160,10 @@ export const withUserDetailQuery = withQuery(gql`
}) {
...CoralAdmin_Moderation_CommentConnection
}
+ ...${getDefinitionName(UserDetailComment.fragments.root)}
${getSlotFragmentSpreads(slots, 'root')}
}
+ ${UserDetailComment.fragments.root}
${commentConnectionFragment}
`, {
options: ({userId, statuses}) => {
diff --git a/client/coral-admin/src/containers/UserDetailComment.js b/client/coral-admin/src/containers/UserDetailComment.js
index 6b3572434..9eef5934f 100644
--- a/client/coral-admin/src/containers/UserDetailComment.js
+++ b/client/coral-admin/src/containers/UserDetailComment.js
@@ -3,10 +3,20 @@ import UserDetailComment from '../components/UserDetailComment';
import withFragments from 'coral-framework/hocs/withFragments';
import {getDefinitionName} from 'coral-framework/utils';
import CommentLabels from './CommentLabels';
+import CommentDetails from './CommentDetails';
export default withFragments({
+ root: gql`
+ fragment CoralAdmin_UserDetailComment_root on RootQuery {
+ __typename
+ ...${getDefinitionName(CommentLabels.fragments.root)}
+ ...${getDefinitionName(CommentDetails.fragments.root)}
+ }
+ ${CommentLabels.fragments.root}
+ ${CommentDetails.fragments.root}
+ `,
comment: gql`
- fragment CoralAdmin_UserDetail_comment on Comment {
+ fragment CoralAdmin_UserDetailComment_comment on Comment {
id
body
created_at
@@ -17,22 +27,13 @@ export default withFragments({
title
url
}
- actions {
- ... on FlagAction {
- id
- reason
- message
- user {
- id
- username
- }
- }
- }
editing {
edited
}
...${getDefinitionName(CommentLabels.fragments.comment)}
+ ...${getDefinitionName(CommentDetails.fragments.comment)}
}
${CommentLabels.fragments.comment}
+ ${CommentDetails.fragments.comment}
`
})(UserDetailComment);
diff --git a/client/coral-admin/src/routes/Community/components/ActionButton.css b/client/coral-admin/src/routes/Community/components/ActionButton.css
deleted file mode 100644
index 8f328e8b8..000000000
--- a/client/coral-admin/src/routes/Community/components/ActionButton.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.actionButton {
- transform: scale(.8);
- margin: 0;
-}
diff --git a/client/coral-admin/src/routes/Community/components/ActionButton.js b/client/coral-admin/src/routes/Community/components/ActionButton.js
deleted file mode 100644
index 0ef9b8a39..000000000
--- a/client/coral-admin/src/routes/Community/components/ActionButton.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import styles from './ActionButton.css';
-import {Button} from 'coral-ui';
-import {menuActionsMap} from '../../../utils/moderationQueueActionsMap';
-
-import t from 'coral-framework/services/i18n';
-
-// TODO: Needs refactoring.
-const ActionButton = ({type = '', user, ...props}) => {
- return (
-
- );
-};
-
-export default ActionButton;
diff --git a/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js b/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js
index 1d78c015a..e617def53 100644
--- a/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js
+++ b/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js
@@ -47,7 +47,6 @@ class FlaggedAccounts extends React.Component {
this.props.viewUserDetail(this.props.user.id);
+ showRejectUsernameDialog = () => this.props.showRejectUsernameDialog({id: this.props.user.id});
+ approveUser = () => this.props.approveUser({
+ userId: this.props.user.id,
+ });
render() {
const {
user,
- modActionButtons,
viewUserDetail,
selected,
- approveUser,
- showRejectUsernameDialog,
me,
className,
} = this.props;
@@ -125,14 +126,12 @@ class User extends React.Component {
- {modActionButtons.map((action, i) =>
-
- )}
+
+
diff --git a/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js b/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js
index a9877368a..20c411e52 100644
--- a/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js
+++ b/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js
@@ -51,7 +51,7 @@ class RejectUsernameDialog extends Component {
const next = () => this.setState({stage: stage + 1});
const suspend = async () => {
try {
- await rejectUsername({id: user.user.id, message: this.state.email});
+ await rejectUsername({id: user.id, message: this.state.email});
this.props.handleClose();
} catch (err) {
diff --git a/client/coral-admin/src/routes/Community/containers/Community.js b/client/coral-admin/src/routes/Community/containers/Community.js
index 4e60c64d7..6e20a3167 100644
--- a/client/coral-admin/src/routes/Community/containers/Community.js
+++ b/client/coral-admin/src/routes/Community/containers/Community.js
@@ -78,7 +78,11 @@ const withData = withQuery(gql`
${FlaggedAccounts.fragments.root}
${FlaggedUser.fragments.root}
${FlaggedUser.fragments.me}
-`);
+`, {
+ options: {
+ fetchPolicy: 'network-only',
+ },
+});
export default compose(
connect(mapStateToProps, mapDispatchToProps),
diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js
index c761ff591..42c9c2d13 100644
--- a/client/coral-admin/src/routes/Moderation/components/Comment.js
+++ b/client/coral-admin/src/routes/Moderation/components/Comment.js
@@ -8,13 +8,13 @@ import styles from './Comment.css';
import CommentLabels from 'coral-admin/src/components/CommentLabels';
import CommentAnimatedEdit from 'coral-admin/src/components/CommentAnimatedEdit';
import Slot from 'coral-framework/components/Slot';
-import {getActionSummary} from 'coral-framework/utils';
-import ActionButton from 'coral-admin/src/components/ActionButton';
import ActionsMenu from 'coral-admin/src/components/ActionsMenu';
import ActionsMenuItem from 'coral-admin/src/components/ActionsMenuItem';
import CommentBodyHighlighter from 'coral-admin/src/components/CommentBodyHighlighter';
import IfHasLink from 'coral-admin/src/components/IfHasLink';
import cn from 'classnames';
+import ApproveButton from 'coral-admin/src/components/ApproveButton';
+import RejectButton from 'coral-admin/src/components/RejectButton';
import t, {timeago} from 'coral-framework/services/i18n';
@@ -45,11 +45,19 @@ class Comment extends React.Component {
return viewUserDetail(comment.user.id);
};
+ approve = () => (this.props.comment.status === 'ACCEPTED'
+ ? null
+ : this.props.acceptComment({commentId: this.props.comment.id})
+ );
+
+ reject = () => (this.props.comment.status === 'REJECTED'
+ ? null
+ : this.props.rejectComment({commentId: this.props.comment.id})
+ );
+
render() {
const {
- actions = [],
comment,
- viewUserDetail,
suspectWords,
bannedWords,
selected,
@@ -58,15 +66,9 @@ class Comment extends React.Component {
root,
currentUserId,
currentAsset,
- acceptComment,
- rejectComment,
} = this.props;
- const flagActionSummaries = getActionSummary('FlagActionSummary', comment);
- const flagActions = comment.actions && comment.actions.filter((a) => a.__typename === 'FlagAction');
-
const selectionStateCSS = selected ? 'mdl-shadow--16dp' : 'mdl-shadow--2dp';
-
const queryData = {root, comment, asset: comment.asset};
return (
@@ -153,28 +155,14 @@ class Comment extends React.Component {
- {actions.map((action, i) => {
- const active =
- (action === 'REJECT' && comment.status === 'REJECTED') ||
- (action === 'APPROVE' && comment.status === 'ACCEPTED');
- return (
-
- (comment.status === 'ACCEPTED'
- ? null
- : acceptComment({commentId: comment.id}))}
- rejectComment={() =>
- (comment.status === 'REJECTED'
- ? null
- : rejectComment({commentId: comment.id}))}
- />
- );
- })}
+
+
- {flagActions && flagActions.length
- ?
- : null}
-
);
@@ -214,6 +195,8 @@ Comment.propTypes = {
showSuspendUserDialog: PropTypes.func.isRequired,
currentUserId: PropTypes.string.isRequired,
comment: PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ status: PropTypes.string.isRequired,
body: PropTypes.string.isRequired,
action_summaries: PropTypes.array,
actions: PropTypes.array,
@@ -230,7 +213,6 @@ Comment.propTypes = {
}),
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
- actions: PropTypes.array.isRequired,
selected: PropTypes.bool,
};
diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js
index 517892a77..47ed56925 100644
--- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js
+++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js
@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import Comment from '../containers/Comment';
import styles from './ModerationQueue.css';
import EmptyCard from '../../../components/EmptyCard';
-import {actionsMap} from '../../../utils/moderationQueueActionsMap';
import LoadMore from '../../../components/LoadMore';
import ViewMore from './ViewMore';
import t from 'coral-framework/services/i18n';
@@ -140,7 +139,6 @@ class ModerationQueue extends React.Component {
if (singleView) {
const index = comments.findIndex((comment) => comment.id === selectedCommentId);
const comment = comments[index];
- const status = comment.action_summaries ? 'FLAGGED' : comment.status;
return (
{
- const status = comment.action_summaries ? 'FLAGGED' : comment.status;
return gql`
organizationName
moderation
}
+ ...${getDefinitionName(Comment.fragments.root)}
}
+ ${Comment.fragments.root}
${commentConnectionFragment}
`, {
options: (props) => {
diff --git a/client/coral-admin/src/utils/moderationQueueActionsMap.js b/client/coral-admin/src/utils/moderationQueueActionsMap.js
deleted file mode 100644
index 95b0ecb55..000000000
--- a/client/coral-admin/src/utils/moderationQueueActionsMap.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const actionsMap = {
- PREMOD: ['APPROVE', 'REJECT'],
- FLAGGED: ['APPROVE', 'REJECT'],
- REJECTED: ['APPROVE', 'REJECTED']
-};
-
-export const menuActionsMap = {
- 'REJECT': {status: 'REJECTED', text: 'reject', icon: 'close', key: 'f'},
- 'REJECTED': {status: 'REJECTED', text: 'rejected', icon: 'close'},
- 'APPROVE': {status: 'ACCEPTED', text: 'approve', icon: 'done', key: 'd'},
- 'FLAGGED': {status: 'FLAGGED', text: 'flag', icon: 'flag', filter: 'Untouched'},
- 'BAN': {status: 'BANNED', text: 'ban_user', icon: 'not interested'},
- '': {icon: 'done'}
-};
diff --git a/client/coral-ui/components/Button.css b/client/coral-ui/components/Button.css
index 1b7efb205..ce2cff350 100644
--- a/client/coral-ui/components/Button.css
+++ b/client/coral-ui/components/Button.css
@@ -130,59 +130,6 @@
background: #00a291;
}
-.type--approve {
- display: block;
- color: #519954;
- border: solid 2px rgba(81, 153, 84, 0.75);
- background: white;
- padding: 10px 12px;
- box-sizing: border-box;
- vertical-align: middle;
- line-height: 24px;
- font-size: 17px;
- height: 47px;
- border-radius: 3px;
- text-transform: capitalize;
- box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
- width: 129px;
-
- &:hover {
- box-shadow: none;
- color: white;
- background-color: #519954;
- }
-}
-
-.type--reject, .type--rejected {
- display: block;
- color: #D03235;
- border: solid 1px #D03235;
- background: white;
- padding: 10px 11px;
- box-sizing: border-box;
- vertical-align: middle;
- line-height: 24px;
- font-size: 17px;
- height: 47px;
- border-radius: 3px;
- text-transform: capitalize;
- box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
- width: 129px;
-
- &:hover {
- color: white;
- background-color: #D03235;
- box-shadow: none;
- }
-}
-
-.type--rejected {
- color: white;
- background-color: #D03235;
- box-shadow: none;
- cursor: not-allowed;
-}
-
.type--ban, .type--actions {
display: block;
color: #616161;
diff --git a/plugins/talk-plugin-flag-details/.eslintrc.json b/plugins/talk-plugin-flag-details/.eslintrc.json
new file mode 100644
index 000000000..78f7c2397
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "@coralproject/eslint-config-talk"
+}
diff --git a/plugins/talk-plugin-flag-details/client/.babelrc b/plugins/talk-plugin-flag-details/client/.babelrc
new file mode 100644
index 000000000..60be246eb
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/client/.babelrc
@@ -0,0 +1,14 @@
+{
+ "presets": [
+ "es2015"
+ ],
+ "plugins": [
+ "add-module-exports",
+ "transform-class-properties",
+ "transform-decorators-legacy",
+ "transform-object-assign",
+ "transform-object-rest-spread",
+ "transform-async-to-generator",
+ "transform-react-jsx"
+ ]
+}
\ No newline at end of file
diff --git a/plugins/talk-plugin-flag-details/client/.eslintrc.json b/plugins/talk-plugin-flag-details/client/.eslintrc.json
new file mode 100644
index 000000000..c8a6db18a
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/client/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "@coralproject/eslint-config-talk/client"
+}
diff --git a/plugins/talk-plugin-flag-details/client/components/FlagDetails.css b/plugins/talk-plugin-flag-details/client/components/FlagDetails.css
new file mode 100644
index 000000000..302e24858
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/client/components/FlagDetails.css
@@ -0,0 +1,43 @@
+
+.info {
+ vertical-align: middle;
+ list-style: none;
+ display: inline-block;
+ padding: 0;
+ font-size: 12px;
+}
+
+.detail {
+ padding: 0;
+ list-style: none;
+ font-size: 12px;
+ font-weight: 500;
+}
+
+.subDetail {
+ margin-left:10px;
+ padding: 0;
+ list-style: none;
+ font-size: 12px;
+ font-weight: normal;
+ color: #888;
+}
+
+.lessDetail {
+ display: inline-block;
+ margin-right: 10px;
+}
+
+.username {
+ color: #393B44;
+ text-decoration: none;
+ cursor: pointer;
+ font-weight: 600;
+ padding: 2px 5px;
+ border-radius: 2px;
+ margin-left: -5px;
+ transition: background-color 200ms ease;
+ &:hover {
+ background-color: #E0E0E0;
+ }
+}
diff --git a/plugins/talk-plugin-flag-details/client/components/FlagDetails.js b/plugins/talk-plugin-flag-details/client/components/FlagDetails.js
new file mode 100644
index 000000000..0d415217d
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/client/components/FlagDetails.js
@@ -0,0 +1,79 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+import styles from './FlagDetails.css';
+import {t} from 'plugin-api/beta/client/services';
+import CommentDetail from 'coral-admin/src/components/CommentDetail';
+
+class FlagDetails extends Component {
+
+ render() {
+ const {comment: {actions}, viewUserDetail, more} = this.props;
+
+ const flagActions = actions && actions.filter((a) => a.__typename === 'FlagAction');
+ const summaries = flagActions.reduce((sum, action) => {
+ if (!(action.reason in sum)) {
+ sum[action.reason] = {count: 0, userFlagged: false, actions: []};
+ }
+ sum[action.reason].count++;
+ if (action.user) {
+ sum[action.reason].userFlagged = true;
+ }
+ sum[action.reason].actions.push(action);
+ return sum;
+ }, {});
+
+ const userFlagReasons = Object.keys(summaries).filter((reason) => summaries[reason].userFlagged);
+
+ return (
+
+ {Object.keys(summaries).map((reason) =>
+
+ {reason} {summaries[reason].userFlagged && `(${summaries[reason].count})`}
+
+ )}
+
+ }>
+ {more && userFlagReasons.length > 0 && (
+
+ {userFlagReasons
+ .map((reason) => (
+ -
+ {reason} ({summaries[reason].count})
+
+
+ ))
+ }
+
+ )}
+
+ );
+ }
+}
+
+FlagDetails.propTypes = {
+ more: PropTypes.bool,
+ comment: PropTypes.shape({
+ actions: PropTypes.arrayOf(PropTypes.shape({
+ message: PropTypes.string,
+ user: PropTypes.shape({username: PropTypes.string})
+ })).isRequired,
+ }).isRequired,
+ viewUserDetail: PropTypes.func.isRequired,
+};
+
+export default FlagDetails;
diff --git a/plugins/talk-plugin-flag-details/client/containers/FlagDetails.js b/plugins/talk-plugin-flag-details/client/containers/FlagDetails.js
new file mode 100644
index 000000000..2ee88d2dd
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/client/containers/FlagDetails.js
@@ -0,0 +1,37 @@
+import {compose, gql} from 'react-apollo';
+import FlagDetails from '../components/FlagDetails';
+import {bindActionCreators} from 'redux';
+import {withFragments, excludeIf} from 'plugin-api/beta/client/hocs';
+import {viewUserDetail} from 'coral-admin/src/actions/userDetail';
+import {connect} from 'react-redux';
+
+const mapDispatchToProps = (dispatch) => ({
+ ...bindActionCreators({
+ viewUserDetail,
+ }, dispatch)
+});
+
+const enhance = compose(
+ connect(null, mapDispatchToProps),
+ withFragments({
+ comment: gql`
+ fragment CoralAdmin_FlagDetails_comment on Comment {
+ actions {
+ __typename
+ ... on FlagAction {
+ id
+ reason
+ message
+ user {
+ id
+ username
+ }
+ }
+ }
+ }
+ `
+ }),
+ excludeIf(({comment: {actions}}) => !actions.some((action) => action.__typename === 'FlagAction')),
+);
+
+export default enhance(FlagDetails);
diff --git a/plugins/talk-plugin-flag-details/client/index.js b/plugins/talk-plugin-flag-details/client/index.js
new file mode 100644
index 000000000..045194872
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/client/index.js
@@ -0,0 +1,9 @@
+import FlagDetails from './containers/FlagDetails';
+import translations from './translations.yml';
+
+export default {
+ translations,
+ slots: {
+ adminCommentDetailArea: [FlagDetails],
+ }
+};
diff --git a/plugins/talk-plugin-flag-details/client/translations.yml b/plugins/talk-plugin-flag-details/client/translations.yml
new file mode 100644
index 000000000..3b2511025
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/client/translations.yml
@@ -0,0 +1,3 @@
+en:
+ talk-plugin-fag-details:
+
diff --git a/plugins/talk-plugin-flag-details/index.js b/plugins/talk-plugin-flag-details/index.js
new file mode 100644
index 000000000..f053ebf79
--- /dev/null
+++ b/plugins/talk-plugin-flag-details/index.js
@@ -0,0 +1 @@
+module.exports = {};
diff --git a/plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js b/plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js
index 32b83fbb3..28f75de37 100644
--- a/plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js
+++ b/plugins/talk-plugin-toxic-comments/client/containers/ToxicDetail.js
@@ -15,7 +15,7 @@ const enhance = compose(
}
}`,
}),
- excludeIf(({comment: {toxicity}}) => toxicity === null),
+ excludeIf(({comment: {toxicity}, more}) => !more || toxicity === null),
);
export default enhance(ToxicDetail);