]> git.immae.eu Git - github/bastienwirtz/homer.git/commitdiff
Merge pull request #246 from waschinski/mealie-service
authorBastien Wirtz <bastien.wirtz@gmail.com>
Tue, 14 Sep 2021 20:38:23 +0000 (13:38 -0700)
committerGitHub <noreply@github.com>
Tue, 14 Sep 2021 20:38:23 +0000 (13:38 -0700)
Adding Mealie service

12 files changed:
docs/configuration.md
docs/customservices.md
package.json
src/assets/app.scss
src/components/services/AdGuardHome.vue
src/components/services/OpenWeather.vue [new file with mode: 0644]
src/components/services/PaperlessNG.vue
src/components/services/PiHole.vue
src/components/services/Ping.vue
src/components/services/Radarr.vue
src/components/services/Sonarr.vue
yarn.lock

index f160ae009d490ab2bd26957570486f1f551690db..68711ec4325795dfffeb992a82fe28429e70ede0 100644 (file)
@@ -7,7 +7,7 @@ Title, icons, links, colors, and services can be configured in the `config.yml`
 # Homepage configuration
 # See https://fontawesome.com/icons for icons options
 
-# Optional: Use external configuration file. 
+# Optional: Use external configuration file.
 # Using this will ignore remaining config in this file
 # externalConfig: https://example.com/server-luci/config.yaml
 
@@ -136,6 +136,9 @@ services:
         # background: red # optional color for card to set color directly without custom stylesheet
 ```
 
+
+View [Custom Services](customservices.md) for details about all available custom services (like PiHole) and how to configure them.
+
 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
index 43f45f480734519719b87815c0afd293585243d4..150e232fd002e406f04f31e38d454fe322aedbf9 100644 (file)
@@ -19,6 +19,27 @@ The following configuration is available for the PiHole service.
         type: "PiHole"
 ```
 
+
+## OpenWeatherMap
+
+Using the OpenWeatherMap service you can display weather information about a given location.
+The following configuration is available for the OpenWeatherMap service:
+
+```
+items:
+     - name: "Weather"
+       location: "Amsterdam" # your location.
+       locationId: "2759794" # Optional: Specify OpenWeatherMap city ID for better accuracy
+       apiKey: "<---insert-api-key-here--->" # insert your own API key here. Request one from https://openweathermap.org/api.
+       units: "metric" # units to display temperature. Can be one of: metric, imperial, kelvin. Defaults to kelvin.
+       background: "square" # choose which type of background you want behind the image. Can be one of: square, cicle, none. Defaults to none.
+       type: "OpenWeather"
+```
+
+**Remarks:**
+If for some reason your city can't be found by entering the name in the `location` property, you could also try to configure the OWM city ID in the `locationId` property. To retrieve your specific City ID, go to the [OWM website](https://openweathermap.org), search for your city and retrieve the ID from the URL (for example, the City ID of Amsterdam is 2759794).
+
+
 ## Medusa
 
 This service displays News (grey), Warning (orange) or Error (red) notifications bubbles from the Medusa application.
@@ -50,4 +71,4 @@ For Paperless you need an API-Key which you have to store at the item in the fie
 
 ## Ping
 
-For Paperless you need an API-Key which you have to store at the item in the field `apikey`.
+For Ping you need an API-Key which you have to store at the item in the field `apikey`.
index 61b3073c3e76f866597a87b1729f692a84ad0bb7..c5486bbc9721fcaf484e41fd448371e90f873f31 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "homer",
-  "version": "21.07.1",
+  "version": "21.09.1",
   "license": "Apache-2.0",
   "scripts": {
     "serve": "vue-cli-service serve",
@@ -8,9 +8,9 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
-    "@fortawesome/fontawesome-free": "^5.15.3",
+    "@fortawesome/fontawesome-free": "^5.15.4",
     "bulma": "^0.9.3",
-    "core-js": "^3.15.2",
+    "core-js": "^3.17.3",
     "js-yaml": "^4.1.0",
     "lodash.merge": "^4.6.2",
     "register-service-worker": "^1.7.2",
index 6bb50686259aa06ab029156b3af72abcde01dae7..f2dfb37e4f8f9798c3e6c92889a0f0edae4c83d3 100644 (file)
@@ -106,7 +106,7 @@ body {
     }
 
     .first-line {
-      height: 100px;
+      min-height: 100px;
       vertical-align: center;
       background-color: var(--highlight-primary);
 
@@ -121,7 +121,7 @@ body {
       }
 
       .container {
-        height: 80px;
+        min-height: 80px;
         padding: 10px 0;
       }
 
@@ -140,8 +140,7 @@ body {
         }
       }
     }
