Moving commentList to ModerationList

This commit is contained in:
David Jay
2017-01-03 16:57:53 -05:00
parent 5c5a7f5ba5
commit b517adab56
11 changed files with 87 additions and 48 deletions
+1 -1
View File
@@ -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';
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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({
+8
View File
@@ -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.
+6
View File
@@ -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: {
+6 -6
View File
@@ -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'
}
}
};