mirror of
https://github.com/wassname/talk.git
synced 2026-08-06 13:41:02 +08:00
Refactor and pluginize comment details
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "@coralproject/eslint-config-talk"
|
||||
}
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "@coralproject/eslint-config-talk/client"
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 (
|
||||
<CommentDetail
|
||||
icon={'flag'}
|
||||
header={`${t('community.flags')} (${Object.keys(summaries).length})`}
|
||||
info={
|
||||
<ul className={styles.info}>
|
||||
{Object.keys(summaries).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>
|
||||
)}
|
||||
</CommentDetail>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -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);
|
||||
@@ -0,0 +1,9 @@
|
||||
import FlagDetails from './containers/FlagDetails';
|
||||
import translations from './translations.yml';
|
||||
|
||||
export default {
|
||||
translations,
|
||||
slots: {
|
||||
adminCommentDetailArea: [FlagDetails],
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
en:
|
||||
talk-plugin-fag-details:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
@@ -15,7 +15,7 @@ const enhance = compose(
|
||||
}
|
||||
}`,
|
||||
}),
|
||||
excludeIf(({comment: {toxicity}}) => toxicity === null),
|
||||
excludeIf(({comment: {toxicity}, more}) => !more || toxicity === null),
|
||||
);
|
||||
|
||||
export default enhance(ToxicDetail);
|
||||
|
||||
Reference in New Issue
Block a user