Improve initial load error handling
This commit is contained in:
parent
ce241c93e0
commit
b52938aa42
12
index.html
12
index.html
@ -79,6 +79,14 @@
|
|||||||
#splash__error {
|
#splash__error {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
transition: opacity 0.5s ease-in;
|
transition: opacity 0.5s ease-in;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 60rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#splash__error-message {
|
||||||
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
#splash__error[aria-hidden=true] {
|
#splash__error[aria-hidden=true] {
|
||||||
@ -125,7 +133,9 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div id="splash__error" role="alert" aria-hidden="true">
|
<div id="splash__error" role="alert" aria-hidden="true">
|
||||||
Failed to load server configuration. Retrying<span id="splash__error-attempt"></span>...
|
<span>Failed to load server configuration.</span>
|
||||||
|
<span id="splash__error-message"></span>
|
||||||
|
<span id="splash__error-retry">Retrying<span id="splash__error-attempt"></span>...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -81,6 +81,10 @@
|
|||||||
transition: opacity 0.5s ease-in;
|
transition: opacity 0.5s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#splash__error-message {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
#splash__error[aria-hidden=true] {
|
#splash__error[aria-hidden=true] {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
16
src/App.vue
16
src/App.vue
@ -29,6 +29,7 @@ import {useStore} from "@/store";
|
|||||||
import {ActionTypes} from "@/store/action-types";
|
import {ActionTypes} from "@/store/action-types";
|
||||||
import {parseUrl} from '@/util';
|
import {parseUrl} from '@/util';
|
||||||
import {MutationTypes} from "@/store/mutation-types";
|
import {MutationTypes} from "@/store/mutation-types";
|
||||||
|
import API from '@/api';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'App',
|
name: 'App',
|
||||||
@ -50,15 +51,24 @@ export default defineComponent({
|
|||||||
configAttempts = ref(0),
|
configAttempts = ref(0),
|
||||||
|
|
||||||
loadConfiguration = () => {
|
loadConfiguration = () => {
|
||||||
store.dispatch(ActionTypes.LOAD_CONFIGURATION, undefined).then(() => {
|
let validated = false;
|
||||||
|
|
||||||
|
API.validateConfiguration().then(() => {
|
||||||
|
validated = true;
|
||||||
|
|
||||||
|
return store.dispatch(ActionTypes.LOAD_CONFIGURATION, undefined).then(() => {
|
||||||
startUpdates();
|
startUpdates();
|
||||||
window.hideSplash();
|
window.hideSplash();
|
||||||
|
});
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error('Failed to load server configuration: ', e);
|
console.error('Failed to load server configuration: ', e);
|
||||||
window.showSplashError(++configAttempts.value);
|
window.showSplashError(e, !validated, ++configAttempts.value);
|
||||||
|
|
||||||
|
//Don't retry if config isn't valid
|
||||||
|
if(validated) {
|
||||||
setTimeout(() => loadConfiguration(), 1000);
|
setTimeout(() => loadConfiguration(), 1000);
|
||||||
});
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
startUpdates = () => {
|
startUpdates = () => {
|
||||||
|
32
src/api.ts
32
src/api.ts
@ -553,10 +553,40 @@ function buildUpdates(data: Array<any>): DynmapUpdates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
validateConfiguration(): Promise<void> {
|
||||||
|
const check = '\nCheck your standalone/config.js file exists and is being loaded correctly.';
|
||||||
|
|
||||||
|
if(!window.config || !window.config.url) {
|
||||||
|
return Promise.reject(`Dynmap's configuration is missing. ${check}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!window.config.url.configuration) {
|
||||||
|
return Promise.reject(`Dynmap's configuration URL is missing. ${check}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!window.config.url.update) {
|
||||||
|
return Promise.reject(`Dynmap's update URL is missing. ${check}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!window.config.url.markers) {
|
||||||
|
return Promise.reject(`Dynmap's markers URL is missing. ${check}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!window.config.url.tiles) {
|
||||||
|
return Promise.reject(`Dynmap's tiles URL is missing. ${check}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!window.config.url.sendmessage) {
|
||||||
|
return Promise.reject(`Dynmap's sendmessage URL is missing. ${check}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
|
||||||
getConfiguration(): Promise<DynmapConfigurationResponse> {
|
getConfiguration(): Promise<DynmapConfigurationResponse> {
|
||||||
return fetch(window.config.url.configuration).then(response => {
|
return fetch(window.config.url.configuration).then(response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network request failed');
|
throw new Error('Network request failed: ' + response.statusText);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
|
20
src/main.ts
20
src/main.ts
@ -23,7 +23,10 @@ import 'normalize-scss/sass/normalize/_import-now.scss';
|
|||||||
import '@/scss/style.scss';
|
import '@/scss/style.scss';
|
||||||
|
|
||||||
const splash = document.getElementById('splash'),
|
const splash = document.getElementById('splash'),
|
||||||
|
splashSpinner = document.getElementById('splash__spinner'),
|
||||||
splashError = document.getElementById('splash__error'),
|
splashError = document.getElementById('splash__error'),
|
||||||
|
splashErrorMessage = document.getElementById('splash__error-message'),
|
||||||
|
splashRetry = document.getElementById('splash__error-retry'),
|
||||||
splashAttempt = document.getElementById('splash__error-attempt'),
|
splashAttempt = document.getElementById('splash__error-attempt'),
|
||||||
svgs = import.meta.globEager('/assets/icons/*.svg');
|
svgs = import.meta.globEager('/assets/icons/*.svg');
|
||||||
|
|
||||||
@ -35,14 +38,27 @@ window.hideSplash = function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
window.showSplashError = function(attempts: number) {
|
window.showSplashError = function(message: string, fatal: boolean, attempts: number) {
|
||||||
if(splashError) {
|
if(splashError) {
|
||||||
splashError.setAttribute('aria-hidden', 'false');
|
splashError.setAttribute('aria-hidden', 'false');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(splashAttempt) {
|
if(splashErrorMessage) {
|
||||||
|
splashErrorMessage.innerText = message || 'Unknown error';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(splashSpinner && fatal) {
|
||||||
|
splashSpinner.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(splashAttempt && splashRetry) {
|
||||||
|
if(fatal) {
|
||||||
|
splashAttempt.hidden = splashRetry.hidden = true;
|
||||||
|
} else if(attempts) {
|
||||||
|
splashAttempt.hidden = splashRetry.hidden = false;
|
||||||
splashAttempt.textContent = attempts.toString();
|
splashAttempt.textContent = attempts.toString();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(splash) {
|
if(splash) {
|
||||||
|
Loading…
Reference in New Issue
Block a user