From ba07da6b1011e77c9ed42e8643e62b903c6c6d7b Mon Sep 17 00:00:00 2001 From: Bastien Wirtz Date: Sat, 6 Mar 2021 22:50:58 -0800 Subject: Avoid full reload when swithcing page. --- public/assets/additionnal-page.yml.dist | 35 ++++++++++++++++++ public/assets/config.yml.dist | 5 +++ public/assets/page2.yml | 34 ----------------- src/App.vue | 65 ++++++++++++++++++--------------- src/components/Message.vue | 25 +++++++++---- 5 files changed, 94 insertions(+), 70 deletions(-) create mode 100644 public/assets/additionnal-page.yml.dist delete mode 100644 public/assets/page2.yml diff --git a/public/assets/additionnal-page.yml.dist b/public/assets/additionnal-page.yml.dist new file mode 100644 index 0000000..f918dc1 --- /dev/null +++ b/public/assets/additionnal-page.yml.dist @@ -0,0 +1,35 @@ +--- +# Additionnal page configuration + +# Additionnal configurations are loaded using its file name, minus the extension, as an anchor (https://#). +# `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 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: +links: + - name: "Home" + icon: "fas fa-home" + url: "#" + - name: "Contribute" + icon: "fab fa-github" + url: "https://github.com/bastienwirtz/homer" + target: "_blank" # optional html a tag target attribute + - name: "Wiki" + icon: "fas fa-book" + url: "https://www.wikipedia.org/" + +services: + - name: "More applications on another page!" + icon: "fas fa-cloud" + items: + - name: "Awesome app on a second page!" + logo: "assets/tools/sample.png" + subtitle: "Bookmark example" + tag: "app" + url: "https://www.reddit.com/r/selfhosted/" + target: "_blank" diff --git a/public/assets/config.yml.dist b/public/assets/config.yml.dist index 85478ec..65c5098 100644 --- a/public/assets/config.yml.dist +++ b/public/assets/config.yml.dist @@ -56,6 +56,11 @@ links: - name: "Wiki" icon: "fas fa-book" 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 # First level array represent a group. diff --git a/public/assets/page2.yml b/public/assets/page2.yml deleted file mode 100644 index 00001e9..0000000 --- a/public/assets/page2.yml +++ /dev/null @@ -1,34 +0,0 @@ -# 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 - -# this overwrites title and subtitle: -title: "Page2" -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: - -# 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: - - name: "Home" - icon: "fas fa-home" - url: "/" - - name: "Contribute" - icon: "fab fa-github" - url: "https://github.com/bastienwirtz/homer" - target: "_blank" # optional html a tag target attribute - - name: "Wiki" - icon: "fas fa-book" - 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: - - name: "NEW" - icon: "fas fa-cloud" - items: - - name: "Awesome app on a second page!" - logo: "assets/tools/sample.png" - subtitle: "Bookmark example" - tag: "app" - url: "https://www.reddit.com/r/selfhosted/" - target: "_blank" diff --git a/src/App.vue b/src/App.vue index cd1d9ba..aff340c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -13,7 +13,9 @@
@@ -149,36 +151,41 @@ export default { }; }, created: async function () { - const defaults = jsyaml.load(defaultConfig); - let config; - 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); - } + this.buildDashboard(); + window.onhashchange = this.buildDashboard; }, 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") { return fetch(path).then((response) => { if (response.redirected) { diff --git a/src/components/Message.vue b/src/components/Message.vue index 2f71f3f..7c6acdd 100644 --- a/src/components/Message.vue +++ b/src/components/Message.vue @@ -22,7 +22,6 @@ export default { }, data: function () { return { - show: false, message: {}, }; }, @@ -30,14 +29,23 @@ export default { // Look for a new message if an endpoint is provided. this.message = Object.assign({}, this.item); 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: { - getMessage: async function() { + getMessage: async function () { if (this.item && 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 for (const prop of ["title", "style", "content"]) { 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) { @@ -60,7 +69,9 @@ export default { mapRemoteMessage: function (message) { let mapped = {}; // 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; }, }, -- cgit v1.2.3