diff options
author | Bastien Wirtz <bastien.wirtz@gmail.com> | 2021-03-06 22:50:58 -0800 |
---|---|---|
committer | Bastien Wirtz <bastien.wirtz@gmail.com> | 2021-03-06 22:50:58 -0800 |
commit | ba07da6b1011e77c9ed42e8643e62b903c6c6d7b (patch) | |
tree | 6311707cb628e64a2787b680a9a4d517505faa51 | |
parent | 00b46a6ddebcbbe581f201bd4089c38f6d666fb9 (diff) | |
download | homer-ba07da6b1011e77c9ed42e8643e62b903c6c6d7b.tar.gz homer-ba07da6b1011e77c9ed42e8643e62b903c6c6d7b.tar.zst homer-ba07da6b1011e77c9ed42e8643e62b903c6c6d7b.zip |
Avoid full reload when swithcing page.
-rw-r--r-- | public/assets/additionnal-page.yml.dist (renamed from public/assets/page2.yml) | 21 | ||||
-rw-r--r-- | public/assets/config.yml.dist | 5 | ||||
-rw-r--r-- | src/App.vue | 65 | ||||
-rw-r--r-- | src/components/Message.vue | 25 |
4 files changed, 70 insertions, 46 deletions
diff --git a/public/assets/page2.yml b/public/assets/additionnal-page.yml.dist index 00001e9..f918dc1 100644 --- a/public/assets/page2.yml +++ b/public/assets/additionnal-page.yml.dist | |||
@@ -1,18 +1,20 @@ | |||
1 | # this config is used by a page linked in the navbar | 1 | --- |
2 | # this pages will use the same configuration from config.yml, but will overwrite fields present here | 2 | # Additionnal page configuration |
3 | 3 | ||
4 | # this overwrites title and subtitle: | 4 | # Additionnal configurations are loaded using its file name, minus the extension, as an anchor (https://<mydashboad>#<config>). |
5 | title: "Page2" | 5 | # `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 |
6 | subtitle: "this is the second page" | ||
7 | 6 | ||
8 | # this overwrites message config. Setting it to empty to remove message from this page and keep it only in the main one: | 7 | |
9 | message: | 8 | subtitle: "this is another dashboard page" |
9 | |||
10 | # This overwrites message config. Setting it to empty to remove message from this page and keep it only in the main one: | ||
11 | message: ~ | ||
10 | 12 | ||
11 | # 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: | 13 | # 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: |
12 | links: | 14 | links: |
13 | - name: "Home" | 15 | - name: "Home" |
14 | icon: "fas fa-home" | 16 | icon: "fas fa-home" |
15 | url: "/" | 17 | url: "#" |
16 | - name: "Contribute" | 18 | - name: "Contribute" |
17 | icon: "fab fa-github" | 19 | icon: "fab fa-github" |
18 | url: "https://github.com/bastienwirtz/homer" | 20 | url: "https://github.com/bastienwirtz/homer" |
@@ -21,9 +23,8 @@ links: | |||
21 | icon: "fas fa-book" | 23 | icon: "fas fa-book" |
22 | url: "https://www.wikipedia.org/" | 24 | url: "https://www.wikipedia.org/" |
23 | 25 | ||
24 | # 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: | ||
25 | services: | 26 | services: |
26 | - name: "NEW" | 27 | - name: "More applications on another page!" |
27 | icon: "fas fa-cloud" | 28 | icon: "fas fa-cloud" |
28 | items: | 29 | items: |
29 | - name: "Awesome app on a second page!" | 30 | - name: "Awesome app on a second page!" |
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: | |||
56 | - name: "Wiki" | 56 | - name: "Wiki" |
57 | icon: "fas fa-book" | 57 | icon: "fas fa-book" |
58 | url: "https://www.wikipedia.org/" | 58 | url: "https://www.wikipedia.org/" |
59 | # 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 | ||
60 | # see url field and assets/additionnal-page.yml.dist used in this example: | ||
61 | - name: "another page!" | ||
62 | icon: "fas fa-file-alt" | ||
63 | url: "#additionnal-page" | ||
59 | 64 | ||
60 | # Services | 65 | # Services |
61 | # First level array represent a group. | 66 | # First level array represent a group. |
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 @@ | |||
13 | <section v-if="config.header" class="first-line"> | 13 | <section v-if="config.header" class="first-line"> |
14 | <div v-cloak class="container"> | 14 | <div v-cloak class="container"> |
15 | <div class="logo"> | 15 | <div class="logo"> |
16 | <a href="#"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a> | 16 | <a href="#"> |
17 | <img v-if="config.logo" :src="config.logo" alt="dashboard logo" /> | ||
18 | </a> | ||
17 | <i v-if="config.icon" :class="config.icon"></i> | 19 | <i v-if="config.icon" :class="config.icon"></i> |
18 | </div> | 20 | </div> |
19 | <div class="dashboard-title"> | 21 | <div class="dashboard-title"> |
@@ -149,36 +151,41 @@ export default { | |||
149 | }; | 151 | }; |
150 | }, | 152 | }, |
151 | created: async function () { | 153 | created: async function () { |
152 | const defaults = jsyaml.load(defaultConfig); | 154 | this.buildDashboard(); |
153 | let config; | 155 | window.onhashchange = this.buildDashboard; |
154 | window.onhashchange = function() { location.reload(); }; | ||
155 | try { | ||
156 | config = await this.getConfig(); | ||
157 | const path = (window.location.hash.substring(1) != '') ? window.location.hash.substring(1) : null; | ||
158 | if (path) { | ||
159 | let pathConfig = await this.getConfig(`assets/${path}.yml`); // the slash (/) is included in the pathname | ||
160 | for (const prop in pathConfig) config[prop] = pathConfig[prop]; | ||
161 | } | ||
162 | // config = await this.getConfig(path ? `assets/${path}.yml` : null); | ||
163 | //config = await (path ? this.getConfig(`assets/${path}.yml`) : this.getConfig()) | ||
164 | } catch (error) { | ||
165 | console.log(error); | ||
166 | config = this.handleErrors("⚠️ Error loading configuration", error); | ||
167 | } | ||
168 | this.config = merge(defaults, config); | ||
169 | this.services = this.config.services; | ||
170 | document.title = | ||
171 | this.config.documentTitle || | ||
172 | `${this.config.title} | ${this.config.subtitle}`; | ||
173 | if (this.config.stylesheet) { | ||
174 | let stylesheet = ""; | ||
175 | for (const file of this.config.stylesheet) { | ||
176 | stylesheet += `@import "${file}";`; | ||
177 | } | ||
178 | this.createStylesheet(stylesheet); | ||
179 | } | ||
180 | }, | 156 | }, |
181 | methods: { | 157 | methods: { |
158 | buildDashboard: async function () { | ||
159 | const defaults = jsyaml.load(defaultConfig); | ||
160 | let config; | ||
161 | try { | ||
162 | config = await this.getConfig(); | ||
163 | const path = | ||
164 | window.location.hash.substring(1) != "" | ||
165 | ? window.location.hash.substring(1) | ||
166 | : null; | ||
167 | |||
168 | if (path) { | ||
169 | let pathConfig = await this.getConfig(`assets/${path}.yml`); // the slash (/) is included in the pathname | ||
170 | config = Object.assign(config, pathConfig); | ||
171 | } | ||
172 | } catch (error) { | ||
173 | console.log(error); | ||
174 | config = this.handleErrors("⚠️ Error loading configuration", error); | ||
175 | } | ||
176 | this.config = merge(defaults, config); | ||
177 | this.services = this.config.services; | ||
178 | document.title = | ||
179 | this.config.documentTitle || | ||
180 | `${this.config.title} | ${this.config.subtitle}`; | ||
181 | if (this.config.stylesheet) { | ||
182 | let stylesheet = ""; | ||
183 | for (const file of this.config.stylesheet) { | ||
184 | stylesheet += `@import "${file}";`; | ||
185 | } | ||
186 | this.createStylesheet(stylesheet); | ||
187 | } | ||
188 | }, | ||
182 | getConfig: function (path = "assets/config.yml") { | 189 | getConfig: function (path = "assets/config.yml") { |
183 | return fetch(path).then((response) => { | 190 | return fetch(path).then((response) => { |
184 | if (response.redirected) { | 191 | 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 { | |||
22 | }, | 22 | }, |
23 | data: function () { | 23 | data: function () { |
24 | return { | 24 | return { |
25 | show: false, | ||
26 | message: {}, | 25 | message: {}, |
27 | }; | 26 | }; |
28 | }, | 27 | }, |
@@ -30,14 +29,23 @@ export default { | |||
30 | // Look for a new message if an endpoint is provided. | 29 | // Look for a new message if an endpoint is provided. |
31 | this.message = Object.assign({}, this.item); | 30 | this.message = Object.assign({}, this.item); |
32 | await this.getMessage(); | 31 | await this.getMessage(); |
33 | this.show = this.message.title || this.message.content; | ||
34 | }, | 32 | }, |
35 | 33 | computed: { | |
34 | show: function () { | ||
35 | return this.message.title || this.message.content; | ||
36 | }, | ||
37 | }, | ||
38 | watch: { | ||
39 | item: function (item) { | ||
40 | this.message = Object.assign({}, item); | ||
41 | }, | ||
42 | }, | ||
36 | methods: { | 43 | methods: { |
37 | getMessage: async function() { | 44 | getMessage: async function () { |
38 | if (this.item && this.item.url) { | 45 | if (this.item && this.item.url) { |
39 | let fetchedMessage = await this.downloadMessage(this.item.url); | 46 | let fetchedMessage = await this.downloadMessage(this.item.url); |
40 | if (this.item.mapping) fetchedMessage = this.mapRemoteMessage(fetchedMessage); | 47 | if (this.item.mapping) |
48 | fetchedMessage = this.mapRemoteMessage(fetchedMessage); | ||
41 | // keep the original config value if no value is provided by the endpoint | 49 | // keep the original config value if no value is provided by the endpoint |
42 | for (const prop of ["title", "style", "content"]) { | 50 | for (const prop of ["title", "style", "content"]) { |
43 | if (prop in fetchedMessage && fetchedMessage[prop] !== null) { | 51 | if (prop in fetchedMessage && fetchedMessage[prop] !== null) { |
@@ -45,7 +53,8 @@ export default { | |||
45 | } | 53 | } |
46 | } | 54 | } |
47 | } | 55 | } |
48 | if (this.item.refreshInterval) setTimeout(this.getMessage, this.item.refreshInterval); | 56 | if (this.item.refreshInterval) |
57 | setTimeout(this.getMessage, this.item.refreshInterval); | ||
49 | }, | 58 | }, |
50 | 59 | ||
51 | downloadMessage: function (url) { | 60 | downloadMessage: function (url) { |
@@ -60,7 +69,9 @@ export default { | |||
60 | mapRemoteMessage: function (message) { | 69 | mapRemoteMessage: function (message) { |
61 | let mapped = {}; | 70 | let mapped = {}; |
62 | // map property from message into mapped according to mapping config (only if field has a value): | 71 | // map property from message into mapped according to mapping config (only if field has a value): |
63 | for (const prop in this.item.mapping) if (message[this.item.mapping[prop]]) mapped[prop] = message[this.item.mapping[prop]]; | 72 | for (const prop in this.item.mapping) |
73 | if (message[this.item.mapping[prop]]) | ||
74 | mapped[prop] = message[this.item.mapping[prop]]; | ||
64 | return mapped; | 75 | return mapped; |
65 | }, | 76 | }, |
66 | }, | 77 | }, |