Merge branch 'master' into new-comments

This commit is contained in:
David Jay
2017-02-23 16:21:36 -05:00
committed by GitHub
10 changed files with 95 additions and 50 deletions
@@ -0,0 +1,14 @@
import React, {PropTypes} from 'react';
import {Card} from 'coral-ui';
const EmptyCard = props => (
<Card style={{textAlign: 'center', maxWidth: 400, margin: '0 auto'}}>
{props.children}
</Card>
);
EmptyCard.propTypes = {
children: PropTypes.node.isRequired
};
export default EmptyCard;
@@ -1,12 +1,12 @@
import React from 'react'; import React from 'react';
import I18n from 'coral-framework/modules/i18n/i18n'; import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../../translations.json'; import translations from 'coral-admin/src/translations.json';
import styles from './Community.css'; import styles from './Community.css';
import Table from './Table'; import Table from './Table';
import Loading from './Loading'; import Loading from './Loading';
import NoResults from './NoResults';
import {Pager} from 'coral-ui'; import {Pager} from 'coral-ui';
import EmptyCard from '../../components/EmptyCard';
const lang = new I18n(translations); const lang = new I18n(translations);
@@ -54,13 +54,14 @@ const Community = ({isFetching, commenters, ...props}) => {
</div> </div>
<div className={styles.mainContent}> <div className={styles.mainContent}>
{ isFetching && <Loading /> } { isFetching && <Loading /> }
{ !hasResults && <NoResults /> } {
{ hasResults && hasResults
<Table ? <Table
headers={tableHeaders} headers={tableHeaders}
data={commenters} data={commenters}
onHeaderClickHandler={props.onHeaderClickHandler} onHeaderClickHandler={props.onHeaderClickHandler}
/> />
: <EmptyCard>{lang.t('community.no-results')}</EmptyCard>
} }
<Pager <Pager
totalPages={props.totalPages} totalPages={props.totalPages}
@@ -1,9 +0,0 @@
import React from 'react';
const NoResults = () => (
<div>
No users found with that user name or email address
</div>
);
export default NoResults;
@@ -1,14 +1,21 @@
import React, {PropTypes} from 'react'; import React, {PropTypes} from 'react';
import Comment from './components/Comment'; import Comment from './components/Comment';
import EmptyCard from '../../components/EmptyCard';
import {actionsMap} from './helpers/moderationQueueActionsMap'; import {actionsMap} from './helpers/moderationQueueActionsMap';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from 'coral-admin/src/translations';
const lang = new I18n(translations);
const ModerationQueue = ({activeTab = 'premod', ...props}) => { const ModerationQueue = ({activeTab = 'premod', ...props}) => {
const areComments = props.data[activeTab].length;
return ( return (
<div id="moderationList"> <div id="moderationList">
<ul> <ul style={{paddingLeft: 0}}>
{ {
props.data[activeTab].map((comment, i) => { areComments
? props.data[activeTab].map((comment, i) => {
const status = comment.action_summaries ? 'FLAGGED' : comment.status; const status = comment.action_summaries ? 'FLAGGED' : comment.status;
return <Comment return <Comment
key={i} key={i}
@@ -22,6 +29,7 @@ const ModerationQueue = ({activeTab = 'premod', ...props}) => {
currentAsset={props.currentAsset} currentAsset={props.currentAsset}
/>; />;
}) })
: <EmptyCard>{lang.t('modqueue.emptyqueue')}</EmptyCard>
} }
</ul> </ul>
</div> </div>
@@ -29,7 +37,12 @@ const ModerationQueue = ({activeTab = 'premod', ...props}) => {
}; };
ModerationQueue.propTypes = { ModerationQueue.propTypes = {
data: PropTypes.object.isRequired data: PropTypes.object.isRequired,
acceptComment: PropTypes.func.isRequired,
rejectComment: PropTypes.func.isRequired,
showBanUserDialog: PropTypes.func.isRequired,
currentAsset: PropTypes.object,
suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired
}; };
export default ModerationQueue; export default ModerationQueue;
@@ -1,4 +1,4 @@
import React from 'react'; import React, {PropTypes} from 'react';
import timeago from 'timeago.js'; import timeago from 'timeago.js';
import Linkify from 'react-linkify'; import Linkify from 'react-linkify';
import Highlighter from 'react-highlight-words'; import Highlighter from 'react-highlight-words';
@@ -17,7 +17,7 @@ const lang = new I18n(translations);
const Comment = ({actions = [], ...props}) => { const Comment = ({actions = [], ...props}) => {
const links = linkify.getMatches(props.comment.body); const links = linkify.getMatches(props.comment.body);
const actionSumaries = props.comment.action_summaries; const actionSummaries = props.comment.action_summaries;
return ( return (
<li tabIndex={props.index} <li tabIndex={props.index}
className={`mdl-card mdl-shadow--2dp ${styles.Comment} ${styles.listItem} ${props.isActive && !props.hideActive ? styles.activeItem : ''}`}> className={`mdl-card mdl-shadow--2dp ${styles.Comment} ${styles.listItem} ${props.isActive && !props.hideActive ? styles.activeItem : ''}`}>
@@ -42,7 +42,7 @@ const Comment = ({actions = [], ...props}) => {
/> />
)} )}
</div> </div>
{props.comment.user.banned === 'banned' ? {props.comment.user.status === 'banned' ?
<span className={styles.banned}> <span className={styles.banned}>
<Icon name='error_outline'/> <Icon name='error_outline'/>
{lang.t('comment.banned_user')} {lang.t('comment.banned_user')}
@@ -62,11 +62,31 @@ const Comment = ({actions = [], ...props}) => {
</Linkify> </Linkify>
</p> </p>
</div> </div>
{actionSumaries && <FlagBox actionSumaries={actionSumaries} />} {actionSummaries && <FlagBox actionSummaries={actionSummaries} />}
</li> </li>
); );
}; };
Comment.propTypes = {
acceptComment: PropTypes.func.isRequired,
rejectComment: PropTypes.func.isRequired,
suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired,
currentAsset: PropTypes.object,
isActive: PropTypes.bool.isRequired,
comment: PropTypes.shape({
body: PropTypes.string.isRequired,
action_summaries: PropTypes.array,
created_at: PropTypes.string.isRequired,
user: PropTypes.shape({
status: PropTypes.string
}),
asset: PropTypes.shape({
title: PropTypes.string,
id: PropTypes.string
})
})
};
const linkStyles = { const linkStyles = {
backgroundColor: 'rgb(255, 219, 135)', backgroundColor: 'rgb(255, 219, 135)',
padding: '1px 2px' padding: '1px 2px'
@@ -5,7 +5,7 @@ const FlagBox = props => (
<div className={styles.flagBox}> <div className={styles.flagBox}>
<h3>Flags:</h3> <h3>Flags:</h3>
<ul> <ul>
{props.actionSumaries.map((action, i) => {props.actionSummaries.map((action, i) =>
<li key={i}>{!action.reason ? <i>No reason provided</i> : action.reason} (<strong>{action.count}</strong>)</li> <li key={i}>{!action.reason ? <i>No reason provided</i> : action.reason} (<strong>{action.count}</strong>)</li>
)} )}
</ul> </ul>
@@ -13,7 +13,7 @@ const FlagBox = props => (
); );
FlagBox.propTypes = { FlagBox.propTypes = {
actionSumaries: PropTypes.array.isRequired actionSummaries: PropTypes.array.isRequired
}; };
export default FlagBox; export default FlagBox;
@@ -8,6 +8,7 @@ import {Link} from 'react-router';
import {Pager, Icon} from 'coral-ui'; import {Pager, Icon} from 'coral-ui';
import {DataTable, TableHeader, RadioGroup, Radio} from 'react-mdl'; import {DataTable, TableHeader, RadioGroup, Radio} from 'react-mdl';
import EmptyCard from 'coral-admin/src/components/EmptyCard';
const limit = 25; const limit = 25;
@@ -142,22 +143,25 @@ class Streams extends Component {
<Radio value='asc'>{lang.t('streams.oldest')}</Radio> <Radio value='asc'>{lang.t('streams.oldest')}</Radio>
</RadioGroup> </RadioGroup>
</div> </div>
<div className={styles.mainContent}> {
<DataTable className={styles.streamsTable} rows={assetsIds} onClick={this.goToModeration}> assetsIds.length
<TableHeader name="title" cellFormatter={this.renderTitle}>{lang.t('streams.article')}</TableHeader> ? <div className={styles.mainContent}>
<TableHeader name="publication_date" cellFormatter={this.renderDate}> <DataTable className={styles.streamsTable} rows={assetsIds} onClick={this.goToModeration}>
{lang.t('streams.pubdate')} <TableHeader name="title" cellFormatter={this.renderTitle}>{lang.t('streams.article')}</TableHeader>
</TableHeader> <TableHeader name="publication_date" cellFormatter={this.renderDate}>
<TableHeader name="closedAt" cellFormatter={this.renderStatus} className={styles.status}> {lang.t('streams.pubdate')}
{lang.t('streams.status')} </TableHeader>
</TableHeader> <TableHeader name="closedAt" cellFormatter={this.renderStatus} className={styles.status}>
</DataTable> {lang.t('streams.status')}
<Pager </TableHeader>
totalPages={Math.ceil((assets.count || 0) / limit)} </DataTable>
page={this.state.page} <Pager
onNewPageHandler={this.onPageClick} totalPages={Math.ceil((assets.count || 0) / limit)}
/> page={this.state.page}
</div> onNewPageHandler={this.onPageClick} />
</div>
: <EmptyCard>{lang.t('streams.empty_result')}</EmptyCard>
}
</div> </div>
); );
} }
+5 -1
View File
@@ -7,7 +7,7 @@
"admin": "Administrator", "admin": "Administrator",
"moderator": "Moderator", "moderator": "Moderator",
"role": "Select role...", "role": "Select role...",
"no-results": "No users found with that user name or email address.", "no-results": "No users found with that user name or email address. They're hiding!",
"status": "Status", "status": "Status",
"select-status": "Select status...", "select-status": "Select status...",
"active": "Active", "active": "Active",
@@ -32,6 +32,7 @@
"prevcomment": "Go to the previous comment", "prevcomment": "Go to the previous comment",
"singleview": "Toggle single comment edit view", "singleview": "Toggle single comment edit view",
"thismenu": "Open this menu", "thismenu": "Open this menu",
"emptyqueue": "No more comments to moderate! You're all caught up. Go have some ☕️",
"showshortcuts": "Show Shortcuts" "showshortcuts": "Show Shortcuts"
}, },
"comment": { "comment": {
@@ -113,6 +114,7 @@
"comment_count": "Comments" "comment_count": "Comments"
}, },
"streams": { "streams": {
"empty_result": "No assets match this search. Maybe try widening your search?",
"search": "Search", "search": "Search",
"filter-streams": "Filter Streams", "filter-streams": "Filter Streams",
"stream-status": "Stream Status", "stream-status": "Stream Status",
@@ -152,6 +154,7 @@
"flagged": "marcado", "flagged": "marcado",
"shortcuts": "Atajos de teclado", "shortcuts": "Atajos de teclado",
"close": "Cerrar", "close": "Cerrar",
"emptyqueue": "No se encontro ningún usuario. Están escondidos.",
"showshortcuts": "Mostrar atajos" "showshortcuts": "Mostrar atajos"
}, },
"comment": { "comment": {
@@ -220,6 +223,7 @@
"comment_count": "Comentarios" "comment_count": "Comentarios"
}, },
"streams": { "streams": {
"empty_result": "No se encuentro articulo con esta busqueda. Tal vez extender la busqueda?",
"search": "", "search": "",
"filter-streams": "", "filter-streams": "",
"stream-status": "", "stream-status": "",
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"en":{ "en":{
"userNoComment": "This user has not yet left a comment.", "userNoComment": "You've never left a comment. Join the conversation!",
"allComments": "All Comments", "allComments": "All Comments",
"profileSettings": "Profile Settings", "profileSettings": "Profile Settings",
"myCommentHistory": "My comment History" "myCommentHistory": "My comment History"
}, },
"es":{ "es":{
"userNoComment": "Aún no ha escrito ningún comentario.", "userNoComment": "No has dejado áun ningún comentario. ¡Unete a la conversación!",
"allComments": "Todos los comentarios", "allComments": "Todos los comentarios",
"profileSettings": "Configuración del perfil", "profileSettings": "Configuración del perfil",
"myCommentHistory": "Mi historial de comentarios" "myCommentHistory": "Mi historial de comentarios"
+2 -4
View File
@@ -150,10 +150,8 @@ const createPublicComment = (context, commentInput) => {
item_id: comment.id, item_id: comment.id,
item_type: 'COMMENTS', item_type: 'COMMENTS',
action_type: 'FLAG', action_type: 'FLAG',
metadata: { group_id: 'Matched suspect word filter',
field: 'body', metadata: {}
details: 'Matched suspect word filters.'
}
}) })
.then(() => comment); .then(() => comment);
} }