forked from extern/homer
Avoid full reload when swithcing page.
This commit is contained in:
parent
00b46a6dde
commit
ba07da6b10
@ -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!"
|
@ -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.
|
||||||
|
65
src/App.vue
65
src/App.vue
@ -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) {
|
||||||
|
@ -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;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user