mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-26 23:52:10 +08:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
805f119a25 | ||
|
|
74f76e2656 | ||
|
|
4d38222ba0 | ||
|
|
b9b7c482d4 | ||
|
|
1c5d9ca223 | ||
|
|
8fba3eee1d | ||
|
|
0d6aabc737 | ||
|
|
b124e12509 | ||
|
|
0a23bfe263 | ||
|
|
9fa38c9ba8 | ||
|
|
9484a9ff56 | ||
|
|
ed928bfa25 | ||
|
|
a996d43bbf | ||
|
|
6ce67b5ab8 | ||
|
|
5d531b11e7 | ||
|
|
eccd96a775 | ||
|
|
407376b3b7 | ||
|
|
d6188e52fe | ||
|
|
0a1a3bb8c2 | ||
|
|
16b45a313e | ||
|
|
1d820b02cb | ||
|
|
55a434c039 | ||
|
|
7831da6f6a | ||
|
|
bebecacc89 | ||
|
|
0d7072beea | ||
|
|
95ab0706b6 | ||
|
|
a522153df2 | ||
|
|
1804d0af0f | ||
|
|
9d16e280cd |
7
.github/DISCUSSION_TEMPLATE/support.yml
vendored
7
.github/DISCUSSION_TEMPLATE/support.yml
vendored
@@ -1,4 +1,11 @@
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### ⚠️ Before opening a discussion:
|
||||
|
||||
- [Check the troubleshooting guide](https://gethomepage.dev/latest/troubleshooting/).
|
||||
- [Search existing issues](https://github.com/gethomepage/homepage/search?q=&type=issues) [and discussions](https://github.com/gethomepage/homepage/search?q=&type=discussions).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -13,7 +13,7 @@ body:
|
||||
attributes:
|
||||
label: Before submitting, please confirm the following
|
||||
options:
|
||||
- label: I confirm this was discussed, and the maintainers suggest I open an issue (note that AI bots are not maintainers).
|
||||
- label: I confirm this was discussed, and the maintainers asked that I open an issue.
|
||||
required: true
|
||||
- label: I am aware that if I create this issue without a discussion, it will be removed without a response.
|
||||
required: true
|
||||
|
||||
@@ -36,7 +36,7 @@ Inside of the service you'd like to connect to a pod:
|
||||
|
||||
The `app` field is used to create a label selector, in this example case it would match pods with the label: `app.kubernetes.io/name=emby`.
|
||||
|
||||
Sometimes this is insufficient for complex or atypical application deployments. In these cases, the `pod-selector` field can be used. Any field selector can be used with it, so it allows for some very powerful selection capabilities.
|
||||
Sometimes this is insufficient for complex or atypical application deployments. In these cases, the `podSelector` field can be used. Any field selector can be used with it, so it allows for some very powerful selection capabilities.
|
||||
|
||||
For instance, it can be utilized to roll multiple underlying deployments under one application to see a high-level aggregate:
|
||||
|
||||
@@ -47,7 +47,7 @@ For instance, it can be utilized to roll multiple underlying deployments under o
|
||||
description: Matrix Synapse Powered Chat
|
||||
app: matrix-element
|
||||
namespace: comms
|
||||
pod-selector: >-
|
||||
podSelector: >-
|
||||
app.kubernetes.io/instance in (
|
||||
matrix-element,
|
||||
matrix-media-repo,
|
||||
@@ -58,7 +58,7 @@ For instance, it can be utilized to roll multiple underlying deployments under o
|
||||
|
||||
!!! note
|
||||
|
||||
A blank string as a pod-selector does not deactivate it, but will actually select all pods in the namespace. This is a useful way to capture the resource usage of a complex application siloed to a single namespace, like Longhorn.
|
||||
A blank string as a podSelector does not deactivate it, but will actually select all pods in the namespace. This is a useful way to capture the resource usage of a complex application siloed to a single namespace, like Longhorn.
|
||||
|
||||
## Automatic Service Discovery
|
||||
|
||||
|
||||
@@ -34,13 +34,6 @@ These companies help the Homepage project by providing services, tools, and reso
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 16px;">
|
||||
<a href="https://glimelab.ai/"><img src="https://framerusercontent.com/images/28KxmT1G06GrFM8TKeNAC03QIms.svg" alt="Crowdin" style="max-width: 100%; height: 64px; display: block;" /></a>
|
||||
<p>
|
||||
GlimeLab provides the project with the awesome AI chatbot here and on GitHub and Discord.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 16px;">
|
||||
<a href="https://www.jetbrains.com/"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.png" alt="JetBrains" style="max-width: 100%; height: 64px; display: block;" /></a>
|
||||
<p>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
var glimeScript;
|
||||
var glimeStyles = [];
|
||||
document$.subscribe(function () {
|
||||
if (!glimeScript) {
|
||||
glimeScript = document.createElement("script");
|
||||
glimeScript.setAttribute("src", "https://cdn.glimelab.ai/widget/1.0.0/widget.js");
|
||||
glimeScript.setAttribute("onload", "onGlimeLoad()");
|
||||
document.head.appendChild(glimeScript);
|
||||
} else {
|
||||
var newGlimeStyle = document.createElement("style");
|
||||
document.head.appendChild(newGlimeStyle);
|
||||
var i = 0;
|
||||
glimeStyles.forEach((rule) => {
|
||||
newGlimeStyle.sheet.insertRule(rule.cssText, i);
|
||||
i++;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
onGlimeLoad = () => {
|
||||
window.glime.init("Bl3mlvfCnTnRm5");
|
||||
setTimeout(() => {
|
||||
const sheets = document.styleSheets;
|
||||
[...sheets].forEach((sheet) => {
|
||||
if (!sheet.href) {
|
||||
[...sheet.cssRules].forEach((rule) => {
|
||||
if (!rule || rule.href || !rule.selectorText) return;
|
||||
if (rule.selectorText.indexOf(".css-") === 0 || rule.selectorText.indexOf("glime") > -1) {
|
||||
glimeStyles.push(rule);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
};
|
||||
@@ -14,6 +14,16 @@
|
||||
--md-default-fg-color: white;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="default"] .md-search__inner {
|
||||
--md-default-fg-color--light: gray;
|
||||
--md-default-fg-color--lighter: black;
|
||||
--md-default-bg-color: hsla(0, 0%, 100%, 0.9);
|
||||
}
|
||||
|
||||
[data-md-color-scheme="default"] .md-search__inner .md-search__input {
|
||||
color: var(--md-default-fg-color--light);
|
||||
}
|
||||
|
||||
[data-md-toggle="search"]:not(:checked) ~ .md-header .md-search__form::after {
|
||||
position: absolute;
|
||||
top: 0.3rem;
|
||||
@@ -35,10 +45,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
#glimeRoot * {
|
||||
font-family: var(--md-text-font) !important;
|
||||
}
|
||||
|
||||
#carbonads {
|
||||
margin-top: 10px;
|
||||
}
|
||||
@@ -92,11 +98,11 @@
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: transparent !important;
|
||||
background-image: url("https://raw.githubusercontent.com/gethomepage/homepage/main/docs/assets/blossom_valley.jpg");
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
background-position: center;
|
||||
background-color: transparent;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
@@ -152,6 +158,12 @@ body[data-md-color-scheme="default"] {
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.md-header:has(.md-search-result__item),
|
||||
.md-header:has(.md-search__input.focus-visible) {
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
.md-footer-meta {
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -212,7 +224,7 @@ body[data-md-color-scheme="default"] {
|
||||
}
|
||||
|
||||
.md-search__scrollwrap {
|
||||
background-color: hsla(0, 0%, 0%, 0.3);
|
||||
background-color: hsla(0, 0%, 0%, 0.8);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ hide:
|
||||
- navigation
|
||||
---
|
||||
|
||||
## Introducing the Homepage AI Bot
|
||||
|
||||
Thanks to the generous folks at [Glime](https://glimelab.ai), Homepage is now equipped with a pretty clever AI-powered bot. The bot has full knowledge of our docs, GitHub issues and discussions and is great at answering specific questions about setting up your Homepage. To use the bot, just hit the 'Ask AI' button on any page in our docs, [open a GitHub discussion](https://github.com/gethomepage/homepage/discussions) or check out the [#ai-support channel on Discord](https://discord.com/channels/1019316731635834932/1177885603552038993)!
|
||||
|
||||
## General Troubleshooting Tips
|
||||
|
||||
- For API errors, clicking the "API Error Information" button in the widget will usually show some helpful information as to whether the issue is reaching the service host, an authentication issue, etc.
|
||||
|
||||
@@ -6,6 +6,8 @@ icon: material/widgets
|
||||
|
||||
Homepage has two types of widgets: info and service. Below we'll cover each type and how to configure them.
|
||||
|
||||
The left navigation of this site contains links to all available widgets.
|
||||
|
||||
## Service Widgets
|
||||
|
||||
Service widgets are used to display the status of a service, often a web service or API. Services (and their widgets) are defined in your `services.yaml` file. Here's an example:
|
||||
|
||||
@@ -2,3 +2,18 @@
|
||||
title: Info Widgets
|
||||
description: Homepage info widgets.
|
||||
---
|
||||
|
||||
You can also find a list of all available info widgets in the sidebar navigation.
|
||||
|
||||
- [Date & Time](datetime.md)
|
||||
- [Glances](glances.md)
|
||||
- [Greeting](greeting.md)
|
||||
- [Kubernetes](kubernetes.md)
|
||||
- [Logo](logo.md)
|
||||
- [Longhorn](longhorn.md)
|
||||
- [OpenMeteo](openmeteo.md)
|
||||
- [OpenWeatherMap](openweathermap.md)
|
||||
- [Resources](resources.md)
|
||||
- [Search](search.md)
|
||||
- [Stocks](stocks.md)
|
||||
- [UniFi Controller](unifi_controller.md)
|
||||
|
||||
@@ -9,6 +9,8 @@ The disk path is the path reported by `df` (Mounted On), or the mount point of t
|
||||
|
||||
The cpu and memory resource information are the container's usage while [glances](glances.md) displays statistics for the host machine on which it is installed.
|
||||
|
||||
The resources widget primarily relies on a popular tool called [systeminformation](https://systeminformation.io). Thus, any limitiations of that software apply, for example, BRTFS RAID is not supported for the disk usage. In this case users may want to use the [glances widget](glances.md) instead.
|
||||
|
||||
_Note: unfortunately, the package used for getting CPU temp ([systeminformation](https://systeminformation.io)) is not compatible with some setups and will not report any value(s) for CPU temp._
|
||||
|
||||
**Any disk you wish to access must be mounted to your container as a volume.**
|
||||
|
||||
@@ -9,7 +9,9 @@ You can display general connectivity status from your Unifi (Network) Controller
|
||||
|
||||
An optional 'site' parameter can be supplied, if it is not the widget will use the default site for the controller.
|
||||
|
||||
_Note: If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache._
|
||||
!!! hint
|
||||
|
||||
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache.
|
||||
|
||||
<img width="162" alt="unifi_infowidget" src="https://user-images.githubusercontent.com/4887959/197706832-f5a8706b-7282-4892-a666-b7d999752562.png">
|
||||
|
||||
|
||||
17
docs/widgets/services/frigate.md
Normal file
17
docs/widgets/services/frigate.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Frigate
|
||||
description: Frigate Widget Configuration
|
||||
---
|
||||
|
||||
Learn more about [Frigate](https://frigate.video/).
|
||||
|
||||
Allowed fields: `["cameras", "uptime", "version"]`.
|
||||
|
||||
A recent event listing is disabled by default, but can be enabled with the `enableRecentEvents` option.
|
||||
|
||||
```yaml
|
||||
widget:
|
||||
type: frigate
|
||||
url: http://frigate.host.or.ip:port
|
||||
enableRecentEvents: true # Optional, defaults to false
|
||||
```
|
||||
@@ -2,3 +2,127 @@
|
||||
title: Service Widgets
|
||||
description: Homepage service widgets.
|
||||
---
|
||||
|
||||
You can also find a list of all available service widgets in the sidebar navigation.
|
||||
|
||||
- [Adguard Home](adguard-home.md)
|
||||
- [Atsumeru](atsumeru.md)
|
||||
- [Audiobookshelf](audiobookshelf.md)
|
||||
- [Authentik](authentik.md)
|
||||
- [Autobrr](autobrr.md)
|
||||
- [Azure DevOps](azuredevops.md)
|
||||
- [Bazarr](bazarr.md)
|
||||
- [Caddy](caddy.md)
|
||||
- [Calendar](calendar.md)
|
||||
- [Calibre-Web](calibre-web.md)
|
||||
- [ChangeDetection.io](changedetectionio.md)
|
||||
- [Channels DVR Server](channelsdvrserver.md)
|
||||
- [Cloudflared](cloudflared.md)
|
||||
- [Coin Market Cap](coin-market-cap.md)
|
||||
- [CrowdSec](crowdsec.md)
|
||||
- [Custom API](customapi.md)
|
||||
- [Deluge](deluge.md)
|
||||
- [DiskStation](diskstation.md)
|
||||
- [DownloadStation](downloadstation.md)
|
||||
- [Emby](emby.md)
|
||||
- [ESPHome](esphome.md)
|
||||
- [EVCC](evcc.md)
|
||||
- [Fileflows](fileflows.md)
|
||||
- [Flood](flood.md)
|
||||
- [FreshRSS](freshrss.md)
|
||||
- [Frigate](frigate.md)
|
||||
- [Fritz!Box](fritzbox.md)
|
||||
- [GameDig](gamedig.md)
|
||||
- [Gatus](gatus.md)
|
||||
- [Ghostfolio](ghostfolio.md)
|
||||
- [Gitea](gitea.md)
|
||||
- [Glances](glances.md)
|
||||
- [Gluetun](gluetun.md)
|
||||
- [Gotify](gotify.md)
|
||||
- [Grafana](grafana.md)
|
||||
- [HDHomeRun](hdhomerun.md)
|
||||
- [Healthchecks](healthchecks.md)
|
||||
- [Home Assistant](homeassistant.md)
|
||||
- [HomeBox](homebox.md)
|
||||
- [Homebridge](homebridge.md)
|
||||
- [iFrame](iframe.md)
|
||||
- [Immich](immich.md)
|
||||
- [Jackett](jackett.md)
|
||||
- [JDownloader](jdownloader.md)
|
||||
- [Jellyfin](jellyfin.md)
|
||||
- [Jellyseerr](jellyseerr.md)
|
||||
- [Kavita](kavita.md)
|
||||
- [Komga](komga.md)
|
||||
- [Kopia](kopia.md)
|
||||
- [Lidarr](lidarr.md)
|
||||
- [Linkwarden](linkwarden.md)
|
||||
- [Mastodon](mastodon.md)
|
||||
- [Mealie](mealie.md)
|
||||
- [Medusa](medusa.md)
|
||||
- [Mikrotik](mikrotik.md)
|
||||
- [Minecraft](minecraft.md)
|
||||
- [Miniflux](miniflux.md)
|
||||
- [MJpeg](mjpeg.md)
|
||||
- [Moonraker](moonraker.md)
|
||||
- [Mylar](mylar.md)
|
||||
- [MySpeed](myspeed.md)
|
||||
- [Navidrome](navidrome.md)
|
||||
- [NetAlertX](netalertx.md)
|
||||
- [Netdata](netdata.md)
|
||||
- [Nextcloud](nextcloud.md)
|
||||
- [NextDNS](nextdns.md)
|
||||
- [NGINX Proxy Manager](nginx-proxy-manager.md)
|
||||
- [NZBGet](nzbget.md)
|
||||
- [OctoPrint](octoprint.md)
|
||||
- [Omada](omada.md)
|
||||
- [Ombi](ombi.md)
|
||||
- [OpenDTU](opendtu.md)
|
||||
- [OpenMediaVault](openmediavault.md)
|
||||
- [OpenWRT](openwrt.md)
|
||||
- [OPNsense](opnsense.md)
|
||||
- [Overseerr](overseerr.md)
|
||||
- [PaperlessNGX](paperlessngx.md)
|
||||
- [Peanut](peanut.md)
|
||||
- [pfSense](pfsense.md)
|
||||
- [PhotoPrism](photoprism.md)
|
||||
- [Pi-hole](pihole.md)
|
||||
- [PlantIt](plantit.md)
|
||||
- [Plex & Tautulli](plex-tautulli.md)
|
||||
- [Plex](plex.md)
|
||||
- [Portainer](portainer.md)
|
||||
- [Prometheus](prometheus.md)
|
||||
- [Prowlarr](prowlarr.md)
|
||||
- [Proxmox](proxmox.md)
|
||||
- [Proxmox Backup Server](proxmoxbackupserver.md)
|
||||
- [Pterodactyl](pterodactyl.md)
|
||||
- [PyLoad](pyload.md)
|
||||
- [qBittorrent](qbittorrent.md)
|
||||
- [QNAP](qnap.md)
|
||||
- [Radarr](radarr.md)
|
||||
- [Readarr](readarr.md)
|
||||
- [ROMM](romm.md)
|
||||
- [ruTorrent](rutorrent.md)
|
||||
- [SABnzbd](sabnzbd.md)
|
||||
- [Scrutiny](scrutiny.md)
|
||||
- [Sonarr](sonarr.md)
|
||||
- [Speedtest Tracker](speedtest-tracker.md)
|
||||
- [Stash](stash.md)
|
||||
- [Stocks](stocks.md)
|
||||
- [SwagDashboard](swagdashboard.md)
|
||||
- [Syncthing Relay Server](syncthing-relay-server.md)
|
||||
- [Tailscale](tailscale.md)
|
||||
- [Tandoor](tandoor.md)
|
||||
- [TDarr](tdarr.md)
|
||||
- [Traefik](traefik.md)
|
||||
- [Transmission](transmission.md)
|
||||
- [TrueNAS](truenas.md)
|
||||
- [TubeArchivist](tubearchivist.md)
|
||||
- [UniFi Controller](unifi-controller.md)
|
||||
- [Unmanic](unmanic.md)
|
||||
- [Uptime Kuma](uptime-kuma.md)
|
||||
- [UptimeRobot](uptimerobot.md)
|
||||
- [UrBackup](urbackup.md)
|
||||
- [Watchtower](watchtower.md)
|
||||
- [WGEasy](wgeasy.md)
|
||||
- [WhatsUpDocker](whatsupdocker.md)
|
||||
- [xTeVe](xteve.md)
|
||||
|
||||
15
docs/widgets/services/linkwarden.md
Normal file
15
docs/widgets/services/linkwarden.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Linkwarden
|
||||
description: Linkwarden Widget Configuration
|
||||
---
|
||||
|
||||
Learn more about [Linkwarden](https://linkwarden.app/).
|
||||
|
||||
Allowed fields: `["links", "collections", "tags"]`.
|
||||
|
||||
```yaml
|
||||
widget:
|
||||
type: linkwarden
|
||||
url: http://linkwarden.host.or.ip
|
||||
key: myApiKeyHere # On your Linkwarden install, go to Settings > Access Tokens. Generate a token.
|
||||
```
|
||||
@@ -9,7 +9,7 @@ This widget requires the installation of the [pfsense-api](https://github.com/ja
|
||||
|
||||
Once pfSense API is installed, you can set the API to be read-only in System > API > Settings.
|
||||
|
||||
There are two currently supported authentication modes: 'Local Database' and 'API Token'. For 'Local Database', use `username` and `password` with the credentials of an admin user. For 'API Token', utilize the `headers` parameter with `client_token` and `client_id` obtained from pfSense as shown below. Do not use both headers and username / password.
|
||||
There are two currently supported authentication modes: 'Local Database' and 'API Key' (v2) / 'API Token' (v1). For 'Local Database', use `username` and `password` with the credentials of an admin user. The specifics of using the API key / token depend on the version of the pfSense API, see the config examples below. Do not use both headers and username / password.
|
||||
|
||||
The interface to monitor is defined by updating the `wan` parameter. It should be referenced as it is shown under Interfaces > Assignments in pfSense.
|
||||
|
||||
@@ -17,14 +17,25 @@ Load is returned instead of cpu utilization. This is a limitation in the pfSense
|
||||
|
||||
Allowed fields: `["load", "memory", "temp", "wanStatus", "wanIP", "disk"]` (maximum of 4)
|
||||
|
||||
For version 2:
|
||||
|
||||
```yaml
|
||||
widget:
|
||||
type: pfsense
|
||||
url: http://pfsense.host.or.ip:port
|
||||
username: user # optional, or API token
|
||||
password: pass # optional, or API token
|
||||
username: user # optional, or API key
|
||||
password: pass # optional, or API key
|
||||
headers: # optional, or username/password
|
||||
Authorization: client_id client_token
|
||||
X-API-Key: key
|
||||
wan: igb0
|
||||
version: 2 # optional, defaults to 1 for api v1
|
||||
fields: ["load", "memory", "temp", "wanStatus"] # optional
|
||||
```
|
||||
|
||||
For version 1:
|
||||
|
||||
```yaml
|
||||
headers: # optional, or username/password
|
||||
Authorization: client_id client_token # obtained from pfSense API
|
||||
version: 1
|
||||
```
|
||||
|
||||
@@ -5,7 +5,7 @@ description: Tube Archivist Widget Configuration
|
||||
|
||||
Learn more about [Tube Archivist](https://github.com/tubearchivist/tubearchivist).
|
||||
|
||||
Requires API key.
|
||||
You must be running at least version 0.4.4
|
||||
|
||||
Allowed fields: `["downloads", "videos", "channels", "playlists"]`.
|
||||
|
||||
@@ -13,5 +13,5 @@ Allowed fields: `["downloads", "videos", "channels", "playlists"]`.
|
||||
widget:
|
||||
type: tubearchivist
|
||||
url: http://tubearchivist.host.or.ip
|
||||
key: apikeyapikeyapikeyapikeyapikey
|
||||
key: tubearchivistapikey
|
||||
```
|
||||
|
||||
@@ -11,9 +11,11 @@ You can display general connectivity status from your Unifi (Network) Controller
|
||||
|
||||
An optional 'site' parameter can be supplied, if it is not the widget will use the default site for the controller.
|
||||
|
||||
Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "wlan_users", "wlan_devices"]` (maximum of four).
|
||||
Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "wlan_users", "wlan_devices"]` (maximum of four). Fields unsupported by the unifi device will not be shown.
|
||||
|
||||
Note that fields unsupported by the unifi device will not be shown.
|
||||
!!! hint
|
||||
|
||||
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache.
|
||||
|
||||
```yaml
|
||||
widget:
|
||||
|
||||
@@ -55,6 +55,7 @@ nav:
|
||||
- widgets/services/fileflows.md
|
||||
- widgets/services/flood.md
|
||||
- widgets/services/freshrss.md
|
||||
- widgets/services/frigate.md
|
||||
- widgets/services/fritzbox.md
|
||||
- widgets/services/gamedig.md
|
||||
- widgets/services/gatus.md
|
||||
@@ -79,6 +80,7 @@ nav:
|
||||
- widgets/services/komga.md
|
||||
- widgets/services/kopia.md
|
||||
- widgets/services/lidarr.md
|
||||
- widgets/services/linkwarden.md
|
||||
- widgets/services/mastodon.md
|
||||
- widgets/services/mealie.md
|
||||
- widgets/services/medusa.md
|
||||
@@ -225,8 +227,6 @@ theme:
|
||||
|
||||
extra_css:
|
||||
- "stylesheets/extra.css"
|
||||
extra_javascript:
|
||||
- "scripts/extra.js"
|
||||
|
||||
extra:
|
||||
version:
|
||||
|
||||
114
package-lock.json
generated
114
package-lock.json
generated
@@ -26,7 +26,7 @@
|
||||
"next-i18next": "^12.1.0",
|
||||
"ping": "^0.4.4",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"raw-body": "^2.5.2",
|
||||
"raw-body": "^3.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^11.18.6",
|
||||
@@ -34,9 +34,9 @@
|
||||
"recharts": "^2.12.6",
|
||||
"rrule": "^2.8.1",
|
||||
"swr": "^1.3.0",
|
||||
"systeminformation": "^5.22.7",
|
||||
"systeminformation": "^5.23.2",
|
||||
"tough-cookie": "^4.1.3",
|
||||
"urbackup-server-api": "^0.8.9",
|
||||
"urbackup-server-api": "^0.52.0",
|
||||
"winston": "^3.11.0",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
@@ -49,7 +49,7 @@
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"postcss": "^8.4.38",
|
||||
@@ -638,6 +638,18 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/core": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
|
||||
"integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/eslint-patch": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz",
|
||||
@@ -1230,17 +1242,17 @@
|
||||
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
|
||||
},
|
||||
"node_modules/async-mutex": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz",
|
||||
"integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==",
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz",
|
||||
"integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.1"
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/async-mutex/node_modules/tslib": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
@@ -2855,21 +2867,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
|
||||
"integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
|
||||
"integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"prettier-linter-helpers": "^1.0.0"
|
||||
"prettier-linter-helpers": "^1.0.0",
|
||||
"synckit": "^0.9.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint-plugin-prettier"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=7.28.0",
|
||||
"prettier": ">=2.0.0"
|
||||
"@types/eslint": ">=8.0.0",
|
||||
"eslint": ">=8.0.0",
|
||||
"eslint-config-prettier": "*",
|
||||
"prettier": ">=3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/eslint": {
|
||||
"optional": true
|
||||
},
|
||||
"eslint-config-prettier": {
|
||||
"optional": true
|
||||
}
|
||||
@@ -5695,30 +5716,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
|
||||
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"iconv-lite": "0.6.3",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body/node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
@@ -6750,10 +6760,32 @@
|
||||
"react": "^16.11.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz",
|
||||
"integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.1.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/synckit/node_modules/tslib": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/systeminformation": {
|
||||
"version": "5.22.7",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.7.tgz",
|
||||
"integrity": "sha512-AWxlP05KeHbpGdgvZkcudJpsmChc2Y5Eo/GvxG/iUA/Aws5LZKHAMSeAo+V+nD+nxWZaxrwpWcnx4SH3oxNL3A==",
|
||||
"version": "5.23.2",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.2.tgz",
|
||||
"integrity": "sha512-FoipTSwzZR68ZAjXZ8DRH2DFEErMAOi9JvRMsn6i/hTp6Hd4W4nM1W6a+kUyMrp/pd1SIuUzUZvvkQ21yE6Dig==",
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
@@ -7267,12 +7299,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/urbackup-server-api": {
|
||||
"version": "0.8.9",
|
||||
"resolved": "https://registry.npmjs.org/urbackup-server-api/-/urbackup-server-api-0.8.9.tgz",
|
||||
"integrity": "sha512-Igu6A0xSZeMsiN6PWT7zG4aD+iJR5fXT/j5+xwAvnD/vCNfvVrettIsXv6MftxOajvTmtlgaYu8KDoH1EJQ6DQ==",
|
||||
"version": "0.52.0",
|
||||
"resolved": "https://registry.npmjs.org/urbackup-server-api/-/urbackup-server-api-0.52.0.tgz",
|
||||
"integrity": "sha512-KfroCFZEWCuCkWye1F1JwI2fkO1za/Mf1a8TNGTujzxU0ZGzDqhA1zCOcvV97q7nH1TKFNpw5tMZ06fSCKv2UA==",
|
||||
"dependencies": {
|
||||
"async-mutex": "^0.3.1",
|
||||
"node-fetch": "^2.6.1"
|
||||
"async-mutex": "^0.5.0",
|
||||
"node-fetch": "^2.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"next-i18next": "^12.1.0",
|
||||
"ping": "^0.4.4",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"raw-body": "^2.5.2",
|
||||
"raw-body": "^3.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^11.18.6",
|
||||
@@ -36,9 +36,9 @@
|
||||
"recharts": "^2.12.6",
|
||||
"rrule": "^2.8.1",
|
||||
"swr": "^1.3.0",
|
||||
"systeminformation": "^5.22.7",
|
||||
"systeminformation": "^5.23.2",
|
||||
"tough-cookie": "^4.1.3",
|
||||
"urbackup-server-api": "^0.8.9",
|
||||
"urbackup-server-api": "^0.52.0",
|
||||
"winston": "^3.11.0",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
@@ -51,7 +51,7 @@
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"postcss": "^8.4.38",
|
||||
|
||||
6142
pnpm-lock.yaml
generated
6142
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -900,5 +900,10 @@
|
||||
"open": "Oop - VS Mark",
|
||||
"closed": "Toe - VS Mark",
|
||||
"invalidConfiguration": "Ongeldige opstelling"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Optyd",
|
||||
"version": "Weergawe"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "مدة التشغيل",
|
||||
"version": "الإصدار"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"wait": "Si us plau, espereu"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Cercar…"
|
||||
"placeholder": "Cerca…"
|
||||
},
|
||||
"resources": {
|
||||
"cpu": "CPU",
|
||||
@@ -125,8 +125,8 @@
|
||||
"flood": {
|
||||
"download": "Descarregar",
|
||||
"upload": "Pujada",
|
||||
"leech": "Company",
|
||||
"seed": "Llavor"
|
||||
"leech": "Sangonera",
|
||||
"seed": "Llavors"
|
||||
},
|
||||
"freshrss": {
|
||||
"subscriptions": "Subcripcions",
|
||||
@@ -203,14 +203,14 @@
|
||||
"transmission": {
|
||||
"download": "Descarregar",
|
||||
"upload": "Pujada",
|
||||
"leech": "Company",
|
||||
"seed": "Llavor"
|
||||
"leech": "Sangonera",
|
||||
"seed": "Llavors"
|
||||
},
|
||||
"qbittorrent": {
|
||||
"download": "Descarregar",
|
||||
"upload": "Pujada",
|
||||
"leech": "Company",
|
||||
"seed": "Llavor"
|
||||
"leech": "Sangonera",
|
||||
"seed": "Llavors"
|
||||
},
|
||||
"qnap": {
|
||||
"cpuUsage": "Ús de CPU",
|
||||
@@ -223,14 +223,14 @@
|
||||
"deluge": {
|
||||
"download": "Descarregar",
|
||||
"upload": "Pujada",
|
||||
"leech": "Company",
|
||||
"seed": "Llavor"
|
||||
"leech": "Sangonera",
|
||||
"seed": "Llavors"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Descarregar",
|
||||
"upload": "Pujada",
|
||||
"leech": "Company",
|
||||
"seed": "Llavor"
|
||||
"leech": "Sangonera",
|
||||
"seed": "Llavors"
|
||||
},
|
||||
"sonarr": {
|
||||
"wanted": "Volgut",
|
||||
@@ -241,7 +241,7 @@
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Volgut",
|
||||
"missing": "Faltant",
|
||||
"missing": "Falten",
|
||||
"queued": "En cua",
|
||||
"movies": "Pel·lícules",
|
||||
"queue": "Cua",
|
||||
@@ -386,7 +386,7 @@
|
||||
"down": "Fora de línia"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Llegir",
|
||||
"read": "Llegit",
|
||||
"unread": "Sense llegir"
|
||||
},
|
||||
"authentik": {
|
||||
@@ -414,8 +414,8 @@
|
||||
"days": "d",
|
||||
"hours": "h",
|
||||
"crit": "Crític",
|
||||
"read": "Llegir",
|
||||
"write": "Escriure",
|
||||
"read": "Llegit",
|
||||
"write": "Escriptura",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Intercanvi"
|
||||
@@ -423,9 +423,9 @@
|
||||
"quicklaunch": {
|
||||
"bookmark": "Marcador",
|
||||
"service": "Servei",
|
||||
"search": "Cercar",
|
||||
"search": "Cerca",
|
||||
"custom": "Personalitzat",
|
||||
"visit": "Visitar",
|
||||
"visit": "Visita",
|
||||
"url": "URL",
|
||||
"searchsuggestion": "Suggeriment"
|
||||
},
|
||||
@@ -581,7 +581,7 @@
|
||||
"numberOfLeases": "IPs assignades"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "Tots els fluxos",
|
||||
"streams_all": "Tots els streams",
|
||||
"streams_active": "Transmissions actives",
|
||||
"streams_xepg": "Canals XEPG"
|
||||
},
|
||||
@@ -600,7 +600,7 @@
|
||||
"moonraker": {
|
||||
"printer_state": "Estat de l'impressora",
|
||||
"print_status": "Estat de l'impressió",
|
||||
"print_progress": "Progress",
|
||||
"print_progress": "Progrés",
|
||||
"layers": "Capes"
|
||||
},
|
||||
"octoprint": {
|
||||
@@ -614,14 +614,14 @@
|
||||
"status": "Estat"
|
||||
},
|
||||
"pfsense": {
|
||||
"load": "Promig Càrrega",
|
||||
"load": "Càrrega mitjana",
|
||||
"memory": "Ús Memòria",
|
||||
"wanStatus": "Estat WAN",
|
||||
"up": "Actiu",
|
||||
"down": "Inactiu",
|
||||
"temp": "Temp",
|
||||
"disk": "Ús Disc",
|
||||
"wanIP": "WAN IP"
|
||||
"wanIP": "IP WAN"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
@@ -677,7 +677,7 @@
|
||||
},
|
||||
"grafana": {
|
||||
"dashboards": "Taulells",
|
||||
"datasources": "Origen de dades",
|
||||
"datasources": "Orígens de dades",
|
||||
"totalalerts": "Alertes Totals",
|
||||
"alertstriggered": "Alertes disparades"
|
||||
},
|
||||
@@ -718,10 +718,10 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Avui",
|
||||
"gross_percent_1y": "Un any",
|
||||
"gross_percent_max": "Tot"
|
||||
"gross_percent_max": "Sempre"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
"podcasts": "Pòdcasts",
|
||||
"books": "Llibres",
|
||||
"podcastsDuration": "Durada",
|
||||
"booksDuration": "Durada"
|
||||
@@ -760,8 +760,8 @@
|
||||
"failed": "Error",
|
||||
"canceled": "Cancel·lat",
|
||||
"inProgress": "En curs",
|
||||
"totalPrs": "RP Totals",
|
||||
"myPrs": "Els meus RP",
|
||||
"totalPrs": "PRs Totals",
|
||||
"myPrs": "Les meves PRs",
|
||||
"approved": "Aprovat"
|
||||
},
|
||||
"gamedig": {
|
||||
@@ -798,7 +798,7 @@
|
||||
},
|
||||
"openwrt": {
|
||||
"uptime": "Temps actiu",
|
||||
"cpuLoad": "Càrrega promig de CPU (5m)",
|
||||
"cpuLoad": "Càrrega mitjana de CPU (5min)",
|
||||
"up": "Actiu",
|
||||
"down": "Inactiu",
|
||||
"bytesTx": "Enviat",
|
||||
@@ -849,10 +849,10 @@
|
||||
"scenesPlayed": "Escenes reproduïdes",
|
||||
"playCount": "Total reproduccions",
|
||||
"playDuration": "Temps visionat",
|
||||
"sceneSize": "Tamany Escena",
|
||||
"sceneSize": "Tamany d'escenes",
|
||||
"sceneDuration": "Duració Escenes",
|
||||
"images": "Imatges",
|
||||
"imageSize": "Mida Imatges",
|
||||
"imageSize": "Tamany d'imatges",
|
||||
"galleries": "Biblioteques",
|
||||
"performers": "Intèrprets",
|
||||
"studios": "Estudis",
|
||||
@@ -884,10 +884,10 @@
|
||||
"total": "Total"
|
||||
},
|
||||
"swagdashboard": {
|
||||
"proxied": "Proxied",
|
||||
"auth": "With Auth",
|
||||
"outdated": "Outdated",
|
||||
"banned": "Banned"
|
||||
"proxied": "Intermediat",
|
||||
"auth": "Amb autentificació",
|
||||
"outdated": "Obsolet",
|
||||
"banned": "Bloquejat"
|
||||
},
|
||||
"myspeed": {
|
||||
"ping": "Latència",
|
||||
@@ -895,10 +895,15 @@
|
||||
"upload": "Pujada"
|
||||
},
|
||||
"stocks": {
|
||||
"stocks": "Stocks",
|
||||
"loading": "Loading",
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
"stocks": "Accions",
|
||||
"loading": "Carregant",
|
||||
"open": "Obert - Mercat EEUU",
|
||||
"closed": "Tancat - Mercat EEUU",
|
||||
"invalidConfiguration": "Configuració no vàlida"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Temps actiu",
|
||||
"version": "Versió"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Doba spuštění",
|
||||
"version": "Verze"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Oppetid",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Offen - US-Markt",
|
||||
"closed": "Geschlossen - US-Markt",
|
||||
"invalidConfiguration": "Ungültige Konfiguration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Betriebszeit",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Χρόνος Λειτουργίας",
|
||||
"version": "Έκδοση"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,15 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
},
|
||||
"linkwarden": {
|
||||
"links": "Links",
|
||||
"collections": "Collections",
|
||||
"tags": "Tags"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
"unknown": "Desconocido",
|
||||
"healthy": "Saludable",
|
||||
"starting": "Comenzando",
|
||||
"unhealthy": "Insalubre",
|
||||
"unhealthy": "No saludable",
|
||||
"not_found": "No encontrado",
|
||||
"exited": "Terminado",
|
||||
"partial": "Parcial"
|
||||
@@ -895,10 +895,15 @@
|
||||
"upload": "Subida"
|
||||
},
|
||||
"stocks": {
|
||||
"stocks": "Stocks",
|
||||
"loading": "Loading",
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
"stocks": "Acciones",
|
||||
"loading": "Cargando",
|
||||
"open": "Abierto - Mercado EEUU",
|
||||
"closed": "Cerrado - Mercado EEUU",
|
||||
"invalidConfiguration": "Configuración no válida"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Tiempo activo",
|
||||
"version": "Versión"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Démarré depuis",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Vrijeme rada",
|
||||
"version": "Verzija"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Üzemidő",
|
||||
"version": "Verzió"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Waktu Aktif",
|
||||
"version": "Versi"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Tempo di attività",
|
||||
"version": "Versione"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "稼働時間",
|
||||
"version": "バージョン"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "버전"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Masa Hidup",
|
||||
"version": "Versi"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Online",
|
||||
"version": "Versie"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Oppetid",
|
||||
"version": "Versjon"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Czas działania",
|
||||
"version": "Wersja"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Ligado",
|
||||
"version": "Versão"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,10 +895,15 @@
|
||||
"upload": "Carregar"
|
||||
},
|
||||
"stocks": {
|
||||
"stocks": "Stocks",
|
||||
"loading": "Loading",
|
||||
"stocks": "Ações",
|
||||
"loading": "Carregando",
|
||||
"open": "Abrir - Mercado Americano",
|
||||
"closed": "Fechado - Mercado americano",
|
||||
"invalidConfiguration": "Configuração Inválida"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Ligado",
|
||||
"version": "Versão"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Время работы",
|
||||
"version": "Версия"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Prevádzka",
|
||||
"version": "Verzia"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Odprto - US trg",
|
||||
"closed": "Zaprto - US trg",
|
||||
"invalidConfiguration": "Neveljavna konfiguracija"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Čas delovanja",
|
||||
"version": "Verzija"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Açık - ABD Pazarı",
|
||||
"closed": "Kapalı - ABD Pazarı",
|
||||
"invalidConfiguration": "Geçersiz Yapılandırma"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Çalışma Süresi",
|
||||
"version": "Versiyon"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Час роботи",
|
||||
"version": "Версія"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "運行時間",
|
||||
"version": "版本"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "运行时间",
|
||||
"version": "版本"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,5 +900,10 @@
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Cameras",
|
||||
"uptime": "運行時間",
|
||||
"version": "版本"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export function slugifyAndEncode(tabName) {
|
||||
export default function Tab({ tab }) {
|
||||
const { activeTab, setActiveTab } = useContext(TabContext);
|
||||
|
||||
const matchesTab = decodeURI(activeTab) === slugify(tab);
|
||||
const matchesTab = decodeURIComponent(activeTab) === slugify(tab);
|
||||
|
||||
return (
|
||||
<li
|
||||
|
||||
@@ -48,8 +48,8 @@ export default async function handler(req, res) {
|
||||
logger.error(`no pods found with namespace=${namespace} and labelSelector=${labelSelector}`);
|
||||
return;
|
||||
}
|
||||
const someReady = pods.find((pod) => pod.status.phase === "Running");
|
||||
const allReady = pods.every((pod) => pod.status.phase === "Running");
|
||||
const someReady = pods.find((pod) => ["Succeeded", "Running"].includes(pod.status.phase));
|
||||
const allReady = pods.every((pod) => ["Succeeded", "Running"].includes(pod.status.phase));
|
||||
let status = "down";
|
||||
if (allReady) {
|
||||
status = "running";
|
||||
|
||||
@@ -399,7 +399,10 @@ export function cleanServiceGroups(groups) {
|
||||
expandOneStreamToTwoRows,
|
||||
showEpisodeNumber,
|
||||
|
||||
// glances, pihole
|
||||
// frigate
|
||||
enableRecentEvents,
|
||||
|
||||
// glances, pihole, pfsense
|
||||
version,
|
||||
|
||||
// glances
|
||||
@@ -509,6 +512,9 @@ export function cleanServiceGroups(groups) {
|
||||
if (type === "unifi") {
|
||||
if (site) cleanedService.widget.site = site;
|
||||
}
|
||||
if (type === "pfsense") {
|
||||
if (version) cleanedService.widget.version = version;
|
||||
}
|
||||
if (type === "proxmox") {
|
||||
if (node) cleanedService.widget.node = node;
|
||||
}
|
||||
@@ -611,6 +617,9 @@ export function cleanServiceGroups(groups) {
|
||||
if (type === "wgeasy") {
|
||||
if (threshold !== undefined) cleanedService.widget.threshold = parseInt(threshold, 10);
|
||||
}
|
||||
if (type === "frigate") {
|
||||
if (enableRecentEvents !== undefined) cleanedService.widget.enableRecentEvents = enableRecentEvents;
|
||||
}
|
||||
}
|
||||
|
||||
return cleanedService;
|
||||
|
||||
@@ -35,9 +35,16 @@ export default async function credentialedProxyHandler(req, res, map) {
|
||||
} else if (widget.type === "gotify") {
|
||||
headers["X-gotify-Key"] = `${widget.key}`;
|
||||
} else if (
|
||||
["authentik", "cloudflared", "ghostfolio", "mealie", "tailscale", "tandoor", "pterodactyl"].includes(
|
||||
widget.type,
|
||||
)
|
||||
[
|
||||
"authentik",
|
||||
"cloudflared",
|
||||
"ghostfolio",
|
||||
"linkwarden",
|
||||
"mealie",
|
||||
"tailscale",
|
||||
"tandoor",
|
||||
"pterodactyl",
|
||||
].includes(widget.type)
|
||||
) {
|
||||
headers.Authorization = `Bearer ${widget.key}`;
|
||||
} else if (widget.type === "truenas") {
|
||||
|
||||
@@ -29,6 +29,7 @@ const components = {
|
||||
fileflows: dynamic(() => import("./fileflows/component")),
|
||||
flood: dynamic(() => import("./flood/component")),
|
||||
freshrss: dynamic(() => import("./freshrss/component")),
|
||||
frigate: dynamic(() => import("./frigate/component")),
|
||||
fritzbox: dynamic(() => import("./fritzbox/component")),
|
||||
gamedig: dynamic(() => import("./gamedig/component")),
|
||||
gatus: dynamic(() => import("./gatus/component")),
|
||||
@@ -53,6 +54,7 @@ const components = {
|
||||
komga: dynamic(() => import("./komga/component")),
|
||||
kopia: dynamic(() => import("./kopia/component")),
|
||||
lidarr: dynamic(() => import("./lidarr/component")),
|
||||
linkwarden: dynamic(() => import("./linkwarden/component")),
|
||||
mastodon: dynamic(() => import("./mastodon/component")),
|
||||
mealie: dynamic(() => import("./mealie/component")),
|
||||
medusa: dynamic(() => import("./medusa/component")),
|
||||
|
||||
70
src/widgets/frigate/component.jsx
Normal file
70
src/widgets/frigate/component.jsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
const { widget } = service;
|
||||
|
||||
const { data, error } = useWidgetAPI(widget, "stats");
|
||||
const { data: eventsData, error: eventsError } = useWidgetAPI(widget, "events");
|
||||
|
||||
if (error) {
|
||||
return <Container service={service} error={error} />;
|
||||
}
|
||||
|
||||
if (eventsError) {
|
||||
return <Container service={service} error={eventsError} />;
|
||||
}
|
||||
|
||||
if (!data || !eventsData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="frigate.cameras" />
|
||||
<Block label="frigate.uptime" />
|
||||
<Block label="frigate.version" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container service={service}>
|
||||
<Block
|
||||
label="frigate.cameras"
|
||||
value={t("common.number", {
|
||||
value: data.num_cameras,
|
||||
})}
|
||||
/>
|
||||
<Block
|
||||
label="frigate.uptime"
|
||||
value={t("common.uptime", {
|
||||
value: data.uptime,
|
||||
})}
|
||||
/>
|
||||
<Block label="frigate.version" value={data.version} />
|
||||
</Container>
|
||||
{widget.enableRecentEvents &&
|
||||
eventsData?.map((event) => (
|
||||
<div
|
||||
key={event.id}
|
||||
className="text-theme-700 dark:text-theme-200 _relative h-5 rounded-md bg-theme-200/50 dark:bg-theme-900/20 m-1 px-1 flex"
|
||||
>
|
||||
<div className="text-xs z-10 self-center ml-2 relative h-4 grow mr-2">
|
||||
<div className="absolute w-full h-4 whitespace-nowrap text-ellipsis overflow-hidden text-left">
|
||||
{event.camera} ({event.label} {t("common.percent", { value: event.score * 100 })})
|
||||
</div>
|
||||
</div>
|
||||
<div className="self-center text-xs flex justify-end mr-1.5 pl-1 z-10 text-ellipsis overflow-hidden whitespace-nowrap">
|
||||
{t("common.date", {
|
||||
value: event.start_time,
|
||||
formatParams: { value: { timeStyle: "short", dateStyle: "medium" } },
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
38
src/widgets/frigate/widget.js
Normal file
38
src/widgets/frigate/widget.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { asJson } from "utils/proxy/api-helpers";
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
stats: {
|
||||
endpoint: "stats",
|
||||
map: (data) => {
|
||||
const jsonData = asJson(data);
|
||||
return {
|
||||
num_cameras: jsonData?.cameras !== undefined ? Object.keys(jsonData?.cameras).length : 0,
|
||||
uptime: jsonData?.service?.uptime,
|
||||
version: jsonData?.service.version,
|
||||
};
|
||||
},
|
||||
},
|
||||
events: {
|
||||
endpoint: "events",
|
||||
map: (data) =>
|
||||
asJson(data)
|
||||
.slice(0, 5)
|
||||
.map((event) => ({
|
||||
id: event.id,
|
||||
camera: event.camera,
|
||||
label: event.label,
|
||||
start_time: new Date(event.start_time * 1000),
|
||||
thumbnail: event.thumbnail,
|
||||
score: event.data.score,
|
||||
type: event.data.type,
|
||||
})),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -10,7 +10,8 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: versionData, error: versionError } = useWidgetAPI(widget, "version");
|
||||
// see https://github.com/gethomepage/homepage/issues/2282
|
||||
const endpoint = versionData?.major >= 1 && versionData?.minor > 84 ? "statistics" : "stats";
|
||||
const endpoint =
|
||||
versionData?.major > 1 || (versionData?.major === 1 && versionData?.minor > 84) ? "statistics" : "stats";
|
||||
const { data: immichData, error: immichError } = useWidgetAPI(widget, endpoint);
|
||||
|
||||
if (immichError || versionError || immichData?.statusCode === 401) {
|
||||
|
||||
55
src/widgets/linkwarden/component.jsx
Normal file
55
src/widgets/linkwarden/component.jsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
|
||||
const [stats, setStats] = useState({
|
||||
totalLinks: null,
|
||||
collections: { total: null },
|
||||
tags: { total: null },
|
||||
});
|
||||
|
||||
const { data: collectionsStatsData, error: collectionsStatsError } = useWidgetAPI(widget, "collections");
|
||||
const { data: tagsStatsData, error: tagsStatsError } = useWidgetAPI(widget, "tags");
|
||||
|
||||
useEffect(() => {
|
||||
if (collectionsStatsData?.response && tagsStatsData?.response) {
|
||||
setStats({
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
totalLinks: collectionsStatsData.response.reduce((sum, collection) => sum + (collection._count?.links || 0), 0),
|
||||
collections: {
|
||||
total: collectionsStatsData.response.length,
|
||||
},
|
||||
tags: {
|
||||
total: tagsStatsData.response.length,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [collectionsStatsData, tagsStatsData]);
|
||||
|
||||
if (collectionsStatsError || tagsStatsError) {
|
||||
return <Container service={service} error={collectionsStatsError || tagsStatsError} />;
|
||||
}
|
||||
|
||||
if (!tagsStatsData || !collectionsStatsData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="linkwarden.links" />
|
||||
<Block label="linkwarden.collections" />
|
||||
<Block label="linkwarden.tags" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="linkwarden.links" value={stats.totalLinks} />
|
||||
<Block label="linkwarden.collections" value={stats.collections.total} />
|
||||
<Block label="linkwarden.tags" value={stats.tags.total} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
17
src/widgets/linkwarden/widget.js
Normal file
17
src/widgets/linkwarden/widget.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/v1/{endpoint}",
|
||||
proxyHandler: credentialedProxyHandler,
|
||||
|
||||
mappings: {
|
||||
collections: {
|
||||
endpoint: "collections",
|
||||
},
|
||||
tags: {
|
||||
endpoint: "tags",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -9,8 +9,12 @@ export default function Component({ service }) {
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { data: systemData, error: systemError } = useWidgetAPI(widget, "system");
|
||||
const { data: interfaceData, error: interfaceError } = useWidgetAPI(widget, "interface");
|
||||
const version = widget.version ?? 1;
|
||||
const { data: systemData, error: systemError } = useWidgetAPI(widget, version === 1 ? "system" : "systemv2");
|
||||
const { data: interfaceData, error: interfaceError } = useWidgetAPI(
|
||||
widget,
|
||||
version === 1 ? "interface" : "interfacev2",
|
||||
);
|
||||
|
||||
const showWanIP = widget.fields?.filter((f) => f !== "wanIP").length <= 4 && widget.fields?.includes("wanIP");
|
||||
const showDiskUsage = widget.fields?.filter((f) => f !== "disk").length <= 4 && widget.fields?.includes("disk");
|
||||
@@ -34,14 +38,20 @@ export default function Component({ service }) {
|
||||
}
|
||||
|
||||
const wan = interfaceData.data.filter((l) => l.hwif === widget.wan)[0];
|
||||
let memUsage = systemData?.data.mem_usage;
|
||||
let diskUsage = systemData.data.disk_usage;
|
||||
if (version === 1) {
|
||||
memUsage *= 100;
|
||||
diskUsage *= 100;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="pfsense.load" value={systemData.data.load_avg[0]} />
|
||||
<Block
|
||||
label="pfsense.memory"
|
||||
value={t("common.percent", { value: (systemData.data.mem_usage * 100).toFixed(2) })}
|
||||
label="pfsense.load"
|
||||
value={version === 1 ? systemData.data.load_avg[0] : systemData.data.cpu_load_avg[0]}
|
||||
/>
|
||||
<Block label="pfsense.memory" value={t("common.percent", { value: memUsage.toFixed(2) })} />
|
||||
<Block
|
||||
label="pfsense.temp"
|
||||
value={t("common.number", { value: systemData.data.temp_c, style: "unit", unit: "celsius" })}
|
||||
@@ -57,12 +67,7 @@ export default function Component({ service }) {
|
||||
}
|
||||
/>
|
||||
{showWanIP && <Block label="pfsense.wanIP" value={wan.ipaddr} />}
|
||||
{showDiskUsage && (
|
||||
<Block
|
||||
label="pfsense.disk"
|
||||
value={t("common.percent", { value: (systemData.data.disk_usage * 100).toFixed(2) })}
|
||||
/>
|
||||
)}
|
||||
{showDiskUsage && <Block label="pfsense.disk" value={t("common.percent", { value: diskUsage.toFixed(2) })} />}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/v1/{endpoint}",
|
||||
api: "{url}/api/{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
system: {
|
||||
endpoint: "status/system",
|
||||
endpoint: "v1/status/system",
|
||||
validate: ["data"],
|
||||
},
|
||||
interface: {
|
||||
endpoint: "status/interface",
|
||||
endpoint: "v1/status/interface",
|
||||
validate: ["data"],
|
||||
},
|
||||
systemv2: {
|
||||
endpoint: "v2/status/system",
|
||||
validate: ["data"],
|
||||
},
|
||||
interfacev2: {
|
||||
endpoint: "v2/status/interfaces?limit=0&offset=0",
|
||||
validate: ["data"],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@ const widget = {
|
||||
healthy: entry.healthy,
|
||||
allocated: entry.allocated,
|
||||
free: entry.free,
|
||||
data: entry.topology.data,
|
||||
data: entry.topology?.data ?? [],
|
||||
})),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -32,16 +32,10 @@ export default function Component({ service }) {
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block
|
||||
label="tubearchivist.downloads"
|
||||
value={t("common.number", { value: downloadsData?.paginate?.total_hits })}
|
||||
/>
|
||||
<Block label="tubearchivist.videos" value={t("common.number", { value: videosData?.paginate?.total_hits })} />
|
||||
<Block label="tubearchivist.channels" value={t("common.number", { value: channelsData?.paginate?.total_hits })} />
|
||||
<Block
|
||||
label="tubearchivist.playlists"
|
||||
value={t("common.number", { value: playlistsData?.paginate?.total_hits })}
|
||||
/>
|
||||
<Block label="tubearchivist.downloads" value={t("common.number", { value: downloadsData.pending ?? 0 })} />
|
||||
<Block label="tubearchivist.videos" value={t("common.number", { value: videosData.doc_count ?? 0 })} />
|
||||
<Block label="tubearchivist.channels" value={t("common.number", { value: channelsData.doc_count ?? 0 })} />
|
||||
<Block label="tubearchivist.playlists" value={t("common.number", { value: playlistsData.doc_count ?? 0 })} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,20 +6,19 @@ const widget = {
|
||||
|
||||
mappings: {
|
||||
downloads: {
|
||||
endpoint: "download",
|
||||
validate: ["paginate"],
|
||||
endpoint: "stats/download",
|
||||
},
|
||||
videos: {
|
||||
endpoint: "video",
|
||||
validate: ["paginate"],
|
||||
endpoint: "stats/video",
|
||||
validate: ["doc_count"],
|
||||
},
|
||||
channels: {
|
||||
endpoint: "channel",
|
||||
validate: ["paginate"],
|
||||
endpoint: "stats/channel",
|
||||
validate: ["doc_count"],
|
||||
},
|
||||
playlists: {
|
||||
endpoint: "playlist",
|
||||
validate: ["paginate"],
|
||||
endpoint: "stats/playlist",
|
||||
validate: ["doc_count"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function Component({ service }) {
|
||||
return <Container service={service} error={infoError} />;
|
||||
}
|
||||
|
||||
if (!infoData) {
|
||||
if (!infoData || infoData.errorCode) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="wgeasy.connected" />
|
||||
|
||||
@@ -23,6 +23,7 @@ import evcc from "./evcc/widget";
|
||||
import fileflows from "./fileflows/widget";
|
||||
import flood from "./flood/widget";
|
||||
import freshrss from "./freshrss/widget";
|
||||
import frigate from "./frigate/widget";
|
||||
import fritzbox from "./fritzbox/widget";
|
||||
import gamedig from "./gamedig/widget";
|
||||
import gatus from "./gatus/widget";
|
||||
@@ -45,6 +46,7 @@ import kavita from "./kavita/widget";
|
||||
import komga from "./komga/widget";
|
||||
import kopia from "./kopia/widget";
|
||||
import lidarr from "./lidarr/widget";
|
||||
import linkwarden from "./linkwarden/widget";
|
||||
import mastodon from "./mastodon/widget";
|
||||
import mealie from "./mealie/widget";
|
||||
import medusa from "./medusa/widget";
|
||||
@@ -141,6 +143,7 @@ const widgets = {
|
||||
fileflows,
|
||||
flood,
|
||||
freshrss,
|
||||
frigate,
|
||||
fritzbox,
|
||||
gamedig,
|
||||
gatus,
|
||||
@@ -165,6 +168,7 @@ const widgets = {
|
||||
komga,
|
||||
kopia,
|
||||
lidarr,
|
||||
linkwarden,
|
||||
mastodon,
|
||||
mealie,
|
||||
medusa,
|
||||
|
||||
Reference in New Issue
Block a user