mirror of
https://github.com/wassname/talk.git
synced 2026-08-12 12:30:39 +08:00
Moving commentList to ModerationList
This commit is contained in:
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import timeago from 'timeago.js';
|
||||
import Linkify from 'react-linkify';
|
||||
|
||||
import styles from './CommentList.css';
|
||||
import styles from './ModerationList.css';
|
||||
|
||||
import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from '../translations.json';
|
||||
|
||||
+54
-30
@@ -1,5 +1,5 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
import styles from './CommentList.css';
|
||||
import styles from './ModerationList.css';
|
||||
import key from 'keymaster';
|
||||
import Hammer from 'hammerjs';
|
||||
import Comment from 'components/Comment';
|
||||
@@ -13,15 +13,17 @@ const modActions = {
|
||||
};
|
||||
|
||||
// Renders a comment list and allow performing actions
|
||||
export default class CommentList extends React.Component {
|
||||
export default class ModerationList extends React.Component {
|
||||
static propTypes = {
|
||||
isActive: PropTypes.bool,
|
||||
singleView: PropTypes.bool,
|
||||
commentIds: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
comments: PropTypes.object.isRequired,
|
||||
users: PropTypes.object.isRequired,
|
||||
commentIds: PropTypes.arrayOf(PropTypes.string),
|
||||
actionIds: PropTypes.arrayOf(PropTypes.string),
|
||||
comments: PropTypes.object,
|
||||
users: PropTypes.object,
|
||||
actions: PropTypes.object,
|
||||
onClickAction: PropTypes.func,
|
||||
|
||||
|
||||
// list of actions (flags, etc) associated with the comments
|
||||
modActions: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
loading: PropTypes.bool,
|
||||
@@ -73,11 +75,11 @@ export default class CommentList extends React.Component {
|
||||
// Add key handlers. Each action has one and added j/k for moving around
|
||||
bindKeyHandlers () {
|
||||
this.props.modActions.filter(action => modActions[action].key).forEach(action => {
|
||||
key(modActions[action].key, 'commentList', () => this.props.isActive && this.actionKeyHandler(modActions[action].status));
|
||||
key(modActions[action].key, 'moderationList', () => this.props.isActive && this.actionKeyHandler(modActions[action].status));
|
||||
});
|
||||
key('j', 'commentList', () => this.props.isActive && this.moveKeyHandler('down'));
|
||||
key('k', 'commentList', () => this.props.isActive && this.moveKeyHandler('up'));
|
||||
key.setScope('commentList');
|
||||
key('j', 'moderationList', () => this.props.isActive && this.moveKeyHandler('down'));
|
||||
key('k', 'moderationList', () => this.props.isActive && this.moveKeyHandler('up'));
|
||||
key.setScope('moderationList');
|
||||
}
|
||||
|
||||
// Perform an action using the keys only if the comment is active
|
||||
@@ -111,7 +113,7 @@ export default class CommentList extends React.Component {
|
||||
}
|
||||
|
||||
unbindKeyHandlers () {
|
||||
key.deleteScope('commentList');
|
||||
key.deleteScope('moderationList');
|
||||
}
|
||||
|
||||
// If we are performing an action over a comment (aka removing from the list) we need to select a new active.
|
||||
@@ -135,31 +137,53 @@ export default class CommentList extends React.Component {
|
||||
this.props.onClickShowBanDialog(userId, userName, commentId);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {singleView, commentIds, comments, users, hideActive, key, suspectWords} = this.props;
|
||||
mapModItems = (itemId, index) => {
|
||||
const {comments, users, actions, modActions, suspectWords, hideActive} = this.props;
|
||||
const {active} = this.state;
|
||||
|
||||
// Because ids are unique, the id will either appear as an action or as a comment.
|
||||
|
||||
const item = comments[itemId] || actions[itemId];
|
||||
let modItem;
|
||||
|
||||
if (item.body) {
|
||||
// If the item is a comment...
|
||||
const author = users[item.author_id];
|
||||
modItem = <Comment
|
||||
suspectWords={suspectWords}
|
||||
comment={item}
|
||||
author={author}
|
||||
key={index}
|
||||
index={index}
|
||||
onClickAction={this.onClickAction}
|
||||
onClickShowBanDialog={this.onClickShowBanDialog}
|
||||
modActions={modActions}
|
||||
actionsMap={modActions}
|
||||
isActive={itemId === active}
|
||||
hideActive={hideActive} />;
|
||||
} else {
|
||||
// If the item is an action...
|
||||
modItem = <h2>Action</h2>;
|
||||
}
|
||||
return modItem;
|
||||
}
|
||||
|
||||
render () {
|
||||
const {singleView, commentIds, actionIds, comments, actions, key} = this.props;
|
||||
|
||||
// Combine moderations and actions into a single stream and sort by most recently updated.
|
||||
const moderationIds = [ ...commentIds, ...actionIds ].sort((a, b) => {
|
||||
const itemA = comments[a] || actions[a];
|
||||
const itemB = comments[b] || actions[b];
|
||||
return itemB.updated_at - itemA.updated_at;
|
||||
});
|
||||
|
||||
return (
|
||||
<ul
|
||||
className={`${styles.list} ${singleView ? styles.singleView : ''}`} {...key}
|
||||
id='commentList'
|
||||
id='moderationList'
|
||||
>
|
||||
{commentIds.map((commentId, index) => {
|
||||
const comment = comments[commentId];
|
||||
const author = users[comment.author_id];
|
||||
return <Comment
|
||||
suspectWords={suspectWords}
|
||||
comment={comment}
|
||||
author={author}
|
||||
key={index}
|
||||
index={index}
|
||||
onClickAction={this.onClickAction}
|
||||
onClickShowBanDialog={this.onClickShowBanDialog}
|
||||
modActions={this.props.modActions}
|
||||
actionsMap={modActions}
|
||||
isActive={commentId === active}
|
||||
hideActive={hideActive} />;
|
||||
})}
|
||||
{moderationIds.map(this.mapModItems)}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
@@ -3,11 +3,11 @@ import styles from './CommentStream.css';
|
||||
import {Snackbar} from 'react-mdl';
|
||||
import {connect} from 'react-redux';
|
||||
import {createComment, flagComment} from 'actions/comments';
|
||||
import CommentList from 'components/CommentList';
|
||||
import ModerationList from 'components/ModerationList';
|
||||
import CommentBox from 'components/CommentBox';
|
||||
|
||||
/**
|
||||
* Renders a comment stream using a CommentList component
|
||||
* Renders a comment stream using a ModerationList component
|
||||
* and adds a box for adding a new comment
|
||||
*/
|
||||
|
||||
@@ -39,12 +39,12 @@ class CommentStream extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
// Render the comment box along with the CommentList
|
||||
// Render the comment box along with the ModerationList
|
||||
render ({comments, users}, {snackbar, snackbarMsg}) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<CommentBox onSubmit={this.onSubmit} />
|
||||
<CommentList isActive hideActive
|
||||
<ModerationList isActive hideActive
|
||||
singleView={false}
|
||||
commentIds={comments.ids}
|
||||
comments={comments.byId}
|
||||
|
||||
@@ -81,7 +81,8 @@ class ModerationContainer extends React.Component {
|
||||
const mapStateToProps = state => ({
|
||||
comments: state.comments.toJS(),
|
||||
settings: state.settings.toJS(),
|
||||
users: state.users.toJS()
|
||||
users: state.users.toJS(),
|
||||
actions: state.actions.toJS(),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import styles from './ModerationQueue.css';
|
||||
|
||||
import ModerationKeysModal from 'components/ModerationKeysModal';
|
||||
import CommentList from 'components/CommentList';
|
||||
import ModerationList from 'components/ModerationList';
|
||||
import BanUserDialog from 'components/BanUserDialog';
|
||||
|
||||
import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
@@ -22,7 +22,7 @@ export default ({onTabClick, ...props}) => (
|
||||
className={`mdl-tabs__tab ${styles.tab}`}>{lang.t('modqueue.flagged')}</a>
|
||||
</div>
|
||||
<div className={`mdl-tabs__panel is-active ${styles.listContainer}`} id='pending'>
|
||||
<CommentList
|
||||
<ModerationList
|
||||
suspectWords={props.settings.settings.wordlist.suspect}
|
||||
isActive={props.activeTab === 'pending'}
|
||||
singleView={props.singleView}
|
||||
@@ -41,7 +41,7 @@ export default ({onTabClick, ...props}) => (
|
||||
/>
|
||||
</div>
|
||||
<div className={`mdl-tabs__panel ${styles.listContainer}`} id='rejected'>
|
||||
<CommentList
|
||||
<ModerationList
|
||||
suspectWords={props.settings.settings.wordlist.suspect}
|
||||
isActive={props.activeTab === 'rejected'}
|
||||
singleView={props.singleView}
|
||||
@@ -54,7 +54,7 @@ export default ({onTabClick, ...props}) => (
|
||||
/>
|
||||
</div>
|
||||
<div className={`mdl-tabs__panel ${styles.listContainer}`} id='flagged'>
|
||||
<CommentList
|
||||
<ModerationList
|
||||
suspectWords={props.settings.settings.wordlist.suspect}
|
||||
isActive={props.activeTab === 'rejected'}
|
||||
singleView={props.singleView}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as actions from '../constants/users';
|
||||
import * as actions from '../constants/user';
|
||||
import * as assetActions from '../constants/assets';
|
||||
import {addNotification} from '../actions/notification';
|
||||
import {addItem} from '../actions/items';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Map} from 'immutable';
|
||||
import * as authActions from '../constants/auth';
|
||||
import * as actions from '../constants/users';
|
||||
import * as actions from '../constants/user';
|
||||
import * as assetActions from '../constants/assets';
|
||||
|
||||
const initialState = Map({
|
||||
|
||||
@@ -821,6 +821,14 @@ definitions:
|
||||
current_user:
|
||||
type: object
|
||||
description: Will include the action performed by the currently logged in user if that user has taken an action on this item. Otherwise will return null.
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Oldest created_at of actions in this set.
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Newest updated_at of actions in this set.
|
||||
Action:
|
||||
type: object
|
||||
description: A single action taken by a user.
|
||||
|
||||
@@ -137,6 +137,12 @@ ActionSchema.statics.getActionSummaries = function(item_ids, current_user_id = '
|
||||
metadata: {
|
||||
$push: '$metadata'
|
||||
},
|
||||
created_at: {
|
||||
$min: '$created_at'
|
||||
},
|
||||
updated_at: {
|
||||
$max : '$updated_at'
|
||||
},
|
||||
current_user: {
|
||||
$max: {
|
||||
$cond: {
|
||||
|
||||
@@ -8,7 +8,7 @@ const embedStreamCommands = {
|
||||
},
|
||||
approveComment() {
|
||||
return this
|
||||
.waitForElementVisible('@commentList')
|
||||
.waitForElementVisible('@moderationList')
|
||||
.waitForElementVisible('@approveButton')
|
||||
.click('@approveButton');
|
||||
}
|
||||
@@ -17,17 +17,17 @@ const embedStreamCommands = {
|
||||
module.exports = {
|
||||
commands: [embedStreamCommands],
|
||||
elements: {
|
||||
commentList: {
|
||||
selector: '#commentList'
|
||||
moderationList: {
|
||||
selector: '#moderationList'
|
||||
},
|
||||
banButton: {
|
||||
selector: '#commentList .actions:first-child .ban'
|
||||
selector: '#moderationList .actions:first-child .ban'
|
||||
},
|
||||
rejectButton: {
|
||||
selector: '#commentList .actions:first-child .reject'
|
||||
selector: '#moderationList .actions:first-child .reject'
|
||||
},
|
||||
approveButton: {
|
||||
selector: '#commentList .actions:first-child .approve'
|
||||
selector: '#moderationList .actions:first-child .approve'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user