From 905d41af7ed5b1085f8344253921e17f1de3a374 Mon Sep 17 00:00:00 2001 From: Jack & Burger Date: Fri, 13 Jul 2018 10:41:12 +0300 Subject: [PATCH] Option to disable comments manually (#154) --- web/.eslintrc.js | 2 +- web/app/common/api.js | 14 ++++++ .../auth-panel/__tests__/auth-panel.test.js | 2 +- web/app/components/auth-panel/auth-panel.jsx | 29 ++++++++++++- web/app/components/comment/comment.jsx | 3 +- web/app/components/root/root.jsx | 43 +++++++++++++++++-- web/app/components/thread/thread.jsx | 3 ++ 7 files changed, 87 insertions(+), 9 deletions(-) diff --git a/web/.eslintrc.js b/web/.eslintrc.js index bbd55376..2915f941 100644 --- a/web/.eslintrc.js +++ b/web/.eslintrc.js @@ -43,7 +43,7 @@ module.exports = { 'no-undef-init': 2, 'no-shadow-restricted-names': 2, 'handle-callback-err': 0, - 'no-lonely-if': 2, + 'no-lonely-if': 0, 'constructor-super': 2, 'no-this-before-super': 2, 'no-dupe-class-members': 2, diff --git a/web/app/common/api.js b/web/app/common/api.js index 96ea41ef..d79faf2e 100644 --- a/web/app/common/api.js +++ b/web/app/common/api.js @@ -118,6 +118,18 @@ export const getBlocked = () => withCredentials: true, }); +export const disableComments = () => + fetcher.put({ + url: `/admin/readonly?site=${siteId}&url=${url}&ro=1`, + withCredentials: true, + }); + +export const enableComments = () => + fetcher.put({ + url: `/admin/readonly?site=${siteId}&url=${url}&ro=0`, + withCredentials: true, + }); + export default { logOut, getConfig, @@ -140,4 +152,6 @@ export default { blockUser, unblockUser, getBlocked, + disableComments, + enableComments, }; diff --git a/web/app/components/auth-panel/__tests__/auth-panel.test.js b/web/app/components/auth-panel/__tests__/auth-panel.test.js index fa946807..ce8f1bb7 100644 --- a/web/app/components/auth-panel/__tests__/auth-panel.test.js +++ b/web/app/components/auth-panel/__tests__/auth-panel.test.js @@ -67,7 +67,7 @@ describe('', () => { const adminAction = container.querySelector('.auth-panel__admin-action'); - expect(adminAction.textContent).toEqual('Show blocked'); + expect(adminAction.textContent).toEqual('Show blocked users'); }); }); }); diff --git a/web/app/components/auth-panel/auth-panel.jsx b/web/app/components/auth-panel/auth-panel.jsx index e0327b3b..a2560f8c 100644 --- a/web/app/components/auth-panel/auth-panel.jsx +++ b/web/app/components/auth-panel/auth-panel.jsx @@ -10,6 +10,7 @@ export default class AuthPanel extends Component { this.toggleUserId = this.toggleUserId.bind(this); this.toggleBlockedVisibility = this.toggleBlockedVisibility.bind(this); + this.toggleCommentsAvailability = this.toggleCommentsAvailability.bind(this); this.onSortChange = this.onSortChange.bind(this); } @@ -31,8 +32,20 @@ export default class AuthPanel extends Component { this.setState({ isBlockedVisible: !this.state.isBlockedVisible }); } + toggleCommentsAvailability() { + if (this.props.isCommentsDisabled) { + if (this.props.onCommentsEnable) { + this.props.onCommentsEnable(); + } + } else { + if (this.props.onCommentsDisable) { + this.props.onCommentsDisable(); + } + } + } + render(props, { isUserIdVisible, isBlockedVisible }) { - const { user, providers = [], sort } = props; + const { user, providers = [], sort, isCommentsDisabled } = props; const sortArray = getSortArray(sort); @@ -82,7 +95,19 @@ export default class AuthPanel extends Component { {...getHandleClickProps(this.toggleBlockedVisibility)} role="link" > - {isBlockedVisible ? 'Hide' : 'Show'} blocked + {isBlockedVisible ? 'Hide' : 'Show'} blocked users + + )} + + {user.admin && ' • '} + + {user.admin && ( + + {isCommentsDisabled ? 'Enable' : 'Disable'} comments )} diff --git a/web/app/components/comment/comment.jsx b/web/app/components/comment/comment.jsx index 53c52c7d..74b139d5 100644 --- a/web/app/components/comment/comment.jsx +++ b/web/app/components/comment/comment.jsx @@ -320,7 +320,7 @@ export default class Comment extends Component { editTimeLeft, } ) { - const { data, mods = {} } = props; + const { data, mods = {}, isCommentsDisabled } = props; const isAdmin = !guest && store.get('user').admin; const isGuest = guest || !Object.keys(store.get('user')).length; const isCurrentUser = (data.user && data.user.id) === (store.get('user') && store.get('user').id); @@ -500,6 +500,7 @@ export default class Comment extends Component {
{!deleted && + !isCommentsDisabled && !mods.disabled && !isGuest && mods.view !== 'user' && ( diff --git a/web/app/components/root/root.jsx b/web/app/components/root/root.jsx index 04713530..986a6d47 100644 --- a/web/app/components/root/root.jsx +++ b/web/app/components/root/root.jsx @@ -48,6 +48,8 @@ export default class Root extends Component { this.onSignOut = this.onSignOut.bind(this); this.onBlockedUsersShow = this.onBlockedUsersShow.bind(this); this.onBlockedUsersHide = this.onBlockedUsersHide.bind(this); + this.onCommentsDisable = this.onCommentsDisable.bind(this); + this.onCommentsEnable = this.onCommentsEnable.bind(this); this.onSortChange = this.onSortChange.bind(this); this.onUnblockSomeone = this.onUnblockSomeone.bind(this); this.checkUrlHash = this.checkUrlHash.bind(this); @@ -56,6 +58,7 @@ export default class Root extends Component { componentWillMount() { store.onUpdate('comments', comments => this.setState({ comments })); + store.onUpdate('info', info => this.setState({ info })); } componentDidMount() { @@ -73,7 +76,10 @@ export default class Root extends Component { .catch(() => store.set('user', {})), api .getPostComments({ sort, url }) - .then(({ comments = [] } = {}) => store.set('comments', comments)) + .then(({ comments = [], info = {} } = {}) => { + store.set('comments', comments); + store.set('info', info); + }) .catch(() => store.set('comments', [])), ]).finally(() => { this.setState({ @@ -145,12 +151,31 @@ export default class Root extends Component { }); } + onCommentsEnable() { + api.enableComments(siteId, url).then(() => { + const info = store.get('info'); + info.read_only = false; + this.setState({ info }); + }); + } + + onCommentsDisable() { + api.disableComments(siteId, url).then(() => { + const info = store.get('info'); + info.read_only = true; + this.setState({ info }); + }); + } + onBlockedUsersHide() { const { wasSomeoneUnblocked, sort } = this.state; // if someone was unblocked let's reload comments if (wasSomeoneUnblocked) { - api.getPostComments({ sort, url }).then(({ comments } = {}) => store.set('comments', comments)); + api.getPostComments({ sort, url }).then(({ comments, info } = {}) => { + store.set('comments', comments); + store.set('info', info); + }); } this.setState({ @@ -172,7 +197,10 @@ export default class Root extends Component { api .getPostComments({ sort, url }) - .then(({ comments } = {}) => store.set('comments', comments)) + .then(({ comments, info } = {}) => { + store.set('comments', comments); + store.set('info', info); + }) .finally(() => { this.setState({ isCommentsListLoading: false }); }); @@ -201,6 +229,7 @@ export default class Root extends Component { { config = {}, comments = [], + info = {}, user, sort, isLoaded, @@ -223,6 +252,7 @@ export default class Root extends Component { // TODO: i think we should do it on backend const pinnedComments = store.getPinnedComments(); const isGuest = !Object.keys(user).length; + const isCommentsDisabled = info != null && info.read_only === true; return (
@@ -231,16 +261,20 @@ export default class Root extends Component { user={user} sort={sort} providers={config.auth_providers} + isCommentsDisabled={isCommentsDisabled} onSignIn={this.onSignIn} onSignOut={this.onSignOut} onBlockedUsersShow={this.onBlockedUsersShow} onBlockedUsersHide={this.onBlockedUsersHide} + onCommentsEnable={this.onCommentsEnable} + onCommentsDisable={this.onCommentsDisable} onSortChange={this.onSortChange} /> {!isBlockedVisible && (
- {!isGuest && } + {!isGuest && + !isCommentsDisabled && } {!!pinnedComments.length && (
@@ -259,6 +293,7 @@ export default class Root extends Component { mix="root__thread" mods={{ level: 0 }} data={thread} + isCommentsDisabled={isCommentsDisabled} onReply={this.addComment} onEdit={this.replaceComment} /> diff --git a/web/app/components/thread/thread.jsx b/web/app/components/thread/thread.jsx index 0f5b2b45..1b2342af 100644 --- a/web/app/components/thread/thread.jsx +++ b/web/app/components/thread/thread.jsx @@ -21,6 +21,7 @@ class Thread extends Component { collapsed, data: { comment, replies = [] }, mods = {}, + isCommentsDisabled, } = props; return ( @@ -31,6 +32,7 @@ class Thread extends Component { >