Avoid full reload when swithcing page.

This commit is contained in:
Bastien Wirtz 2021-03-06 22:50:58 -08:00
parent 00b46a6dde
commit ba07da6b10
4 changed files with 70 additions and 46 deletions

View File

@ -1,18 +1,20 @@
# this config is used by a page linked in the navbar ---
# this pages will use the same configuration from config.yml, but will overwrite fields present here # Additionnal page configuration
# this overwrites title and subtitle: # Additionnal configurations are loaded using its file name, minus the extension, as an anchor (https://<mydashboad>#<config>).
title: "Page2" # `config.yml` is still used as a base configuration, and all values here will overwrite it, so you don't have to re-defined everything
subtitle: "this is the second page"
# this overwrites message config. Setting it to empty to remove message from this page and keep it only in the main one:
message: subtitle: "this is another dashboard page"
# This overwrites message config. Setting it to empty to remove message from this page and keep it only in the main one:
message: ~
# as we want to include a differente link here (so we can get back to home page), we need to replicate all links or they will be revome when overwriting the links field: # as we want to include a differente link here (so we can get back to home page), we need to replicate all links or they will be revome when overwriting the links field:
links: links:
- name: "Home" - name: "Home"
icon: "fas fa-home" icon: "fas fa-home"
url: "/" url: "#"
- name: "Contribute" - name: "Contribute"
icon: "fab fa-github" icon: "fab fa-github"
url: "https://github.com/bastienwirtz/homer" url: "https://github.com/bastienwirtz/homer"
@ -21,9 +23,8 @@ links:
icon: "fas fa-book" icon: "fas fa-book"
url: "https://www.wikipedia.org/" url: "https://www.wikipedia.org/"
# we keep the first group from the main page, but remove the second group. We need to replicate that first group or it will be removed:
services: services:
- name: "NEW" - name: "More applications on another page!"
icon: "fas fa-cloud" icon: "fas fa-cloud"
items: items:
- name: "Awesome app on a second page!" - name: "Awesome app on a second page!"

View File

@ -56,6 +56,11 @@ links:
- name: "Wiki" - name: "Wiki"
icon: "fas fa-book" icon: "fas fa-book"
url: "https://www.wikipedia.org/" url: "https://www.wikipedia.org/"
# this will link to a second homer page that will load config from additionnal-page.yml and keep default config values as in config.yml file
# see url field and assets/additionnal-page.yml.dist used in this example:
- name: "another page!"
icon: "fas fa-file-alt"
url: "#additionnal-page"
# Services # Services
# First level array represent a group. # First level array represent a group.

View File

