Show banner on server errors.

This commit is contained in:
quthla 2019-10-24 21:35:36 +02:00 committed by Jannis Mattheis
parent ed254547db
commit 9715ecaeb1
5 changed files with 33 additions and 19 deletions

View File

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

View File

@ -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 (
<div
style={{
@ -18,7 +19,7 @@ export const NetworkLostBanner = ({height, retry}: NetworkLostBannerProps) => {
position: 'relative',
}}>
<Typography align="center" variant="h6" style={{lineHeight: `${height}px`}}>
No network connection.{' '}
{message}{' '}
<Button variant="outlined" onClick={retry}>
Retry
</Button>

View File

@ -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<
<MuiThemeProvider theme={theme}>
<HashRouter>
<div>
{hasNetwork ? null : (
<NetworkLostBanner height={64} retry={() => tryReconnect()} />
{!connectionErrorMessage ? null : (
<ConnectionErrorBanner
height={64}
retry={() => tryReconnect()}
message={connectionErrorMessage}
/>
)}
<div style={{display: 'flex'}}>
<CssBaseline />
<Header
style={{top: hasNetwork ? 0 : 64}}
style={{top: !connectionErrorMessage ? 0 : 64}}
admin={admin}
name={name}
version={version}

View File

@ -30,9 +30,9 @@ export const registerReactions = (stores: StoreMapping) => {
);
reaction(
() => stores.currentUser.hasNetwork,
(hasNetwork) => {
if (hasNetwork) {
() => stores.currentUser.connectionErrorMessage,
(connectionErrorMessage) => {
if (!connectionErrorMessage) {
clearAll();
loadAll();
}

View File

@ -44,7 +44,7 @@ class Login extends Component<Stores<'currentUser'>> {
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