mirror of
https://github.com/wassname/talk.git
synced 2026-08-15 12:55:10 +08:00
Merge branch 'view-char-count' of github.com:coralproject/talk into view-char-count
This commit is contained in:
@@ -14,18 +14,18 @@ const linkify = new Linkify();
|
|||||||
|
|
||||||
// Render a single comment for the list
|
// Render a single comment for the list
|
||||||
export default props => {
|
export default props => {
|
||||||
const authorStatus = props.author.get('status');
|
|
||||||
const {comment, author} = props;
|
const {comment, author} = props;
|
||||||
const links = linkify.getMatches(comment.get('body'));
|
let authorStatus = author.status;
|
||||||
|
const links = linkify.getMatches(comment.body);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li tabIndex={props.index} className={`${styles.listItem} ${props.isActive && !props.hideActive ? styles.activeItem : ''}`}>
|
<li tabIndex={props.index} className={`${styles.listItem} ${props.isActive && !props.hideActive ? styles.activeItem : ''}`}>
|
||||||
<div className={styles.itemHeader}>
|
<div className={styles.itemHeader}>
|
||||||
<div className={styles.author}>
|
<div className={styles.author}>
|
||||||
<i className={`material-icons ${styles.avatar}`}>person</i>
|
<i className={`material-icons ${styles.avatar}`}>person</i>
|
||||||
<span>{author.get('displayName') || lang.t('comment.anon')}</span>
|
<span>{author.displayName || lang.t('comment.anon')}</span>
|
||||||
<span className={styles.created}>{timeago().format(comment.get('createdAt') || (Date.now() - props.index * 60 * 1000), lang.getLocale().replace('-', '_'))}</span>
|
<span className={styles.created}>{timeago().format(comment.createdAt || (Date.now() - props.index * 60 * 1000), lang.getLocale().replace('-', '_'))}</span>
|
||||||
{comment.get('flagged') ? <p className={styles.flagged}>{lang.t('comment.flagged')}</p> : null}
|
{comment.flagged ? <p className={styles.flagged}>{lang.t('comment.flagged')}</p> : null}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{links ?
|
{links ?
|
||||||
@@ -42,7 +42,7 @@ export default props => {
|
|||||||
<div className={styles.itemBody}>
|
<div className={styles.itemBody}>
|
||||||
<span className={styles.body}>
|
<span className={styles.body}>
|
||||||
<Linkify component='span' properties={{style: linkStyles}}>
|
<Linkify component='span' properties={{style: linkStyles}}>
|
||||||
{comment.get('body')}
|
{comment.body}
|
||||||
</Linkify>
|
</Linkify>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,9 +52,10 @@ export default props => {
|
|||||||
|
|
||||||
// Get the button of the action performed over a comment if any
|
// Get the button of the action performed over a comment if any
|
||||||
const getActionButton = (action, i, props) => {
|
const getActionButton = (action, i, props) => {
|
||||||
const status = props.comment.get('status');
|
const {comment, author} = props;
|
||||||
const flagged = props.comment.get('flagged');
|
const status = comment.status;
|
||||||
const banned = (props.author.get('status') === 'banned');
|
const flagged = comment.flagged;
|
||||||
|
const banned = (author.status === 'banned');
|
||||||
|
|
||||||
if (action === 'flag' && (status || flagged === true)) {
|
if (action === 'flag' && (status || flagged === true)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -64,17 +65,19 @@ const getActionButton = (action, i, props) => {
|
|||||||
<Button
|
<Button
|
||||||
disabled={banned ? 'disabled' : ''}
|
disabled={banned ? 'disabled' : ''}
|
||||||
cStyle='black'
|
cStyle='black'
|
||||||
onClick={() => props.onClickShowBanDialog(props.author.get('id'), props.author.get('displayName'), props.comment.get('id'))}
|
onClick={() => props.onClickShowBanDialog(author.id, author.displayName, comment.id)}
|
||||||
key={i} >
|
key={i} >
|
||||||
{lang.t('comment.ban_user')}
|
{lang.t('comment.ban_user')}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<FabButton icon={props.actionsMap[action].icon} className={styles.actionButton}
|
<FabButton
|
||||||
|
className={styles.actionButton}
|
||||||
|
icon={props.actionsMap[action].icon}
|
||||||
cStyle={action}
|
cStyle={action}
|
||||||
key={i}
|
key={i}
|
||||||
onClick={() => props.onClickAction(props.actionsMap[action].status, props.comment.get('id'))}
|
onClick={() => props.onClickAction(props.actionsMap[action].status, comment.id)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export default class CommentList extends React.Component {
|
|||||||
// If entering to singleview and no active, active is the first eleement
|
// If entering to singleview and no active, active is the first eleement
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
if (nextProps.singleView && !this.state.active) {
|
if (nextProps.singleView && !this.state.active) {
|
||||||
this.setState({active: nextProps.commentIds.get(0)});
|
this.setState({active: nextProps.commentIds[0]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,12 +81,12 @@ export default class CommentList extends React.Component {
|
|||||||
const {commentIds} = this.props;
|
const {commentIds} = this.props;
|
||||||
const {active} = this.state;
|
const {active} = this.state;
|
||||||
// check boundaries
|
// check boundaries
|
||||||
if (active === null || !commentIds.size) {
|
if (active === null || !commentIds.length) {
|
||||||
this.setState({active: commentIds.get(0)});
|
this.setState({active: commentIds[0]});
|
||||||
} else if (direction === 'up' && active !== commentIds.first()) {
|
} else if (direction === 'up' && active !== commentIds[0]) {
|
||||||
this.setState({active: commentIds.get(commentIds.indexOf(active) - 1)});
|
this.setState({active: commentIds[commentIds.indexOf(active) - 1]});
|
||||||
} else if (direction === 'down' && active !== commentIds.last()) {
|
} else if (direction === 'down' && active !== commentIds[commentIds.length - 1]) {
|
||||||
this.setState({active: commentIds.get(commentIds.indexOf(active) + 1)});
|
this.setState({active: commentIds[commentIds.indexOf(active) + 1]});
|
||||||
}
|
}
|
||||||
|
|
||||||
// scroll to the position
|
// scroll to the position
|
||||||
@@ -105,10 +105,10 @@ export default class CommentList extends React.Component {
|
|||||||
// activate the next comment
|
// activate the next comment
|
||||||
if (id === this.state.active) {
|
if (id === this.state.active) {
|
||||||
const {commentIds} = this.props;
|
const {commentIds} = this.props;
|
||||||
if (commentIds.last() === this.state.active) {
|
if (commentIds[commentIds.length - 1] === this.state.active) {
|
||||||
this.setState({active: commentIds.get(commentIds.size - 2)});
|
this.setState({active: commentIds[commentIds.length - 2]});
|
||||||
} else {
|
} else {
|
||||||
this.setState({active: commentIds.get(Math.min(commentIds.indexOf(this.state.active) + 1, commentIds.size - 1))});
|
this.setState({active: commentIds[Math.min(commentIds.indexOf(this.state.active) + 1, commentIds.length - 1)]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.props.onClickAction(action, id, author_id);
|
this.props.onClickAction(action, id, author_id);
|
||||||
@@ -125,10 +125,10 @@ export default class CommentList extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<ul className={`${styles.list} ${singleView ? styles.singleView : ''}`} {...key}>
|
<ul className={`${styles.list} ${singleView ? styles.singleView : ''}`} {...key}>
|
||||||
{commentIds.map((commentId, index) => {
|
{commentIds.map((commentId, index) => {
|
||||||
const comment = comments.get(commentId);
|
const comment = comments[commentId];
|
||||||
|
const author = users[comment.author_id];
|
||||||
return <Comment comment={comment}
|
return <Comment comment={comment}
|
||||||
author={users.get(comment.get('author_id'))}
|
author={author}
|
||||||
ref={el => { if (el && commentId === active) { this._active = el; } }}
|
|
||||||
key={index}
|
key={index}
|
||||||
index={index}
|
index={index}
|
||||||
onClickAction={this.onClickAction}
|
onClickAction={this.onClickAction}
|
||||||
@@ -137,7 +137,7 @@ export default class CommentList extends React.Component {
|
|||||||
actionsMap={actions}
|
actionsMap={actions}
|
||||||
isActive={commentId === active}
|
isActive={commentId === active}
|
||||||
hideActive={hideActive} />;
|
hideActive={hideActive} />;
|
||||||
}).toArray()}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ class CommentStream extends React.Component {
|
|||||||
<CommentBox onSubmit={this.onSubmit} />
|
<CommentBox onSubmit={this.onSubmit} />
|
||||||
<CommentList isActive hideActive
|
<CommentList isActive hideActive
|
||||||
singleView={false}
|
singleView={false}
|
||||||
commentIds={comments.get('ids')}
|
commentIds={comments.ids}
|
||||||
comments={comments.get('byId')}
|
comments={comments.byId}
|
||||||
users={users.get('byId')}
|
users={users.byId}
|
||||||
onClickAction={this.onClickAction}
|
onClickAction={this.onClickAction}
|
||||||
actions={['flag']}
|
actions={['flag']}
|
||||||
loading={comments.loading} />
|
loading={comments.loading} />
|
||||||
@@ -58,4 +58,9 @@ class CommentStream extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(({comments, users}) => ({comments, users}))(CommentStream);
|
const mapStateToProps = state => ({
|
||||||
|
comments: state.comments.toJS(),
|
||||||
|
users: state.users.toJS()
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(CommentStream);
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ class ModerationQueue extends React.Component {
|
|||||||
const {comments, users} = this.props;
|
const {comments, users} = this.props;
|
||||||
const {activeTab, singleView, modalOpen} = this.state;
|
const {activeTab, singleView, modalOpen} = this.state;
|
||||||
|
|
||||||
|
const premodIds = comments.ids.filter(id => comments.byId[id].status === 'premod');
|
||||||
|
const rejectedIds = comments.ids.filter(id => comments.byId[id].status === 'rejected');
|
||||||
|
const flaggedIds = comments.ids.filter(id => comments.byId[id].flagged === true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='mdl-tabs mdl-js-tabs mdl-js-ripple-effect'>
|
<div className='mdl-tabs mdl-js-tabs mdl-js-ripple-effect'>
|
||||||
@@ -94,41 +98,26 @@ class ModerationQueue extends React.Component {
|
|||||||
<CommentList
|
<CommentList
|
||||||
isActive={activeTab === 'pending'}
|
isActive={activeTab === 'pending'}
|
||||||
singleView={singleView}
|
singleView={singleView}
|
||||||
commentIds={
|
commentIds={premodIds}
|
||||||
comments.get('ids')
|
comments={comments.byId}
|
||||||
.filter(id =>
|
users={users.byId}
|
||||||
comments
|
|
||||||
.get('byId')
|
|
||||||
.get(id)
|
|
||||||
.get('status') === 'premod')
|
|
||||||
}
|
|
||||||
comments={comments.get('byId')}
|
|
||||||
users={users.get('byId')}
|
|
||||||
onClickAction={(action, commentId) => this.onCommentAction(action, commentId)}
|
onClickAction={(action, commentId) => this.onCommentAction(action, commentId)}
|
||||||
onClickShowBanDialog={(userId, userName, commentId) => this.showBanUserDialog(userId, userName, commentId)}
|
onClickShowBanDialog={(userId, userName, commentId) => this.showBanUserDialog(userId, userName, commentId)}
|
||||||
actions={['reject', 'approve', 'ban']}
|
actions={['reject', 'approve', 'ban']}
|
||||||
loading={comments.loading} />
|
loading={comments.loading} />
|
||||||
<BanUserDialog
|
<BanUserDialog
|
||||||
open={comments.get('showBanUserDialog')}
|
open={comments.showBanUserDialog}
|
||||||
handleClose={() => this.hideBanUserDialog()}
|
handleClose={() => this.hideBanUserDialog()}
|
||||||
onClickBanUser={(userId, commentId) => this.banUser(userId, commentId)}
|
onClickBanUser={(userId, commentId) => this.banUser(userId, commentId)}
|
||||||
user={comments.get('banUser')}/>
|
user={comments.banUser}/>
|
||||||
</div>
|
</div>
|
||||||
<div className={`mdl-tabs__panel ${styles.listContainer}`} id='rejected'>
|
<div className={`mdl-tabs__panel ${styles.listContainer}`} id='rejected'>
|
||||||
<CommentList
|
<CommentList
|
||||||
isActive={activeTab === 'rejected'}
|
isActive={activeTab === 'rejected'}
|
||||||
singleView={singleView}
|
singleView={singleView}
|
||||||
commentIds={
|
commentIds={rejectedIds}
|
||||||
comments
|
comments={comments.byId}
|
||||||
.get('ids')
|
users={users.byId}
|
||||||
.filter(id =>
|
|
||||||
comments
|
|
||||||
.get('byId')
|
|
||||||
.get(id)
|
|
||||||
.get('status') === 'rejected')
|
|
||||||
}
|
|
||||||
comments={comments.get('byId')}
|
|
||||||
users={users.get('byId')}
|
|
||||||
onClickAction={(action, id) => this.onCommentAction(action, id)}
|
onClickAction={(action, id) => this.onCommentAction(action, id)}
|
||||||
actions={['approve']}
|
actions={['approve']}
|
||||||
loading={comments.loading} />
|
loading={comments.loading} />
|
||||||
@@ -137,12 +126,9 @@ class ModerationQueue extends React.Component {
|
|||||||
<CommentList
|
<CommentList
|
||||||
isActive={activeTab === 'rejected'}
|
isActive={activeTab === 'rejected'}
|
||||||
singleView={singleView}
|
singleView={singleView}
|
||||||
commentIds={comments.get('ids').filter(id => {
|
commentIds={flaggedIds}
|
||||||
const data = comments.get('byId').get(id);
|
comments={comments.byId}
|
||||||
return !data.get('status') && data.get('flagged') === true;
|
users={users.byId}
|
||||||
})}
|
|
||||||
comments={comments.get('byId')}
|
|
||||||
users={users.get('byId')}
|
|
||||||
onClickAction={(action, id) => this.onCommentAction(action, id)}
|
onClickAction={(action, id) => this.onCommentAction(action, id)}
|
||||||
actions={['reject', 'approve']}
|
actions={['reject', 'approve']}
|
||||||
loading={comments.loading} />
|
loading={comments.loading} />
|
||||||
@@ -155,6 +141,11 @@ class ModerationQueue extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(({comments, users}) => ({comments, users}))(ModerationQueue);
|
const mapStateToProps = state => ({
|
||||||
|
comments: state.comments.toJS(),
|
||||||
|
users: state.users.toJS()
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(ModerationQueue);
|
||||||
|
|
||||||
const lang = new I18n(translations);
|
const lang = new I18n(translations);
|
||||||
|
|||||||
Reference in New Issue
Block a user