From acd500457f1ce7c35d8455bf925fddfb63024de7 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Fri, 30 Jun 2023 18:50:58 +0200 Subject: [PATCH] Status de connexion WebSocket et /ws sur NGINX --- .../collaborative/CollaborativeEditor.jsx | 1 + .../CollaborativeEditorWebSocketStatus.jsx | 20 +++++++++++++++++++ ...aborativeEditorWebSocketStatus.module.scss | 3 +++ .../collaborative/CollaborativeTextEditor.jsx | 20 ++++++++++++++----- .../CollaborativeTextEditor.module.scss | 12 ++++++++++- .../components/collaborative/collaborating.js | 11 +++++++++- front/src/createReduxStore.js | 4 ++-- graphql/resolvers/articleResolver.js | 4 ++-- .../files/stylo-dev.huma-num.fr.conf | 2 +- infrastructure/files/stylo.huma-num.fr.conf | 2 +- 10 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 front/src/components/collaborative/CollaborativeEditorWebSocketStatus.jsx create mode 100644 front/src/components/collaborative/CollaborativeEditorWebSocketStatus.module.scss diff --git a/front/src/components/collaborative/CollaborativeEditor.jsx b/front/src/components/collaborative/CollaborativeEditor.jsx index c5dcdf8bf..6b2711a45 100644 --- a/front/src/components/collaborative/CollaborativeEditor.jsx +++ b/front/src/components/collaborative/CollaborativeEditor.jsx @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { useHistory, useParams } from 'react-router-dom' import useGraphQL, { useMutation } from '../../hooks/graphql.js' +import CollaborativeEditorWebSocketStatus from './CollaborativeEditorWebSocketStatus.jsx' import { stopCollaborativeSession, getCollaborativeSession } from './CollaborativeSession.graphql' diff --git a/front/src/components/collaborative/CollaborativeEditorWebSocketStatus.jsx b/front/src/components/collaborative/CollaborativeEditorWebSocketStatus.jsx new file mode 100644 index 000000000..df10fa32c --- /dev/null +++ b/front/src/components/collaborative/CollaborativeEditorWebSocketStatus.jsx @@ -0,0 +1,20 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Dot, Loading } from '@geist-ui/core' + + +import styles from './CollaborativeEditorWebSocketStatus.module.scss' + +export default function CollaborativeEditorWebSocketStatus ({ status }) { + return ( + <> + {status === 'connected' && Connected} + {status === 'disconnected' && Disconnected} + {status === 'connecting' && Connecting } + + ) +} + +CollaborativeEditorWebSocketStatus.propTypes = { + status: PropTypes.string.isRequired +} diff --git a/front/src/components/collaborative/CollaborativeEditorWebSocketStatus.module.scss b/front/src/components/collaborative/CollaborativeEditorWebSocketStatus.module.scss new file mode 100644 index 000000000..08d048fd3 --- /dev/null +++ b/front/src/components/collaborative/CollaborativeEditorWebSocketStatus.module.scss @@ -0,0 +1,3 @@ +.dot { + font-size: 0.8rem !important; +} diff --git a/front/src/components/collaborative/CollaborativeTextEditor.jsx b/front/src/components/collaborative/CollaborativeTextEditor.jsx index 114e07d3e..30a9238eb 100644 --- a/front/src/components/collaborative/CollaborativeTextEditor.jsx +++ b/front/src/components/collaborative/CollaborativeTextEditor.jsx @@ -6,6 +6,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { shallowEqual, useDispatch, useSelector } from 'react-redux' import { MonacoBinding } from 'y-monaco' import * as collaborating from './collaborating.js' +import CollaborativeEditorWebSocketStatus from './CollaborativeEditorWebSocketStatus.jsx' import CollaborativeEditorWriters from './CollaborativeEditorWriters.jsx' import styles from './CollaborativeTextEditor.module.scss' @@ -44,6 +45,7 @@ const colors = [ export default function CollaborativeTextEditor ({ collaborativeSessionId }) { const connectingRef = useRef(false) const [dynamicStyles, setDynamicStyles] = useState('') + const [ websocketStatus, setWebsocketStatus] = useState('') const [yStatus, setYStatus] = useState() const [yText, setYText] = useState() const [awareness, setAwareness] = useState() @@ -60,8 +62,8 @@ export default function CollaborativeTextEditor ({ collaborativeSessionId }) { const options = useMemo(() => ({ automaticLayout: true, - readOnly: false, - contextmenu: true, + readOnly: websocketStatus !== 'connected', + contextmenu: websocketStatus === 'connected', autoClosingBrackets: 'never', wordBasedSuggestions: false, overviewRulerLanes: 0, @@ -73,7 +75,7 @@ export default function CollaborativeTextEditor ({ collaborativeSessionId }) { minimap: { enabled: false } - }), []) + }), [websocketStatus]) const handleUpdateArticleStructureAndStats = throttle(({ text }) => { dispatch({ type: 'UPDATE_ARTICLE_STATS', md: text }) @@ -114,6 +116,9 @@ export default function CollaborativeTextEditor ({ collaborativeSessionId }) { }` }).join('\n')) }, + onStatusUpdated: (status) => { + setWebsocketStatus(status) + } }) const yText = yDocument.getText('main') const yStatus= yDocument.getText('status') @@ -154,8 +159,13 @@ export default function CollaborativeTextEditor ({ collaborativeSessionId }) { -
- +
+
+ +
+
+ +
{} -export function connect({ roomName, websocketEndpoint, user, onChange = noop, onConnection = noop }) { +export function connect({ roomName, websocketEndpoint, user, onChange = noop, onConnection = noop, onStatusUpdated = noop, onConnectionError = noop, onConnectionClosed = noop }) { const doc = new Y.Doc() const awareness = new awarenessProtocol.Awareness(doc); const wsProvider = new WebsocketProvider(websocketEndpoint, roomName, doc, { @@ -22,6 +22,15 @@ export function connect({ roomName, websocketEndpoint, user, onChange = noop, on wsProvider.once('sync', () => onConnection({ states: awareness.getStates(), })) + wsProvider.on('status', function(event) { + onStatusUpdated(event.status) + }) + wsProvider.on('connection-close', function(wsClosedEvent) { + onConnectionClosed(wsClosedEvent) + }) + wsProvider.on('connection-error', function(wsErrorEvent) { + onConnectionError(wsErrorEvent) + }) awareness.setLocalState({ user }) diff --git a/front/src/createReduxStore.js b/front/src/createReduxStore.js index 291b0e130..9fc387d3a 100644 --- a/front/src/createReduxStore.js +++ b/front/src/createReduxStore.js @@ -18,9 +18,9 @@ function toWebsocketEndpoint (endpoint) { if (endpoint) { const endpointUrl = new URL(endpoint) const protocol = endpointUrl.protocol - return `${protocol === 'https:' ? 'wss' : 'ws'}://${endpointUrl.hostname}:${endpointUrl.port}` + return `${protocol === 'https:' ? 'wss' : 'ws'}://${endpointUrl.hostname}:${endpointUrl.port}/ws` } - return `ws://127.0.0.1:3030` + return `ws://127.0.0.1:3030/ws` } // Définition du store Redux et de l'ensemble des actions diff --git a/graphql/resolvers/articleResolver.js b/graphql/resolvers/articleResolver.js index 02d24a143..7d453cae9 100644 --- a/graphql/resolvers/articleResolver.js +++ b/graphql/resolvers/articleResolver.js @@ -357,7 +357,7 @@ module.exports = { createdAt: new Date() } article.collaborativeSession = collaborativeSession - const yDoc = getYDoc(collaborativeSessionId.toString()) + const yDoc = getYDoc(`ws/${collaborativeSessionId.toString()}`) const yText = yDoc.getText('main') yText.insert(0, article.workingVersion.md) await article.save() @@ -366,7 +366,7 @@ module.exports = { async stopCollaborativeSession(article) { if (article.collaborativeSession && article.collaborativeSession.id) { - const yDoc = getYDoc(article.collaborativeSession.id.toString()) + const yDoc = getYDoc(`ws/${article.collaborativeSession.id.toString()}`) const yStatus = yDoc.getText('status') yStatus.delete(0, yStatus.length) yStatus.insert(0, 'ended') diff --git a/infrastructure/files/stylo-dev.huma-num.fr.conf b/infrastructure/files/stylo-dev.huma-num.fr.conf index 59b0a31f3..75036701c 100644 --- a/infrastructure/files/stylo-dev.huma-num.fr.conf +++ b/infrastructure/files/stylo-dev.huma-num.fr.conf @@ -44,7 +44,7 @@ server { proxy_redirect off; } - location ~ ^/(graphql|login/openid|login/local|login/zotero|logout|authorization-code) { + location ~ ^/(graphql|login/openid|login/local|login/zotero|logout|authorization-code|ws) { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; diff --git a/infrastructure/files/stylo.huma-num.fr.conf b/infrastructure/files/stylo.huma-num.fr.conf index efa81acb7..445a91899 100644 --- a/infrastructure/files/stylo.huma-num.fr.conf +++ b/infrastructure/files/stylo.huma-num.fr.conf @@ -44,7 +44,7 @@ server { proxy_redirect off; } - location ~ ^/(graphql|login/openid|login/local|login/zotero|logout|authorization-code) { + location ~ ^/(graphql|login/openid|login/local|login/zotero|logout|authorization-code|ws) { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;