Merge branch 'master' of github.com:coralproject/talk into coral-reaction

This commit is contained in:
Belen Curcio
2017-05-10 13:46:11 -03:00
8 changed files with 32 additions and 34 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ export const toggleModal = open => ({type: actions.TOGGLE_MODAL, open});
export const singleView = () => ({type: actions.SINGLE_VIEW});
// Ban User Dialog
export const showBanUserDialog = (user, commentId, showRejectedNote) => ({type: actions.SHOW_BANUSER_DIALOG, user, commentId, showRejectedNote});
export const showBanUserDialog = (user, commentId, commentStatus, showRejectedNote) => ({type: actions.SHOW_BANUSER_DIALOG, user, commentId, commentStatus, showRejectedNote});
export const hideBanUserDialog = (showDialog) => ({type: actions.HIDE_BANUSER_DIALOG, showDialog});
// hide shortcuts note
@@ -8,14 +8,14 @@ import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../translations';
const lang = new I18n(translations);
const onBanClick = (userId, commentId, handleBanUser, rejectComment, handleClose) => (e) => {
const onBanClick = (userId, commentId, commentStatus, handleBanUser, rejectComment, handleClose) => (e) => {
e.preventDefault();
handleBanUser({userId})
.then(handleClose)
.then(() => rejectComment({commentId}));
.then(() => commentStatus === 'REJECTED' ? null : rejectComment({commentId}));
};
const BanUserDialog = ({open, handleClose, handleBanUser, rejectComment, user, commentId, showRejectedNote}) => (
const BanUserDialog = ({open, handleClose, handleBanUser, rejectComment, user, commentId, commentStatus, showRejectedNote}) => (
<Dialog
className={styles.dialog}
id="banuserDialog"
@@ -36,7 +36,7 @@ const BanUserDialog = ({open, handleClose, handleBanUser, rejectComment, user, c
<Button cStyle="cancel" className={styles.cancel} onClick={handleClose} raised>
{lang.t('bandialog.cancel')}
</Button>
<Button cStyle="black" className={styles.ban} onClick={onBanClick(user.id, commentId, handleBanUser, rejectComment, handleClose)} raised>
<Button cStyle="black" className={styles.ban} onClick={onBanClick(user.id, commentId, commentStatus, handleBanUser, rejectComment, handleClose)} raised>
{lang.t('bandialog.yes_ban_user')}
</Button>
</div>
@@ -193,10 +193,12 @@
box-shadow: none;
color: white;
background-color: #519954;
cursor: not-allowed;
}
.reject__active, .rejected__active {
color: white;
background-color: #D03235;
box-shadow: none;
cursor: not-allowed;
}
@@ -6,7 +6,6 @@ import {getMetrics} from 'coral-admin/src/graphql/queries';
import FlagWidget from './FlagWidget';
import ActivityWidget from './ActivityWidget';
import CountdownTimer from 'coral-admin/src/components/CountdownTimer';
import {showBanUserDialog, hideBanUserDialog} from 'coral-admin/src/actions/moderation';
import {Spinner} from 'coral-ui';
@@ -43,12 +42,7 @@ const mapStateToProps = state => {
};
};
const mapDispatchToProps = dispatch => ({
showBanUserDialog: (user, commentId) => dispatch(showBanUserDialog(user, commentId)),
hideBanUserDialog: () => dispatch(hideBanUserDialog(false))
});
export default compose(
connect(mapStateToProps, mapDispatchToProps),
connect(mapStateToProps),
getMetrics
)(Dashboard);
@@ -43,12 +43,13 @@ class ModerationContainer extends Component {
const {acceptComment, rejectComment} = this.props;
const {selectedIndex} = this.state;
const comments = this.getComments();
const commentId = {commentId: comments[selectedIndex].id};
const comment = comments[selectedIndex];
const commentId = {commentId: comment.id};
if (accept) {
acceptComment(commentId);
comment.status !== 'ACCEPTED' && acceptComment(commentId);
} else {
rejectComment(commentId);
comment.status !== 'REJECTED' && rejectComment(commentId);
}
}
@@ -185,6 +186,7 @@ class ModerationContainer extends Component {
open={moderation.banDialog}
user={moderation.user}
commentId={moderation.commentId}
commentStatus={moderation.commentStatus}
handleClose={props.hideBanUserDialog}
handleBanUser={props.banUser}
showRejectedNote={moderation.showRejectedNote}
@@ -212,7 +214,7 @@ const mapDispatchToProps = dispatch => ({
singleView: () => dispatch(singleView()),
updateAssets: assets => dispatch(updateAssets(assets)),
fetchSettings: () => dispatch(fetchSettings()),
showBanUserDialog: (user, commentId, showRejectedNote) => dispatch(showBanUserDialog(user, commentId, showRejectedNote)),
showBanUserDialog: (user, commentId, commentStatus, showRejectedNote) => dispatch(showBanUserDialog(user, commentId, commentStatus, showRejectedNote)),
hideBanUserDialog: () => dispatch(hideBanUserDialog(false)),
hideShortcutsNote: () => dispatch(hideShortcutsNote()),
});
@@ -18,7 +18,7 @@ import I18n from 'coral-framework/modules/i18n/i18n';
import translations from 'coral-admin/src/translations.json';
const lang = new I18n(translations);
const Comment = ({actions = [], comment, ...props}) => {
const Comment = ({actions = [], comment, suspectWords, bannedWords, ...props}) => {
const links = linkify.getMatches(comment.body);
const linkText = links ? links.map(link => link.raw) : [];
const flagActionSummaries = getActionSummary('FlagActionSummary', comment);
@@ -30,6 +30,13 @@ const Comment = ({actions = [], comment, ...props}) => {
commentType = 'flagged';
}
// since words are checked against word boundaries on the backend,
// this should be the behavior on the front end as well.
// currently the highlighter plugin does not support this out of the box.
const searchWords = [...suspectWords, ...bannedWords].filter(w => {
return new RegExp(`(^|\\s)${w}(\\s|$)`).test(comment.body);
}).concat(linkText);
return (
<li tabIndex={props.index} className={`mdl-card ${props.selected ? 'mdl-shadow--16dp' : 'mdl-shadow--2dp'} ${styles.Comment} ${styles.listItem} ${props.selected ? styles.selected : ''}`}>
<div className={styles.container}>
@@ -41,7 +48,7 @@ const Comment = ({actions = [], comment, ...props}) => {
<span className={styles.created}>
{timeago().format(comment.created_at || (Date.now() - props.index * 60 * 1000), lang.getLocale().replace('-', '_'))}
</span>
<BanUserButton user={comment.user} onClick={() => props.showBanUserDialog(comment.user, comment.id, comment.status !== 'REJECTED')} />
<BanUserButton user={comment.user} onClick={() => props.showBanUserDialog(comment.user, comment.id, comment.status, comment.status !== 'REJECTED')} />
<CommentType type={commentType} />
</div>
{comment.user.status === 'banned' ?
@@ -60,7 +67,7 @@ const Comment = ({actions = [], comment, ...props}) => {
<div className={styles.itemBody}>
<p className={styles.body}>
<Highlighter
searchWords={[...props.suspectWords, ...props.bannedWords, ...linkText]}
searchWords={searchWords}
textToHighlight={comment.body} /> <a className={styles.external} href={`${comment.asset.url}#${comment.id}`} target="_blank"><Icon name='open_in_new' /> {lang.t('comment.view_context')}</a>
</p>
<div className={styles.sideActions}>
@@ -74,8 +81,8 @@ const Comment = ({actions = [], comment, ...props}) => {
user={comment.user}
status={comment.status}
active={active}
acceptComment={() => props.acceptComment({commentId: comment.id})}
rejectComment={() => props.rejectComment({commentId: comment.id})} />;
acceptComment={() => comment.status === 'ACCEPTED' ? null : props.acceptComment({commentId: comment.id})}
rejectComment={() => comment.status === 'REJECTED' ? null : props.rejectComment({commentId: comment.id})} />;
})}
</div>
</div>
@@ -6,6 +6,7 @@ const initialState = Map({
modalOpen: false,
user: Map({}),
commentId: null,
commentStatus: null,
banDialog: false,
shortcutsNoteVisible: window.localStorage.getItem('coral:shortcutsNote') || 'show'
});
@@ -14,12 +15,14 @@ export default function moderation (state = initialState, action) {
switch (action.type) {
case actions.HIDE_BANUSER_DIALOG:
return state
.set('banDialog', false);
.set('banDialog', false)
.set('commentStatus', null);
case actions.SHOW_BANUSER_DIALOG:
return state
.merge({
user: Map(action.user),
commentId: action.commentId,
commentStatus: action.commentStatus,
showRejectedNote: action.showRejectedNote,
banDialog: true
});
+2 -12
View File
@@ -95,18 +95,12 @@ Slots properties take an`Array` so we can add as many components as we want.
`Note: the concepts in this section are still to be implemented. Code samples are for discussion and may change.`
In order to allow you to build more complex plugins, we have wrapped some of our functionality in higher order componenets that expose a simple api.
In order to allow you to build more complex plugins, we have wrapped some of our functionality in higher order components that expose a simple api.
### Reactions
Reactions provide users the ability to 'like', 'respect', etc... comments.
```
<Reaction name="love">
<img class="coralsrc="" />
</Reaction>
```
Note: some server side work will need to accompany this client side component. See the like and respect plugins as examples.
### Comment Stream
@@ -115,11 +109,7 @@ Comment streams may be created with filtering and ordering in place:
* filter by user
* filter by tag
* sort by date ascending / descrnding
```
<CommentStream userFilter="[userId]" tagFilter="[tag]" sort="[ascending|descending]"></CommentStream>
```
* sort by date ascending / descending
### Comment Commit hooks