mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-30 02:02:12 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6188e52fe | ||
|
|
0a1a3bb8c2 | ||
|
|
16b45a313e | ||
|
|
1d820b02cb | ||
|
|
55a434c039 | ||
|
|
7831da6f6a | ||
|
|
bebecacc89 | ||
|
|
0d7072beea | ||
|
|
95ab0706b6 | ||
|
|
a522153df2 | ||
|
|
1804d0af0f | ||
|
|
9d16e280cd |
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,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,126 @@
|
||||
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)
|
||||
- [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)
|
||||
|
||||
@@ -26,5 +26,6 @@ widget:
|
||||
headers: # optional, or username/password
|
||||
Authorization: client_id client_token
|
||||
wan: igb0
|
||||
version: 2 # optional, defaults to 1 for api v1
|
||||
fields: ["load", "memory", "temp", "wanStatus"] # optional
|
||||
```
|
||||
|
||||
@@ -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
|
||||
@@ -225,8 +226,6 @@ theme:
|
||||
|
||||
extra_css:
|
||||
- "stylesheets/extra.css"
|
||||
extra_javascript:
|
||||
- "scripts/extra.js"
|
||||
|
||||
extra:
|
||||
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,10 @@
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,10 @@
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,8 +895,8 @@
|
||||
"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"
|
||||
|
||||
@@ -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) => pod.status.phase in ["Completed", "Running"]);
|
||||
const allReady = pods.every((pod) => pod.status.phase in ["Completed", "Running"]);
|
||||
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;
|
||||
|
||||
@@ -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")),
|
||||
|
||||
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;
|
||||
@@ -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"],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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";
|
||||
@@ -141,6 +142,7 @@ const widgets = {
|
||||
fileflows,
|
||||
flood,
|
||||
freshrss,
|
||||
frigate,
|
||||
fritzbox,
|
||||
gamedig,
|
||||
gatus,
|
||||
|
||||
Reference in New Issue
Block a user