@ -13,7 +13,9 @@
<section v-if="config.header" class="first-line"> <section v-if="config.header" class="first-line">
<div v-cloak class="container"> <div v-cloak class="container">
<div class="logo"> <div class="logo">
<a href="#"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a> <a href="#">
<img v-if="config.logo" :src="config.logo" alt="dashboard logo" />
</a>
<i v-if="config.icon" :class="config.icon"></i> <i v-if="config.icon" :class="config.icon"></i>
</div> </div>
<div class="dashboard-title"> <div class="dashboard-title">
@ -149,36 +151,41 @@ export default {
}; };
}, },
created: async function () { created: async function () {
const defaults = jsyaml.load(defaultConfig); this.buildDashboard();
let config; window.onhashchange = this.buildDashboard;
window.onhashchange = function() { location.reload(); };
try {
config = await this.getConfig();
const path = (window.location.hash.substring(1) != '') ? window.location.hash.substring(1) : null;
if (path) {
let pathConfig = await this.getConfig(`assets/${path}.yml`); // the slash (/) is included in the pathname
for (const prop in pathConfig) config[prop] = pathConfig[prop];
}
// config = await this.getConfig(path ? `assets/${path}.yml` : null);
//config = await (path ? this.getConfig(`assets/${path}.yml`) : this.getConfig())
} catch (error) {
console.log(error);
config = this.handleErrors("⚠️ Error loading configuration", error);
}
this.config = merge(defaults, config);
this.services = this.config.services;
document.title =
this.config.documentTitle ||
`${this.config.title} | ${this.config.subtitle}`;
if (this.config.stylesheet) {
let stylesheet = "";
for (const file of this.config.stylesheet) {
stylesheet += `@import "${file}";`;
}
this.createStylesheet(stylesheet);
}
}, },
methods: { methods: {
buildDashboard: async function () {
const defaults = jsyaml.load(defaultConfig);
let config;
try {
config = await this.getConfig();
const path =
window.location.hash.substring(1) != ""
? window.location.hash.substring(1)
: null;
if (path) {
let pathConfig = await this.getConfig(`assets/${path}.yml`); // the slash (/) is included in the pathname
config = Object.assign(config, pathConfig);
}
} catch (error) {
console.log(error);
config = this.handleErrors("⚠️ Error loading configuration", error);
}
this.config = merge(defaults, config);
this.services = this.config.services;
document.title =
this.config.documentTitle ||
`${this.config.title} | ${this.config.subtitle}`;
if (this.config.stylesheet) {
let stylesheet = "";
for (const file of this.config.stylesheet) {
stylesheet += `@import "${file}";`;
}
this.createStylesheet(stylesheet);
}
},
getConfig: function (path = "assets/config.yml") { getConfig: function (path = "assets/config.yml") {
return fetch(path).then((response) => { return fetch(path).then((response) => {
if (response.redirected) { if (response.redirected) {

View File

@ -22,7 +22,6 @@ export default {
}, },
data: function () { data: function () {
return { return {
show: false,
message: {}, message: {},
}; };
}, },
@ -30,14 +29,23 @@ export default {
// Look for a new message if an endpoint is provided. // Look for a new message if an endpoint is provided.
this.message = Object.assign({}, this.item); this.message = Object.assign({}, this.item);
await this.getMessage(); await this.getMessage();
this.show = this.message.title || this.message.content;
}, },
computed: {
show: function () {
return this.message.title || this.message.content;
},
},
watch: {
item: function (item) {
this.message = Object.assign({}, item);
},
},
methods: { methods: {
getMessage: async function() { getMessage: async function () {
if (this.item && this.item.url) { if (this.item && this.item.url) {
let fetchedMessage = await this.downloadMessage(this.item.url); let fetchedMessage = await this.downloadMessage(this.item.url);
if (this.item.mapping) fetchedMessage = this.mapRemoteMessage(fetchedMessage); if (this.item.mapping)
fetchedMessage = this.mapRemoteMessage(fetchedMessage);
// keep the original config value if no value is provided by the endpoint // keep the original config value if no value is provided by the endpoint
for (const prop of ["title", "style", "content"]) { for (const prop of ["title", "style", "content"]) {
if (prop in fetchedMessage && fetchedMessage[prop] !== null) { if (prop in fetchedMessage && fetchedMessage[prop] !== null) {
@ -45,7 +53,8 @@ export default {
} }
} }
} }
if (this.item.refreshInterval) setTimeout(this.getMessage, this.item.refreshInterval); if (this.item.refreshInterval)
setTimeout(this.getMessage, this.item.refreshInterval);
}, },
downloadMessage: function (url) { downloadMessage: function (url) {
@ -60,7 +69,9 @@ export default {
mapRemoteMessage: function (message) { mapRemoteMessage: function (message) {
let mapped = {}; let mapped = {};
// map property from message into mapped according to mapping config (only if field has a value): // map property from message into mapped according to mapping config (only if field has a value):
for (const prop in this.item.mapping) if (message[this.item.mapping[prop]]) mapped[prop] = message[this.item.mapping[prop]]; for (const prop in this.item.mapping)
if (message[this.item.mapping[prop]])
mapped[prop] = message[this.item.mapping[prop]];
return mapped; return mapped;
}, },
}, },