Implement user flag details as slot component

This commit is contained in:
Chi Vinh Le
2017-10-02 21:37:47 +07:00
parent 9b39017f25
commit c2f22bbf98
6 changed files with 151 additions and 40 deletions
@@ -7,23 +7,21 @@ import {Slot, IfSlotIsNotEmpty, CommentDetail} from 'plugin-api/beta/client/comp
class FlagDetails extends Component {
render() {
const {comment: {actions}, viewUserDetail, more, data, root, comment} = this.props;
const {comment: {actions}, more, data, root, comment} = 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: 0, 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);
const reasons = Object.keys(summaries);
const queryData = {
root,
comment,
@@ -35,36 +33,13 @@ class FlagDetails extends Component {
header={`${t('community.flags')} (${Object.keys(summaries).length})`}
info={
<ul className={styles.info}>
{Object.keys(summaries).map((reason) =>
{reasons.map((reason) =>
<li key={reason} className={styles.lessDetail}>
{reason} {summaries[reason].userFlagged && `(${summaries[reason].count})`}
</li>
)}
</ul>
}>
{more && userFlagReasons.length > 0 && (
<ul className={styles.detail}>
{userFlagReasons
.map((reason) => (
<li key={reason}>
{reason} ({summaries[reason].count})
<ul className={styles.subDetail}>
{summaries[reason].actions.map((action) =>
<li key={action.user.id}>
{action.user &&
<a className={styles.username} onClick={() => viewUserDetail(action.user.id)}>
{action.user.username}
</a>
}
{action.message}
</li>
)}
</ul>
</li>
))
}
</ul>
)}
{more && (
<IfSlotIsNotEmpty
slot="adminCommentMoreFlagDetails"
@@ -84,13 +59,14 @@ class FlagDetails extends Component {
FlagDetails.propTypes = {
more: PropTypes.bool,
data: PropTypes.object,
root: PropTypes.object,
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;
@@ -0,0 +1,45 @@
.info {
vertical-align: middle;
list-style: none;
display: inline-block;
padding: 0;
font-size: 12px;
margin: 0;
}
.detail {
margin: 0;
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;
}
}
@@ -0,0 +1,59 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import styles from './UserFlagDetails.css';
class UserFlagDetails extends Component {
render() {
const {comment: {actions}, viewUserDetail} = this.props;
const flagActions = actions && actions.filter((a) => a.__typename === 'FlagAction');
const summaries = flagActions.reduce((sum, action) => {
if (!action.user) {
return sum;
}
if (!(action.reason in sum)) {
sum[action.reason] = {count: 0, actions: []};
}
sum[action.reason].count++;
sum[action.reason].actions.push(action);
return sum;
}, {});
return (
<ul className={styles.detail}>
{Object.keys(summaries)
.map((reason) => (
<li key={reason}>
{reason} ({summaries[reason].count})
<ul className={styles.subDetail}>
{summaries[reason].actions.map((action) =>
<li key={action.user.id}>
{action.user &&
<a className={styles.username} onClick={() => viewUserDetail(action.user.id)}>
{action.user.username}
</a>
}
{action.message}
</li>
)}
</ul>
</li>
))
}
</ul>
);
}
}
UserFlagDetails.propTypes = {
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 UserFlagDetails;
@@ -1,23 +1,13 @@
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 'plugin-api/beta/client/actions/admin';
import {connect} from 'react-redux';
import {getSlotFragmentSpreads} from 'plugin-api/beta/client/utils';
const slots = [
'adminCommentMoreFlagDetails',
];
const mapDispatchToProps = (dispatch) => ({
...bindActionCreators({
viewUserDetail,
}, dispatch)
});
const enhance = compose(
connect(null, mapDispatchToProps),
withFragments({
root: gql`
fragment CoralAdmin_FlagDetails_root on RootQuery {
@@ -0,0 +1,39 @@
import {compose, gql} from 'react-apollo';
import UserFlagDetails from '../components/UserFlagDetails';
import {bindActionCreators} from 'redux';
import {withFragments, excludeIf} from 'plugin-api/beta/client/hocs';
import {viewUserDetail} from 'plugin-api/beta/client/actions/admin';
import {connect} from 'react-redux';
const mapDispatchToProps = (dispatch) => ({
...bindActionCreators({
viewUserDetail,
}, dispatch)
});
const enhance = compose(
connect(null, mapDispatchToProps),
withFragments({
comment: gql`
fragment CoralAdmin_UserFlagDetails_comment on Comment {
actions {
__typename
... on FlagAction {
id
reason
message
user {
id
username
}
}
}
}
`
}),
excludeIf(({comment: {actions}}) =>
!actions.some((action) => action.__typename === 'FlagAction' && action.user
)),
);
export default enhance(UserFlagDetails);
@@ -1,9 +1,11 @@
import FlagDetails from './containers/FlagDetails';
import UserFlagDetails from './containers/UserFlagDetails';
import translations from './translations.yml';
export default {
translations,
slots: {
adminCommentDetailArea: [FlagDetails],
adminCommentMoreFlagDetails: [UserFlagDetails],
}
};