mirror of https://github.com/Lissy93/dashy.git
🔀 Merge pull request #257 from Lissy93/FEATURE/custom-error-pages
[FEATURE] Custom Error Pages
This commit is contained in:
commit
877585b19d
|
@ -1,5 +1,9 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## ✨ 1.8.4 - Custom Error Pages [PR #257](https://github.com/Lissy93/dashy/pull/257)
|
||||||
|
- Creates a 404 Not Found page
|
||||||
|
- Routes any missing views to the 404 page
|
||||||
|
|
||||||
## ⚡️ 1.8.3 - Improved UX for Initial Load [PR #238](https://github.com/Lissy93/dashy/pull/238)
|
## ⚡️ 1.8.3 - Improved UX for Initial Load [PR #238](https://github.com/Lissy93/dashy/pull/238)
|
||||||
- Removes the old splash screen
|
- Removes the old splash screen
|
||||||
- Adds placeholder in the HTML index, which will usually be visible on initial load
|
- Adds placeholder in the HTML index, which will usually be visible on initial load
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
# SUPPORT
|
# Support
|
||||||
|
|
||||||
For help with getting Dashy up and running, please see the [Discussion](https://github.com/Lissy93/dashy/discussions).
|
To raise a bug, please **[Open a new Issue](https://github.com/Lissy93/dashy/issues/new/choose)**.
|
||||||
|
|
||||||
If you'd like to help support Dashy's future development, see [Contributing](/docs/contributing.md)
|
To report a potential vulnerability, please see **[Security](https://github.com/Lissy93/dashy/blob/master/.github/SECURITY.md#reporting-a-security-issue)**.
|
||||||
|
|
||||||
|
For help with getting Dashy up and running, please see the **[Discussions](https://github.com/Lissy93/dashy/discussions)**.
|
||||||
|
|
||||||
|
If you'd like to help support Dashy's future development, see **[Contributing](https://github.com/Lissy93/dashy/blob/master/docs/contributing.md)**.
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Dashy",
|
"name": "Dashy",
|
||||||
"version": "1.8.3",
|
"version": "1.8.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "server",
|
"main": "server",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,46 +1,32 @@
|
||||||
<template>
|
<template>
|
||||||
<modal :name="modalName" :resizable="true" width="60%" height="60%" classes="dashy-modal">
|
<modal :name="modalName" :resizable="true" width="55%" height="80%" classes="dashy-modal">
|
||||||
<div class="about-modal">
|
<div class="about-modal">
|
||||||
<router-link to="/about" class="title"><h2>App Info</h2></router-link>
|
<router-link to="/about" class="title"><h2>App Info</h2></router-link>
|
||||||
<!-- App Version -->
|
|
||||||
<h3>Version</h3>
|
|
||||||
<AppVersion class="app-version" />
|
|
||||||
<!-- Error Log -->
|
<!-- Error Log -->
|
||||||
<h3>Error Log</h3>
|
<h3>Error Log</h3>
|
||||||
<pre v-if="errorLog" class="logs"><code>{{ errorLog }}</code></pre>
|
<pre v-if="errorLog" class="logs"><code>{{ errorLog }}</code></pre>
|
||||||
<p v-else>No recent errors detected :)</p>
|
<p v-else>No recent errors detected :)</p>
|
||||||
<!-- Service Worker Status -->
|
|
||||||
<h3>Service Worker Status</h3>
|
|
||||||
<pre class="logs"><code>{{ serviceWorkerInfo }}</code></pre>
|
|
||||||
<!-- Config Validation Status -->
|
|
||||||
<h3>Config Validation Status</h3>
|
|
||||||
<pre class="logs"><code>{{getIsConfigValidStatus()}}</code></pre>
|
|
||||||
<hr />
|
<hr />
|
||||||
<!-- Help Links -->
|
<!-- Help Links -->
|
||||||
<h3>Help & Support</h3>
|
<h3>Help & Support</h3>
|
||||||
<ul>
|
For getting support with running or configuring Dashy, see the <a href="https://github.com/Lissy93/dashy/discussions">Discussions</a>
|
||||||
<li><a href="https://github.com/Lissy93/dashy/discussions">Get Support</a></li>
|
<h3>Report a Bug</h3>
|
||||||
<li><a href="https://github.com/Lissy93/dashy/issues/new/choose">Report a Bug</a></li>
|
If you think you've found a bug, then please <a href="https://github.com/Lissy93/dashy/issues/new/choose">raise it on GitHub</a>.
|
||||||
</ul>
|
<br>Include version you are running, environment info, output of the console (press F12),
|
||||||
<span class="small-note">Please include the following info in your bug report: </span>
|
and any suppoting scerenshots.
|
||||||
<a class="info" @click="showInfo = !showInfo">{{ showInfo ? 'Hide' : 'Show'}} system info</a>
|
<h3>Supporting Dashy</h3>
|
||||||
<div class="system-info" v-if="showInfo">
|
For ways that you can get involved, check out the <a href="https://github.com/Lissy93/dashy/blob/master/docs/contributing.md">Contributing</a> page.
|
||||||
<h4>System Info</h4>
|
<h3>More Info</h3>
|
||||||
<code><b>Dashy Version:</b> V {{appVersion}}</code><br>
|
Source: <a href="https://github.com/lissy93/dashy">github.com/lissy93/dashy</a><br>
|
||||||
<code><b>Browser:</b> {{systemInfo.browser}}</code><br>
|
Documentation: <a href="https://dashy.to/docs">dashy.to/docs</a>
|
||||||
<code><b>Is Mobile?</b> {{systemInfo.isMobile ? 'Yes' : 'No'}}</code><br>
|
|
||||||
<code><b>OS:</b> {{systemInfo.os}}</code><br>
|
|
||||||
</div>
|
|
||||||
<!-- About App -->
|
|
||||||
<h3>About</h3>
|
|
||||||
<p class="about-text">
|
|
||||||
Source: <a href="https://github.com/lissy93/dashy">github.com/lissy93/dashy</a><br>
|
|
||||||
Documentation: <a href="https://dashy.to/docs">dashy.to/docs</a>
|
|
||||||
</p>
|
|
||||||
<!-- License -->
|
<!-- License -->
|
||||||
<h3>License</h3>
|
<h3>License</h3>
|
||||||
<p>Licensed under MIT X11. Copyright © 2021</p>
|
Licensed under MIT X11. Copyright <a href="https://aliciasykes.com">Alicia Sykes</a> © 2021.<br>
|
||||||
<br><br>
|
For licenses for third-party modules, please see <a href="https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md">Legal</a>.
|
||||||
|
For a list of contributors, and application thank-you's, see <a href="https://github.com/Lissy93/dashy/blob/master/docs/credits.md">Credits</a>
|
||||||
|
<!-- App Version -->
|
||||||
|
<h3>Version</h3>
|
||||||
|
<AppVersion class="app-version" />
|
||||||
</div>
|
</div>
|
||||||
</modal>
|
</modal>
|
||||||
</template>
|
</template>
|
||||||
|
@ -58,71 +44,13 @@ export default {
|
||||||
return {
|
return {
|
||||||
modalName: modalNames.ABOUT_APP,
|
modalName: modalNames.ABOUT_APP,
|
||||||
appVersion: process.env.VUE_APP_VERSION,
|
appVersion: process.env.VUE_APP_VERSION,
|
||||||
systemInfo: this.getSystemInfo(),
|
|
||||||
errorLog: this.getErrorLog(),
|
errorLog: this.getErrorLog(),
|
||||||
serviceWorkerInfo: 'Checking...',
|
|
||||||
showInfo: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.serviceWorkerInfo = this.getSwStatus();
|
|
||||||
}, 100);
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
getErrorLog() {
|
getErrorLog() {
|
||||||
return sessionStorage.getItem(sessionStorageKeys.ERROR_LOG) || '';
|
return sessionStorage.getItem(sessionStorageKeys.ERROR_LOG) || '';
|
||||||
},
|
},
|
||||||
getIsConfigValidStatus() {
|
|
||||||
const isValidVar = process.env.VUE_APP_CONFIG_VALID;
|
|
||||||
if (isValidVar === undefined) return 'Config validation status is missing';
|
|
||||||
return `Config is ${isValidVar ? 'Valid' : 'Invalid'}`;
|
|
||||||
},
|
|
||||||
getSwStatus() {
|
|
||||||
const sessionData = sessionStorage[sessionStorageKeys.SW_STATUS];
|
|
||||||
const swInfo = sessionData ? JSON.parse(sessionData) : {};
|
|
||||||
let swStatus = '';
|
|
||||||
if (swInfo.registered) swStatus += 'Service worker registered\n';
|
|
||||||
if (swInfo.ready) swStatus += 'Dashy is being served from service worker\n';
|
|
||||||
if (swInfo.cached) swStatus += 'Content has been cached for offline use\n';
|
|
||||||
if (swInfo.updateFound) swStatus += 'New content is downloading\n';
|
|
||||||
if (swInfo.updated) swStatus += 'New content is available; please refresh\n';
|
|
||||||
if (swInfo.offline) swStatus += 'No internet connection found. App is running in offline mode\n';
|
|
||||||
if (swInfo.error) swStatus += 'Error during service worker registration\n';
|
|
||||||
if (swInfo.devMode) swStatus += 'App running in dev mode, no need for service worker\n';
|
|
||||||
if (swStatus.length === 0) swStatus += 'No service worker info available';
|
|
||||||
return swStatus;
|
|
||||||
},
|
|
||||||
getSystemInfo() {
|
|
||||||
const { userAgent } = navigator;
|
|
||||||
|
|
||||||
// Find Operating System
|
|
||||||
let os = 'Unknown';
|
|
||||||
if (userAgent.indexOf('Win') !== -1) os = 'Windows';
|
|
||||||
else if (userAgent.indexOf('Mac') !== -1) os = 'MacOS';
|
|
||||||
else if (userAgent.indexOf('Android') !== -1) os = 'Android';
|
|
||||||
else if (userAgent.indexOf('iPhone') !== -1) os = 'iOS';
|
|
||||||
else if (userAgent.indexOf('Linux') !== -1) os = 'Linux';
|
|
||||||
else if (userAgent.indexOf('X11') !== -1) os = 'UNIX';
|
|
||||||
|
|
||||||
// Find Browser
|
|
||||||
let browser = 'Unknown';
|
|
||||||
if (userAgent.indexOf('Opera') !== -1) browser = 'Opera';
|
|
||||||
else if (userAgent.indexOf('Chrome') !== -1) browser = 'Chrome';
|
|
||||||
else if (userAgent.indexOf('Safari') !== -1) browser = 'Safari';
|
|
||||||
else if (userAgent.indexOf('Firefox') !== -1) browser = 'Firefox';
|
|
||||||
else if (userAgent.indexOf('MSIE') !== -1) browser = 'IE';
|
|
||||||
else browser = 'Unknown';
|
|
||||||
|
|
||||||
const isMobile = !!navigator.userAgent.match(/iphone|android|blackberry/ig) || false;
|
|
||||||
|
|
||||||
return {
|
|
||||||
os,
|
|
||||||
browser,
|
|
||||||
userAgent,
|
|
||||||
isMobile,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -152,40 +80,17 @@ div.about-modal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
font-size: 1.3rem;
|
font-size: 1rem;
|
||||||
margin: 1rem 0 0.2rem 0;
|
margin: 0.5rem 0 0.2rem 0;
|
||||||
color: var(--about-page-accent);
|
color: var(--about-page-accent);
|
||||||
}
|
}
|
||||||
p.small-note {
|
|
||||||
margin: 0.2rem 0;
|
|
||||||
}
|
|
||||||
p.about-text {
|
|
||||||
margin: 0.2rem 0;
|
|
||||||
}
|
|
||||||
a {
|
a {
|
||||||
color: var(--about-page-accent);
|
color: var(--about-page-accent);
|
||||||
}
|
}
|
||||||
ul {
|
|
||||||
margin-top: 0.2rem;
|
|
||||||
}
|
|
||||||
a.info {
|
a.info {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
margin-left: 0.2rem;
|
margin-left: 0.2rem;
|
||||||
}
|
}
|
||||||
.system-info {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
background: var(--black);
|
|
||||||
color: var(--white);
|
|
||||||
border-radius: var(--curve-factor-small);
|
|
||||||
padding: 0.5rem;
|
|
||||||
border: 1px solid var(--white);
|
|
||||||
width: fit-content;
|
|
||||||
h4 {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
margin: 0 0 0.2rem 0;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.app-version {
|
.app-version {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,17 @@ import Vue from 'vue';
|
||||||
import Router from 'vue-router';
|
import Router from 'vue-router';
|
||||||
import ProgressBar from 'rsup-progress';
|
import ProgressBar from 'rsup-progress';
|
||||||
|
|
||||||
// Import views
|
// Import views, that are not lazy-loaded
|
||||||
import Home from '@/views/Home.vue';
|
import Home from '@/views/Home.vue';
|
||||||
import Login from '@/views/Login.vue';
|
import Login from '@/views/Login.vue';
|
||||||
import Workspace from '@/views/Workspace.vue';
|
import Workspace from '@/views/Workspace.vue';
|
||||||
import Minimal from '@/views/Minimal.vue';
|
import Minimal from '@/views/Minimal.vue';
|
||||||
import DownloadConfig from '@/views/DownloadConfig.vue';
|
|
||||||
|
|
||||||
// Import helper functions, config data and defaults
|
// Import helper functions, config data and defaults
|
||||||
import { isAuthEnabled, isLoggedIn, isGuestAccessEnabled } from '@/utils/Auth';
|
import { isAuthEnabled, isLoggedIn, isGuestAccessEnabled } from '@/utils/Auth';
|
||||||
import { config } from '@/utils/ConfigHelpers';
|
import { config } from '@/utils/ConfigHelpers';
|
||||||
import { metaTagData, startingView, routePaths } from '@/utils/defaults';
|
import { metaTagData, startingView, routePaths } from '@/utils/defaults';
|
||||||
|
import ErrorHandler from '@/utils/ErrorHandler';
|
||||||
|
|
||||||
Vue.use(Router);
|
Vue.use(Router);
|
||||||
const progress = new ProgressBar({ color: 'var(--progress-bar)' });
|
const progress = new ProgressBar({ color: 'var(--progress-bar)' });
|
||||||
|
@ -102,16 +102,32 @@ const router = new Router({
|
||||||
{ // The about app page
|
{ // The about app page
|
||||||
path: routePaths.about,
|
path: routePaths.about,
|
||||||
name: 'about', // We lazy load the About page so as to not slow down the app
|
name: 'about', // We lazy load the About page so as to not slow down the app
|
||||||
component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
|
component: () => import('./views/About.vue'),
|
||||||
meta: makeMetaTags('About Dashy'),
|
meta: makeMetaTags('About Dashy'),
|
||||||
},
|
},
|
||||||
{ // The export config page
|
{ // The export config page
|
||||||
path: routePaths.download,
|
path: routePaths.download,
|
||||||
name: 'download',
|
name: 'download',
|
||||||
component: DownloadConfig,
|
component: () => import('./views/DownloadConfig.vue'),
|
||||||
props: config,
|
props: config,
|
||||||
meta: makeMetaTags('Download Config'),
|
meta: makeMetaTags('Download Config'),
|
||||||
},
|
},
|
||||||
|
{ // Page not found, any non-defined routes will land here
|
||||||
|
path: routePaths.notFound,
|
||||||
|
name: '404',
|
||||||
|
component: () => import('./views/404.vue'),
|
||||||
|
meta: makeMetaTags('404 Not Found'),
|
||||||
|
beforeEnter: (to, from, next) => {
|
||||||
|
if (to.redirectedFrom) { // Log error, if redirected here from another route
|
||||||
|
ErrorHandler(`Route not found: '${to.redirectedFrom}'`);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // Redirect any not-found routed to the 404 view
|
||||||
|
path: '*',
|
||||||
|
redirect: '/404',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ module.exports = {
|
||||||
about: '/about',
|
about: '/about',
|
||||||
login: '/login',
|
login: '/login',
|
||||||
download: '/download',
|
download: '/download',
|
||||||
|
notFound: '/404',
|
||||||
},
|
},
|
||||||
/* Server Endpoints */
|
/* Server Endpoints */
|
||||||
serviceEndpoints: {
|
serviceEndpoints: {
|
||||||
|
@ -84,6 +85,7 @@ module.exports = {
|
||||||
'login',
|
'login',
|
||||||
'download',
|
'download',
|
||||||
'landing-page-minimal',
|
'landing-page-minimal',
|
||||||
|
// '404',
|
||||||
],
|
],
|
||||||
/* Key names for local storage identifiers */
|
/* Key names for local storage identifiers */
|
||||||
localStorageKeys: {
|
localStorageKeys: {
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
<template>
|
||||||
|
<main class="not-found-page">
|
||||||
|
<h1 class="not-found-title">404</h1>
|
||||||
|
<h2 class="not-found-sad-face">:(</h2>
|
||||||
|
<p class="not-found-subtitle">Page Not Found</p>
|
||||||
|
<p class="not-found-message">
|
||||||
|
Facing Issues?
|
||||||
|
<a href="https://git.io/JzpL5">Get Support</a>.
|
||||||
|
</p>
|
||||||
|
<router-link to="/" class="go-home">Back Home</router-link>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'not-found',
|
||||||
|
methods: {
|
||||||
|
setTheme() {
|
||||||
|
document.getElementsByTagName('html')[0].setAttribute('data-theme', 'dashy-docs');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setTheme();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import '@/styles/media-queries.scss';
|
||||||
|
@import '@/styles/style-helpers.scss';
|
||||||
|
main.not-found-page {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
cursor: default;
|
||||||
|
background: #202020;
|
||||||
|
min-height: calc(99vh - var(--footer-height));
|
||||||
|
background-color: #202020;
|
||||||
|
h1.not-found-title, h2.not-found-sad-face {
|
||||||
|
font-size: 20vh;
|
||||||
|
font-family: Tahoma, monospace;
|
||||||
|
cursor: default;
|
||||||
|
color: #0c0c0c;
|
||||||
|
text-shadow: 0px 4px 4px #090909, 0 0 0 #000, 0px 2px 2px #000000;
|
||||||
|
margin: 1rem 0 0;
|
||||||
|
}
|
||||||
|
h2.not-found-sad-face {
|
||||||
|
font-size: 4rem;
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-family: monospace;
|
||||||
|
cursor: default;
|
||||||
|
color: #0c0c0c;
|
||||||
|
margin: 0.2rem 0;
|
||||||
|
text-shadow: 0 1px 1px #090909, 0 0 0 #000, 0 1px 1px #000000;
|
||||||
|
}
|
||||||
|
p.not-found-subtitle {
|
||||||
|
font-size: 2.8rem;
|
||||||
|
}
|
||||||
|
p.not-found-message {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: normal;
|
||||||
|
a {
|
||||||
|
color: #0c0c0c;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a.go-home {
|
||||||
|
padding: 0.3rem 1rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 1.7rem;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: Tahoma, monospace;
|
||||||
|
color: #0c0c0c;
|
||||||
|
margin: 2rem 0 0;
|
||||||
|
text-decoration: none;
|
||||||
|
background: #db78fc;
|
||||||
|
box-shadow: 0 4px #b83ddd;
|
||||||
|
&:hover { box-shadow: 0 2px #b83ddd; }
|
||||||
|
}
|
||||||
|
::selection { background-color: #db78fc; color: #121212; }
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue