From 00029514f77d9cd5afd9f427f71b057af5c98f3d Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Tue, 3 Nov 2020 00:04:48 +0800 Subject: [PATCH] ClientConnectionInterruption: allow retrying with current settings --- .../src/javascript/actions/ClientActions.ts | 11 +-- .../general/ClientConnectionInterruption.tsx | 97 +++++++++++++++---- .../src/javascript/i18n/strings.compiled.json | 42 ++++---- client/src/javascript/i18n/strings.json | 5 + server/middleware/clientActivityStream.ts | 4 +- server/routes/api/torrents.ts | 8 +- server/services/torrentService.ts | 2 +- 7 files changed, 122 insertions(+), 47 deletions(-) diff --git a/client/src/javascript/actions/ClientActions.ts b/client/src/javascript/actions/ClientActions.ts index a567b8be..c2833766 100644 --- a/client/src/javascript/actions/ClientActions.ts +++ b/client/src/javascript/actions/ClientActions.ts @@ -63,14 +63,9 @@ const ClientActions = { axios .get(`${baseURI}api/client/connection-test`) .then((json) => json.data) - .then( - () => { - // do nothing. - }, - () => { - // do nothing. - }, - ), + .then(() => { + // do nothing. + }), } as const; export default ClientActions; diff --git a/client/src/javascript/components/general/ClientConnectionInterruption.tsx b/client/src/javascript/components/general/ClientConnectionInterruption.tsx index 7b3bd591..9dff9781 100644 --- a/client/src/javascript/components/general/ClientConnectionInterruption.tsx +++ b/client/src/javascript/components/general/ClientConnectionInterruption.tsx @@ -2,18 +2,33 @@ import {FormattedMessage} from 'react-intl'; import {observer} from 'mobx-react'; import * as React from 'react'; -import {Button, Form, FormRow, Panel, PanelContent, PanelHeader, PanelFooter} from '../../ui'; +import { + Button, + Form, + FormError, + FormRow, + Panel, + PanelContent, + PanelHeader, + PanelFooter, + Select, + SelectItem, +} from '../../ui'; import AuthActions from '../../actions/AuthActions'; import AuthStore from '../../stores/AuthStore'; +import ClientActions from '../../actions/ClientActions'; import ClientConnectionSettingsForm from './connection-settings/ClientConnectionSettingsForm'; import FloodActions from '../../actions/FloodActions'; import type {ClientConnectionSettingsFormType} from './connection-settings/ClientConnectionSettingsForm'; const ClientConnectionInterruption: React.FC = () => { + const [error, setError] = React.useState(null); + const [isSubmitting, setSubmitting] = React.useState(false); + const [selection, setSelection] = React.useState('retry'); const settingsFormRef = React.useRef(null); - if (!AuthStore.currentUser.isAdmin && !AuthStore.currentUser.isInitialUser) { + if (!AuthStore.currentUser.isAdmin) { return ( @@ -28,25 +43,43 @@ const ClientConnectionInterruption: React.FC = () => { return (
{ - const currentUsername = AuthStore.currentUser.username; + onSubmit={async () => { + setSubmitting(true); - if (currentUsername == null) { - return; + if (selection === 'config') { + const currentUsername = AuthStore.currentUser.username; + const connectionSettings = settingsFormRef.current?.getConnectionSettings(); + + if (currentUsername == null || connectionSettings == null) { + setError('connection.settings.error.empty'); + setSubmitting(false); + return; + } + + try { + await AuthActions.updateUser(currentUsername, {client: connectionSettings}) + .then(() => { + // do nothing. + }) + .catch((e) => { + setError('general.error.unknown'); + throw e; + }); + } catch { + setSubmitting(false); + return; + } } - const connectionSettings = settingsFormRef.current?.getConnectionSettings(); - if (connectionSettings == null) { - return; - } - - AuthActions.updateUser(currentUsername, {client: connectionSettings}) + await ClientActions.testConnection() .then(() => { FloodActions.restartActivityStream(); }) .catch(() => { - // do nothing. + setError('connection-interruption.verification-error'); }); + + setSubmitting(false); }}>

@@ -54,13 +87,43 @@ const ClientConnectionInterruption: React.FC = () => {

- + {error && ( + + + + + + )} + {AuthStore.currentUser.isAdmin ? ( + + + + ) : ( +

+ +

+ )} + {selection === 'config' && }
- + {selection === 'retry' && ( + + )} + {selection === 'config' && ( + + )}
diff --git a/client/src/javascript/i18n/strings.compiled.json b/client/src/javascript/i18n/strings.compiled.json index 6154c781..5d32cfac 100644 --- a/client/src/javascript/i18n/strings.compiled.json +++ b/client/src/javascript/i18n/strings.compiled.json @@ -407,6 +407,12 @@ "value": "No" } ], + "button.retry": [ + { + "type": 0, + "value": "Retry" + } + ], "button.save": [ { "type": 0, @@ -425,42 +431,42 @@ "value": "Adding..." } ], - "button.test": [ - { - "type": 0, - "value": "Test" - } - ], "button.yes": [ { "type": 0, "value": "Yes" } ], + "connection-interruption.action.selection.config": [ + { + "type": 0, + "value": "Update client connection settings" + } + ], + "connection-interruption.action.selection.retry": [ + { + "type": 0, + "value": "Retry with current client connection settings" + } + ], "connection-interruption.heading": [ { "type": 0, "value": "Cannot connect to the client" } ], + "connection-interruption.not.admin": [ + { + "type": 0, + "value": "Please contact your Flood administrator if this continues." + } + ], "connection-interruption.verification-error": [ { "type": 0, "value": "Connection could not be verified." } ], - "connection-interruption.verification-success": [ - { - "type": 0, - "value": "Connection successful" - } - ], - "connection-interruption.verify-settings-prompt": [ - { - "type": 0, - "value": "Let's verify your connection settings." - } - ], "connection.settings.client.select": [ { "type": 0, diff --git a/client/src/javascript/i18n/strings.json b/client/src/javascript/i18n/strings.json index 2979553f..db1ac637 100644 --- a/client/src/javascript/i18n/strings.json +++ b/client/src/javascript/i18n/strings.json @@ -30,11 +30,16 @@ "button.cancel": "Cancel", "button.download": "Download", "button.no": "No", + "button.retry": "Retry", "button.save": "Save Settings", "button.save.feed": "Save", "button.state.adding": "Adding...", "button.yes": "Yes", "button.new": "New", + "connection-interruption.action.selection.retry": "Retry with current client connection settings", + "connection-interruption.action.selection.config": "Update client connection settings", + "connection-interruption.not.admin": "Please contact your Flood administrator if this continues.", + "connection-interruption.verification-error": "Connection could not be verified.", "connection.settings.client.select": "Client", "connection.settings.error.empty": "Connection settings can not be empty.", "connection.settings.rtorrent": "rTorrent", diff --git a/server/middleware/clientActivityStream.ts b/server/middleware/clientActivityStream.ts index 2050f1fa..a73e5c0f 100644 --- a/server/middleware/clientActivityStream.ts +++ b/server/middleware/clientActivityStream.ts @@ -22,7 +22,7 @@ export default async (req: Request console.error(e)); + const fetchTorrentList = serviceInstances.torrentService.fetchTorrentList(); if (serviceInstances.clientGatewayService == null) { return; @@ -82,7 +82,7 @@ export default async (req: Request { req.services?.torrentService .fetchTorrentList() - .then(callback) + .then((data) => { + if (data == null) { + callback(null, new Error()); + } else { + callback(data); + } + }) .catch((err) => { callback(null, err); }); diff --git a/server/services/torrentService.ts b/server/services/torrentService.ts index ff3b5a63..94b4c7c5 100644 --- a/server/services/torrentService.ts +++ b/server/services/torrentService.ts @@ -73,7 +73,7 @@ class TorrentService extends BaseService { this.services?.clientGatewayService ?.fetchTorrentList() .then(this.handleFetchTorrentListSuccess) - .catch(this.handleFetchTorrentListError) || Promise.reject() + .catch(this.handleFetchTorrentListError) || Promise.resolve(this.handleFetchTorrentListError()) ); };