mirror of
https://github.com/wassname/talk.git
synced 2026-07-31 12:50:48 +08:00
Understanding reducers
This commit is contained in:
@@ -5,14 +5,15 @@ import styles from './CommentList.css';
|
||||
import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from '../translations.json';
|
||||
import Linkify from 'react-linkify';
|
||||
import {FabButton} from 'coral-ui';
|
||||
import {Icon} from 'react-mdl';
|
||||
import {FabButton, Button} from 'coral-ui';
|
||||
|
||||
const linkify = new Linkify();
|
||||
|
||||
// Render a single comment for the list
|
||||
export default props => {
|
||||
const links = linkify.getMatches(props.comment.get('body'));
|
||||
const banned = props.comment.get('banned');
|
||||
|
||||
return (
|
||||
<li tabIndex={props.index} className={`${styles.listItem} ${props.isActive && !props.hideActive ? styles.activeItem : ''}`}>
|
||||
@@ -27,15 +28,13 @@ export default props => {
|
||||
{links ?
|
||||
<span className={styles.hasLinks}><Icon name='error_outline'/> Contains Link</span> : null}
|
||||
<div className={styles.actions}>
|
||||
{props.actions.map((action, i) => canShowAction(action, props.comment) ? (
|
||||
<FabButton icon={props.actionsMap[action].icon} className={styles.actionButton}
|
||||
cStyle={action}
|
||||
key={i}
|
||||
onClick={() => props.onClickAction(props.actionsMap[action].status, props.comment.get('id'))}
|
||||
/>
|
||||
) : null)}
|
||||
{props.actions.map((action, i) => getActionButton(action, i, props))}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{banned ?
|
||||
<span className={styles.banned}><Icon name='error_outline'/> Banned User</span> : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.itemBody}>
|
||||
<span className={styles.body}>
|
||||
@@ -48,15 +47,28 @@ export default props => {
|
||||
);
|
||||
};
|
||||
|
||||
// Check if an action can be performed over a comment
|
||||
const canShowAction = (action, comment) => {
|
||||
const status = comment.get('status');
|
||||
const flagged = comment.get('flagged');
|
||||
// Get the button of the action performed over a comment if any
|
||||
const getActionButton = (action, i, props) => {
|
||||
const status = props.comment.get('status');
|
||||
const flagged = props.comment.get('flagged');
|
||||
|
||||
if (action === 'flag' && (status || flagged === true)) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
if (action === 'ban') {
|
||||
return (
|
||||
<Button
|
||||
cStyle='darkGrey'
|
||||
onClick={() => props.onClickAction(props.actionsMap[action].status, props.comment.get('id'))}>{lang.t('comment.ban_user')}</Button>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<FabButton icon={props.actionsMap[action].icon} className={styles.actionButton}
|
||||
cStyle={action}
|
||||
key={i}
|
||||
onClick={() => props.onClickAction(props.actionsMap[action].status, props.comment.get('id'))}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const linkStyles = {
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
|
||||
}
|
||||
|
||||
|
||||
.hasLinks {
|
||||
color: #f00;
|
||||
text-align: right;
|
||||
@@ -133,3 +132,14 @@
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.banned {
|
||||
color: #f00;
|
||||
text-align: left;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import Comment from 'components/Comment';
|
||||
const actions = {
|
||||
'reject': {status: 'rejected', icon: 'close', key: 'r'},
|
||||
'approve': {status: 'accepted', icon: 'done', key: 't'},
|
||||
'flag': {status: 'flagged', icon: 'flag', filter: 'Untouched'}
|
||||
'flag': {status: 'flagged', icon: 'flag', filter: 'Untouched'},
|
||||
'ban': {status: 'ban'}
|
||||
};
|
||||
|
||||
// Renders a comment list and allow performing actions
|
||||
|
||||
@@ -6,6 +6,7 @@ import ModerationKeysModal from 'components/ModerationKeysModal';
|
||||
import CommentList from 'components/CommentList';
|
||||
|
||||
import {updateStatus} from 'actions/comments';
|
||||
import {updateUserStatus} from 'actions/users';
|
||||
import styles from './ModerationQueue.css';
|
||||
|
||||
import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
@@ -51,8 +52,15 @@ class ModerationQueue extends React.Component {
|
||||
}
|
||||
|
||||
// Dispatch the update status action
|
||||
onCommentAction (status, id) {
|
||||
this.props.dispatch(updateStatus(status, id));
|
||||
onCommentAction (action, id) {
|
||||
// if we are banning a user by the action then dispatch updateUserStatus
|
||||
// action = 'banned' in the case of banning
|
||||
if (action === 'banned') {
|
||||
this.props.dispatch(updateUserStatus(action, id));
|
||||
}
|
||||
|
||||
// If not banning then change the status to approved or flagged as action = status
|
||||
this.props.dispatch(updateStatus(action, id));
|
||||
}
|
||||
|
||||
onTabClick (activeTab) {
|
||||
@@ -61,7 +69,7 @@ class ModerationQueue extends React.Component {
|
||||
|
||||
// Render the tabbed lists moderation queues
|
||||
render () {
|
||||
const {comments} = this.props;
|
||||
const {comments, commenters} = this.props;
|
||||
const {activeTab, singleView, modalOpen} = this.state;
|
||||
|
||||
return (
|
||||
@@ -86,8 +94,9 @@ class ModerationQueue extends React.Component {
|
||||
.get('status'))
|
||||
}
|
||||
comments={comments.get('byId')}
|
||||
commenters={commenters}
|
||||
onClickAction={(action, id) => this.onCommentAction(action, id)}
|
||||
actions={['reject', 'approve']}
|
||||
actions={['reject', 'approve', 'ban']}
|
||||
loading={comments.loading} />
|
||||
</div>
|
||||
<div className={`mdl-tabs__panel ${styles.listContainer}`} id='rejected'>
|
||||
@@ -104,6 +113,7 @@ class ModerationQueue extends React.Component {
|
||||
.get('status') === 'rejected')
|
||||
}
|
||||
comments={comments.get('byId')}
|
||||
commenters={commenters}
|
||||
onClickAction={(action, id) => this.onCommentAction(action, id)}
|
||||
actions={['approve']}
|
||||
loading={comments.loading} />
|
||||
@@ -117,6 +127,7 @@ class ModerationQueue extends React.Component {
|
||||
return !data.get('status') && data.get('flagged') === true;
|
||||
})}
|
||||
comments={comments.get('byId')}
|
||||
commenters={commenters}
|
||||
onClickAction={(action, id) => this.onCommentAction(action, id)}
|
||||
actions={['reject', 'approve']}
|
||||
loading={comments.loading} />
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
import {Map, List} from 'immutable';
|
||||
|
||||
const initialState = Map({
|
||||
byId: Map(),
|
||||
ids: List(),
|
||||
loading: false
|
||||
});
|
||||
|
||||
// Handle the users actions
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case 'SET_COMMENTER_STATUS': return updateUserStatus(state, action);
|
||||
default: return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Update a user status
|
||||
const updateUserStatus = (state, action) => {
|
||||
const byId = state.get('byId');
|
||||
const data = byId.get(action.id).set('status', action.status.toLowerCase());
|
||||
return state.set('byId', byId.set(action.id, data));
|
||||
};
|
||||
@@ -24,6 +24,9 @@ export default store => next => action => {
|
||||
case 'COMMENT_CREATE':
|
||||
createComment(store, action.name, action.body);
|
||||
break;
|
||||
case 'BAN_USER':
|
||||
banUser(store, action.comment);
|
||||
break;
|
||||
}
|
||||
|
||||
next(action);
|
||||
@@ -68,3 +71,11 @@ const createComment = (store, name, comment) => {
|
||||
.then(res => store.dispatch({type: 'COMMENT_CREATE_SUCCESS', comment: res}))
|
||||
.catch(error => store.dispatch({type: 'COMMENT_CREATE_FAILED', error}));
|
||||
};
|
||||
|
||||
// Ban a user
|
||||
const banUser = (store, comment) => {
|
||||
fetch(`${base}/user/${comment.get('author_id')}/status`, getInit('POST', {status: comment.get('status')}))
|
||||
.then(handleResp)
|
||||
.then(res => store.dispatch({type: 'USER_BAN_SUCESSS', res}))
|
||||
.catch(error => store.dispatch({type: 'USER_BAN_FAILED', error}));
|
||||
};
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
},
|
||||
"comment": {
|
||||
"flagged": "flagged",
|
||||
"anon": "Anonymous"
|
||||
"anon": "Anonymous",
|
||||
"ban_user": "Ban User"
|
||||
},
|
||||
"embedlink": {
|
||||
"copy": "Copy to Clipboard"
|
||||
@@ -76,7 +77,8 @@
|
||||
},
|
||||
"comment": {
|
||||
"flagged": "marcado",
|
||||
"anon": "Anónimo"
|
||||
"anon": "Anónimo",
|
||||
"ban_user": "Suspender Usuario"
|
||||
},
|
||||
"configure": {
|
||||
"enable-pre-moderation": "Habilitar pre-moderación",
|
||||
|
||||
@@ -62,7 +62,7 @@ router.post('/:user_id/role', authorization.needed('admin'), (req, res, next) =>
|
||||
|
||||
router.post('/:user_id/status', (req, res, next) => {
|
||||
User
|
||||
.setStatus(req.params.user_id, req.body.status)
|
||||
.setStatus(req.params.user_id, req.body.status, res.body.comment_id)
|
||||
.then(status => {
|
||||
res.send(status);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user