Merge branch dev into main

pull/4533/head^2 v0.10.7
shamoon 3 weeks ago
commit 0717607a97

@ -54,3 +54,11 @@ body:
description: Please include output from your [troubleshooting tests](https://gethomepage.dev/more/troubleshooting/#service-widget-errors), if relevant. description: Please include output from your [troubleshooting tests](https://gethomepage.dev/more/troubleshooting/#service-widget-errors), if relevant.
validations: validations:
required: true required: true
- type: markdown
attributes:
value: |
## ⚠️ STOP ⚠️
Before you submit this support request, please ensure you have entered your configuration files and actually followed the steps from the troubleshooting guide linked above, if relevant. The troubleshooting steps often help to solve the problem.
*Please remember that this project is maintained by regular people **just like you**, so if you don't take the time to fill out the requested information, don't expect a reply back.*

@ -1,3 +1,14 @@
<!--
==== STOP ====================
======== STOP ================
============ STOP ============
================ STOP ========
==================== STOP ====
⚠️ Before opening this pull request please review the guidelines in the checklist below.
If this PR does not meet those guidelines it will not be accepted, and everyone will be sad.
-->
## Proposed change ## Proposed change
<!-- <!--

@ -118,7 +118,7 @@ jobs:
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
push: ${{ github.event_name != 'pull_request' && !(github.event_name == 'push' && startsWith(github.ref, 'refs/heads/feature')) }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
build-args: | build-args: |

@ -212,9 +212,9 @@ jobs:
} }
const CUTOFF_1_DAYS = 180; const CUTOFF_1_DAYS = 180;
const CUTOFF_1_COUNT = 5; const CUTOFF_1_COUNT = 10;
const CUTOFF_2_DAYS = 365; const CUTOFF_2_DAYS = 365;
const CUTOFF_2_COUNT = 10; const CUTOFF_2_COUNT = 20;
const cutoff1Date = new Date(); const cutoff1Date = new Date();
cutoff1Date.setDate(cutoff1Date.getDate() - CUTOFF_1_DAYS); cutoff1Date.setDate(cutoff1Date.getDate() - CUTOFF_1_DAYS);

