Merge branch 'master' of github.com:coralproject/talk into featured-adm

This commit is contained in:
Belen Curcio
2017-08-01 11:28:10 -03:00
11 changed files with 124 additions and 15 deletions
+1 -1
View File
@@ -11,4 +11,4 @@
"transform-async-to-generator",
"transform-react-jsx"
]
}
}
@@ -20,8 +20,9 @@ import {TopRightMenu} from './TopRightMenu';
import CommentContent from './CommentContent';
import Slot from 'coral-framework/components/Slot';
import IgnoredCommentTombstone from './IgnoredCommentTombstone';
import InactiveCommentLabel from './InactiveCommentLabel';
import {EditableCommentContent} from './EditableCommentContent';
import {getActionSummary, iPerformedThisAction, forEachError} from 'coral-framework/utils';
import {getActionSummary, iPerformedThisAction, forEachError, isCommentActive} from 'coral-framework/utils';
import t from 'coral-framework/services/i18n';
const isStaff = (tags) => !tags.every((t) => t.tag.name !== 'STAFF');
@@ -317,7 +318,10 @@ export default class Comment extends React.Component {
} = this.props;
const view = this.getVisibileReplies();
const isActive = ['NONE', 'ACCEPTED'].indexOf(comment.status) >= 0;
// Inactive comments can be viewed by moderators and admins (e.g. using permalinks).
const isActive = isCommentActive(comment.status);
const {loadingState} = this.state;
const isPending = comment.id.indexOf('pending') >= 0;
const isHighlighted = highlighted === comment.id;
@@ -435,7 +439,7 @@ export default class Comment extends React.Component {
}
</span>
}
{ (currentUser && (comment.user.id !== currentUser.id)) &&
{ isActive && (currentUser && (comment.user.id !== currentUser.id)) &&
/* TopRightMenu allows currentUser to ignore other users' comments */
<span className={cn(styles.topRight, styles.topRightMenu)}>
@@ -445,6 +449,9 @@ export default class Comment extends React.Component {
addNotification={addNotification} />
</span>
}
{ !isActive &&
<InactiveCommentLabel status={comment.status}/>
}
</div>
<div className={styles.content}>
{
@@ -0,0 +1,32 @@
.root {
display: inline-block;
color: white;
background: grey;
height: 22px;
box-sizing: border-box;
line-height: 19px;
padding: 2px 6px 2px 4px;
border-radius: 2px;
font-size: 12px;
text-transform: capitalize;
}
.icon {
font-size: 14px;
vertical-align: text-top;
margin: 0;
margin-right: 4px;
}
.label {
display: inline-block;
}
.premod {
background: #063B9A;
}
.rejected {
background: #d03235;
}
@@ -0,0 +1,36 @@
import React, {PropTypes} from 'react';
import t from 'coral-framework/services/i18n';
import styles from './InactiveCommentLabel.css';
import {Icon} from 'coral-ui';
import cn from 'classnames';
const InactiveCommentLabel = ({status, className, ...rest}) => {
let label;
let icon;
switch (status) {
case 'PREMOD':
label = t('modqueue.premod');
icon = 'query_builder';
break;
case 'REJECTED':
label = t('modqueue.rejected');
icon = 'close';
break;
default:
throw new Error(`Unknown inactive status ${status}`);
}
return (
<span {...rest} className={cn(className, styles.root, styles[status.toLowerCase()])}>
<Icon name={icon} className={styles.icon}/>
<span className={styles.label}>{label}</span>
</span>
);
};
InactiveCommentLabel.propTypes = {
status: PropTypes.string.isRequired,
};
export default InactiveCommentLabel;
@@ -13,6 +13,7 @@ import t, {timeago} from 'coral-framework/services/i18n';
import {getSlotComponents} from 'coral-framework/helpers/plugins';
import CommentBox from 'talk-plugin-commentbox/CommentBox';
import QuestionBox from 'talk-plugin-questionbox/QuestionBox';
import {isCommentActive} from 'coral-framework/utils';
import {Button, TabBar, Tab, TabCount, TabContent, TabPane} from 'coral-ui';
import cn from 'classnames';
@@ -105,7 +106,9 @@ class Stream extends React.Component {
// even though the permalinked comment is the highlighted one, we're displaying its parent + replies
let highlightedComment = comment && getTopLevelParent(comment);
if (highlightedComment) {
const isInactive = ['NONE', 'ACCEPTED'].indexOf(comment.status) === -1;
// Inactive comments can be viewed by moderators and admins (e.g. using permalinks).
const isInactive = !isCommentActive(comment.status);
if (comment.parent && isInactive) {
// the highlighted comment is not active and as such not in the replies, so we
+5
View File
@@ -267,6 +267,11 @@ Talk.render = function(el, opts) {
console.warn(
'This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages.'
);
if (!window.location.origin) {
window.location.origin = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`;
}
query.asset_url = window.location.origin + window.location.pathname;
}
}
+4
View File
@@ -187,3 +187,7 @@ export function buildUrl({protocol, hostname, port, pathname, search, hash} = wi
export function getSlotFragmentSpreads(slots, resource) {
return `...${slots.map((s) => `TalkSlot_${capitalize(s)}_${resource}`).join('\n...')}\n`;
}
export function isCommentActive(commentStatus) {
return ['NONE', 'ACCEPTED'].indexOf(commentStatus) >= 0;
}
+6
View File
@@ -78,6 +78,12 @@ const CONFIG = {
// messages through the websocket to keep the socket alive.
KEEP_ALIVE: process.env.TALK_KEEP_ALIVE || '30s',
//------------------------------------------------------------------------------
// Cache configuration
//------------------------------------------------------------------------------
CACHE_EXPIRY_COMMENT_COUNT: process.env.TALK_CACHE_EXPIRY_COMMENT_COUNT || '1hr',
//------------------------------------------------------------------------------
// Recaptcha configuration
//------------------------------------------------------------------------------
+6
View File
@@ -45,6 +45,7 @@ These are only used during the webpack build.
thread. (Default `3`)
- `TALK_DEFAULT_STREAM_TAB` (_optional_) - specify the default stream tab in the
admin. (Default `all`)
- `TALK_DISABLE_EMBED_POLYFILL` (_optional_) - when set to `TRUE`, the build process will not include the [babel-polyfill](https://babeljs.io/docs/usage/polyfill/) in the embed.js target. (Default `FALSE`)
### Database
@@ -127,6 +128,11 @@ The default could be read as:
- At the moment of writing, beheviour is not attached to the flagging
reliability, but it is recorded.
### Cache
- `TALK_CACHE_EXPIRY_COMMENT_COUNT` (_optional_) - configure the duration for which
comment counts are cached for. (Default `1hr`)
### Plugins
Plugins configuration can be found on the [Plugins]({{ "/docs/running/plugins/" | absolute_url }}) page.
+7 -3
View File
@@ -8,6 +8,10 @@ const {
SEARCH_NON_NULL_OR_ACCEPTED_COMMENTS,
SEARCH_OTHERS_COMMENTS
} = require('../../perms/constants');
const {
CACHE_EXPIRY_COMMENT_COUNT
} = require('../../config');
const ms = require('ms');
const CommentModel = require('../../models/comment');
const UsersService = require('../../services/users');
@@ -481,11 +485,11 @@ module.exports = (context) => ({
get: new DataLoader((ids) => getComments(context, ids)),
getByQuery: (query) => getCommentsByQuery(context, query),
getCountByQuery: (query) => getCommentCountByQuery(context, query),
countByAssetID: new SharedCounterDataLoader('Comments.totalCommentCount', 3600, (ids) => getCountsByAssetID(context, ids)),
countByAssetID: new SharedCounterDataLoader('Comments.totalCommentCount', ms(CACHE_EXPIRY_COMMENT_COUNT), (ids) => getCountsByAssetID(context, ids)),
countByAssetIDPersonalized: (query) => getCountsByAssetIDPersonalized(context, query),
parentCountByAssetID: new SharedCounterDataLoader('Comments.countByAssetID', 3600, (ids) => getParentCountsByAssetID(context, ids)),
parentCountByAssetID: new SharedCounterDataLoader('Comments.countByAssetID', ms(CACHE_EXPIRY_COMMENT_COUNT), (ids) => getParentCountsByAssetID(context, ids)),
parentCountByAssetIDPersonalized: (query) => getParentCountByAssetIDPersonalized(context, query),
countByParentID: new SharedCounterDataLoader('Comments.countByParentID', 3600, (ids) => getCountsByParentID(context, ids)),
countByParentID: new SharedCounterDataLoader('Comments.countByParentID', ms(CACHE_EXPIRY_COMMENT_COUNT), (ids) => getCountsByParentID(context, ids)),
countByParentIDPersonalized: (query) => getCountByParentIDPersonalized(context, query),
genRecentReplies: new DataLoader((ids) => genRecentReplies(context, ids)),
genRecentComments: new DataLoader((ids) => genRecentComments(context, ids))
+13 -7
View File
@@ -33,6 +33,7 @@ const buildEmbeds = [
const config = {
devtool: 'cheap-module-source-map',
target: 'web',
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/client/',
@@ -153,11 +154,15 @@ if (process.env.NODE_ENV === 'production') {
// Applies the base configuration to the following entries.
const applyConfig = (entries, root = {}) => _.merge({}, config, {
entry: entries.reduce((entry, {name, path}) => {
entry[name] = [
'babel-polyfill',
path
];
entry: entries.reduce((entry, {name, path, disablePolyfill = false}) => {
if (disablePolyfill) {
entry[name] = path;
} else {
entry[name] = [
'babel-polyfill',
path
];
}
return entry;
}, {})
@@ -171,7 +176,8 @@ module.exports = [
// Load in the root embed.
{
name: 'embed',
path: path.join(__dirname, 'client/coral-embed/src/index')
path: path.join(__dirname, 'client/coral-embed/src/index'),
disablePolyfill: process.env.TALK_DISABLE_EMBED_POLYFILL === 'TRUE'
}
], {
@@ -183,7 +189,7 @@ module.exports = [
// All framework targets/embeds/plugins.
applyConfig([
// // Load in all the targets.
// Load in all the targets.
...buildTargets.map((target) => ({
name: `${target}/bundle`,
path: path.join(__dirname, 'client/', target, '/src/index')