-    .navbar,
-    .navbar-menu {
+    .navbar {
       background-color: var(--highlight-secondary);
 
       a {
@@ -153,6 +152,9 @@ body {
           background-color: var(--highlight-hover);
         }
       }
+       .navbar-menu {
+      background-color: inherit;
+      }
     }
     .navbar-end {
       text-align: right;
index d4a2b89119a8969e55d0fbb5d125272827ead010..19a2f7da8df2987691e1e1d68357dcbe6af1db86 100644 (file)
@@ -51,9 +51,9 @@ export default {
   },
   methods: {
     fetchStatus: async function () {
-      this.status = await fetch(`${this.item.url}/control/status`).then(
-        (response) => response.json()
-      );
+      this.status = await fetch(`${this.item.url}/control/status`, {
+        credentials: "include",
+      }).then((response) => response.json());
     },
   },
 };
diff --git a/src/components/services/OpenWeather.vue b/src/components/services/OpenWeather.vue
new file mode 100644 (file)
index 0000000..09ff76a
--- /dev/null
@@ -0,0 +1,135 @@
+<template>
+  <div>
+    <div class="card" :class="item.class">
+      <a
+        :href="`https://openweathermap.org/city/${id}`"
+        :target="item.target"
+        rel="noreferrer"
+      >
+        <div class="card-content">
+          <div class="media">
+            <div v-if="icon" class="media-left" :class="item.background">
+              <figure class="image is-48x48">
+                <img
+                  :src="`https://openweathermap.org/img/wn/${icon}@2x.png`"
+                  :alt="conditions"
+                  :title="conditions"
+                />
+              </figure>
+            </div>
+            <div class="media-content">
+              <p v-if="error" class="error">Data could not be retrieved</p>
+              <div v-else>
+                <p class="title is-4">{{ name }}</p>
+                <p class="subtitle is-6">
+                  {{ temp | tempSuffix(this.item.units) }}
+                </p>
+              </div>
+            </div>
+          </div>
+          <div class="tag" :class="item.tagstyle" v-if="item.tag">
+            <strong class="tag-text">#{{ item.tag }}</strong>
+          </div>
+        </div>
+      </a>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "OpenWeather",
+  props: {
+    item: Object,
+  },
+  data: () => ({
+    id: null,
+    icon: null,
+    name: null,
+    temp: null,
+    conditions: null,
+    error: false,
+  }),
+  created() {
+    this.fetchWeather();
+  },
+  methods: {
+    fetchWeather: async function () {
+      let locationQuery;
+
+      // Use location ID if specified, otherwise retrieve value from location (name).
+      if (this.item.locationId) {
+        locationQuery = `id=${this.item.locationId}`;
+      } else {
+        locationQuery = `q=${this.item.location}`;
+      }
+
+      const url = `https://api.openweathermap.org/data/2.5/weather?${locationQuery}&appid=${this.item.apiKey}&units=${this.item.units}`;
+      fetch(url)
+        .then((response) => {
+          if (!response.ok) {
+            throw Error(response.statusText);
+          }
+          return response.json();
+        })
+        .then((weather) => {
+          this.id = weather.id;
+          this.name = weather.name;
+          this.temp = parseInt(weather.main.temp).toFixed(1);
+          this.icon = weather.weather[0].icon;
+          this.conditions = weather.weather[0].description;
+        })
+        .catch((e) => {
+          console.log(e);
+          this.error = true;
+        });
+    },
+  },
+  filters: {
+    tempSuffix: function (value, type) {
+      if (!value) return "";
+
+      let unit = "K";
+      if (type === "metric") {
+        unit = "°C";
+      } else if (type === "imperial") {
+        unit = "°F";
+      }
+      return `${value} ${unit}`;
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+// Add a border around the weather image.
+// Otherwise the image is not always distinguishable.
+.media-left {
+  &.circle,
+  &.square {
+    background-color: #e4e4e4;
+  }
+
+  &.circle {
+    border-radius: 90%;
+  }
+
+  img {
+    max-height: 100%;
+  }
+}
+
+.error {
+  color: #de0000;
+}
+
+// Change background color in dark mode.
+.is-dark {
+  .media-left {
+    &.circle,
+    &.square {
+      background-color: #909090;
+    }
+  }
+}
+</style>
index 4fb31f852661cc31d633b4d9567e87d2275af87c..af13317859e1f7e1117cf29bcf9ec02adf9b9ce6 100644 (file)
@@ -59,6 +59,7 @@ export default {
       }
       const url = `${this.item.url}/api/documents/`;
       this.api = await fetch(url, {
+        credentials: "include",
         headers: {
           Authorization: "Token " + this.item.apikey,
         },
index 7042a7b2a5055662e7434bead008af4036a6e934..87f7090d4ad8b16f47b5a2285db872f8102074ba 100644 (file)
@@ -64,7 +64,9 @@ export default {
   methods: {
     fetchStatus: async function () {
       const url = `${this.item.url}/api.php`;
-      this.api = await fetch(url)
+      this.api = await fetch(url, {
+        credentials: "include",
+      })
         .then((response) => response.json())
         .catch((e) => console.log(e));
     },
index 8a9b7a4e0579dbea2e04daf99fd21b733bdc9ed0..e693af4cc210eb66ca530a1f9f2fa502bd3a0e1d 100644 (file)
@@ -50,7 +50,11 @@ export default {
   methods: {
     fetchStatus: async function () {
       const url = `${this.item.url}`;
-      fetch(url, { method: "HEAD", cache: "no-cache" })
+      fetch(url, {
+        method: "HEAD",
+        cache: "no-cache",
+        credentials: "include",
+      })
         .then((response) => {
           if (!response.ok) {
             throw Error(response.statusText);
index 93831a7bd87121c10fb5b5e638f94d59eae37ed2..9d3829279ca55f5ee48cf829561609ce3af2c095 100644 (file)
@@ -70,10 +70,7 @@ export default {
   },
   methods: {
     fetchConfig: function () {
-      fetch(`${this.item.url}/api/health`, {
-        credentials: "include",
-        headers: { "X-Api-Key": `${this.item.apikey}` },
-      })
+      fetch(`${this.item.url}/api/health?apikey=${this.item.apikey}`)
         .then((response) => {
           if (response.status != 200) {
             throw new Error(response.statusText);
@@ -95,10 +92,7 @@ export default {
           console.error(e);
           this.serverError = true;
         });
-      fetch(`${this.item.url}/api/queue`, {
-        credentials: "include",
-        headers: { "X-Api-Key": `${this.item.apikey}` },
-      })
+      fetch(`${this.item.url}/api/queue?apikey=${this.item.apikey}`)
         .then((response) => {
           if (response.status != 200) {
             throw new Error(response.statusText);
index 8cebac45432fdaa7ceb2fe3cf7a107c48533eb27..7851b6b6b1dbc484e2da5218a2fa7926c239f746 100644 (file)
@@ -70,10 +70,7 @@ export default {
   },
   methods: {
     fetchConfig: function () {
-      fetch(`${this.item.url}/api/health`, {
-        credentials: "include",
-        headers: { "X-Api-Key": `${this.item.apikey}` },
-      })
+      fetch(`${this.item.url}/api/health?apikey=${this.item.apikey}`)
         .then((response) => {
           if (response.status != 200) {
             throw new Error(response.statusText);
@@ -95,10 +92,7 @@ export default {
           console.error(e);
           this.serverError = true;
         });
-      fetch(`${this.item.url}/api/queue`, {
-        credentials: "include",
-        headers: { "X-Api-Key": `${this.item.apikey}` },
-      })
+      fetch(`${this.item.url}/api/queue?apikey=${this.item.apikey}`)
         .then((response) => {
           if (response.status != 200) {
             throw new Error(response.statusText);
index c79c2fd2166323090e934f4bb38deb67bd010661..79ad871bb9c8104b7616515a63f837c2a5c87d14 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
     "@babel/helper-validator-identifier" "^7.14.5"
     to-fast-properties "^2.0.0"
 
-"@fortawesome/fontawesome-free@^5.15.3":
-  version "5.15.3"
-  resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.3.tgz#c36ffa64a2a239bf948541a97b6ae8d729e09a9a"
-  integrity sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w==
+"@fortawesome/fontawesome-free@^5.15.4":
+  version "5.15.4"
+  resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz#ecda5712b61ac852c760d8b3c79c96adca5554e5"
+  integrity sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==
 
 "@hapi/address@2.x.x":
   version "2.1.4"
@@ -2773,7 +2773,12 @@ core-js@^2.4.0:
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
   integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
 
-core-js@^3.15.2, core-js@^3.6.5:
+core-js@^3.17.3:
+  version "3.17.3"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.17.3.tgz#8e8bd20e91df9951e903cabe91f9af4a0895bc1e"
+  integrity sha512-lyvajs+wd8N1hXfzob1LdOCCHFU4bGMbqqmLn1Q4QlCpDqWPpGf+p0nj+LNrvDDG33j0hZXw2nsvvVpHysxyNw==
+
+core-js@^3.6.5:
   version "3.15.2"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.15.2.tgz#740660d2ff55ef34ce664d7e2455119c5bdd3d61"
   integrity sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==