@ -52,7 +52,7 @@ Homepage has built-in support for Docker, and can automatically discover and add
## Service Widgets ## Service Widgets
Homepage also has support for over 100 3rd party services, including all popular starr apps, and most popular self-hosted apps. Some examples include: Radarr, Sonarr, Lidarr, Bazarr, Ombi, Tautulli, Plex, Jellyfin, Emby, Transmission, qBittorrent, Deluge, Jackett, NZBGet, SABnzbd, etc. As well as service integrations, Homepage also has a number of information providers, sourcing information from a variety of external 3rd party APIs. See the [Service](https://gethomepage.dev/widgets/) page for more information. Homepage also has support for hundreds of 3rd-party services, including all popular \*arr apps, and most popular self-hosted apps. Some examples include: Radarr, Sonarr, Lidarr, Bazarr, Ombi, Tautulli, Plex, Jellyfin, Emby, Transmission, qBittorrent, Deluge, Jackett, NZBGet, SABnzbd, etc. As well as service integrations, Homepage also has a number of information providers, sourcing information from a variety of external 3rd-party APIs. See the [Service](https://gethomepage.dev/widgets/) page for more information.
## Information Widgets ## Information Widgets

@ -153,6 +153,18 @@ labels:
- homepage.widget.fields=["field1","field2"] # optional - homepage.widget.fields=["field1","field2"] # optional
``` ```
Multiple widgets can be specified by incrementing the index, e.g.
```yaml
labels: ...
- homepage.widget[0].type=emby
- homepage.widget[0].url=http://emby.home
- homepage.widget[0].key=yourembyapikeyhere
- homepage.widget[1].type=uptimekuma
- homepage.widget[1].url=http://uptimekuma.home
- homepage.widget[1].slug=youreventslughere
```
You can add specify fields for e.g. the [CustomAPI](../widgets/services/customapi.md) widget by using array-style dot notation: You can add specify fields for e.g. the [CustomAPI](../widgets/services/customapi.md) widget by using array-style dot notation:
```yaml ```yaml

@ -0,0 +1,24 @@
---
title: Information Widgets
description: Homepage info widgets.
---
Information widgets are widgets that provide information about your system or environment and are displayed at the top of the homepage. You can find a list of all available info widgets under the [Info Widgets](../widgets/info/index.md) section.
Info widgets are defined in the widgets.yaml
Each widget has its own configuration options, which are detailed in the widget's documentation.
## Layout
Info widgets are displayed in the order they are defined in the `widgets.yaml` file. You can change the order by moving the widgets around in the file. However, some widgets (weather, search and datetime) are aligned to the right side of the screen which can affect the layout of the widgets.
## Adding A Link
You can add a link to an info widget such as the logo or text widgets by adding an `href` option, for example:
```yaml
logo:
href: https://example.com
target: _blank # Optional, can be set in settings
```

@ -1,40 +0,0 @@
---
title: Service Widgets
description: Service Widget Configuration
---
Unless otherwise noted, URLs should not end with a `/` or other API path. Each widget will handle the path on its own.
Each service can have one widget attached to it (often matching the service type, but that's not forced).
In addition to the href of the service, you can also specify the target location in which to open that link. See [Link Target](settings.md#link-target) for more details.
Using Emby as an example, this is how you would attach the Emby service widget.
```yaml
- Emby:
icon: emby.png
href: http://emby.host.or.ip/
description: Movies & TV Shows
widget:
type: emby
url: http://emby.host.or.ip
key: apikeyapikeyapikeyapikeyapikey
```
## Field Visibility
Each widget can optionally provide a list of which fields should be visible via the `fields` widget property. If no fields are specified, then all fields will be displayed. The `fields` property must be a valid YAML array of strings. As an example, here is the entry for Sonarr showing only a couple of fields.
**In all cases a widget will work and display all fields without specifying the `fields` property.**
```yaml
- Sonarr:
icon: sonarr.png
href: http://sonarr.host.or.ip
widget:
type: sonarr
fields: ["wanted", "queued"]
url: http://sonarr.host.or.ip
key: apikeyapikeyapikeyapikeyapikey
```

@ -21,6 +21,23 @@ Groups are defined as top-level array entries.
<img width="1038" alt="Service Groups" src="https://user-images.githubusercontent.com/82196/187040754-28065242-4534-4409-881c-93d1921c6141.png"> <img width="1038" alt="Service Groups" src="https://user-images.githubusercontent.com/82196/187040754-28065242-4534-4409-881c-93d1921c6141.png">
### Nested Groups
Groups can be nested by using the same format as the top-level groups.
```yaml
- Group A:
- Service A:
href: http://localhost/
- Group B:
- Service B:
href: http://localhost/
- Service C:
href: http://localhost/
```
## Services ## Services
Services are defined as array entries on groups, Services are defined as array entries on groups,
@ -43,6 +60,60 @@ Services are defined as array entries on groups,
<img width="1038" alt="Service Services" src="https://user-images.githubusercontent.com/82196/187040763-038023a2-8bee-4d87-b5cc-13447e7365a4.png"> <img width="1038" alt="Service Services" src="https://user-images.githubusercontent.com/82196/187040763-038023a2-8bee-4d87-b5cc-13447e7365a4.png">
### Service Widgets
Each service can have widgets attached to it (often matching the service type, but that's not forced).
In addition to the href of the service, you can also specify the target location in which to open that link. See [Link Target](settings.md#link-target) for more details.
Using Emby as an example, this is how you would attach the Emby service widget.
```yaml
- Emby:
icon: emby.png
href: http://emby.host.or.ip/
description: Movies & TV Shows
widget:
type: emby
url: http://emby.host.or.ip
key: apikeyapikeyapikeyapikeyapikey
```
#### Multiple Widgets
Each service can have multiple widgets attached to it, for example:
```yaml
- Emby:
icon: emby.png
href: http://emby.host.or.ip/
description: Movies & TV Shows
widgets:
- type: emby
url: http://emby.host.or.ip
key: apikeyapikeyapikeyapikeyapikey
- type: uptimekuma
url: http://uptimekuma.host.or.ip:port
slug: statuspageslug
```
#### Field Visibility
Each widget can optionally provide a list of which fields should be visible via the `fields` widget property. If no fields are specified, then all fields will be displayed. The `fields` property must be a valid YAML array of strings. As an example, here is the entry for Sonarr showing only a couple of fields.
**In all cases a widget will work and display all fields without specifying the `fields` property.**
```yaml
- Sonarr:
icon: sonarr.png
href: http://sonarr.host.or.ip
widget:
type: sonarr
fields: ["wanted", "queued"]
url: http://sonarr.host.or.ip
key: apikeyapikeyapikeyapikeyapikey
```
## Descriptions ## Descriptions
Services may have descriptions, Services may have descriptions,

@ -13,6 +13,14 @@ You can customize the title of the page if you'd like.
title: My Awesome Homepage title: My Awesome Homepage
``` ```
## Description
You can customize the description of the page if you'd like.
```yaml
description: A description of my awesome homepage
```
## Start URL ## Start URL
You can customize the start_url as required for installable apps. The default is "/". You can customize the start_url as required for installable apps. The default is "/".
@ -118,6 +126,22 @@ As an example, this would produce the following layout:
<img width="1260" alt="Screenshot 2022-09-15 at 8 03 57 PM" src="https://user-images.githubusercontent.com/82196/190466646-8ca94505-0fcf-4964-9687-3a6c7cd3144f.png"> <img width="1260" alt="Screenshot 2022-09-15 at 8 03 57 PM" src="https://user-images.githubusercontent.com/82196/190466646-8ca94505-0fcf-4964-9687-3a6c7cd3144f.png">
### Icons-Only Layout
You can also specify the an icon-only layout for bookmarks, either like so:
```yaml
layout:
Media:
iconsOnly: true
```
or globally:
```yaml
bookmarksStyle: icons
```
### Sorting ### Sorting
Service groups and bookmark groups can be mixed in order, **but should use different group names**. If you do not specify any bookmark groups they will all show at the bottom of the page. Service groups and bookmark groups can be mixed in order, **but should use different group names**. If you do not specify any bookmark groups they will all show at the bottom of the page.
@ -137,6 +161,27 @@ layout:
columns: 3 columns: 3
``` ```
### Nested Groups
If your services config has nested groups, you can apply settings to these groups by nesting them in the layout block
and using the same settings. For example
```yaml
layout:
Group A:
style: row
columns: 4
Group C:
style: row
columns: 2
Nested Group A:
style: row
columns: 2
Nested Group B:
style: row
columns: 2
```
### Headers ### Headers
You can hide headers for each section in the layout as well by passing `header` as false, like so: You can hide headers for each section in the layout as well by passing `header` as false, like so:
@ -348,12 +393,12 @@ This can also be set for individual services. Note setting this at the service l
## Providers ## Providers
The `providers` section allows you to define shared API provider options and secrets. Currently this allows you to define your weather API keys in secret and is also the location of the Longhorn URL and credentials. The `providers` section allows you to define shared API provider options and secrets.
```yaml ```yaml
providers: providers:
openweathermap: openweathermapapikey openweathermap: openweathermapapikey
weatherapi: weatherapiapikey finnhub: yourfinnhubapikeyhere
longhorn: longhorn:
url: https://longhorn.example.com url: https://longhorn.example.com
username: admin username: admin
@ -363,10 +408,10 @@ providers:
You can then pass `provider` instead of `apiKey` in your widget configuration. You can then pass `provider` instead of `apiKey` in your widget configuration.
```yaml ```yaml
- weatherapi: - openweathermap:
latitude: 50.449684 latitude: 50.449684
longitude: 30.525026 longitude: 30.525026
provider: weatherapi provider: openweathermap
``` ```
## Quick Launch ## Quick Launch

@ -175,6 +175,7 @@ data:
expanded: true expanded: true
cpu: true cpu: true
memory: true memory: true
network: default
- search: - search:
provider: duckduckgo provider: duckduckgo
target: _blank target: _blank
@ -209,7 +210,7 @@ rules:
- get - get
- list - list
- apiGroups: - apiGroups:
- traefik.containo.us - traefik.io
resources: resources:
- ingressroutes - ingressroutes
verbs: verbs:
@ -370,7 +371,7 @@ prevent unnecessary re-renders on page loads and window / tab focusing. The
procedure for enabling sticky sessions depends on your Ingress controller. Below procedure for enabling sticky sessions depends on your Ingress controller. Below
is an example using Traefik as the Ingress controller. is an example using Traefik as the Ingress controller.
``` ```yaml
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: IngressRoute kind: IngressRoute
metadata: metadata:

@ -17,7 +17,7 @@ hide:
All service widgets work essentially the same, that is, homepage makes a proxied call to an API made available by that service. The majority of the time widgets don't work it is a configuration issue. Of course, sometimes things do break. Some basic steps to try: All service widgets work essentially the same, that is, homepage makes a proxied call to an API made available by that service. The majority of the time widgets don't work it is a configuration issue. Of course, sometimes things do break. Some basic steps to try:
1. Ensure that you follow the rule mentioned on https://gethomepage.dev/configs/service-widgets/. **Unless otherwise noted, URLs should not end with a / or other API path. Each widget will handle the path on its own.**. This is very important as including a trailing slash can result in an error. 1. **URLs should not end with a / or other API path. Each widget will handle the path on its own.**. Including a trailing slash can result in an error.
2. Verify the homepage installation can connect to the IP address or host you are using for the widget `url`. This is most simply achieved by pinging the server from the homepage machine, in Docker this means _from inside the container_ itself, e.g.: 2. Verify the homepage installation can connect to the IP address or host you are using for the widget `url`. This is most simply achieved by pinging the server from the homepage machine, in Docker this means _from inside the container_ itself, e.g.:

@ -48,7 +48,7 @@ self-hosted / open-source alternative, we ask that any widgets, etc. are develop
## New Feature Guidelines ## New Feature Guidelines
- New features should usually be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users. - New features should be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users.
- If you have ideas for a larger feature you may want to open a discussion first. - If you have ideas for a larger feature you may want to open a discussion first.
## Service Widget Guidelines ## Service Widget Guidelines

@ -50,7 +50,7 @@ You can also pass API keys from the widget configuration to the proxy handler, f
### `credentialedProxyHandler` ### `credentialedProxyHandler`
A proxy handler that makes authenticated by setting request headers. Credentials are pulled from the widgets configuration. A proxy handler that makes authenticated requests by setting request headers. Credentials are pulled from the widgets configuration.
By default the key is passed as an `X-API-Key` header. If you need to pass the key as something else, either add a case to the credentialedProxyHandler or create a new proxy handler. By default the key is passed as an `X-API-Key` header. If you need to pass the key as something else, either add a case to the credentialedProxyHandler or create a new proxy handler.

@ -19,12 +19,17 @@ Service widgets are used to display the status of a service, often a web service
description: Watch movies and TV shows. description: Watch movies and TV shows.
server: localhost server: localhost
container: plex container: plex
widget: widgets:
type: tautulli - type: tautulli
url: http://172.16.1.1:8181 url: http://172.16.1.1:8181
key: aabbccddeeffgghhiijjkkllmmnnoo key: aabbccddeeffgghhiijjkkllmmnnoo
- type: uptimekuma
url: http://172.16.1.2:8080
slug: aaaaaaabbbbb
``` ```
More detail on configuring service widgets can be found in the [Service Widgets Config](../configs/services.md) section.
## Info Widgets ## Info Widgets
Info widgets are used to display information in the header, often about your system or environment. Info widgets are defined your `widgets.yaml` file. Here's an example: Info widgets are used to display information in the header, often about your system or environment. Info widgets are defined your `widgets.yaml` file. Here's an example:
@ -36,3 +41,5 @@ Info widgets are used to display information in the header, often about your sys
longitude: -117.51 longitude: -117.51
cache: 5 cache: 5
``` ```
More detail on configuring info widgets can be found in the [Info Widgets Config](../configs/info-widgets.md) section.

@ -3,7 +3,7 @@ title: Open-Meteo
description: Open-Meteo Information Widget Configuration description: Open-Meteo Information Widget Configuration
--- ---
No registration is required at all! See [https://open-meteo.com/en/docs](https://open-meteo.com/en/docs) Homepage's recommended weather widget. No registration is required at all! See [https://open-meteo.com/en/docs](https://open-meteo.com/en/docs)
```yaml ```yaml
- openmeteo: - openmeteo:

@ -24,9 +24,10 @@ _Note: unfortunately, the package used for getting CPU temp ([systeminformation]
tempmin: 0 # optional, minimum cpu temp tempmin: 0 # optional, minimum cpu temp
tempmax: 100 # optional, maximum cpu temp tempmax: 100 # optional, maximum cpu temp
uptime: true uptime: true
units: imperial # only used by cpu temp units: imperial # only used by cpu temp, options: 'imperial' or 'metric'
refresh: 3000 # optional, in ms refresh: 3000 # optional, in ms
diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk
network: true # optional, uses 'default' if true or specify a network interface name
``` ```
You can also pass a `label` option, which allows you to group resources under named sections, You can also pass a `label` option, which allows you to group resources under named sections,

@ -7,7 +7,7 @@ _(Find the Unifi Controller service widget [here](../services/unifi-controller.m
You can display general connectivity status from your Unifi (Network) Controller. You can display general connectivity status from your Unifi (Network) Controller.
!!! !!! warning
When authenticating you will want to use a local account that has at least read privileges. When authenticating you will want to use a local account that has at least read privileges.

@ -1,22 +0,0 @@
---
title: Weather API
description: Weather API Information Widget Configuration
---
**Note: this widget is considered 'deprecated' since there is no longer a free Weather API tier for new members. See the openmeteo or openweathermap widgets for alternatives.**
The free tier is all that's required, you will need to [register](https://www.weatherapi.com/signup.aspx) and grab your API key.
```yaml
- weatherapi:
label: Kyiv # optional
latitude: 50.449684
longitude: 30.525026
units: metric # or imperial
apiKey: yourweatherapikey
cache: 5 # Time in minutes to cache API responses, to stay within limits
format: # optional, Intl.NumberFormat options
maximumFractionDigits: 1
```
You can optionally not pass a `latitude` and `longitude` and the widget will use your current location (requires a secure context, eg. HTTPS).

@ -7,11 +7,16 @@ Learn more about [Beszel](https://github.com/henrygd/beszel)
The widget has two modes, a single system with detailed info if `systemId` is provided, or an overview of all systems if `systemId` is not provided. The widget has two modes, a single system with detailed info if `systemId` is provided, or an overview of all systems if `systemId` is not provided.
The `systemID` in the `id` field on the collections page of Beszel. The `systemID` is the `id` field on the collections page of Beszel under the PocketBase admin panel. You can also use the 'nice name' from the Beszel UI.
Allowed fields for 'overview' mode: `["systems", "up"]` Allowed fields for 'overview' mode: `["systems", "up"]`
Allowed fields for a single system: `["name", "status", "updated", "cpu", "memory", "disk", "network"]` Allowed fields for a single system: `["name", "status", "updated", "cpu", "memory", "disk", "network"]`
| Beszel Version | Homepage Widget Version |
| -------------- | ----------------------- |
| < 0.9.0 | 1 (default) |
| >= 0.9.0 | 2 |
```yaml ```yaml
widget: widget:
type: beszel type: beszel
@ -19,4 +24,5 @@ widget:
username: username # email username: username # email
password: password password: password
systemId: systemId # optional systemId: systemId # optional
version: 2 # optional, default is 1
``` ```

@ -14,4 +14,5 @@ widget:
type: deluge type: deluge
url: http://deluge.host.or.ip url: http://deluge.host.or.ip
password: password # webui password password: password # webui password
enableLeechProgress: true # optional, defaults to false
``` ```

@ -16,5 +16,6 @@ To group both `offline` and `unknown` devices together, users should use the `of
widget: widget:
type: esphome type: esphome
url: http://esphome.host.or.ip:port url: http://esphome.host.or.ip:port
key: myesphomecookie # only if auth enabled, get the value from a request from the frontend e.g. `authenticated=myesphomecookie` username: myesphomeuser # only if auth enabled
password: myesphomepass # only if auth enabled
``` ```

@ -3,7 +3,7 @@ title: EVCC
description: EVCC Widget Configuration description: EVCC Widget Configuration
--- ---
Learn more about [EVSS](https://github.com/evcc-io/evcc). Learn more about [EVCC](https://github.com/evcc-io/evcc).
Allowed fields: `["pv_power", "grid_power", "home_power", "charge_power]`. Allowed fields: `["pv_power", "grid_power", "home_power", "charge_power]`.

@ -51,6 +51,8 @@ The metric field in the configuration determines the type of system monitoring d
`process`: Top 5 processes based on CPU usage. Gives an overview of which processes are consuming the most resources. `process`: Top 5 processes based on CPU usage. Gives an overview of which processes are consuming the most resources.
`containers`: Docker or Kubernetes containers list. Shows up to 5 containers running on the system and their resource usage.
`network:<interface_name>`: Network data usage for the specified interface. Replace `<interface_name>` with the name of your network interface, e.g., `network:enp0s25`, as specified in glances. `network:<interface_name>`: Network data usage for the specified interface. Replace `<interface_name>` with the name of your network interface, e.g., `network:enp0s25`, as specified in glances.
`sensor:<sensor_id>`: Temperature of the specified sensor, typically used to monitor CPU temperature. Replace `<sensor_id>` with the name of your sensor, e.g., `sensor:Package id 0` as specified in glances. `sensor:<sensor_id>`: Temperature of the specified sensor, typically used to monitor CPU temperature. Replace `<sensor_id>` with the name of your sensor, e.g., `sensor:Package id 0` as specified in glances.

@ -14,6 +14,7 @@ Allowed fields: `["name", "address", "last_seen", "status"]`.
```yaml ```yaml
widget: widget:
type: headscale type: headscale
url: http://headscale.host.or.ip:port
nodeId: nodeid nodeId: nodeid
key: headscaleapiaccesstoken key: headscaleapiaccesstoken
``` ```

@ -15,4 +15,5 @@ widget:
url: http://qbittorrent.host.or.ip url: http://qbittorrent.host.or.ip
username: username username: username
password: password password: password
enableLeechProgress: true # optional, defaults to false
``` ```

@ -9,7 +9,7 @@ _(Find the Unifi Controller information widget [here](../info/unifi_controller.m
You can display general connectivity status from your Unifi (Network) Controller. You can display general connectivity status from your Unifi (Network) Controller.
!!! !!! warning
When authenticating you will want to use a local account that has at least read privileges. When authenticating you will want to use a local account that has at least read privileges.

@ -21,8 +21,8 @@ nav:
- configs/index.md - configs/index.md
- configs/settings.md - configs/settings.md
- configs/bookmarks.md - configs/bookmarks.md
- configs/info-widgets.md
- configs/services.md - configs/services.md
- configs/service-widgets.md
- configs/kubernetes.md - configs/kubernetes.md
- configs/docker.md - configs/docker.md
- configs/custom-css-js.md - configs/custom-css-js.md
@ -142,6 +142,7 @@ nav:
- widgets/services/spoolman.md - widgets/services/spoolman.md
- widgets/services/stash.md - widgets/services/stash.md
- widgets/services/stocks.md - widgets/services/stocks.md
- widgets/services/suwayomi.md
- widgets/services/swagdashboard.md - widgets/services/swagdashboard.md
- widgets/services/syncthing-relay-server.md - widgets/services/syncthing-relay-server.md
- widgets/services/tailscale.md - widgets/services/tailscale.md
@ -177,7 +178,6 @@ nav:
- widgets/info/search.md - widgets/info/search.md
- widgets/info/stocks.md - widgets/info/stocks.md
- widgets/info/unifi_controller.md - widgets/info/unifi_controller.md
- widgets/info/weather.md
- "Learn": - "Learn":
- widgets/authoring/index.md - widgets/authoring/index.md
- "Getting Started": widgets/authoring/getting-started.md - "Getting Started": widgets/authoring/getting-started.md

121
package-lock.json generated

@ -15,7 +15,7 @@
"compare-versions": "^6.1.0", "compare-versions": "^6.1.0",
"dockerode": "^4.0.2", "dockerode": "^4.0.2",
"follow-redirects": "^1.15.9", "follow-redirects": "^1.15.9",
"gamedig": "^5.1.2", "gamedig": "^5.1.4",
"i18next": "^21.10.0", "i18next": "^21.10.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"json-rpc-2.0": "^1.7.0", "json-rpc-2.0": "^1.7.0",
@ -34,7 +34,7 @@
"recharts": "^2.12.6", "recharts": "^2.12.6",
"rrule": "^2.8.1", "rrule": "^2.8.1",
"swr": "^1.3.0", "swr": "^1.3.0",
"systeminformation": "^5.23.2", "systeminformation": "^5.23.8",
"tough-cookie": "^4.1.3", "tough-cookie": "^4.1.3",
"urbackup-server-api": "^0.52.1", "urbackup-server-api": "^0.52.1",
"winston": "^3.11.0", "winston": "^3.11.0",
@ -50,7 +50,7 @@
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.1", "eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.47", "postcss": "^8.4.47",
"prettier": "^3.2.5", "prettier": "^3.2.5",
@ -2115,9 +2115,9 @@
} }
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
@ -2729,9 +2729,9 @@
} }
}, },
"node_modules/es-abstract": { "node_modules/es-abstract": {
"version": "1.23.3", "version": "1.23.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz",
"integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2750,7 +2750,7 @@
"function.prototype.name": "^1.1.6", "function.prototype.name": "^1.1.6",
"get-intrinsic": "^1.2.4", "get-intrinsic": "^1.2.4",
"get-symbol-description": "^1.0.2", "get-symbol-description": "^1.0.2",
"globalthis": "^1.0.3", "globalthis": "^1.0.4",
"gopd": "^1.0.1", "gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2", "has-property-descriptors": "^1.0.2",
"has-proto": "^1.0.3", "has-proto": "^1.0.3",
@ -2766,10 +2766,10 @@
"is-string": "^1.0.7", "is-string": "^1.0.7",
"is-typed-array": "^1.1.13", "is-typed-array": "^1.1.13",
"is-weakref": "^1.0.2", "is-weakref": "^1.0.2",
"object-inspect": "^1.13.1", "object-inspect": "^1.13.3",
"object-keys": "^1.1.1", "object-keys": "^1.1.1",
"object.assign": "^4.1.5", "object.assign": "^4.1.5",
"regexp.prototype.flags": "^1.5.2", "regexp.prototype.flags": "^1.5.3",
"safe-array-concat": "^1.1.2", "safe-array-concat": "^1.1.2",
"safe-regex-test": "^1.0.3", "safe-regex-test": "^1.0.3",
"string.prototype.trim": "^1.2.9", "string.prototype.trim": "^1.2.9",
@ -2834,9 +2834,9 @@
} }
}, },
"node_modules/es-iterator-helpers": { "node_modules/es-iterator-helpers": {
"version": "1.0.19", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz",
"integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2847,12 +2847,13 @@
"es-set-tostringtag": "^2.0.3", "es-set-tostringtag": "^2.0.3",
"function-bind": "^1.1.2", "function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4", "get-intrinsic": "^1.2.4",
"globalthis": "^1.0.3", "globalthis": "^1.0.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2", "has-property-descriptors": "^1.0.2",
"has-proto": "^1.0.3", "has-proto": "^1.0.3",
"has-symbols": "^1.0.3", "has-symbols": "^1.0.3",
"internal-slot": "^1.0.7", "internal-slot": "^1.0.7",
"iterator.prototype": "^1.1.2", "iterator.prototype": "^1.1.3",
"safe-array-concat": "^1.1.2" "safe-array-concat": "^1.1.2"
}, },
"engines": { "engines": {
@ -3280,17 +3281,18 @@
} }
}, },
"node_modules/eslint-plugin-react": { "node_modules/eslint-plugin-react": {
"version": "7.37.1", "version": "7.37.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz",
"integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"array-includes": "^3.1.8", "array-includes": "^3.1.8",
"array.prototype.findlast": "^1.2.5", "array.prototype.findlast": "^1.2.5",
"array.prototype.flatmap": "^1.3.2", "array.prototype.flatmap": "^1.3.2",
"array.prototype.tosorted": "^1.1.4", "array.prototype.tosorted": "^1.1.4",
"doctrine": "^2.1.0", "doctrine": "^2.1.0",
"es-iterator-helpers": "^1.0.19", "es-iterator-helpers": "^1.1.0",
"estraverse": "^5.3.0", "estraverse": "^5.3.0",
"hasown": "^2.0.2", "hasown": "^2.0.2",
"jsx-ast-utils": "^2.4.1 || ^3.0.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0",
@ -3847,9 +3849,9 @@
} }
}, },
"node_modules/gamedig": { "node_modules/gamedig": {
"version": "5.1.3", "version": "5.1.4",
"resolved": "https://registry.npmjs.org/gamedig/-/gamedig-5.1.3.tgz", "resolved": "https://registry.npmjs.org/gamedig/-/gamedig-5.1.4.tgz",
"integrity": "sha512-ECksJC4idM3a+P+a+j9/XHcPOsP4DUrwowK38QucDQ4x5T7mQDWErY2n8NE4kV4HKjCq16ifNMAEt+/nyCKWog==", "integrity": "sha512-MgSbNVGh5QMdrmRTrZ3W7W6sC5/Mx+dMgTy2uZCKQ9vns9eFXkQj61Pw2Y2FNHNMMp4DXFSUMYAPJWLcR16Wwg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cheerio": "1.0.0-rc.12", "cheerio": "1.0.0-rc.12",
@ -3858,7 +3860,6 @@
"iconv-lite": "0.6.3", "iconv-lite": "0.6.3",
"long": "5.2.3", "long": "5.2.3",
"minimist": "1.2.8", "minimist": "1.2.8",
"punycode": "2.3.1",
"seek-bzip": "2.0.0", "seek-bzip": "2.0.0",
"varint": "6.0.0" "varint": "6.0.0"
}, },
@ -4677,13 +4678,16 @@
} }
}, },
"node_modules/is-finalizationregistry": { "node_modules/is-finalizationregistry": {
"version": "1.0.2", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz",
"integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind": "^1.0.2" "call-bind": "^1.0.7"
},
"engines": {
"node": ">= 0.4"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -4974,9 +4978,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/iterator.prototype": { "node_modules/iterator.prototype": {
"version": "1.1.2", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz",
"integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -4985,6 +4989,9 @@
"has-symbols": "^1.0.3", "has-symbols": "^1.0.3",
"reflect.getprototypeof": "^1.0.4", "reflect.getprototypeof": "^1.0.4",
"set-function-name": "^2.0.1" "set-function-name": "^2.0.1"
},
"engines": {
"node": ">= 0.4"
} }
}, },
"node_modules/jackspeak": { "node_modules/jackspeak": {
@ -5503,9 +5510,9 @@
"optional": true "optional": true
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.7", "version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@ -5758,9 +5765,9 @@
} }
}, },
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.13.2", "version": "1.13.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -6677,19 +6684,19 @@
} }
}, },
"node_modules/reflect.getprototypeof": { "node_modules/reflect.getprototypeof": {
"version": "1.0.6", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz",
"integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind": "^1.0.7", "call-bind": "^1.0.7",
"define-properties": "^1.2.1", "define-properties": "^1.2.1",
"es-abstract": "^1.23.1", "es-abstract": "^1.23.5",
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
"get-intrinsic": "^1.2.4", "get-intrinsic": "^1.2.4",
"globalthis": "^1.0.3", "gopd": "^1.0.1",
"which-builtin-type": "^1.1.3" "which-builtin-type": "^1.1.4"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@ -6705,16 +6712,16 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/regexp.prototype.flags": { "node_modules/regexp.prototype.flags": {
"version": "1.5.2", "version": "1.5.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz",
"integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind": "^1.0.6", "call-bind": "^1.0.7",
"define-properties": "^1.2.1", "define-properties": "^1.2.1",
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
"set-function-name": "^2.0.1" "set-function-name": "^2.0.2"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@ -7673,10 +7680,9 @@
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/systeminformation": { "node_modules/systeminformation": {
"version": "5.23.5", "version": "5.23.8",
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.5.tgz", "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.8.tgz",
"integrity": "sha512-PEpJwhRYxZgBCAlWZhWIgfMTjXLqfcaZ1pJsJn9snWNfBW/Z1YQg1mbIUSWrEV3ErAHF7l/OoVLQeaZDlPzkpA==", "integrity": "sha512-Osd24mNKe6jr/YoXLLK3k8TMdzaxDffhpCxgkfgBHcapykIkd50HXThM3TCEuHO2pPuCsSx2ms/SunqhU5MmsQ==",
"license": "MIT",
"os": [ "os": [
"darwin", "darwin",
"linux", "linux",
@ -8337,17 +8343,18 @@
} }
}, },
"node_modules/which-builtin-type": { "node_modules/which-builtin-type": {
"version": "1.1.4", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz",
"integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind": "^1.0.7",
"function.prototype.name": "^1.1.6", "function.prototype.name": "^1.1.6",
"has-tostringtag": "^1.0.2", "has-tostringtag": "^1.0.2",
"is-async-function": "^2.0.0", "is-async-function": "^2.0.0",
"is-date-object": "^1.0.5", "is-date-object": "^1.0.5",
"is-finalizationregistry": "^1.0.2", "is-finalizationregistry": "^1.1.0",
"is-generator-function": "^1.0.10", "is-generator-function": "^1.0.10",
"is-regex": "^1.1.4", "is-regex": "^1.1.4",
"is-weakref": "^1.0.2", "is-weakref": "^1.0.2",

@ -17,7 +17,7 @@
"compare-versions": "^6.1.0", "compare-versions": "^6.1.0",
"dockerode": "^4.0.2", "dockerode": "^4.0.2",
"follow-redirects": "^1.15.9", "follow-redirects": "^1.15.9",
"gamedig": "^5.1.2", "gamedig": "^5.1.4",
"i18next": "^21.10.0", "i18next": "^21.10.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"json-rpc-2.0": "^1.7.0", "json-rpc-2.0": "^1.7.0",
@ -36,7 +36,7 @@
"recharts": "^2.12.6", "recharts": "^2.12.6",
"rrule": "^2.8.1", "rrule": "^2.8.1",
"swr": "^1.3.0", "swr": "^1.3.0",
"systeminformation": "^5.23.2", "systeminformation": "^5.23.8",
"tough-cookie": "^4.1.3", "tough-cookie": "^4.1.3",
"urbackup-server-api": "^0.52.1", "urbackup-server-api": "^0.52.1",
"winston": "^3.11.0", "winston": "^3.11.0",
@ -52,7 +52,7 @@
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.1", "eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.47", "postcss": "^8.4.47",
"prettier": "^3.2.5", "prettier": "^3.2.5",

@ -30,8 +30,8 @@ importers:
specifier: ^1.15.9 specifier: ^1.15.9
version: 1.15.9 version: 1.15.9
gamedig: gamedig:
specifier: ^5.1.2 specifier: ^5.1.4
version: 5.1.3 version: 5.1.4
i18next: i18next:
specifier: ^21.10.0 specifier: ^21.10.0
version: 21.10.0 version: 21.10.0
@ -87,8 +87,8 @@ importers:
specifier: ^1.3.0 specifier: ^1.3.0
version: 1.3.0(react@18.3.1) version: 1.3.0(react@18.3.1)
systeminformation: systeminformation:
specifier: ^5.23.2 specifier: ^5.23.8
version: 5.23.5 version: 5.23.8
tough-cookie: tough-cookie:
specifier: ^4.1.3 specifier: ^4.1.3
version: 4.1.4 version: 4.1.4
@ -117,7 +117,7 @@ importers:
version: 8.57.1 version: 8.57.1
eslint-config-airbnb: eslint-config-airbnb:
specifier: ^19.0.4 specifier: ^19.0.4
version: 19.0.4(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-jsx-a11y@6.10.0(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.1(eslint@8.57.1))(eslint@8.57.1) version: 19.0.4(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.0(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.2(eslint@8.57.1))(eslint@8.57.1)
eslint-config-next: eslint-config-next:
specifier: ^14.2.3 specifier: ^14.2.3
version: 14.2.8(eslint@8.57.1)(typescript@5.6.3) version: 14.2.8(eslint@8.57.1)(typescript@5.6.3)
@ -134,8 +134,8 @@ importers:
specifier: ^5.2.1 specifier: ^5.2.1
version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.3) version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.3)
eslint-plugin-react: eslint-plugin-react:
specifier: ^7.37.1 specifier: ^7.37.2
version: 7.37.1(eslint@8.57.1) version: 7.37.2(eslint@8.57.1)
eslint-plugin-react-hooks: eslint-plugin-react-hooks:
specifier: ^4.6.2 specifier: ^4.6.2
version: 4.6.2(eslint@8.57.1) version: 4.6.2(eslint@8.57.1)
@ -783,8 +783,8 @@ packages:
resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==} resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
cross-spawn@7.0.3: cross-spawn@7.0.6:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
css-select@5.1.0: css-select@5.1.0:
@ -1006,6 +1006,10 @@ packages:
resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
es-iterator-helpers@1.2.0:
resolution: {integrity: sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==}
engines: {node: '>= 0.4'}
es-object-atoms@1.0.0: es-object-atoms@1.0.0:
resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -1155,8 +1159,8 @@ packages:
peerDependencies: peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
eslint-plugin-react@7.37.1: eslint-plugin-react@7.37.2:
resolution: {integrity: sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==} resolution: {integrity: sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
@ -1316,8 +1320,8 @@ packages:
functions-have-names@1.2.3: functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
gamedig@5.1.3: gamedig@5.1.4:
resolution: {integrity: sha512-ECksJC4idM3a+P+a+j9/XHcPOsP4DUrwowK38QucDQ4x5T7mQDWErY2n8NE4kV4HKjCq16ifNMAEt+/nyCKWog==} resolution: {integrity: sha512-MgSbNVGh5QMdrmRTrZ3W7W6sC5/Mx+dMgTy2uZCKQ9vns9eFXkQj61Pw2Y2FNHNMMp4DXFSUMYAPJWLcR16Wwg==}
engines: {node: '>=16.20.0'} engines: {node: '>=16.20.0'}
hasBin: true hasBin: true
@ -1648,6 +1652,10 @@ packages:
iterator.prototype@1.1.2: iterator.prototype@1.1.2:
resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
iterator.prototype@1.1.3:
resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==}
engines: {node: '>= 0.4'}
jackspeak@2.3.6: jackspeak@2.3.6:
resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
engines: {node: '>=14'} engines: {node: '>=14'}
@ -2520,8 +2528,8 @@ packages:
resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
systeminformation@5.23.5: systeminformation@5.23.8:
resolution: {integrity: sha512-PEpJwhRYxZgBCAlWZhWIgfMTjXLqfcaZ1pJsJn9snWNfBW/Z1YQg1mbIUSWrEV3ErAHF7l/OoVLQeaZDlPzkpA==} resolution: {integrity: sha512-Osd24mNKe6jr/YoXLLK3k8TMdzaxDffhpCxgkfgBHcapykIkd50HXThM3TCEuHO2pPuCsSx2ms/SunqhU5MmsQ==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android]
hasBin: true hasBin: true
@ -3454,7 +3462,7 @@ snapshots:
nan: 2.20.0 nan: 2.20.0
optional: true optional: true
cross-spawn@7.0.3: cross-spawn@7.0.6:
dependencies: dependencies:
path-key: 3.1.1 path-key: 3.1.1
shebang-command: 2.0.0 shebang-command: 2.0.0
@ -3757,6 +3765,24 @@ snapshots:
iterator.prototype: 1.1.2 iterator.prototype: 1.1.2
safe-array-concat: 1.1.2 safe-array-concat: 1.1.2
es-iterator-helpers@1.2.0:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.23.3
es-errors: 1.3.0
es-set-tostringtag: 2.0.3
function-bind: 1.1.2
get-intrinsic: 1.2.4
globalthis: 1.0.4
gopd: 1.0.1
has-property-descriptors: 1.0.2
has-proto: 1.0.3
has-symbols: 1.0.3
internal-slot: 1.0.7
iterator.prototype: 1.1.3
safe-array-concat: 1.1.2
es-object-atoms@1.0.0: es-object-atoms@1.0.0:
dependencies: dependencies:
es-errors: 1.3.0 es-errors: 1.3.0
@ -3781,7 +3807,7 @@ snapshots:
escape-string-regexp@4.0.0: {} escape-string-regexp@4.0.0: {}
eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1): eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.31.0)(eslint@8.57.1):
dependencies: dependencies:
confusing-browser-globals: 1.0.11 confusing-browser-globals: 1.0.11
eslint: 8.57.1 eslint: 8.57.1
@ -3790,13 +3816,13 @@ snapshots:
object.entries: 1.1.8 object.entries: 1.1.8
semver: 6.3.1 semver: 6.3.1
eslint-config-airbnb@19.0.4(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-jsx-a11y@6.10.0(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.1(eslint@8.57.1))(eslint@8.57.1): eslint-config-airbnb@19.0.4(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.0(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.2(eslint@8.57.1))(eslint@8.57.1):
dependencies: dependencies:
eslint: 8.57.1 eslint: 8.57.1
eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0)(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1)
eslint-plugin-react: 7.37.1(eslint@8.57.1) eslint-plugin-react: 7.37.2(eslint@8.57.1)
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
object.assign: 4.1.5 object.assign: 4.1.5
object.entries: 1.1.8 object.entries: 1.1.8
@ -3812,7 +3838,7 @@ snapshots:
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1) eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1)
eslint-plugin-react: 7.37.1(eslint@8.57.1) eslint-plugin-react: 7.37.2(eslint@8.57.1)
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
optionalDependencies: optionalDependencies:
typescript: 5.6.3 typescript: 5.6.3
@ -3839,7 +3865,7 @@ snapshots:
debug: 4.3.6 debug: 4.3.6
enhanced-resolve: 5.17.1 enhanced-resolve: 5.17.1
eslint: 8.57.1 eslint: 8.57.1
eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
fast-glob: 3.3.2 fast-glob: 3.3.2
get-tsconfig: 4.8.0 get-tsconfig: 4.8.0
is-bun-module: 1.1.0 is-bun-module: 1.1.0
@ -3852,7 +3878,7 @@ snapshots:
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
- supports-color - supports-color
eslint-module-utils@2.12.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): eslint-module-utils@2.12.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
dependencies: dependencies:
debug: 3.2.7 debug: 3.2.7
optionalDependencies: optionalDependencies:
@ -3863,7 +3889,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-module-utils@2.9.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): eslint-module-utils@2.9.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
dependencies: dependencies:
debug: 3.2.7 debug: 3.2.7
optionalDependencies: optionalDependencies:
@ -3885,7 +3911,7 @@ snapshots:
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 8.57.1 eslint: 8.57.1
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
hasown: 2.0.2 hasown: 2.0.2
is-core-module: 2.15.1 is-core-module: 2.15.1
is-glob: 4.0.3 is-glob: 4.0.3
@ -3936,14 +3962,14 @@ snapshots:
dependencies: dependencies:
eslint: 8.57.1 eslint: 8.57.1
eslint-plugin-react@7.37.1(eslint@8.57.1): eslint-plugin-react@7.37.2(eslint@8.57.1):
dependencies: dependencies:
array-includes: 3.1.8 array-includes: 3.1.8
array.prototype.findlast: 1.2.5 array.prototype.findlast: 1.2.5
array.prototype.flatmap: 1.3.2 array.prototype.flatmap: 1.3.2
array.prototype.tosorted: 1.1.4 array.prototype.tosorted: 1.1.4
doctrine: 2.1.0 doctrine: 2.1.0
es-iterator-helpers: 1.0.19 es-iterator-helpers: 1.2.0
eslint: 8.57.1 eslint: 8.57.1
estraverse: 5.3.0 estraverse: 5.3.0
hasown: 2.0.2 hasown: 2.0.2
@ -3977,7 +4003,7 @@ snapshots:
'@ungap/structured-clone': 1.2.0 '@ungap/structured-clone': 1.2.0
ajv: 6.12.6 ajv: 6.12.6
chalk: 4.1.2 chalk: 4.1.2
cross-spawn: 7.0.3 cross-spawn: 7.0.6
debug: 4.3.6 debug: 4.3.6
doctrine: 3.0.0 doctrine: 3.0.0
escape-string-regexp: 4.0.0 escape-string-regexp: 4.0.0
@ -4032,7 +4058,7 @@ snapshots:
execa@5.0.0: execa@5.0.0:
dependencies: dependencies:
cross-spawn: 7.0.3 cross-spawn: 7.0.6
get-stream: 6.0.1 get-stream: 6.0.1
human-signals: 2.1.0 human-signals: 2.1.0
is-stream: 2.0.1 is-stream: 2.0.1
@ -4101,7 +4127,7 @@ snapshots:
foreground-child@3.3.0: foreground-child@3.3.0:
dependencies: dependencies:
cross-spawn: 7.0.3 cross-spawn: 7.0.6
signal-exit: 4.1.0 signal-exit: 4.1.0
forever-agent@0.6.1: {} forever-agent@0.6.1: {}
@ -4138,7 +4164,7 @@ snapshots:
functions-have-names@1.2.3: {} functions-have-names@1.2.3: {}
gamedig@5.1.3: gamedig@5.1.4:
dependencies: dependencies:
cheerio: 1.0.0-rc.12 cheerio: 1.0.0-rc.12
gbxremote: 0.2.1 gbxremote: 0.2.1
@ -4146,7 +4172,6 @@ snapshots:
iconv-lite: 0.6.3 iconv-lite: 0.6.3
long: 5.2.3 long: 5.2.3
minimist: 1.2.8 minimist: 1.2.8
punycode: 2.3.1
seek-bzip: 2.0.0 seek-bzip: 2.0.0
varint: 6.0.0 varint: 6.0.0
@ -4496,6 +4521,14 @@ snapshots:
reflect.getprototypeof: 1.0.6 reflect.getprototypeof: 1.0.6
set-function-name: 2.0.2 set-function-name: 2.0.2
iterator.prototype@1.1.3:
dependencies:
define-properties: 1.2.1
get-intrinsic: 1.2.4
has-symbols: 1.0.3
reflect.getprototypeof: 1.0.6
set-function-name: 2.0.2
jackspeak@2.3.6: jackspeak@2.3.6:
dependencies: dependencies:
'@isaacs/cliui': 8.0.2 '@isaacs/cliui': 8.0.2
@ -5387,7 +5420,7 @@ snapshots:
'@pkgr/core': 0.1.1 '@pkgr/core': 0.1.1
tslib: 2.7.0 tslib: 2.7.0
systeminformation@5.23.5: {} systeminformation@5.23.8: {}
tailwind-scrollbar@3.1.0(tailwindcss@3.4.14): tailwind-scrollbar@3.1.0(tailwindcss@3.4.14):
dependencies: dependencies:

@ -120,7 +120,7 @@
"grid_power": "Rooster", "grid_power": "Rooster",
"home_power": "Verbruik", "home_power": "Verbruik",
"charge_power": "Laaier", "charge_power": "Laaier",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Aflaai", "download": "Aflaai",
@ -982,6 +982,9 @@
"name": "Naam", "name": "Naam",
"systems": "Stelsels", "systems": "Stelsels",
"up": "Op", "up": "Op",
"down": "Af",
"paused": "Onderbreek",
"pending": "Afwagtend",
"status": "Status", "status": "Status",
"updated": "Opgedateer", "updated": "Opgedateer",
"cpu": "SVE", "cpu": "SVE",
@ -990,22 +993,22 @@
"network": "NET" "network": "NET"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Programme",
"synced": "Synced", "synced": "Gesinkroniseer",
"outOfSync": "Out Of Sync", "outOfSync": "Nie Gesinchroniseer Nie",
"healthy": "Gesond", "healthy": "Gesond",
"degraded": "Degraded", "degraded": "Gedegradeer",
"progressing": "Progressing", "progressing": "Vorderend",
"missing": "Vermis", "missing": "Vermis",
"suspended": "Suspended" "suspended": "Geskors"
}, },
"spoolman": { "spoolman": {
"loading": "Laai" "loading": "Laai"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Groepe",
"issues": "Kwessies", "issues": "Kwessies",
"merges": "Merge Requests", "merges": "Saamvleg Versoeke",
"projects": "Projects" "projects": "Projekte"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "شبكة", "grid_power": "شبكة",
"home_power": "الاستهلاك", "home_power": "الاستهلاك",
"charge_power": "شاحن", "charge_power": "شاحن",
"watt_hour": "واط ساعة" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "التنزيل", "download": "التنزيل",
@ -982,6 +982,9 @@
"name": "الاسم", "name": "الاسم",
"systems": "Systems", "systems": "Systems",
"up": "يعمل", "up": "يعمل",
"down": "لا يعمل",
"paused": "متوقف",
"pending": "معلق",
"status": "الحالة", "status": "الحالة",
"updated": "محدث", "updated": "محدث",
"cpu": "المعالج", "cpu": "المعالج",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Статус", "status": "Статус",
"updated": "Updated", "updated": "Updated",
"cpu": "Процесор", "cpu": "Процесор",

@ -120,7 +120,7 @@
"grid_power": "Xarxa", "grid_power": "Xarxa",
"home_power": "Consum", "home_power": "Consum",
"charge_power": "Carregador", "charge_power": "Carregador",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Descarregar", "download": "Descarregar",
@ -350,7 +350,7 @@
"queue": "Cua", "queue": "Cua",
"processed": "Processat", "processed": "Processat",
"errored": "Error", "errored": "Error",
"saved": "Desat" "saved": "Estalviat"
}, },
"traefik": { "traefik": {
"routers": "Encaminadors", "routers": "Encaminadors",
@ -581,7 +581,7 @@
"clientIP": "Client" "clientIP": "Client"
}, },
"scrutiny": { "scrutiny": {
"passed": "Aprobat", "passed": "Aprovat",
"failed": "Error", "failed": "Error",
"unknown": "Desconegut" "unknown": "Desconegut"
}, },
@ -820,7 +820,7 @@
"total": "Total", "total": "Total",
"running": "En execució", "running": "En execució",
"stopped": "Aturat", "stopped": "Aturat",
"passed": "Aprobat", "passed": "Aprovat",
"failed": "Error" "failed": "Error"
}, },
"openwrt": { "openwrt": {
@ -982,6 +982,9 @@
"name": "Nom", "name": "Nom",
"systems": "Sistemes", "systems": "Sistemes",
"up": "Actiu", "up": "Actiu",
"down": "Inactiu",
"paused": "En pausa",
"pending": "Pendent",
"status": "Estat", "status": "Estat",
"updated": "Actualitzat", "updated": "Actualitzat",
"cpu": "CPU", "cpu": "CPU",
@ -991,21 +994,21 @@
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Apps",
"synced": "Synced", "synced": "Sincronitzats",
"outOfSync": "Out Of Sync", "outOfSync": "Dessincronitzats",
"healthy": "Saludable", "healthy": "Saludable",
"degraded": "Degraded", "degraded": "Degradats",
"progressing": "Progressing", "progressing": "Progressant",
"missing": "Falten", "missing": "Falten",
"suspended": "Suspended" "suspended": "Suspesos"
}, },
"spoolman": { "spoolman": {
"loading": "Carregant" "loading": "Carregant"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Grups",
"issues": "Problemes", "issues": "Problemes",
"merges": "Merge Requests", "merges": "Merge Requests",
"projects": "Projects" "projects": "Projectes"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Mřížka", "grid_power": "Mřížka",
"home_power": "Spotřeba", "home_power": "Spotřeba",
"charge_power": "Nabíječka", "charge_power": "Nabíječka",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Stahování", "download": "Stahování",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Pozastaveno",
"pending": "Čeká",
"status": "Stav", "status": "Stav",
"updated": "Aktualizováno", "updated": "Aktualizováno",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Gitter", "grid_power": "Gitter",
"home_power": "Forbrug", "home_power": "Forbrug",
"charge_power": "Oplader", "charge_power": "Oplader",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Navn", "name": "Navn",
"systems": "Systems", "systems": "Systems",
"up": "Op", "up": "Op",
"down": "Ned",
"paused": "Pause",
"pending": "Afventer",
"status": "Status", "status": "Status",
"updated": "Opdateret", "updated": "Opdateret",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Netz", "grid_power": "Netz",
"home_power": "verbauch", "home_power": "verbauch",
"charge_power": "Ladegerät", "charge_power": "Ladegerät",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systeme", "systems": "Systeme",
"up": "Senden", "up": "Senden",
"down": "Empfangen",
"paused": "Pausiert",
"pending": "Ausstehend",
"status": "Status", "status": "Status",
"updated": "Aktualisiert", "updated": "Aktualisiert",
"cpu": "CPU", "cpu": "CPU",
@ -1003,9 +1006,9 @@
"loading": "Wird geladen" "loading": "Wird geladen"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Gruppen",
"issues": "Probleme", "issues": "Probleme",
"merges": "Merge Requests", "merges": "Merge Requests",
"projects": "Projects" "projects": "Projekte"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Πλέγμα", "grid_power": "Πλέγμα",
"home_power": "Κατανάλωση", "home_power": "Κατανάλωση",
"charge_power": "Φορτιστής", "charge_power": "Φορτιστής",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Λήξη", "download": "Λήξη",
@ -982,6 +982,9 @@
"name": "Όνομα", "name": "Όνομα",
"systems": "Systems", "systems": "Systems",
"up": "Ping up", "up": "Ping up",
"down": "Ping down",
"paused": "Paused",
"pending": "Σε εκκρεμότητα",
"status": "Κατάσταση", "status": "Κατάσταση",
"updated": "Ενημερώθηκε", "updated": "Ενημερώθηκε",
"cpu": "Επεξεργαστής", "cpu": "Επεξεργαστής",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Elŝuti", "download": "Elŝuti",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Stato", "status": "Stato",
"updated": "Updated", "updated": "Updated",
"cpu": "Ĉefprocesoro", "cpu": "Ĉefprocesoro",

@ -120,7 +120,7 @@
"grid_power": "Red", "grid_power": "Red",
"home_power": "Consumo", "home_power": "Consumo",
"charge_power": "Cargador", "charge_power": "Cargador",
"watt_hour": "vatio-hora (Wh)" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Descarga", "download": "Descarga",
@ -311,13 +311,13 @@
}, },
"suwayomi": { "suwayomi": {
"download": "Descargado", "download": "Descargado",
"nondownload": "Non-Downloaded", "nondownload": "No descargado",
"read": "Leer", "read": "Leer",
"unread": "Sin leer", "unread": "Sin leer",
"downloadedread": "Downloaded & Read", "downloadedread": "Descargado y leído",
"downloadedunread": "Downloaded & Unread", "downloadedunread": "Descargado y no leído",
"nondownloadedread": "Non-Downloaded & Read", "nondownloadedread": "No descargado y leído",
"nondownloadedunread": "Non-Downloaded & Unread" "nondownloadedunread": "No descargado y no leído"
}, },
"tailscale": { "tailscale": {
"address": "Dirección", "address": "Dirección",
@ -980,32 +980,35 @@
}, },
"beszel": { "beszel": {
"name": "Nombre", "name": "Nombre",
"systems": "Systems", "systems": "Sistemas",
"up": "Activo", "up": "Activo",
"down": "Inactivo",
"paused": "Pausado",
"pending": "Pendiente",
"status": "Estado", "status": "Estado",
"updated": "Actualizado", "updated": "Actualizado",
"cpu": "CPU", "cpu": "CPU",
"memory": "MEM", "memory": "MEM",
"disk": "Disk", "disk": "Disco",
"network": "NET" "network": "RED"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Apps",
"synced": "Synced", "synced": "Sincronizado",
"outOfSync": "Out Of Sync", "outOfSync": "Desincronizado",
"healthy": "Saludable", "healthy": "Saludable",
"degraded": "Degraded", "degraded": "Degradado",
"progressing": "Progressing", "progressing": "Progresando",
"missing": "Faltantes", "missing": "Faltantes",
"suspended": "Suspended" "suspended": "Suspendido"
}, },
"spoolman": { "spoolman": {
"loading": "Cargando" "loading": "Cargando"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Grupos",
"issues": "Números", "issues": "Números",
"merges": "Merge Requests", "merges": "Solicitudes de fusión",
"projects": "Projects" "projects": "Proyectos"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Vireillä",
"status": "Tila", "status": "Tila",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -58,7 +58,7 @@
"wlan": "WLAN", "wlan": "WLAN",
"devices": "Équipt.", "devices": "Équipt.",
"lan_devices": "Équipt. LAN", "lan_devices": "Équipt. LAN",
"wlan_devices": "Équipt. WLAN", "wlan_devices": "Périphériques WLAN",
"lan_users": "Utilisateurs LAN", "lan_users": "Utilisateurs LAN",
"wlan_users": "Utilisateurs WLAN", "wlan_users": "Utilisateurs WLAN",
"up": "Up", "up": "Up",
@ -120,7 +120,7 @@
"grid_power": "Grille", "grid_power": "Grille",
"home_power": "Consommation", "home_power": "Consommation",
"charge_power": "Chargeur", "charge_power": "Chargeur",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Récep.", "download": "Récep.",
@ -982,6 +982,9 @@
"name": "Nom", "name": "Nom",
"systems": "Systèmes", "systems": "Systèmes",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "En Pause",
"pending": "En attente",
"status": "Statut", "status": "Statut",
"updated": "Mis à jour", "updated": "Mis à jour",
"cpu": "CPU", "cpu": "CPU",
@ -990,22 +993,22 @@
"network": "Réseau" "network": "Réseau"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Applications",
"synced": "Synced", "synced": "Synchronisé",
"outOfSync": "Out Of Sync", "outOfSync": "Désynchronisé",
"healthy": "Fonctionnel", "healthy": "Fonctionnel",
"degraded": "Degraded", "degraded": "Dégradé",
"progressing": "Progressing", "progressing": "En cours",
"missing": "Manquant", "missing": "Manquant",
"suspended": "Suspended" "suspended": "Suspendu"
}, },
"spoolman": { "spoolman": {
"loading": "Chargement" "loading": "Chargement"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Groupes",
"issues": "Anomalies", "issues": "Anomalies",
"merges": "Merge Requests", "merges": "Demandes de fusion de branches",
"projects": "Projects" "projects": "Projets"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "ממתין",
"status": "סטטוס", "status": "סטטוס",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Raspored", "grid_power": "Raspored",
"home_power": "Potrošnja", "home_power": "Potrošnja",
"charge_power": "Punjač", "charge_power": "Punjač",
"watt_hour": "Kilovat-sat" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Preuzimanje", "download": "Preuzimanje",
@ -982,6 +982,9 @@
"name": "Ime", "name": "Ime",
"systems": "Systems", "systems": "Systems",
"up": "Dostupno", "up": "Dostupno",
"down": "Nedostupno",
"paused": "Zaustavljeno",
"pending": "U tijeku",
"status": "Stanje", "status": "Stanje",
"updated": "Aktualizirano", "updated": "Aktualizirano",
"cpu": "CPU", "cpu": "CPU",

@ -25,7 +25,7 @@
"api_error": "API Hiba", "api_error": "API Hiba",
"information": "Információ", "information": "Információ",
"status": "Státusz", "status": "Státusz",
"url": "LINK", "url": "URL",
"raw_error": "Nyers hiba", "raw_error": "Nyers hiba",
"response_data": "Válaszadatok" "response_data": "Válaszadatok"
}, },
@ -120,7 +120,7 @@
"grid_power": "Rács", "grid_power": "Rács",
"home_power": "Fogyasztás", "home_power": "Fogyasztás",
"charge_power": "Töltő", "charge_power": "Töltő",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Letöltés", "download": "Letöltés",
@ -227,8 +227,8 @@
"seed": "Seed" "seed": "Seed"
}, },
"develancacheui": { "develancacheui": {
"cachehitbytes": "Cache Hit Bytes", "cachehitbytes": "Gyorsítótárban Sikeres Bitek",
"cachemissbytes": "Cache Miss Bytes" "cachemissbytes": "Gyorsítótárban Hibás Bitek"
}, },
"downloadstation": { "downloadstation": {
"download": "Letöltés", "download": "Letöltés",
@ -311,13 +311,13 @@
}, },
"suwayomi": { "suwayomi": {
"download": "Letöltött", "download": "Letöltött",
"nondownload": "Non-Downloaded", "nondownload": "Nem Letöltött",
"read": "Olvasott", "read": "Olvasott",
"unread": "Olvasatlan", "unread": "Olvasatlan",
"downloadedread": "Downloaded & Read", "downloadedread": "Letöltött & Olvasott",
"downloadedunread": "Downloaded & Unread", "downloadedunread": "Letöltött & Olvasatlan",
"nondownloadedread": "Non-Downloaded & Read", "nondownloadedread": "Nem Letöltött & Olvasatlan",
"nondownloadedunread": "Non-Downloaded & Unread" "nondownloadedunread": "Nem Letöltött & Olvasatlan"
}, },
"tailscale": { "tailscale": {
"address": "Cím", "address": "Cím",
@ -335,15 +335,15 @@
}, },
"technitium": { "technitium": {
"totalQueries": "Lekérdezések", "totalQueries": "Lekérdezések",
"totalNoError": "Success", "totalNoError": "Sikerek",
"totalServerFailure": "Failures", "totalServerFailure": "Hibák",
"totalNxDomain": "NX Domains", "totalNxDomain": "NX Domainek",
"totalRefused": "Refused", "totalRefused": "Elutasított",
"totalAuthoritative": "Authoritative", "totalAuthoritative": "Irányadó",
"totalRecursive": "Recursive", "totalRecursive": "Rekurzív",
"totalCached": "Cached", "totalCached": "Gyorsítótárazott",
"totalBlocked": "Blokkolt", "totalBlocked": "Blokkolt",
"totalDropped": "Dropped", "totalDropped": "Eldobott",
"totalClients": "Kliensek" "totalClients": "Kliensek"
}, },
"tdarr": { "tdarr": {
@ -453,7 +453,7 @@
"search": "Keresés", "search": "Keresés",
"custom": "Egyedi", "custom": "Egyedi",
"visit": "Megnéz", "visit": "Megnéz",
"url": "LINK", "url": "URL",
"searchsuggestion": "Javaslat" "searchsuggestion": "Javaslat"
}, },
"wmo": { "wmo": {
@ -854,16 +854,16 @@
}, },
"romm": { "romm": {
"platforms": "Felület", "platforms": "Felület",
"totalRoms": "Games", "totalRoms": "Játékok",
"saves": "Saves", "saves": "Mentések",
"states": "States", "states": "Állapotok",
"screenshots": "Screenshots", "screenshots": "Képernyőképek",
"totalfilesize": "Total Size" "totalfilesize": "Teljes méret"
}, },
"mailcow": { "mailcow": {
"domains": "Domainek", "domains": "Domainek",
"mailboxes": "Mailboxes", "mailboxes": "E-mail fiókok",
"mails": "Mails", "mails": "Mailek",
"storage": "Tárhely" "storage": "Tárhely"
}, },
"netdata": { "netdata": {
@ -912,7 +912,7 @@
}, },
"crowdsec": { "crowdsec": {
"alerts": "Riasztások", "alerts": "Riasztások",
"bans": "Bans" "bans": "Kitiltások"
}, },
"wgeasy": { "wgeasy": {
"connected": "Csatlakozva", "connected": "Csatlakozva",
@ -921,10 +921,10 @@
"total": "Összes" "total": "Összes"
}, },
"swagdashboard": { "swagdashboard": {
"proxied": "Proxied", "proxied": "Proxyzott",
"auth": "With Auth", "auth": "Hitelesítéssel",
"outdated": "Outdated", "outdated": "Elavult",
"banned": "Banned" "banned": "Kitiltott"
}, },
"myspeed": { "myspeed": {
"ping": "Ping", "ping": "Ping",
@ -932,29 +932,29 @@
"upload": "Feltöltés" "upload": "Feltöltés"
}, },
"stocks": { "stocks": {
"stocks": "Stocks", "stocks": "Tőzsde",
"loading": "Loading", "loading": "Betöltés",
"open": "Open - US Market", "open": "Nyitva - US Piac",
"closed": "Closed - US Market", "closed": "Zárva - US Piac",
"invalidConfiguration": "Invalid Configuration" "invalidConfiguration": "Érvénytelen konfiguráció"
}, },
"frigate": { "frigate": {
"cameras": "Cameras", "cameras": "Kamerák",
"uptime": "Üzemidő", "uptime": "Üzemidő",
"version": "Verzió" "version": "Verzió"
}, },
"linkwarden": { "linkwarden": {
"links": "Links", "links": "Linkek",
"collections": "Collections", "collections": "Gyűjtemény",
"tags": "Címkék" "tags": "Címkék"
}, },
"zabbix": { "zabbix": {
"unclassified": "Not classified", "unclassified": "Nem titkosított",
"information": "Információ", "information": "Információ",
"warning": "Warning", "warning": "Figyelmeztetés",
"average": "Average", "average": "Átlag",
"high": "High", "high": "Magas",
"disaster": "Disaster" "disaster": "Katasztrófa"
}, },
"lubelogger": { "lubelogger": {
"vehicle": "Jármű", "vehicle": "Jármű",
@ -962,13 +962,13 @@
"serviceRecords": "Szolgáltatások nyílvántartása", "serviceRecords": "Szolgáltatások nyílvántartása",
"reminders": "Emlékeztetők", "reminders": "Emlékeztetők",
"nextReminder": "Következő emlékeztető", "nextReminder": "Következő emlékeztető",
"none": "None" "none": "Semmi"
}, },
"vikunja": { "vikunja": {
"projects": "Active Projects", "projects": "Aktív Projektek",
"tasks7d": "Tasks Due This Week", "tasks7d": "Hátralévő feladatok a héten",
"tasksOverdue": "Overdue Tasks", "tasksOverdue": "Lejárt feladatok",
"tasksInProgress": "Tasks In Progress" "tasksInProgress": "Folyamatban levő Feladatok"
}, },
"headscale": { "headscale": {
"name": "Név", "name": "Név",
@ -980,32 +980,35 @@
}, },
"beszel": { "beszel": {
"name": "Név", "name": "Név",
"systems": "Systems", "systems": "Rendszerek",
"up": "Fel", "up": "Fel",
"down": "Le",
"paused": "Szünetel",
"pending": "Függőben",
"status": "Státusz", "status": "Státusz",
"updated": "Frissített", "updated": "Frissített",
"cpu": "Processzor", "cpu": "Processzor",
"memory": "RAM", "memory": "RAM",
"disk": "Disk", "disk": "Lemez",
"network": "NET" "network": "Hálózat"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Alkalmazások",
"synced": "Synced", "synced": "Szinkronizált",
"outOfSync": "Out Of Sync", "outOfSync": "Nincs szinkronban",
"healthy": "Egészséges", "healthy": "Egészséges",
"degraded": "Degraded", "degraded": "Leépült",
"progressing": "Progressing", "progressing": "Halad",
"missing": "Hiányzik", "missing": "Hiányzik",
"suspended": "Suspended" "suspended": "Felfüggesztett"
}, },
"spoolman": { "spoolman": {
"loading": "Loading" "loading": "Betöltés"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Csoportok",
"issues": "Problémák", "issues": "Problémák",
"merges": "Merge Requests", "merges": "Merge kérések",
"projects": "Projects" "projects": "Projektek"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Konsumsi", "home_power": "Konsumsi",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Watt/jam" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Unduh", "download": "Unduh",
@ -982,6 +982,9 @@
"name": "Nama", "name": "Nama",
"systems": "Systems", "systems": "Systems",
"up": "Hidup", "up": "Hidup",
"down": "Mati",
"paused": "Pause",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Terbarui", "updated": "Terbarui",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Griglia", "grid_power": "Griglia",
"home_power": "Consumo", "home_power": "Consumo",
"charge_power": "Caricatore", "charge_power": "Caricatore",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -335,7 +335,7 @@
}, },
"technitium": { "technitium": {
"totalQueries": "Richieste", "totalQueries": "Richieste",
"totalNoError": "Success", "totalNoError": "Successo",
"totalServerFailure": "Failures", "totalServerFailure": "Failures",
"totalNxDomain": "NX Domains", "totalNxDomain": "NX Domains",
"totalRefused": "Refused", "totalRefused": "Refused",
@ -590,7 +590,7 @@
"total": "Totale" "total": "Totale"
}, },
"peanut": { "peanut": {
"battery_charge": "Battery Charge", "battery_charge": "Carica Batteria",
"ups_load": "Carico UPS", "ups_load": "Carico UPS",
"ups_status": "Stato UPS", "ups_status": "Stato UPS",
"online": "Online", "online": "Online",
@ -854,7 +854,7 @@
}, },
"romm": { "romm": {
"platforms": "Piattaforme", "platforms": "Piattaforme",
"totalRoms": "Games", "totalRoms": "Giochi",
"saves": "Saves", "saves": "Saves",
"states": "States", "states": "States",
"screenshots": "Screenshots", "screenshots": "Screenshots",
@ -890,7 +890,7 @@
"sceneDuration": "Durata Delle Scene", "sceneDuration": "Durata Delle Scene",
"images": "Immagini", "images": "Immagini",
"imageSize": "Dimensioni immagine", "imageSize": "Dimensioni immagine",
"galleries": "Galleries", "galleries": "Gallerie",
"performers": "Esecutori", "performers": "Esecutori",
"studios": "Studi", "studios": "Studi",
"movies": "Film", "movies": "Film",
@ -933,7 +933,7 @@
}, },
"stocks": { "stocks": {
"stocks": "Stocks", "stocks": "Stocks",
"loading": "Loading", "loading": "Caricamento",
"open": "Open - US Market", "open": "Open - US Market",
"closed": "Closed - US Market", "closed": "Closed - US Market",
"invalidConfiguration": "Invalid Configuration" "invalidConfiguration": "Invalid Configuration"
@ -944,8 +944,8 @@
"version": "Versione" "version": "Versione"
}, },
"linkwarden": { "linkwarden": {
"links": "Links", "links": "Collegamenti",
"collections": "Collections", "collections": "Raccolte",
"tags": "Tag" "tags": "Tag"
}, },
"zabbix": { "zabbix": {
@ -957,12 +957,12 @@
"disaster": "Disaster" "disaster": "Disaster"
}, },
"lubelogger": { "lubelogger": {
"vehicle": "Vehicle", "vehicle": "Veicolo",
"vehicles": "Vehicles", "vehicles": "Veicoli",
"serviceRecords": "Service Records", "serviceRecords": "Service Records",
"reminders": "Reminders", "reminders": "Promemoria",
"nextReminder": "Next Reminder", "nextReminder": "Promemoria Seguente",
"none": "None" "none": "Nessuno"
}, },
"vikunja": { "vikunja": {
"projects": "Active Projects", "projects": "Active Projects",
@ -982,6 +982,9 @@
"name": "Nome", "name": "Nome",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "In Pausa",
"pending": "In attesa",
"status": "Stato", "status": "Stato",
"updated": "Aggiornato", "updated": "Aggiornato",
"cpu": "CPU", "cpu": "CPU",
@ -1000,7 +1003,7 @@
"suspended": "Suspended" "suspended": "Suspended"
}, },
"spoolman": { "spoolman": {
"loading": "Loading" "loading": "Caricamento"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Groups",

@ -120,7 +120,7 @@
"grid_power": "グリッド", "grid_power": "グリッド",
"home_power": "消費", "home_power": "消費",
"charge_power": "チャージャー", "charge_power": "チャージャー",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "ダウンロード", "download": "ダウンロード",
@ -804,7 +804,7 @@
"ping": "Ping" "ping": "Ping"
}, },
"urbackup": { "urbackup": {
"ok": "はい", "ok": "正常",
"errored": "エラー", "errored": "エラー",
"noRecent": "期限切れ", "noRecent": "期限切れ",
"totalUsed": "使用済みストレージ" "totalUsed": "使用済みストレージ"
@ -957,7 +957,7 @@
"disaster": "災害" "disaster": "災害"
}, },
"lubelogger": { "lubelogger": {
"vehicle": "Vehicle", "vehicle": "車両",
"vehicles": "Vehicles", "vehicles": "Vehicles",
"serviceRecords": "Service Records", "serviceRecords": "Service Records",
"reminders": "Reminders", "reminders": "Reminders",
@ -982,6 +982,9 @@
"name": "名前", "name": "名前",
"systems": "Systems", "systems": "Systems",
"up": "稼働", "up": "稼働",
"down": "下へ",
"paused": "一時停止中",
"pending": "保留中",
"status": "状態", "status": "状態",
"updated": "更新済", "updated": "更新済",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "눈금", "grid_power": "눈금",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "다운로드", "download": "다운로드",
@ -982,6 +982,9 @@
"name": "이름", "name": "이름",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "대기 중",
"status": "상태", "status": "상태",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Lejupielāde", "download": "Lejupielāde",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Statuss", "status": "Statuss",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Penggunaan", "home_power": "Penggunaan",
"charge_power": "Pengecas", "charge_power": "Pengecas",
"watt_hour": "Wj" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Muat turun", "download": "Muat turun",
@ -982,6 +982,9 @@
"name": "Nama", "name": "Nama",
"systems": "Systems", "systems": "Systems",
"up": "Hidup", "up": "Hidup",
"down": "Mati",
"paused": "Tangguh",
"pending": "Tertunda",
"status": "Status", "status": "Status",
"updated": "Dikemaskini", "updated": "Dikemaskini",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Netstroom", "grid_power": "Netstroom",
"home_power": "Consumptie", "home_power": "Consumptie",
"charge_power": "Oplader", "charge_power": "Oplader",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -311,13 +311,13 @@
}, },
"suwayomi": { "suwayomi": {
"download": "Gedownload", "download": "Gedownload",
"nondownload": "Non-Downloaded", "nondownload": "Niet gedownload",
"read": "Gelezen", "read": "Gelezen",
"unread": "Ongelezen", "unread": "Ongelezen",
"downloadedread": "Downloaded & Read", "downloadedread": "Gedownload & gelezen",
"downloadedunread": "Downloaded & Unread", "downloadedunread": "Gedownload & ongelezen",
"nondownloadedread": "Non-Downloaded & Read", "nondownloadedread": "Niet-gedownload & gelezen",
"nondownloadedunread": "Non-Downloaded & Unread" "nondownloadedunread": "Niet-gedownload & ongelezen"
}, },
"tailscale": { "tailscale": {
"address": "Adres", "address": "Adres",
@ -980,32 +980,35 @@
}, },
"beszel": { "beszel": {
"name": "Naam", "name": "Naam",
"systems": "Systems", "systems": "Systemen",
"up": "Online", "up": "Online",
"down": "Offline",
"paused": "Gepauzeerd",
"pending": "In afwachting",
"status": "Status", "status": "Status",
"updated": "Bijgewerkt", "updated": "Bijgewerkt",
"cpu": "CPU", "cpu": "CPU",
"memory": "GEH", "memory": "GEH",
"disk": "Disk", "disk": "Schijf",
"network": "NET" "network": "NET"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Apps",
"synced": "Synced", "synced": "Gesynchroniseerd",
"outOfSync": "Out Of Sync", "outOfSync": "Niet gesynchroniseerd",
"healthy": "Gezond", "healthy": "Gezond",
"degraded": "Degraded", "degraded": "Gedegradeerd",
"progressing": "Progressing", "progressing": "Doorvoeren",
"missing": "Ontbreekt", "missing": "Ontbreekt",
"suspended": "Suspended" "suspended": "Onderbroken"
}, },
"spoolman": { "spoolman": {
"loading": "Laden" "loading": "Laden"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Groepen",
"issues": "Problemen", "issues": "Problemen",
"merges": "Merge Requests", "merges": "Merge Verzoeken",
"projects": "Projects" "projects": "Projecten"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Nett", "grid_power": "Nett",
"home_power": "Forbruk", "home_power": "Forbruk",
"charge_power": "Lader", "charge_power": "Lader",
"watt_hour": "W/t" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Last ned", "download": "Last ned",
@ -982,6 +982,9 @@
"name": "Navn", "name": "Navn",
"systems": "Systems", "systems": "Systems",
"up": "Oppe", "up": "Oppe",
"down": "Nede",
"paused": "Pauset",
"pending": "Ventende",
"status": "Status", "status": "Status",
"updated": "Oppdatert", "updated": "Oppdatert",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Siatka", "grid_power": "Siatka",
"home_power": "Zużycie", "home_power": "Zużycie",
"charge_power": "Ładowarka", "charge_power": "Ładowarka",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Pobieranie", "download": "Pobieranie",
@ -311,13 +311,13 @@
}, },
"suwayomi": { "suwayomi": {
"download": "Pobrano", "download": "Pobrano",
"nondownload": "Non-Downloaded", "nondownload": "Niepobrane",
"read": "Przeczytane", "read": "Przeczytane",
"unread": "Nieprzeczytane", "unread": "Nieprzeczytane",
"downloadedread": "Downloaded & Read", "downloadedread": "Pobrane i przeczytane",
"downloadedunread": "Downloaded & Unread", "downloadedunread": "Pobrane i nieprzeczytane",
"nondownloadedread": "Non-Downloaded & Read", "nondownloadedread": "Niepobrane i przeczytane",
"nondownloadedunread": "Non-Downloaded & Unread" "nondownloadedunread": "Niepobrane i nieprzeczytane"
}, },
"tailscale": { "tailscale": {
"address": "Adres", "address": "Adres",
@ -957,18 +957,18 @@
"disaster": "Katastrofa" "disaster": "Katastrofa"
}, },
"lubelogger": { "lubelogger": {
"vehicle": "Vehicle", "vehicle": "Pojazd",
"vehicles": "Vehicles", "vehicles": "Pojazdy",
"serviceRecords": "Service Records", "serviceRecords": "Wpisy serwisowe",
"reminders": "Reminders", "reminders": "Przypomnienia",
"nextReminder": "Next Reminder", "nextReminder": "Następne przypomnienie",
"none": "None" "none": "Brak"
}, },
"vikunja": { "vikunja": {
"projects": "Active Projects", "projects": "Aktywne Projekty",
"tasks7d": "Tasks Due This Week", "tasks7d": "Zadania w tym tygodniu",
"tasksOverdue": "Overdue Tasks", "tasksOverdue": "Zaległe zadania",
"tasksInProgress": "Tasks In Progress" "tasksInProgress": "Zadania w toku"
}, },
"headscale": { "headscale": {
"name": "Nazwa", "name": "Nazwa",
@ -980,32 +980,35 @@
}, },
"beszel": { "beszel": {
"name": "Nazwa", "name": "Nazwa",
"systems": "Systems", "systems": "Systemy",
"up": "Dostępny", "up": "Dostępny",
"down": "Niedostępny",
"paused": "Zatrzymane",
"pending": "Oczekiwane",
"status": "Stan", "status": "Stan",
"updated": "Zaktualizowane", "updated": "Zaktualizowane",
"cpu": "Procesor", "cpu": "Procesor",
"memory": "RAM", "memory": "RAM",
"disk": "Disk", "disk": "Dysk",
"network": "NET" "network": "NET"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Aplikacje",
"synced": "Synced", "synced": "Synchronizowane",
"outOfSync": "Out Of Sync", "outOfSync": "Bez synchronizacji",
"healthy": "Zdrowy", "healthy": "Zdrowy",
"degraded": "Degraded", "degraded": "Zdegradowane",
"progressing": "Progressing", "progressing": "Postępujące",
"missing": "Brakujące", "missing": "Brakujące",
"suspended": "Suspended" "suspended": "Zawieszone"
}, },
"spoolman": { "spoolman": {
"loading": "Wczytywanie" "loading": "Wczytywanie"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Grupy",
"issues": "Zgłoszenia", "issues": "Zgłoszenia",
"merges": "Merge Requests", "merges": "Żądania scaleń",
"projects": "Projects" "projects": "Projekty"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Grelha", "grid_power": "Grelha",
"home_power": "Consumo", "home_power": "Consumo",
"charge_power": "Carregador", "charge_power": "Carregador",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Descarregar", "download": "Descarregar",
@ -982,6 +982,9 @@
"name": "Nome", "name": "Nome",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Pausa",
"pending": "Pendente",
"status": "Estado", "status": "Estado",
"updated": "Atualizado", "updated": "Atualizado",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grade", "grid_power": "Grade",
"home_power": "Consumo", "home_power": "Consumo",
"charge_power": "Carregador", "charge_power": "Carregador",
"watt_hour": "Kw" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Descarregar", "download": "Descarregar",
@ -982,6 +982,9 @@
"name": "Nome", "name": "Nome",
"systems": "Systems", "systems": "Systems",
"up": "Ativo", "up": "Ativo",
"down": "Inativo",
"paused": "Pausado",
"pending": "Pendente",
"status": "Status", "status": "Status",
"updated": "Atualizado", "updated": "Atualizado",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grilă", "grid_power": "Grilă",
"home_power": "Consum", "home_power": "Consum",
"charge_power": "Încărcător", "charge_power": "Încărcător",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Descarcă", "download": "Descarcă",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Sus", "up": "Sus",
"down": "Jos",
"paused": "Paused",
"pending": "În așteptare",
"status": "Stare", "status": "Stare",
"updated": "Updated", "updated": "Updated",
"cpu": "Procesor", "cpu": "Procesor",

@ -120,7 +120,7 @@
"grid_power": "Сетка", "grid_power": "Сетка",
"home_power": "Потребление", "home_power": "Потребление",
"charge_power": "Зарядка", "charge_power": "Зарядка",
"watt_hour": "Вт" "kilowatt": "кВт"
}, },
"flood": { "flood": {
"download": "Скачивание", "download": "Скачивание",
@ -982,6 +982,9 @@
"name": "Имя", "name": "Имя",
"systems": "Системы", "systems": "Системы",
"up": "Онлайн", "up": "Онлайн",
"down": "Офлайн",
"paused": "Приостановлено",
"pending": "В обработке",
"status": "Статус", "status": "Статус",
"updated": "Обновленно", "updated": "Обновленно",
"cpu": "ЦП", "cpu": "ЦП",
@ -990,22 +993,22 @@
"network": "Сеть" "network": "Сеть"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Приложения",
"synced": "Synced", "synced": "Синхронизированные",
"outOfSync": "Out Of Sync", "outOfSync": "Не синхронизированные",
"healthy": "Здоровый", "healthy": "Здоровый",
"degraded": "Degraded", "degraded": "Деградированные",
"progressing": "Progressing", "progressing": "Выполняются",
"missing": "Отсутствует", "missing": "Отсутствует",
"suspended": "Suspended" "suspended": "Приостановленные"
}, },
"spoolman": { "spoolman": {
"loading": "Загрузка" "loading": "Загрузка"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Группы",
"issues": "Вопросы", "issues": "Вопросы",
"merges": "Merge Requests", "merges": "Мердж-реквесты",
"projects": "Projects" "projects": "Проекты"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Mriežka", "grid_power": "Mriežka",
"home_power": "Spotreba", "home_power": "Spotreba",
"charge_power": "Nabíjačka", "charge_power": "Nabíjačka",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Sťahovanie", "download": "Sťahovanie",
@ -982,6 +982,9 @@
"name": "Meno", "name": "Meno",
"systems": "Systems", "systems": "Systems",
"up": "Nahrávanie", "up": "Nahrávanie",
"down": "Sťahovanie",
"paused": "Pozastavené",
"pending": "Čakajúce",
"status": "Stav", "status": "Stav",
"updated": "Aktualizované", "updated": "Aktualizované",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Omrežje", "grid_power": "Omrežje",
"home_power": "Poraba", "home_power": "Poraba",
"charge_power": "Polnilec", "charge_power": "Polnilec",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Prenos", "download": "Prenos",
@ -982,6 +982,9 @@
"name": "Naziv", "name": "Naziv",
"systems": "Sistemi", "systems": "Sistemi",
"up": "Povezan", "up": "Povezan",
"down": "Nepovezan",
"paused": "Pavziran",
"pending": "V teku",
"status": "Stanje", "status": "Stanje",
"updated": "Posodobljen", "updated": "Posodobljen",
"cpu": "CPU", "cpu": "CPU",
@ -1003,9 +1006,9 @@
"loading": "Nalaganje" "loading": "Nalaganje"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Skupine",
"issues": "Težave", "issues": "Težave",
"merges": "Merge Requests", "merges": "Združi zahtevke",
"projects": "Projects" "projects": "Projekti"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Avvaktar",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "పెండింగ్",
"status": "హోదా", "status": "హోదా",
"updated": "నవీకరించబడింది", "updated": "నవీకరించబడింది",
"cpu": "సీపియూ", "cpu": "సీపియూ",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "ดาวน์โหลด", "download": "ดาวน์โหลด",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "สถานะ", "status": "สถานะ",
"updated": "Updated", "updated": "Updated",
"cpu": "ซีพียู", "cpu": "ซีพียู",

@ -120,7 +120,7 @@
"grid_power": "Güç", "grid_power": "Güç",
"home_power": "Tüketim", "home_power": "Tüketim",
"charge_power": "Şarj", "charge_power": "Şarj",
"watt_hour": "Watt/Saat" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "İndirme", "download": "İndirme",
@ -982,6 +982,9 @@
"name": "İsim", "name": "İsim",
"systems": "Systems", "systems": "Systems",
"up": "Yükleme", "up": "Yükleme",
"down": "İndirme",
"paused": "Duraklatıldı",
"pending": "Bekleyen",
"status": "Durum", "status": "Durum",
"updated": "Güncellendi", "updated": "Güncellendi",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Сітка", "grid_power": "Сітка",
"home_power": "Споживання", "home_power": "Споживання",
"charge_power": "Зарядний пристрій", "charge_power": "Зарядний пристрій",
"watt_hour": "Вт/год" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Завантажено", "download": "Завантажено",
@ -311,13 +311,13 @@
}, },
"suwayomi": { "suwayomi": {
"download": "Завантажено", "download": "Завантажено",
"nondownload": "Non-Downloaded", "nondownload": "Не завантажено",
"read": "Прочитано", "read": "Прочитано",
"unread": "Не прочитано", "unread": "Не прочитано",
"downloadedread": "Downloaded & Read", "downloadedread": "Завантажено та Прочитано",
"downloadedunread": "Downloaded & Unread", "downloadedunread": "Завантажено та Непрочитано",
"nondownloadedread": "Non-Downloaded & Read", "nondownloadedread": "Не завантажено та Прочитано",
"nondownloadedunread": "Non-Downloaded & Unread" "nondownloadedunread": "Не завантажено та Не прочитано"
}, },
"tailscale": { "tailscale": {
"address": "Адреса", "address": "Адреса",
@ -965,10 +965,10 @@
"none": "Жодного" "none": "Жодного"
}, },
"vikunja": { "vikunja": {
"projects": "Active Projects", "projects": "Активні проекти",
"tasks7d": "Tasks Due This Week", "tasks7d": "Завдання цього тижня",
"tasksOverdue": "Overdue Tasks", "tasksOverdue": "Прострочені завдання",
"tasksInProgress": "Tasks In Progress" "tasksInProgress": "Завдання в процесі"
}, },
"headscale": { "headscale": {
"name": "Назва", "name": "Назва",
@ -980,32 +980,35 @@
}, },
"beszel": { "beszel": {
"name": "Назва", "name": "Назва",
"systems": "Systems", "systems": "Системи",
"up": "Онлайн", "up": "Онлайн",
"down": "Офлайн",
"paused": "Призупинено",
"pending": "В очікуванні",
"status": "Стан", "status": "Стан",
"updated": "Оновлено", "updated": "Оновлено",
"cpu": "ЦП", "cpu": "ЦП",
"memory": "ОЗП", "memory": "ОЗП",
"disk": "Disk", "disk": "Диск",
"network": "NET" "network": "МЕРЕЖА"
}, },
"argocd": { "argocd": {
"apps": "Apps", "apps": "Додатки",
"synced": "Synced", "synced": "Синхронізовано",
"outOfSync": "Out Of Sync", "outOfSync": "Не синхронізовано",
"healthy": "Здоровий", "healthy": "Здоровий",
"degraded": "Degraded", "degraded": "Деградує",
"progressing": "Progressing", "progressing": "Прогрес",
"missing": "Відсутній", "missing": "Відсутній",
"suspended": "Suspended" "suspended": "Призупинено"
}, },
"spoolman": { "spoolman": {
"loading": "Завантажую" "loading": "Завантажую"
}, },
"gitlab": { "gitlab": {
"groups": "Groups", "groups": "Групи",
"issues": "Питання", "issues": "Питання",
"merges": "Merge Requests", "merges": "Запити на злиття",
"projects": "Projects" "projects": "Проєкти"
} }
} }

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "Download", "download": "Download",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Đang xử lý",
"status": "Trạng thái", "status": "Trạng thái",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "電網", "grid_power": "電網",
"home_power": "電源使用率", "home_power": "電源使用率",
"charge_power": "充電", "charge_power": "充電",
"watt_hour": "瓦時 (Wh)" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "下載速率", "download": "下載速率",
@ -982,6 +982,9 @@
"name": "名稱", "name": "名稱",
"systems": "Systems", "systems": "Systems",
"up": "在線", "up": "在線",
"down": "離線",
"paused": "擱置中",
"pending": "待定",
"status": "狀況", "status": "狀況",
"updated": "已更新", "updated": "已更新",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "Grid", "grid_power": "Grid",
"home_power": "Consumption", "home_power": "Consumption",
"charge_power": "Charger", "charge_power": "Charger",
"watt_hour": "Wh" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "下载", "download": "下载",
@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "暂停",
"pending": "待办的",
"status": "状态", "status": "状态",
"updated": "已升级", "updated": "已升级",
"cpu": "CPU", "cpu": "CPU",

@ -120,7 +120,7 @@
"grid_power": "電網", "grid_power": "電網",
"home_power": "電源使用率", "home_power": "電源使用率",
"charge_power": "充電", "charge_power": "充電",
"watt_hour": "瓦時 (Wh)" "kilowatt": "kW"
}, },
"flood": { "flood": {
"download": "下載速率", "download": "下載速率",
@ -982,6 +982,9 @@
"name": "名稱", "name": "名稱",
"systems": "Systems", "systems": "Systems",
"up": "在線", "up": "在線",
"down": "離線",
"paused": "擱置中",
"pending": "待下載",
"status": "狀態", "status": "狀態",
"updated": "已更新", "updated": "已更新",
"cpu": "CPU", "cpu": "CPU",

@ -7,7 +7,13 @@ import ErrorBoundary from "components/errorboundry";
import List from "components/bookmarks/list"; import List from "components/bookmarks/list";
import ResolvedIcon from "components/resolvedicon"; import ResolvedIcon from "components/resolvedicon";
export default function BookmarksGroup({ bookmarks, layout, disableCollapse, groupsInitiallyCollapsed }) { export default function BookmarksGroup({
bookmarks,
layout,
disableCollapse,
groupsInitiallyCollapsed,
bookmarksStyle,
}) {
const panel = useRef(); const panel = useRef();
useEffect(() => { useEffect(() => {
@ -18,9 +24,9 @@ export default function BookmarksGroup({ bookmarks, layout, disableCollapse, gro
<div <div
key={bookmarks.name} key={bookmarks.name}
className={classNames( className={classNames(
"bookmark-group", "bookmark-group flex-1 overflow-hidden",
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6",
layout?.header === false ? "flex-1 px-1 -my-1 overflow-hidden" : "flex-1 p-1 overflow-hidden", layout?.header === false ? "px-1" : "p-1 pb-0",
)} )}
> >
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}> <Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>
@ -64,7 +70,7 @@ export default function BookmarksGroup({ bookmarks, layout, disableCollapse, gro
> >
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static> <Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
<ErrorBoundary> <ErrorBoundary>
<List bookmarks={bookmarks.bookmarks} layout={layout} /> <List bookmarks={bookmarks.bookmarks} layout={layout} bookmarksStyle={bookmarksStyle} />
</ErrorBoundary> </ErrorBoundary>
</Disclosure.Panel> </Disclosure.Panel>
</Transition> </Transition>

@ -4,12 +4,17 @@ import classNames from "classnames";
import { SettingsContext } from "utils/contexts/settings"; import { SettingsContext } from "utils/contexts/settings";
import ResolvedIcon from "components/resolvedicon"; import ResolvedIcon from "components/resolvedicon";
export default function Item({ bookmark }) { export default function Item({ bookmark, iconOnly = false }) {
const description = bookmark.description ?? new URL(bookmark.href).hostname; const description = bookmark.description ?? new URL(bookmark.href).hostname;
const { settings } = useContext(SettingsContext); const { settings } = useContext(SettingsContext);
return ( return (
<li key={bookmark.name} id={bookmark.id} className="bookmark" data-name={bookmark.name}> <li
key={bookmark.name}
id={bookmark.id}
className={classNames("bookmark", iconOnly && "grid")}
data-name={bookmark.name}
>
<a <a
href={bookmark.href} href={bookmark.href}
title={bookmark.name} title={bookmark.name}
@ -17,25 +22,37 @@ export default function Item({ bookmark }) {
target={bookmark.target ?? settings.target ?? "_blank"} target={bookmark.target ?? settings.target ?? "_blank"}
className={classNames( className={classNames(
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? "-" : ""}${settings.cardBlur}`, settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? "-" : ""}${settings.cardBlur}`,
"block w-full text-left cursor-pointer transition-all h-15 mb-3 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10", "text-left cursor-pointer transition-all rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10",
iconOnly ? "h-[60px] w-[60px] grid" : "block w-full h-15 mb-3",
)} )}
> >
<div className="flex"> {iconOnly ? (
<div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md bookmark-icon"> <div className="flex items-center justify-center text-theme-700 hover:text-theme-700 dark:text-theme-200 text-xl font-medium rounded-md bookmark-icon py-0.5">
{bookmark.icon && ( {bookmark.icon && (
<div className="flex-shrink-0 w-5 h-5"> <div className="w-7 h-7">
<ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} /> <ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} />
</div> </div>
)} )}
{!bookmark.icon && bookmark.abbr} {!bookmark.icon && bookmark.abbr}
</div> </div>
<div className="flex-1 overflow-hidden flex items-center justify-between rounded-r-md bookmark-text"> ) : (
<div className="pl-3 py-2 text-xs bookmark-name">{bookmark.name}</div> <div className="flex">
<div className="shrink truncate px-2 py-2 text-theme-500 dark:text-theme-300 text-xs bookmark-description"> <div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md bookmark-icon">
{description} {bookmark.icon && (
<div className="flex-shrink-0 w-5 h-5">
<ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} />
</div>
)}
{!bookmark.icon && bookmark.abbr}
</div>
<div className="flex-1 overflow-hidden flex items-center justify-between rounded-r-md bookmark-text">
<div className="pl-3 py-2 text-xs bookmark-name">{bookmark.name}</div>
<div className="shrink truncate px-2 py-2 text-theme-500 dark:text-theme-300 text-xs bookmark-description">
{description}
</div>
</div> </div>
</div> </div>
</div> )}
</a> </a>
</li> </li>
); );

@ -4,16 +4,21 @@ import { columnMap } from "../../utils/layout/columns";
import Item from "components/bookmarks/item"; import Item from "components/bookmarks/item";
export default function List({ bookmarks, layout }) { export default function List({ bookmarks, layout, bookmarksStyle }) {
let classes = layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col bookmark-list";
const style = {};
if (layout?.iconsOnly || bookmarksStyle === "icons") {
classes = "grid gap-2 bookmark-list";
style.gridTemplateColumns = "repeat(auto-fill, minmax(60px, 1fr))";
}
return ( return (
<ul <ul className={classNames(classes, "mb-2", layout?.header === false ? "" : "mt-3")} style={style}>
className={classNames(
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
"mt-3 bookmark-list",
)}
>
{bookmarks.map((bookmark) => ( {bookmarks.map((bookmark) => (
<Item key={`${bookmark.name}-${bookmark.href}`} bookmark={bookmark} /> <Item
key={`${bookmark.name}-${bookmark.href}`}
bookmark={bookmark}
iconOnly={layout?.iconsOnly || bookmarksStyle === "icons"}
/>
))} ))}
</ul> </ul>
); );

@ -129,7 +129,7 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
useEffect(() => { useEffect(() => {
const abortController = new AbortController(); const abortController = new AbortController();
if (searchString.length === 0) setResults([]); if (searchString.trim().length === 0) setResults([]);
else { else {
let newResults = servicesAndBookmarks.filter((r) => { let newResults = servicesAndBookmarks.filter((r) => {
const nameMatch = r.name.toLowerCase().includes(searchString); const nameMatch = r.name.toLowerCase().includes(searchString);

@ -3,17 +3,19 @@ import classNames from "classnames";
import { Disclosure, Transition } from "@headlessui/react"; import { Disclosure, Transition } from "@headlessui/react";
import { MdKeyboardArrowDown } from "react-icons/md"; import { MdKeyboardArrowDown } from "react-icons/md";
import { columnMap } from "../../utils/layout/columns";
import List from "components/services/list"; import List from "components/services/list";
import ResolvedIcon from "components/resolvedicon"; import ResolvedIcon from "components/resolvedicon";
export default function ServicesGroup({ export default function ServicesGroup({
group, group,
services,
layout, layout,
fiveColumns, fiveColumns,
disableCollapse, disableCollapse,
useEqualHeights, useEqualHeights,
groupsInitiallyCollapsed, groupsInitiallyCollapsed,
isSubgroup,
}) { }) {
const panel = useRef(); const panel = useRef();
@ -21,14 +23,18 @@ export default function ServicesGroup({
if (layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) panel.current.style.height = `0`; if (layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) panel.current.style.height = `0`;
}, [layout, groupsInitiallyCollapsed]); }, [layout, groupsInitiallyCollapsed]);
let groupPadding = layout?.header === false ? "px-1" : "p-1 pb-0";
if (isSubgroup) groupPadding = "";
return ( return (
<div <div
key={services.name} key={group.name}
className={classNames( className={classNames(
"services-group", "services-group flex-1",
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "", layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1", groupPadding,
isSubgroup ? "subgroup" : "",
)} )}
> >
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}> <Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>
@ -42,7 +48,7 @@ export default function ServicesGroup({
</div> </div>
)} )}
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium service-group-name"> <h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium service-group-name">
{services.name} {group.name}
</h2> </h2>
<MdKeyboardArrowDown <MdKeyboardArrowDown
className={classNames( className={classNames(
@ -74,7 +80,33 @@ export default function ServicesGroup({
}} }}
> >
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static> <Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
<List group={group} services={services.services} layout={layout} useEqualHeights={useEqualHeights} /> <List
groupName={group.name}
services={group.services}
layout={layout}
useEqualHeights={useEqualHeights}
header={layout?.header !== false}
/>
{group.groups?.length > 0 && (
<div
className={`grid ${
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col"
} gap-2`}
>
{group.groups.map((subgroup) => (
<ServicesGroup
key={subgroup.name}
group={subgroup}
layout={layout?.[subgroup.name]}
fiveColumns={fiveColumns}
disableCollapse={disableCollapse}
useEqualHeights={useEqualHeights}
groupsInitiallyCollapsed={groupsInitiallyCollapsed}
isSubgroup
/>
))}
</div>
)}
</Disclosure.Panel> </Disclosure.Panel>
</Transition> </Transition>
</> </>

@ -12,7 +12,7 @@ import Kubernetes from "widgets/kubernetes/component";
import { SettingsContext } from "utils/contexts/settings"; import { SettingsContext } from "utils/contexts/settings";
import ResolvedIcon from "components/resolvedicon"; import ResolvedIcon from "components/resolvedicon";
export default function Item({ service, group, useEqualHeights }) { export default function Item({ service, groupName, useEqualHeights }) {
const hasLink = service.href && service.href !== "#"; const hasLink = service.href && service.href !== "#";
const { settings } = useContext(SettingsContext); const { settings } = useContext(SettingsContext);
const showStats = service.showStats === false ? false : settings.showStats; const showStats = service.showStats === false ? false : settings.showStats;
@ -86,18 +86,18 @@ export default function Item({ service, group, useEqualHeights }) {
<div <div
className={`absolute top-0 right-0 flex flex-row justify-end ${ className={`absolute top-0 right-0 flex flex-row justify-end ${
statusStyle === "dot" ? "gap-0" : "gap-2 mr-2" statusStyle === "dot" ? "gap-0" : "gap-2 mr-2"
} z-30 service-tags`} } z-10 service-tags`}
> >
{service.ping && ( {service.ping && (
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping"> <div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
<Ping group={group} service={service.name} style={statusStyle} /> <Ping groupName={groupName} serviceName={service.name} style={statusStyle} />
<span className="sr-only">Ping status</span> <span className="sr-only">Ping status</span>
</div> </div>
)} )}
{service.siteMonitor && ( {service.siteMonitor && (
<div className="flex-shrink-0 flex items-center justify-center service-tag service-site-monitor"> <div className="flex-shrink-0 flex items-center justify-center service-tag service-site-monitor">
<SiteMonitor group={group} service={service.name} style={statusStyle} /> <SiteMonitor groupName={groupName} serviceName={service.name} style={statusStyle} />
<span className="sr-only">Site monitor status</span> <span className="sr-only">Site monitor status</span>
</div> </div>
)} )}
@ -154,7 +154,9 @@ export default function Item({ service, group, useEqualHeights }) {
</div> </div>
)} )}
{service.widget && <Widget service={service} />} {service.widgets.map((widget) => (
<Widget widget={widget} service={service} key={widget.index} />
))}
</div> </div>
</li> </li>
); );

@ -4,19 +4,20 @@ import { columnMap } from "../../utils/layout/columns";
import Item from "components/services/item"; import Item from "components/services/item";
export default function List({ group, services, layout, useEqualHeights }) { export default function List({ groupName, services, layout, useEqualHeights, header }) {
return ( return (
<ul <ul
className={classNames( className={classNames(
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col", layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
"mt-3 services-list", header ? "mt-3" : "",
"services-list",
)} )}
> >
{services.map((service) => ( {services.map((service) => (
<Item <Item
key={[service.container, service.app, service.name].filter((s) => s).join("-")} key={[service.container, service.app, service.name].filter((s) => s).join("-")}
service={service} service={service}
group={group} groupName={groupName}
useEqualHeights={layout?.useEqualHeights ?? useEqualHeights} useEqualHeights={layout?.useEqualHeights ?? useEqualHeights}
/> />
))} ))}

@ -1,9 +1,9 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useSWR from "swr"; import useSWR from "swr";
export default function Ping({ group, service, style }) { export default function Ping({ groupName, serviceName, style }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { data, error } = useSWR(`/api/ping?${new URLSearchParams({ group, service }).toString()}`, { const { data, error } = useSWR(`/api/ping?${new URLSearchParams({ groupName, serviceName }).toString()}`, {
refreshInterval: 30000, refreshInterval: 30000,
}); });

@ -1,9 +1,9 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useSWR from "swr"; import useSWR from "swr";
export default function SiteMonitor({ group, service, style }) { export default function SiteMonitor({ groupName, serviceName, style }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { data, error } = useSWR(`/api/siteMonitor?${new URLSearchParams({ group, service }).toString()}`, { const { data, error } = useSWR(`/api/siteMonitor?${new URLSearchParams({ groupName, serviceName }).toString()}`, {
refreshInterval: 30000, refreshInterval: 30000,
}); });

@ -3,22 +3,24 @@ import { useTranslation } from "next-i18next";
import ErrorBoundary from "components/errorboundry"; import ErrorBoundary from "components/errorboundry";
import components from "widgets/components"; import components from "widgets/components";
export default function Widget({ service }) { export default function Widget({ widget, service }) {
const { t } = useTranslation("common"); const { t } = useTranslation("common");
const ServiceWidget = components[service.widget.type]; const ServiceWidget = components[widget.type];
const fullService = Object.apply({}, service);
fullService.widget = widget;
if (ServiceWidget) { if (ServiceWidget) {
return ( return (
<ErrorBoundary> <ErrorBoundary>
<ServiceWidget service={service} /> <ServiceWidget service={fullService} />
</ErrorBoundary> </ErrorBoundary>
); );
} }
return ( return (
<div className="bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center p-1 service-missing"> <div className="bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center p-1 service-missing">
<div className="font-thin text-sm">{t("widget.missing_type", { type: service.widget.type })}</div> <div className="font-thin text-sm">{t("widget.missing_type", { type: widget.type })}</div>
</div> </div>
); );
} }

@ -0,0 +1,47 @@
import useSWR from "swr";
import { FaNetworkWired } from "react-icons/fa";
import { useTranslation } from "next-i18next";
import Resource from "../widget/resource";
import Error from "../widget/error";
export default function Network({ options, refresh = 1500 }) {
const { t } = useTranslation();
// eslint-disable-next-line no-param-reassign
if (options.network === true) options.network = "default";
const { data, error } = useSWR(`/api/widgets/resources?type=network&interfaceName=${options.network}`, {
refreshInterval: refresh,
});
if (error || data?.error) {
return <Error />;
}
if (!data || !data.network || !data.network.rx_sec || !data.network.tx_sec) {
return (
<Resource
icon={FaNetworkWired}
value="- ↑"
label="- ↓"
expandedValue="- ↑"
expandedLabel="- ↓"
percentage="0"
wide
/>
);
}
return (
<Resource
icon={FaNetworkWired}
value={`${t("common.byterate", { value: data.network.tx_sec })} ↑`}
label={`${t("common.byterate", { value: data.network.rx_sec })} ↓`}
expandedValue={`${t("common.bytes", { value: data.network.tx_bytes })} ↑`}
expandedLabel={`${t("common.bytes", { value: data.network.rx_bytes })} ↓`}
expanded={options.expanded}
wide
percentage={(100 * data.network.rx_sec) / (data.network.rx_sec + data.network.tx_sec)}
/>
);
}

@ -6,6 +6,7 @@ import Cpu from "./cpu";
import Memory from "./memory"; import Memory from "./memory";
import CpuTemp from "./cputemp"; import CpuTemp from "./cputemp";
import Uptime from "./uptime"; import Uptime from "./uptime";
import Network from "./network";
export default function Resources({ options }) { export default function Resources({ options }) {
const { expanded, units, diskUnits, tempmin, tempmax } = options; const { expanded, units, diskUnits, tempmin, tempmax } = options;
@ -23,6 +24,7 @@ export default function Resources({ options }) {
<Disk key={disk} options={{ disk }} expanded={expanded} diskUnits={diskUnits} refresh={refresh} /> <Disk key={disk} options={{ disk }} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />
)) ))
: options.disk && <Disk options={options} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />} : options.disk && <Disk options={options} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />}
{options.network && <Network options={options} refresh={refresh} />}
{options.cputemp && ( {options.cputemp && (
<CpuTemp expanded={expanded} units={units} refresh={refresh} tempmin={tempmin} tempmax={tempmax} /> <CpuTemp expanded={expanded} units={units} refresh={refresh} tempmin={tempmin} tempmax={tempmax} />
)} )}

@ -94,6 +94,7 @@ export default function Search({ options }) {
if ( if (
options.showSearchSuggestions && options.showSearchSuggestions &&
(selectedProvider.suggestionUrl || options.suggestionUrl) && // custom providers pass url via options (selectedProvider.suggestionUrl || options.suggestionUrl) && // custom providers pass url via options
query.trim().length > 0 &&
query.trim() !== searchSuggestions[0] query.trim() !== searchSuggestions[0]
) { ) {
fetch(`/api/search/searchSuggestion?query=${encodeURIComponent(query)}&providerName=${selectedProvider.name}`, { fetch(`/api/search/searchSuggestion?query=${encodeURIComponent(query)}&providerName=${selectedProvider.name}`, {

@ -51,7 +51,9 @@ export default function Widget({ options }) {
key={stock.ticker} key={stock.ticker}
className="rounded h-full text-xs px-1 w-[4.75rem] flex flex-col items-center justify-center" className="rounded h-full text-xs px-1 w-[4.75rem] flex flex-col items-center justify-center"
> >
<span className="text-theme-800 dark:text-theme-200 text-xs">{stock.ticker}</span> <span className="text-theme-800 dark:text-theme-200 text-xs">
{stock.ticker.split(":").pop()}
</span>
{!viewingPercentChange ? ( {!viewingPercentChange ? (
<span <span
className={ className={

@ -1,10 +1,13 @@
import classNames from "classnames"; import classNames from "classnames";
import { useContext } from "react";
import WidgetIcon from "./widget_icon"; import WidgetIcon from "./widget_icon";
import PrimaryText from "./primary_text"; import PrimaryText from "./primary_text";
import SecondaryText from "./secondary_text"; import SecondaryText from "./secondary_text";
import Raw from "./raw"; import Raw from "./raw";
import { SettingsContext } from "utils/contexts/settings";
export function getAllClasses(options, additionalClassNames = "") { export function getAllClasses(options, additionalClassNames = "") {
if (options?.style?.header === "boxedWidgets") { if (options?.style?.header === "boxedWidgets") {
if (options?.style?.cardBlur !== undefined) { if (options?.style?.cardBlur !== undefined) {
@ -56,7 +59,17 @@ export function getBottomBlock(children) {
} }
export default function Container({ children = [], options, additionalClassNames = "" }) { export default function Container({ children = [], options, additionalClassNames = "" }) {
return ( const { settings } = useContext(SettingsContext);
return options?.href ? (
<a
href={options.href}
target={options.target ?? settings.target ?? "_blank"}
className={getAllClasses(options, `${additionalClassNames} widget-container`)}
>
{getInnerBlock(children)}
{getBottomBlock(children)}
</a>
) : (
<div className={getAllClasses(options, `${additionalClassNames} widget-container`)}> <div className={getAllClasses(options, `${additionalClassNames} widget-container`)}>
{getInnerBlock(children)} {getInnerBlock(children)}
{getBottomBlock(children)} {getBottomBlock(children)}

@ -10,6 +10,7 @@ export default function Resource({
percentage, percentage,
expanded = false, expanded = false,
additionalClassNames = "", additionalClassNames = "",
wide = false,
}) { }) {
const Icon = icon; const Icon = icon;
@ -18,7 +19,11 @@ export default function Resource({
className={`flex-none flex flex-row items-center mr-3 py-1.5 information-widget-resource ${additionalClassNames}`} className={`flex-none flex flex-row items-center mr-3 py-1.5 information-widget-resource ${additionalClassNames}`}
> >
<Icon className="text-theme-800 dark:text-theme-200 w-5 h-5 resource-icon" /> <Icon className="text-theme-800 dark:text-theme-200 w-5 h-5 resource-icon" />
<div className={`flex flex-col ml-3 text-left min-w-[85px] ${expanded ? " expanded" : ""}`}> <div
className={`flex flex-col ml-3 text-left ${expanded ? " expanded" : ""} ${
wide ? " min-w-[120px]" : "min-w-[85px]"
}`}
>
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between"> <div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
<div className="pl-0.5">{value}</div> <div className="pl-0.5">{value}</div>
<div className="pr-1">{label}</div> <div className="pr-1">{label}</div>

@ -4,12 +4,10 @@ export default function Document() {
return ( return (
<Html> <Html>
<Head> <Head>
<meta
name="description"
content="A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations."
/>
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<link rel="manifest" href="/site.webmanifest?v=4" crossOrigin="use-credentials" /> <link rel="manifest" href="/site.webmanifest?v=4" crossOrigin="use-credentials" />
<link rel="preload" href="/api/config/custom.css" as="style" />
<link rel="stylesheet" href="/api/config/custom.css" /> {/* eslint-disable-line @next/next/no-css-tags */}
</Head> </Head>
<body> <body>
<Main /> <Main />

@ -6,10 +6,10 @@ import createLogger from "utils/logger";
const logger = createLogger("ping"); const logger = createLogger("ping");
export default async function handler(req, res) { export default async function handler(req, res) {
const { group, service } = req.query; const { groupName, serviceName } = req.query;
const serviceItem = await getServiceItem(group, service); const serviceItem = await getServiceItem(groupName, serviceName);
if (!serviceItem) { if (!serviceItem) {
logger.debug(`No service item found for group ${group} named ${service}`); logger.debug(`No service item found for group ${groupName} named ${serviceName}`);
return res.status(400).send({ return res.status(400).send({
error: "Unable to find service, see log for details.", error: "Unable to find service, see log for details.",
}); });

@ -9,8 +9,8 @@ const logger = createLogger("servicesProxy");
export default async function handler(req, res) { export default async function handler(req, res) {
try { try {
const { service, group } = req.query; const { service, group, index } = req.query;
const serviceWidget = await getServiceWidget(group, service); const serviceWidget = await getServiceWidget(group, service, index);
let type = serviceWidget?.type; let type = serviceWidget?.type;
// exceptions // exceptions
@ -41,7 +41,7 @@ export default async function handler(req, res) {
const endpoint = mapping?.endpoint; const endpoint = mapping?.endpoint;
const endpointProxy = mapping?.proxyHandler || serviceProxyHandler; const endpointProxy = mapping?.proxyHandler || serviceProxyHandler;
if (mapping.method && mapping.method !== req.method) { if (mapping?.method && mapping.method !== req.method) {
logger.debug("Unsupported method: %s", req.method); logger.debug("Unsupported method: %s", req.method);
return res.status(403).json({ error: "Unsupported method" }); return res.status(403).json({ error: "Unsupported method" });
} }

@ -7,10 +7,10 @@ import { httpProxy } from "utils/proxy/http";
const logger = createLogger("siteMonitor"); const logger = createLogger("siteMonitor");
export default async function handler(req, res) { export default async function handler(req, res) {
const { group, service } = req.query; const { groupName, serviceName } = req.query;
const serviceItem = await getServiceItem(group, service); const serviceItem = await getServiceItem(groupName, serviceName);
if (!serviceItem) { if (!serviceItem) {
logger.debug(`No service item found for group ${group} named ${service}`); logger.debug(`No service item found for group ${groupName} named ${serviceName}`);
return res.status(400).send({ return res.status(400).send({
error: "Unable to find service, see log for details.", error: "Unable to find service, see log for details.",
}); });

@ -7,7 +7,7 @@ const logger = createLogger("resources");
const si = require("systeminformation"); const si = require("systeminformation");
export default async function handler(req, res) { export default async function handler(req, res) {
const { type, target } = req.query; const { type, target, interfaceName = "default" } = req.query;
if (type === "cpu") { if (type === "cpu") {
const load = await si.currentLoad(); const load = await si.currentLoad();
@ -57,6 +57,32 @@ export default async function handler(req, res) {
}); });
} }
if (type === "network") {
let networkData = await si.networkStats();
let interfaceDefault;
logger.debug("networkData:", JSON.stringify(networkData));
if (interfaceName && interfaceName !== "default") {
networkData = networkData.filter((network) => network.iface === interfaceName).at(0);
if (!networkData) {
return res.status(404).json({
error: "Interface not found",
});
}
} else {
interfaceDefault = await si.networkInterfaceDefault();
networkData = networkData.filter((network) => network.iface === interfaceDefault).at(0);
if (!networkData) {
return res.status(404).json({
error: "Default interface not found",
});
}
}
return res.status(200).json({
network: networkData,
interface: interfaceName !== "default" ? interfaceName : interfaceDefault,
});
}
return res.status(400).json({ return res.status(400).json({
error: "invalid type", error: "invalid type",
}); });

@ -1,9 +1,14 @@
import cachedFetch from "utils/proxy/cached-fetch"; import cachedFetch from "utils/proxy/cached-fetch";
import { getSettings } from "utils/config/config"; import { getSettings } from "utils/config/config";
import createLogger from "utils/logger";
const logger = createLogger("stocks");
export default async function handler(req, res) { export default async function handler(req, res) {
const { watchlist, provider, cache } = req.query; const { watchlist, provider, cache } = req.query;
logger.debug("Stocks API request: %o", { watchlist, provider, cache });
if (!watchlist) { if (!watchlist) {
return res.status(400).json({ error: "Missing watchlist" }); return res.status(400).json({ error: "Missing watchlist" });
} }
@ -56,6 +61,7 @@ export default async function handler(req, res) {
// Finnhub free accounts allow up to 60 calls/minute // Finnhub free accounts allow up to 60 calls/minute
// https://finnhub.io/pricing // https://finnhub.io/pricing
const { c, dp } = await cachedFetch(apiUrl, cache || 1); const { c, dp } = await cachedFetch(apiUrl, cache || 1);
logger.debug("Finnhub API response for %s: %o", ticker, { c, dp });
// API sometimes returns 200, but values returned are `null` // API sometimes returns 200, but values returned are `null`
if (c === null || dp === null) { if (c === null || dp === null) {

@ -291,8 +291,7 @@ function Home({ initialSettings }) {
group.services ? ( group.services ? (
<ServicesGroup <ServicesGroup
key={group.name} key={group.name}
group={group.name} group={group}
services={group}
layout={settings.layout?.[group.name]} layout={settings.layout?.[group.name]}
fiveColumns={settings.fiveColumns} fiveColumns={settings.fiveColumns}
disableCollapse={settings.disableCollapse} disableCollapse={settings.disableCollapse}
@ -316,8 +315,7 @@ function Home({ initialSettings }) {
{serviceGroups.map((group) => ( {serviceGroups.map((group) => (
<ServicesGroup <ServicesGroup
key={group.name} key={group.name}
group={group.name} group={group}
services={group}
layout={settings.layout?.[group.name]} layout={settings.layout?.[group.name]}
fiveColumns={settings.fiveColumns} fiveColumns={settings.fiveColumns}
disableCollapse={settings.disableCollapse} disableCollapse={settings.disableCollapse}
@ -335,6 +333,7 @@ function Home({ initialSettings }) {
layout={settings.layout?.[group.name]} layout={settings.layout?.[group.name]}
disableCollapse={settings.disableCollapse} disableCollapse={settings.disableCollapse}
groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed} groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed}
bookmarksStyle={settings.bookmarksStyle}
/> />
))} ))}
</div> </div>
@ -352,13 +351,21 @@ function Home({ initialSettings }) {
settings.useEqualHeights, settings.useEqualHeights,
settings.cardBlur, settings.cardBlur,
settings.groupsInitiallyCollapsed, settings.groupsInitiallyCollapsed,
settings.bookmarksStyle,
initialSettings.layout, initialSettings.layout,
]); ]);
return ( return (
<> <>
<Head> <Head>
<title>{settings.title || "Homepage"}</title> <title>{initialSettings.title || "Homepage"}</title>
<meta
name="description"
content={
initialSettings.description ||
"A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations."
}
/>
{settings.base && <base href={settings.base} />} {settings.base && <base href={settings.base} />}
{settings.favicon ? ( {settings.favicon ? (
<> <>
@ -376,8 +383,6 @@ function Home({ initialSettings }) {
)} )}
<meta name="msapplication-TileColor" content={themes[settings.color || "slate"][settings.theme || "dark"]} /> <meta name="msapplication-TileColor" content={themes[settings.color || "slate"][settings.theme || "dark"]} />
<meta name="theme-color" content={themes[settings.color || "slate"][settings.theme || "dark"]} /> <meta name="theme-color" content={themes[settings.color || "slate"][settings.theme || "dark"]} />
<link rel="preload" href="/api/config/custom.css" as="style" />
<link rel="stylesheet" href="/api/config/custom.css" /> {/* eslint-disable-line @next/next/no-css-tags */}
</Head> </Head>
<Script src="/api/config/custom.js" /> <Script src="/api/config/custom.js" />
@ -454,6 +459,7 @@ function Home({ initialSettings }) {
} }
export default function Wrapper({ initialSettings, fallback }) { export default function Wrapper({ initialSettings, fallback }) {
const { theme } = useContext(ThemeContext);
const wrappedStyle = {}; const wrappedStyle = {};
let backgroundBlur = false; let backgroundBlur = false;
let backgroundSaturate = false; let backgroundSaturate = false;
@ -484,8 +490,9 @@ export default function Wrapper({ initialSettings, fallback }) {
id="page_wrapper" id="page_wrapper"
className={classNames( className={classNames(
"relative", "relative",
initialSettings.theme && initialSettings.theme, theme && theme,
initialSettings.color && `theme-${initialSettings.color}`, initialSettings.color && `theme-${initialSettings.color}`,
theme === "dark" ? "scheme-dark" : "scheme-light",
)} )}
> >
<div <div

@ -1,6 +1,6 @@
--- ---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://gethomepage.dev/configs/services # https://gethomepage.dev/configs/services/
- My First Group: - My First Group:
- My First Service: - My First Service:

@ -1,6 +1,6 @@
--- ---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://gethomepage.dev/configs/settings # https://gethomepage.dev/configs/settings/
providers: providers:
openweathermap: openweathermapapikey openweathermap: openweathermapapikey

@ -1,6 +1,6 @@
--- ---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://gethomepage.dev/configs/service-widgets # https://gethomepage.dev/configs/info-widgets/
- resources: - resources:
cpu: true cpu: true

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save