Merge branch 'master' into admin-auth

This commit is contained in:
Kim Gardner
2018-05-16 12:58:59 -04:00
committed by GitHub
13 changed files with 156 additions and 3 deletions
@@ -82,6 +82,20 @@ class StreamSettings extends React.Component {
this.props.updatePending({ updater });
};
updateDisableCommenting = () => {
const updater = {
disableCommenting: {
$set: !this.props.settings.disableCommenting,
},
};
this.props.updatePending({ updater });
};
updateDisableCommentingMessage = value => {
const updater = { disableCommentingMessage: { $set: value } };
this.props.updatePending({ updater });
};
updateAutoClose = () => {
const updater = {
autoCloseStream: { $set: !this.props.settings.autoCloseStream },
@@ -192,6 +206,25 @@ class StreamSettings extends React.Component {
 
{t('configure.edit_comment_timeframe_text_post')}
</ConfigureCard>
<ConfigureCard
checked={settings.disableCommenting}
onCheckbox={this.updateDisableCommenting}
title={t('configure.disable_commenting_title')}
>
<p>{t('configure.disable_commenting_desc')}</p>
<div
className={cn(
styles.configSettingDisableCommenting,
settings.disableCommenting ? null : styles.hidden
)}
>
<MarkdownEditor
className={styles.descriptionBox}
onChange={this.updateDisableCommentingMessage}
value={settings.disableCommentingMessage}
/>
</div>
</ConfigureCard>
<ConfigureCard
checked={settings.autoCloseStream}
onCheckbox={this.updateAutoClose}
@@ -39,6 +39,8 @@ export default compose(
autoCloseStream
closedTimeout
closedMessage
disableCommenting
disableCommentingMessage
${getSlotFragmentSpreads(slots, 'settings')}
}
`,
@@ -4,6 +4,7 @@ import StreamError from './StreamError';
import Comment from '../containers/Comment';
import BannedAccount from '../../../components/BannedAccount';
import ChangeUsername from '../containers/ChangeUsername';
import Markdown from 'coral-framework/components/Markdown';
import Slot from 'coral-framework/components/Slot';
import InfoBox from './InfoBox';
import { can } from 'coral-framework/services/perms';
@@ -181,7 +182,9 @@ class Stream extends React.Component {
setActiveReplyBox={setActiveReplyBox}
activeReplyBox={activeReplyBox}
notify={notify}
disableReply={asset.isClosed}
disableReply={
asset.isClosed || asset.settings.disableCommenting
}
postComment={postComment}
currentUser={currentUser}
postFlag={postFlag}
@@ -215,7 +218,7 @@ class Stream extends React.Component {
currentUser,
} = this.props;
const { keepCommentBox } = this.state;
const open = !asset.isClosed;
const open = !(asset.isClosed || asset.settings.disableCommenting);
const banned = get(currentUser, 'status.banned.status');
const suspensionUntil = get(currentUser, 'status.suspension.until');
@@ -293,7 +296,13 @@ class Stream extends React.Component {
)}
</div>
) : (
<p>{asset.settings.closedMessage}</p>
<div>
{asset.isClosed ? (
<p>{asset.settings.closedMessage}</p>
) : (
<Markdown content={asset.settings.disableCommentingMessage} />
)}
</div>
)}
<Slot fill="stream" passthrough={slotPassthrough} />
@@ -434,6 +434,8 @@ const fragments = {
questionBoxIcon
closedTimeout
closedMessage
disableCommenting
disableCommentingMessage
charCountEnable
charCount
requireEmailConfirmation
+19
View File
@@ -161,6 +161,24 @@ class ErrAssetCommentingClosed extends TalkError {
}
}
// ErrCommentingDisabled is returned when a comment or action is attempted while
// commenting has been disabled site-wide.
class ErrCommentingDisabled extends TalkError {
constructor(message = null) {
super(
'asset commenting is closed',
{
status: 400,
translation_key: 'COMMENTING_DISABLED',
},
{
// Include the closedMessage in the metadata piece of the error.
message,
}
);
}
}
/**
* ErrAuthentication is returned when there is an error authenticating and the
* message is provided.
@@ -387,6 +405,7 @@ module.exports = {
ErrAuthentication,
ErrCannotIgnoreStaff,
ErrCommentTooShort,
ErrCommentingDisabled,
ErrContainsProfanity,
ErrEditWindowHasEnded,
ErrEmailAlreadyVerified,
+14
View File
@@ -837,6 +837,13 @@ type Settings {
# closed.
closedMessage: String
# disableCommenting will disable commenting site-wide.
disableCommenting: Boolean
# disableCommentingMessage will be shown above the comment stream while
# commenting is disabled site-wide.
disableCommentingMessage: String
# editCommentWindowLength is the length of time (in milliseconds) after a
# comment is posted that it can still be edited by the author.
editCommentWindowLength: Int
@@ -1300,6 +1307,13 @@ input UpdateSettingsInput {
# closed.
closedMessage: String
# disableCommenting will disable commenting site-wide.
disableCommenting: Boolean
# disableCommentingMessage will be shown above the comment stream while
# commenting is disabled site-wide.
disableCommentingMessage: String
# charCountEnable is true when the character count restriction is enabled.
charCountEnable: Boolean
+3
View File
@@ -121,6 +121,8 @@ de:
custom_css_url_desc: "URL eines CSS-Stylesheets zum Überschreiben des Standard-Designs"
days: Tage
description: "Als Administrator können Sie die Einstellungen für den Kommentarbereich dieses Artikels anpassen:"
disable_commenting_title: "Kommentieren global deaktivieren"
disable_commenting_desc: "Verfassen Sie eine Nachricht, die angezeigt wird, solange das Kommentieren deaktiviert ist."
domain_list_text: "Geben Sie Domains an, für die diese Talk-Instanz freigegeben werden soll, z.B. für lokale Test- oder Produktionsumgebungen (Bsp.: localhost:3000 staging.domain.com domain.com)."
domain_list_title: "Zugelassene Domains"
edit_comment_timeframe_heading: "Zeitlimit zur Bearbeitung von Kommentaren"
@@ -223,6 +225,7 @@ de:
LOGIN_MAXIMUM_EXCEEDED: "Sie haben zu häufig erfolglos versucht, sich anzumelden. Bitte warten Sie."
PASSWORD_REQUIRED: "Passwort ist erforderlich"
COMMENTING_CLOSED: "Kommentarbereich ist bereits geschlossen"
COMMENTING_DISABLED: "Die Kommentarfunktion ist derzeit abgeschaltet"
NOT_FOUND: "Ressource nicht gefunden"
ALREADY_EXISTS: "Ressource existiert bereits"
INVALID_ASSET_URL: "Asset-URL ist ungültig"
+3
View File
@@ -124,6 +124,8 @@ en:
custom_css_url_desc: "URL of a CSS stylesheet that will override default Embed Stream styles. Can be internal or external."
days: Days
description: "Change the comment settings on this story."
disable_commenting_title: "Deactivate commenting site-wide"
disable_commenting_desc: "Write a message that will be displayed while commenting is deactivated."
domain_list_text: "Enter the domains you would like to permit for Talk e.g. your local staging and production environments (ex. localhost:3000 staging.domain.com domain.com)."
domain_list_title: "Permitted Domains"
edit_info: "Edit Info"
@@ -247,6 +249,7 @@ en:
LOGIN_MAXIMUM_EXCEEDED: "You have made too many unsuccessful password attempts. Please wait."
PASSWORD_REQUIRED: "Must input a password"
COMMENTING_CLOSED: "Commenting is already closed"
COMMENTING_DISABLED: "Commenting is currently disabled on this site"
NOT_FOUND: "Resource not found"
ALREADY_EXISTS: "Resource already exists"
INVALID_ASSET_URL: "Assert URL is invalid"
+8
View File
@@ -68,6 +68,14 @@ const Setting = new Schema(
type: String,
default: 'Expired',
},
disableCommenting: {
type: Boolean,
default: false,
},
disableCommentingMessage: {
type: String,
default: '',
},
wordlist: {
banned: {
type: Array,
+2
View File
@@ -6,6 +6,7 @@ const {
wordlist,
commentLength,
assetClosed,
commentingDisabled,
karma,
staff,
links,
@@ -36,6 +37,7 @@ const applyStatus = status => () => ({ status });
const phases = [
commentLength,
assetClosed,
commentingDisabled,
wordlist,
staff,
links,
@@ -0,0 +1,9 @@
const { ErrCommentingDisabled } = require('../../../errors');
// This phase checks to see if commenting is site-wide disabled.
module.exports = (ctx, comment, { asset }) => {
// Check to see if the asset has closed commenting...
if (asset.settings.disableCommenting) {
throw new ErrCommentingDisabled(asset.settings.disableCommentingMessage);
}
};
+1
View File
@@ -1,6 +1,7 @@
module.exports.wordlist = require('./wordlist');
module.exports.commentLength = require('./commentLength');
module.exports.assetClosed = require('./assetClosed');
module.exports.commentingDisabled = require('./commentingDisabled');
module.exports.karma = require('./karma');
module.exports.staff = require('./staff');
module.exports.links = require('./links');
@@ -179,6 +179,54 @@ describe('graph.mutations.createComment', () => {
});
});
describe('assets while commenting is disabled', () => {
[
{
disabled: false,
error: null,
},
{
disabled: true,
error: 'COMMENTING_DISABLED',
},
].forEach(({ disabled, error }) => {
describe(`commentingDisabled=${disabled}`, () => {
beforeEach(() =>
AssetModel.create({
id: '123',
settings: { disableCommenting: disabled },
})
);
it(
error ? 'does not create the comment' : 'creates the comment',
() => {
const context = new Context({ user: new UserModel({}) });
return graphql(schema, query, {}, context).then(
({ data, errors }) => {
expect(errors).to.be.undefined;
if (error) {
expect(data.createComment).to.have.property('comment').null;
expect(data.createComment).to.have.property('errors').not
.null;
expect(data.createComment.errors[0]).to.have.property(
'translation_key',
error
);
} else {
expect(data.createComment).to.have.property('comment').not
.null;
expect(data.createComment).to.have.property('errors').null;
}
}
);
}
);
});
});
});
describe('comments made with different asset moderation settings', () => {
[
{ moderation: 'PRE', status: 'PREMOD' },