ClientConnectionInterruption: allow retrying with current settings

This commit is contained in:
Jesse Chan
2020-11-03 00:04:48 +08:00
parent 4c24f56260
commit 00029514f7
7 changed files with 122 additions and 47 deletions

View File

@@ -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;

View File

@@ -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<string | null>(null);
const [isSubmitting, setSubmitting] = React.useState<boolean>(false);
const [selection, setSelection] = React.useState<React.ReactText>('retry');
const settingsFormRef = React.useRef<ClientConnectionSettingsFormType>(null);
if (!AuthStore.currentUser.isAdmin && !AuthStore.currentUser.isInitialUser) {
if (!AuthStore.currentUser.isAdmin) {
return (
<Panel spacing="large">
<PanelHeader>
@@ -28,25 +43,43 @@ const ClientConnectionInterruption: React.FC = () => {
return (
<Panel spacing="large">
<Form
onSubmit={() => {
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);
}}>
<PanelHeader>
<h1>
@@ -54,13 +87,43 @@ const ClientConnectionInterruption: React.FC = () => {
</h1>
</PanelHeader>
<PanelContent>
<ClientConnectionSettingsForm ref={settingsFormRef} />
{error && (
<FormRow>
<FormError>
<FormattedMessage id={error} />
</FormError>
</FormRow>
)}
{AuthStore.currentUser.isAdmin ? (
<FormRow>
<Select id="action" onSelect={setSelection} defaultID="retry">
<SelectItem key="retry" id="retry">
<FormattedMessage id="connection-interruption.action.selection.retry" />
</SelectItem>
<SelectItem key="config" id="config">
<FormattedMessage id="connection-interruption.action.selection.config" />
</SelectItem>
</Select>
</FormRow>
) : (
<p className="copy--lead">
<FormattedMessage id="connection-interruption.not.admin" />
</p>
)}
{selection === 'config' && <ClientConnectionSettingsForm ref={settingsFormRef} />}
</PanelContent>
<PanelFooter hasBorder>
<FormRow justify="end">
<Button type="submit">
<FormattedMessage id="button.save" />
</Button>
{selection === 'retry' && (
<Button type="submit" isLoading={isSubmitting}>
<FormattedMessage id="button.retry" />
</Button>
)}
{selection === 'config' && (
<Button type="submit" isLoading={isSubmitting}>
<FormattedMessage id="button.save" />
</Button>
)}
</FormRow>
</PanelFooter>
</Form>

View File

@@ -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,

View File

@@ -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",

View File

@@ -22,7 +22,7 @@ export default async (req: Request<unknown, unknown, unknown, {historySnapshot:
const serviceInstances = services.getAllServices(user);
const serverEvent = new ServerEvent(res);
const fetchTorrentList = serviceInstances.torrentService.fetchTorrentList()?.catch((e) => console.error(e));
const fetchTorrentList = serviceInstances.torrentService.fetchTorrentList();
if (serviceInstances.clientGatewayService == null) {
return;
@@ -82,7 +82,7 @@ export default async (req: Request<unknown, unknown, unknown, {historySnapshot:
const {timestamps: lastTimestamps} = snapshot || {timestamps: []};
const lastTimestamp = lastTimestamps[lastTimestamps.length - 1];
if (error == null && snapshot != null) {
if (error == null && snapshot != null && lastTimestamp != null) {
serverEvent.emit(lastTimestamp, 'TRANSFER_HISTORY_FULL_UPDATE', snapshot);
}
});

View File

@@ -40,7 +40,13 @@ router.get('/', (req, res) => {
req.services?.torrentService
.fetchTorrentList()
.then(callback)
.then((data) => {
if (data == null) {
callback(null, new Error());
} else {
callback(data);
}
})
.catch((err) => {
callback(null, err);
});

View File

@@ -73,7 +73,7 @@ class TorrentService extends BaseService<TorrentServiceEvents> {
this.services?.clientGatewayService
?.fetchTorrentList()
.then(this.handleFetchTorrentListSuccess)
.catch(this.handleFetchTorrentListError) || Promise.reject()
.catch(this.handleFetchTorrentListError) || Promise.resolve(this.handleFetchTorrentListError())
);
};