From df0ab7c1dc4158e4738109da96e394917dd4a32d Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Tue, 19 Dec 2017 15:11:11 -0700 Subject: [PATCH 1/7] removed body-parser in favor of express.json() --- package.json | 1 - routes/index.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index de3b617a2..c46a4caaa 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,6 @@ "babel-preset-es2015": "6.24.1", "babel-preset-react": "^6.23.0", "bcryptjs": "^2.4.3", - "body-parser": "1.18.2", "bowser": "^1.7.2", "cli-table": "^0.3.1", "clipboard": "^1.7.1", diff --git a/routes/index.js b/routes/index.js index 454e32f58..af7edec3b 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,7 +1,6 @@ const accepts = require('accepts'); const apollo = require('graphql-server-express'); const authentication = require('../middleware/authentication'); -const bodyParser = require('body-parser'); const cookieParser = require('cookie-parser'); const debug = require('debug')('talk:routes'); const enabled = require('debug').enabled; @@ -82,7 +81,7 @@ router.use('/embed', staticTemplate, require('./embed')); router.use(cookieParser()); // Parse the body json if it's there. -router.use(bodyParser.json()); +router.use(express.json()); const passportDebug = require('debug')('talk:passport'); From b46b392af4e15a87c9218821027cdeb2ef38e15c Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 20 Dec 2017 09:31:59 -0700 Subject: [PATCH 2/7] added subscription hooks --- graph/subscriptions.js | 37 ++++++++++++++++++++++++++++++++++--- plugins.js | 4 ++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/graph/subscriptions.js b/graph/subscriptions.js index 59dd6e923..60afc9c45 100644 --- a/graph/subscriptions.js +++ b/graph/subscriptions.js @@ -5,6 +5,7 @@ const debug = require('debug')('talk:graph:subscriptions'); const pubsub = require('../services/pubsub'); const schema = require('./schema'); const Context = require('./context'); +const plugins = require('../services/plugins'); const {deserializeUser} = require('../services/subscriptions'); const setupFunctions = require('./setupFunctions'); @@ -16,16 +17,42 @@ const { const {BASE_PATH} = require('../url'); -const onConnect = ({token}, connection) => { +// Collect all the plugin hooks that should be executed onConnect and +// onDisconnect. +const hooks = plugins.get('server', 'websockets') + .map(({plugin, websockets}) => { + debug(`added websocket hooks ${Object.keys(websockets)} from plugin '${plugin.name}'`); + + return websockets; + }) + .reduce((hooks, {onConnect = null, onDisconnect = null}) => { + if (onConnect) { + hooks.onConnect.push(onConnect); + } + + if (onDisconnect) { + hooks.onDisconnect.push(onDisconnect); + } + + return hooks; + }, { + onConnect: [], + onDisconnect: [], + }); + +const onConnect = async (connectionParams, connection) => { // Attach the token from the connection options if it was provided. - if (token) { + if (connectionParams.token) { debug('token sent via onConnect, attaching to the headers of the upgrade request'); // Attach it to the upgrade request. - connection.upgradeReq.headers['authorization'] = `Bearer ${token}`; + connection.upgradeReq.headers['authorization'] = `Bearer ${connectionParams.token}`; } + + // Call all the hooks. + await Promise.all(hooks.onConnect.map((hook) => hook(connectionParams, connection))); }; const onOperation = (parsedMessage, baseParams, connection) => { @@ -52,6 +79,9 @@ const onOperation = (parsedMessage, baseParams, connection) => { return baseParams; }; +const onDisconnect = (connection) => + Promise.all(hooks.onDisconnect.map((hook) => hook(connection))); + /** * This creates a new subscription manager. */ @@ -62,6 +92,7 @@ const createSubscriptionManager = (server) => new SubscriptionServer({ setupFunctions, }), onConnect, + onDisconnect, onOperation, keepAlive: ms(KEEP_ALIVE) }, { diff --git a/plugins.js b/plugins.js index 487825be7..577289b25 100644 --- a/plugins.js +++ b/plugins.js @@ -57,6 +57,10 @@ const hookSchemas = { resolvers: Joi.object().pattern(/\w/, Joi.object().pattern(/(?:__resolveType|\w+)/, Joi.func())), typeDefs: Joi.string(), schemaLevelResolveFunction: Joi.func(), + websockets: Joi.object({ + onConnect: Joi.func(), + onDisconnect: Joi.func(), + }), }; /** From 2233d993c21ee2db32a4a7ce3abe80ff38702417 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 20 Dec 2017 15:27:55 -0700 Subject: [PATCH 3/7] fixed expiry loading --- graph/loaders/util.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/graph/loaders/util.js b/graph/loaders/util.js index fe2a4e3d0..4d43d1811 100644 --- a/graph/loaders/util.js +++ b/graph/loaders/util.js @@ -72,8 +72,10 @@ class SharedCacheDataLoader extends DataLoader { constructor(prefix, expiry, batchLoadFn, options) { super(SharedCacheDataLoader.batchLoadFn(prefix, expiry, batchLoadFn), options); + // Expiry is provided as a number in ms, we're using commands optimized for + // seconds, so convert this to seconds. + this._expiry = Math.floor(expiry / 1000); this._prefix = prefix; - this._expiry = expiry; this._keyFunc = SharedCacheDataLoader.keyFunc(this._prefix); } From 2d6a05433a626386e7a211c7478b6978d7c14016 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 21 Dec 2017 15:55:18 +0100 Subject: [PATCH 4/7] Mark single dangling comments, reflow issues and scroll enhancement --- .../Moderation/components/ModerationQueue.js | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js index fbb116cd7..59c3b8b7e 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js @@ -190,6 +190,29 @@ class ModerationQueue extends React.Component { componentDidUpdate (prev) { const {commentCount, selectedCommentId} = this.props; + // Switching to multi mode. + if (prev.singleView && !this.props.singleView) { + + // Reflow virtual list. + this.reflowList(); + + // Scroll to selected comment. + if (this.props.selectedCommentId) { + const view = this.state.view; + const index = view.findIndex(({id}) => id === selectedCommentId); + this.listRef.scrollToRow(index); + } + } + + // Switching to single mode. + if (!prev.singleView && this.props.singleView) { + + // Scroll to comment. + if (this.props.selectedCommentId) { + document.querySelector(`#comment_${this.props.selectedCommentId}`).scrollIntoView(); + } + } + // If the user just moderated the last (visible) comment // AND there are more comments available on the server, // go ahead and load more comments @@ -197,7 +220,7 @@ class ModerationQueue extends React.Component { this.props.loadMore(); } - // Scroll to selected comment. + // Scroll to new selected comment. if (prev.selectedCommentId !== selectedCommentId && this.listRef) { const view = this.state.view; @@ -372,6 +395,7 @@ class ModerationQueue extends React.Component { rejectComment={props.rejectComment} currentAsset={props.currentAsset} currentUserId={this.props.currentUserId} + dangling={!this.props.commentBelongToQueue(this.props.activeTab, comment)} />; ); From f9e289561e4ed3335b2d12fc75047b866f85af02 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 21 Dec 2017 18:29:18 +0100 Subject: [PATCH 5/7] Refactor --- .../Moderation/components/ModerationQueue.js | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js index 59c3b8b7e..72df10682 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js @@ -195,22 +195,17 @@ class ModerationQueue extends React.Component { // Reflow virtual list. this.reflowList(); - - // Scroll to selected comment. - if (this.props.selectedCommentId) { - const view = this.state.view; - const index = view.findIndex(({id}) => id === selectedCommentId); - this.listRef.scrollToRow(index); - } } - // Switching to single mode. - if (!prev.singleView && this.props.singleView) { + if ( - // Scroll to comment. - if (this.props.selectedCommentId) { - document.querySelector(`#comment_${this.props.selectedCommentId}`).scrollIntoView(); - } + // Switching mode. + prev.singleView !== this.props.singleView || + + // Select different comment. + prev.selectedCommentId !== selectedCommentId && selectedCommentId + ) { + this.scrollToSelectedComment(); } // If the user just moderated the last (visible) comment @@ -219,15 +214,6 @@ class ModerationQueue extends React.Component { if (prev.comments.length > 0 && this.getCommentCountWithoutDagling() === 0 && commentCount > 0) { this.props.loadMore(); } - - // Scroll to new selected comment. - if (prev.selectedCommentId !== selectedCommentId && this.listRef) { - - const view = this.state.view; - const index = view.findIndex(({id}) => id === selectedCommentId); - - this.listRef.scrollToRow(index); - } } // Returns comment counts without dangling comments. @@ -265,6 +251,17 @@ class ModerationQueue extends React.Component { this.listRef = list; }; + scrollToSelectedComment = (props = this.props, state = this.state) => { + if (props.singleMode) { + document.querySelector(`#comment_${props.selectedCommentId}`).scrollIntoView(); + } + else if(this.listRef) { + const view = state.view; + const index = view.findIndex(({id}) => id === props.selectedCommentId); + this.listRef.scrollToRow(index); + } + } + viewNewComments = (callback) => { this.setState(resetCursors, () => { this.reflowList(); From e34f96832a6115c8238a8bb6f6418a60b1d821c6 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 21 Dec 2017 18:36:15 +0100 Subject: [PATCH 6/7] Refactor --- .../Moderation/components/ModerationQueue.js | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js index 72df10682..77851d568 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js @@ -190,28 +190,22 @@ class ModerationQueue extends React.Component { componentDidUpdate (prev) { const {commentCount, selectedCommentId} = this.props; - // Switching to multi mode. - if (prev.singleView && !this.props.singleView) { + const switchedToMultiMode = prev.singleView && !this.props.singleView; + const switchedMode = prev.singleView !== this.props.singleView; + const selectedDifferentComment = prev.selectedCommentId !== selectedCommentId && selectedCommentId; + const moderatedLastComment = prev.comments.length > 0 && this.getCommentCountWithoutDagling() === 0; + + if (switchedToMultiMode) { // Reflow virtual list. this.reflowList(); } - if ( - - // Switching mode. - prev.singleView !== this.props.singleView || - - // Select different comment. - prev.selectedCommentId !== selectedCommentId && selectedCommentId - ) { + if (switchedMode || selectedDifferentComment) { this.scrollToSelectedComment(); } - // If the user just moderated the last (visible) comment - // AND there are more comments available on the server, - // go ahead and load more comments - if (prev.comments.length > 0 && this.getCommentCountWithoutDagling() === 0 && commentCount > 0) { + if (moderatedLastComment && commentCount > 0) { this.props.loadMore(); } } From 111af0acf86b58fa1fd01397577282b1fae5efa4 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 21 Dec 2017 18:43:39 +0100 Subject: [PATCH 7/7] More refactor --- .../src/routes/Moderation/components/ModerationQueue.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js index 77851d568..83678a4c1 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js @@ -194,6 +194,7 @@ class ModerationQueue extends React.Component { const switchedMode = prev.singleView !== this.props.singleView; const selectedDifferentComment = prev.selectedCommentId !== selectedCommentId && selectedCommentId; const moderatedLastComment = prev.comments.length > 0 && this.getCommentCountWithoutDagling() === 0; + const hasMoreComment = commentCount > 0; if (switchedToMultiMode) { @@ -205,7 +206,7 @@ class ModerationQueue extends React.Component { this.scrollToSelectedComment(); } - if (moderatedLastComment && commentCount > 0) { + if (moderatedLastComment && hasMoreComment) { this.props.loadMore(); } }