Show banner on server errors.
This commit is contained in:
parent
ed254547db
commit
9715ecaeb1
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ export const registerReactions = (stores: StoreMapping) => {
|
|||
);
|
||||
|
||||
reaction(
|
||||
() => stores.currentUser.hasNetwork,
|
||||
(hasNetwork) => {
|
||||
if (hasNetwork) {
|
||||
() => stores.currentUser.connectionErrorMessage,
|
||||
(connectionErrorMessage) => {
|
||||
if (!connectionErrorMessage) {
|
||||
clearAll();
|
||||
loadAll();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue