mirror of
https://github.com/wassname/talk.git
synced 2026-07-20 12:40:47 +08:00
Merge branch 'master' into admin-auth
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,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' },
|
||||
|
||||
Reference in New Issue
Block a user