mirror of
https://github.com/wassname/talk.git
synced 2026-06-29 13:50:35 +08:00
Merge branch 'master' into new-comments
This commit is contained in:
@@ -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 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 Table from './Table';
|
||||
import Loading from './Loading';
|
||||
import NoResults from './NoResults';
|
||||
import {Pager} from 'coral-ui';
|
||||
import EmptyCard from '../../components/EmptyCard';
|
||||
|
||||
const lang = new I18n(translations);
|
||||
|
||||
@@ -54,13 +54,14 @@ const Community = ({isFetching, commenters, ...props}) => {
|
||||
</div>
|
||||
<div className={styles.mainContent}>
|
||||
{ isFetching && <Loading /> }
|
||||
{ !hasResults && <NoResults /> }
|
||||
{ hasResults &&
|
||||
<Table
|
||||
headers={tableHeaders}
|
||||
data={commenters}
|
||||
onHeaderClickHandler={props.onHeaderClickHandler}
|
||||
/>
|
||||
{
|
||||
hasResults
|
||||
? <Table
|
||||
headers={tableHeaders}
|
||||
data={commenters}
|
||||
onHeaderClickHandler={props.onHeaderClickHandler}
|
||||
/>
|
||||
: <EmptyCard>{lang.t('community.no-results')}</EmptyCard>
|
||||
}
|
||||
<Pager
|
||||
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 Comment from './components/Comment';
|
||||
import EmptyCard from '../../components/EmptyCard';
|
||||
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 areComments = props.data[activeTab].length;
|
||||
return (
|
||||
<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;
|
||||
return <Comment
|
||||
key={i}
|
||||
@@ -22,6 +29,7 @@ const ModerationQueue = ({activeTab = 'premod', ...props}) => {
|
||||
currentAsset={props.currentAsset}
|
||||
/>;
|
||||
})
|
||||
: <EmptyCard>{lang.t('modqueue.emptyqueue')}</EmptyCard>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
@@ -29,7 +37,12 @@ const ModerationQueue = ({activeTab = 'premod', ...props}) => {
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, {PropTypes} from 'react';
|
||||
import timeago from 'timeago.js';
|
||||
import Linkify from 'react-linkify';
|
||||
import Highlighter from 'react-highlight-words';
|
||||
@@ -17,7 +17,7 @@ const lang = new I18n(translations);
|
||||
|
||||
const Comment = ({actions = [], ...props}) => {
|
||||
const links = linkify.getMatches(props.comment.body);
|
||||
const actionSumaries = props.comment.action_summaries;
|
||||
const actionSummaries = props.comment.action_summaries;
|
||||
return (
|
||||
<li tabIndex={props.index}
|
||||
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>
|
||||
{props.comment.user.banned === 'banned' ?
|
||||
{props.comment.user.status === 'banned' ?
|
||||
<span className={styles.banned}>
|
||||
<Icon name='error_outline'/>
|
||||
{lang.t('comment.banned_user')}
|
||||
@@ -62,11 +62,31 @@ const Comment = ({actions = [], ...props}) => {
|
||||
</Linkify>
|
||||
</p>
|
||||
</div>
|
||||
{actionSumaries && <FlagBox actionSumaries={actionSumaries} />}
|
||||
{actionSummaries && <FlagBox actionSummaries={actionSummaries} />}
|
||||
</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 = {
|
||||
backgroundColor: 'rgb(255, 219, 135)',
|
||||
padding: '1px 2px'
|
||||
|
||||
@@ -5,7 +5,7 @@ const FlagBox = props => (
|
||||
<div className={styles.flagBox}>
|
||||
<h3>Flags:</h3>
|
||||
<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>
|
||||
)}
|
||||
</ul>
|
||||
@@ -13,7 +13,7 @@ const FlagBox = props => (
|
||||
);
|
||||
|
||||
FlagBox.propTypes = {
|
||||
actionSumaries: PropTypes.array.isRequired
|
||||
actionSummaries: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
export default FlagBox;
|
||||
|
||||
@@ -8,6 +8,7 @@ import {Link} from 'react-router';
|
||||
|
||||
import {Pager, Icon} from 'coral-ui';
|
||||
import {DataTable, TableHeader, RadioGroup, Radio} from 'react-mdl';
|
||||
import EmptyCard from 'coral-admin/src/components/EmptyCard';
|
||||
|
||||
const limit = 25;
|
||||
|
||||
@@ -142,22 +143,25 @@ class Streams extends Component {
|
||||
<Radio value='asc'>{lang.t('streams.oldest')}</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
<div className={styles.mainContent}>
|
||||
<DataTable className={styles.streamsTable} rows={assetsIds} onClick={this.goToModeration}>
|
||||
<TableHeader name="title" cellFormatter={this.renderTitle}>{lang.t('streams.article')}</TableHeader>
|
||||
<TableHeader name="publication_date" cellFormatter={this.renderDate}>
|
||||
{lang.t('streams.pubdate')}
|
||||
</TableHeader>
|
||||
<TableHeader name="closedAt" cellFormatter={this.renderStatus} className={styles.status}>
|
||||
{lang.t('streams.status')}
|
||||
</TableHeader>
|
||||
</DataTable>
|
||||
<Pager
|
||||
totalPages={Math.ceil((assets.count || 0) / limit)}
|
||||
page={this.state.page}
|
||||
onNewPageHandler={this.onPageClick}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
assetsIds.length
|
||||
? <div className={styles.mainContent}>
|
||||
<DataTable className={styles.streamsTable} rows={assetsIds} onClick={this.goToModeration}>
|
||||
<TableHeader name="title" cellFormatter={this.renderTitle}>{lang.t('streams.article')}</TableHeader>
|
||||
<TableHeader name="publication_date" cellFormatter={this.renderDate}>
|
||||
{lang.t('streams.pubdate')}
|
||||
</TableHeader>
|
||||
<TableHeader name="closedAt" cellFormatter={this.renderStatus} className={styles.status}>
|
||||
{lang.t('streams.status')}
|
||||
</TableHeader>
|
||||
</DataTable>
|
||||
<Pager
|
||||
totalPages={Math.ceil((assets.count || 0) / limit)}
|
||||
page={this.state.page}
|
||||
onNewPageHandler={this.onPageClick} />
|
||||
</div>
|
||||
: <EmptyCard>{lang.t('streams.empty_result')}</EmptyCard>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"admin": "Administrator",
|
||||
"moderator": "Moderator",
|
||||
"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",
|
||||
"select-status": "Select status...",
|
||||
"active": "Active",
|
||||
@@ -32,6 +32,7 @@
|
||||
"prevcomment": "Go to the previous comment",
|
||||
"singleview": "Toggle single comment edit view",
|
||||
"thismenu": "Open this menu",
|
||||
"emptyqueue": "No more comments to moderate! You're all caught up. Go have some ☕️",
|
||||
"showshortcuts": "Show Shortcuts"
|
||||
},
|
||||
"comment": {
|
||||
@@ -113,6 +114,7 @@
|
||||
"comment_count": "Comments"
|
||||
},
|
||||
"streams": {
|
||||
"empty_result": "No assets match this search. Maybe try widening your search?",
|
||||
"search": "Search",
|
||||
"filter-streams": "Filter Streams",
|
||||
"stream-status": "Stream Status",
|
||||
@@ -152,6 +154,7 @@
|
||||
"flagged": "marcado",
|
||||
"shortcuts": "Atajos de teclado",
|
||||
"close": "Cerrar",
|
||||
"emptyqueue": "No se encontro ningún usuario. Están escondidos.",
|
||||
"showshortcuts": "Mostrar atajos"
|
||||
},
|
||||
"comment": {
|
||||
@@ -220,6 +223,7 @@
|
||||
"comment_count": "Comentarios"
|
||||
},
|
||||
"streams": {
|
||||
"empty_result": "No se encuentro articulo con esta busqueda. Tal vez extender la busqueda?",
|
||||
"search": "",
|
||||
"filter-streams": "",
|
||||
"stream-status": "",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"en":{
|
||||
"userNoComment": "This user has not yet left a comment.",
|
||||
"userNoComment": "You've never left a comment. Join the conversation!",
|
||||
"allComments": "All Comments",
|
||||
"profileSettings": "Profile Settings",
|
||||
"myCommentHistory": "My comment History"
|
||||
},
|
||||
"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",
|
||||
"profileSettings": "Configuración del perfil",
|
||||
"myCommentHistory": "Mi historial de comentarios"
|
||||
|
||||
@@ -150,10 +150,8 @@ const createPublicComment = (context, commentInput) => {
|
||||
item_id: comment.id,
|
||||
item_type: 'COMMENTS',
|
||||
action_type: 'FLAG',
|
||||
metadata: {
|
||||
field: 'body',
|
||||
details: 'Matched suspect word filters.'
|
||||
}
|
||||
group_id: 'Matched suspect word filter',
|
||||
metadata: {}
|
||||
})
|
||||
.then(() => comment);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user