Merge pull request #175 from luixal/message-remote-fields-mapping

Adds mapping remote field to Homer expected ones when loading message from URL
This commit is contained in:
Bastien Wirtz 2021-03-04 18:40:07 -08:00 committed by GitHub
commit cc7ff88552
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 11 deletions

View File

@ -66,6 +66,17 @@ colors:
# Optional message # Optional message
message: message:
# url: "https://<my-api-endpoint>" # Can fetch information from an endpoint to override value below. # url: "https://<my-api-endpoint>" # Can fetch information from an endpoint to override value below.
# mapping: # allows to map fields from the remote format to the one expected by Homer
# title: 'id' # use value from field 'id' as title
# content: 'value' # value from field 'value' as content
# refreshInterval: 10000 # Optional: time interval to refresh message
#
# Real example using chucknorris.io for showing Chuck Norris facts as messages:
# url: https://api.chucknorris.io/jokes/random
# mapping:
# title: 'id'
# content: 'value'
# refreshInterval: 10000
style: "is-warning" style: "is-warning"
title: "Optional message!" title: "Optional message!"
icon: "fa fa-exclamation-triangle" icon: "fa fa-exclamation-triangle"
@ -118,7 +129,7 @@ services:
# background: red # optional color for card to set color directly without custom stylesheet # background: red # optional color for card to set color directly without custom stylesheet
``` ```
If you choose to fetch message information from an endpoint, the output format should be: If you choose to fetch message information from an endpoint, the output format should be as follows (or you can [custom map fields as shown in tips-and-tricks](./tips-and-tricks.md#mapping-fields)):
```json ```json
{ {

View File

@ -113,6 +113,64 @@ docker create \
## Get the news headlines in Homer ## Get the news headlines in Homer
### Mapping Fields
Most times, the url you're getting headlines from follows a different schema than the one expected by Homer.
For example, if you would like to show jokes from ChuckNorris.io, you'll find that the url https://api.chucknorris.io/jokes/random is giving you info like this:
```json
{
"categories": [],
"created_at": "2020-01-05 13:42:22.089095",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "MR2-BnMBR667xSpQBIleUg",
"updated_at": "2020-01-05 13:42:22.089095",
"url": "https://api.chucknorris.io/jokes/MR2-BnMBR667xSpQBIleUg",
"value": "Chuck Norris can quitely sneak up on himself"
}
```
but... you need that info to be transformed to something like this:
```json
{
"title": "MR2-BnMBR667xSpQBIleUg",
"content": "Chuck Norris can quitely sneak up on himself"
}
```
Now, you can do that using the `mapping` field in your `message` configuration. This example would be something like this:
```yml
message:
url: https://api.chucknorris.io/jokes/random
mapping:
title: 'id'
content: 'value'
```
As you would see, using the ID as a title doesn't seem nice, that's why when a field is empty it would keep the default values, like this:
```yml
message:
url: https://api.chucknorris.io/jokes/random
mapping:
content: 'value'
title: "Chuck Norris Facts!"
```
and even an error message in case the `url` didn't respond or threw an error:
```yml
message:
url: https://api.chucknorris.io/jokes/random
mapping:
content: 'value'
title: "Chuck Norris Facts!"
content: "Message could not be loaded"
```
#### `by @JamiePhonic` #### `by @JamiePhonic`
Homer allows you to set a "message" that will appear at the top of the page, however, you can also supply a `url:`. Homer allows you to set a "message" that will appear at the top of the page, however, you can also supply a `url:`.

View File

@ -29,8 +29,15 @@ export default {
created: async function () { created: async function () {
// 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();
this.show = this.message.title || this.message.content;
},
methods: {
getMessage: async function() {
if (this.item && this.item.url) { if (this.item && this.item.url) {
const fetchedMessage = await this.getMessage(this.item.url); let fetchedMessage = await this.downloadMessage(this.item.url);
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) {
@ -38,10 +45,10 @@ export default {
} }
} }
} }
this.show = this.message.title || this.message.content; if (this.item.refreshInterval) setTimeout(this.getMessage, this.item.refreshInterval);
}, },
methods: {
getMessage: function (url) { downloadMessage: function (url) {
return fetch(url).then(function (response) { return fetch(url).then(function (response) {
if (response.status != 200) { if (response.status != 200) {
return; return;
@ -49,6 +56,13 @@ export default {
return response.json(); return response.json();
}); });
}, },
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]];
return mapped;
},
}, },
}; };
</script> </script>