From 9715ecaeb16475107ba0478640eacd5033531505 Mon Sep 17 00:00:00 2001 From: quthla Date: Thu, 24 Oct 2019 21:35:36 +0200 Subject: [PATCH] Show banner on server errors. --- ui/src/CurrentUser.ts | 23 +++++++++++++------ ...stBanner.tsx => ConnectionErrorBanner.tsx} | 7 +++--- ui/src/layout/Layout.tsx | 14 +++++++---- ui/src/reactions.ts | 6 ++--- ui/src/user/Login.tsx | 2 +- 5 files changed, 33 insertions(+), 19 deletions(-) rename ui/src/common/{NetworkLostBanner.tsx => ConnectionErrorBanner.tsx} (77%) diff --git a/ui/src/CurrentUser.ts b/ui/src/CurrentUser.ts index 6eeea03..59d5a55 100644 --- a/ui/src/CurrentUser.ts +++ b/ui/src/CurrentUser.ts @@ -11,7 +11,7 @@ const tokenKey = 'gotify-login-key'; export class CurrentUser { private tokenCache: string | null = null; private reconnectTimeoutId: number | null = null; - private readonly reconnectTime: number = 3000; + private reconnectTime = 7500; @observable public loggedIn = false; @observable @@ -19,7 +19,7 @@ export class CurrentUser { @observable public user: IUser = {name: 'unknown', admin: false, id: -1}; @observable - public hasNetwork = true; + public connectionErrorMessage: string | null = null; public constructor(private readonly snack: SnackReporter) {} @@ -87,16 +87,24 @@ export class CurrentUser { .then((passThrough) => { this.user = passThrough.data; this.loggedIn = true; - this.hasNetwork = true; + this.connectionErrorMessage = null; + this.reconnectTime = 7500; return passThrough; }) .catch((error: AxiosError) => { if (!error || !error.response) { - this.lostNetwork(); + this.connectionError('No network connection or server unavailable.'); return Promise.reject(error); } - this.hasNetwork = true; + if (error.response.status >= 500) { + this.connectionError( + `${error.response.statusText} (code: ${error.response.status}).` + ); + return Promise.reject(error); + } + + this.connectionErrorMessage = null; if (error.response.status >= 400 && error.response.status < 500) { this.logout(); @@ -135,8 +143,8 @@ export class CurrentUser { }); }; - private lostNetwork = () => { - this.hasNetwork = false; + private connectionError = (message: string) => { + this.connectionErrorMessage = message; if (this.reconnectTimeoutId !== null) { window.clearTimeout(this.reconnectTimeoutId); } @@ -144,5 +152,6 @@ export class CurrentUser { () => this.tryReconnect(true), this.reconnectTime ); + this.reconnectTime = Math.min(this.reconnectTime * 2, 120000); }; } diff --git a/ui/src/common/NetworkLostBanner.tsx b/ui/src/common/ConnectionErrorBanner.tsx similarity index 77% rename from ui/src/common/NetworkLostBanner.tsx rename to ui/src/common/ConnectionErrorBanner.tsx index 11a73d8..71b21e5 100644 --- a/ui/src/common/NetworkLostBanner.tsx +++ b/ui/src/common/ConnectionErrorBanner.tsx @@ -2,12 +2,13 @@ import React from 'react'; import Button from '@material-ui/core/Button'; import Typography from '@material-ui/core/Typography'; -interface NetworkLostBannerProps { +interface ConnectionErrorBannerProps { height: number; retry: () => void; + message: string; } -export const NetworkLostBanner = ({height, retry}: NetworkLostBannerProps) => { +export const ConnectionErrorBanner = ({height, retry, message}: ConnectionErrorBannerProps) => { return (
{ position: 'relative', }}> - No network connection.{' '} + {message}{' '} diff --git a/ui/src/layout/Layout.tsx b/ui/src/layout/Layout.tsx index 98765eb..7fdf906 100644 --- a/ui/src/layout/Layout.tsx +++ b/ui/src/layout/Layout.tsx @@ -20,7 +20,7 @@ import Users from '../user/Users'; import {observer} from 'mobx-react'; import {observable} from 'mobx'; import {inject, Stores} from '../inject'; -import {NetworkLostBanner} from '../common/NetworkLostBanner'; +import {ConnectionErrorBanner} from '../common/ConnectionErrorBanner'; import {IVersion} from '../types'; const styles = (theme: Theme) => ({ @@ -88,8 +88,8 @@ class Layout extends React.Component< authenticating, user: {name, admin}, logout, - hasNetwork, tryReconnect, + connectionErrorMessage, }, } = this.props; const theme = themeMap[currentTheme]; @@ -98,13 +98,17 @@ class Layout extends React.Component<
- {hasNetwork ? null : ( - tryReconnect()} /> + {!connectionErrorMessage ? null : ( + tryReconnect()} + message={connectionErrorMessage} + /> )}
{ ); reaction( - () => stores.currentUser.hasNetwork, - (hasNetwork) => { - if (hasNetwork) { + () => stores.currentUser.connectionErrorMessage, + (connectionErrorMessage) => { + if (!connectionErrorMessage) { clearAll(); loadAll(); } diff --git a/ui/src/user/Login.tsx b/ui/src/user/Login.tsx index cb20ad4..f55be9a 100644 --- a/ui/src/user/Login.tsx +++ b/ui/src/user/Login.tsx @@ -44,7 +44,7 @@ class Login extends Component> { size="large" className="login" color="primary" - disabled={!this.props.currentUser.hasNetwork} + disabled={!!this.props.currentUser.connectionErrorMessage} style={{marginTop: 15, marginBottom: 5}} onClick={this.login}> Login