Merge branch 'dev' into feature/next-15
This commit is contained in:
commit
e3b1f9d78b
8
.github/DISCUSSION_TEMPLATE/support.yml
vendored
8
.github/DISCUSSION_TEMPLATE/support.yml
vendored
@ -54,3 +54,11 @@ body:
|
|||||||
description: Please include output from your [troubleshooting tests](https://gethomepage.dev/more/troubleshooting/#service-widget-errors), if relevant.
|
description: Please include output from your [troubleshooting tests](https://gethomepage.dev/more/troubleshooting/#service-widget-errors), if relevant.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
## ⚠️ STOP ⚠️
|
||||||
|
|
||||||
|
Before you submit this support request, please ensure you have entered your configuration files and actually followed the steps from the troubleshooting guide linked above, if relevant. The troubleshooting steps often help to solve the problem.
|
||||||
|
|
||||||
|
*Please remember that this project is maintained by regular people **just like you**, so if you don't take the time to fill out the requested information, don't expect a reply back.*
|
||||||
|
|||||||
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -6,6 +6,7 @@
|
|||||||
==================== STOP ====
|
==================== STOP ====
|
||||||
|
|
||||||
⚠️ Before opening this pull request please review the guidelines in the checklist below.
|
⚠️ Before opening this pull request please review the guidelines in the checklist below.
|
||||||
|
|
||||||
If this PR does not meet those guidelines it will not be accepted, and everyone will be sad.
|
If this PR does not meet those guidelines it will not be accepted, and everyone will be sad.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -14,9 +15,6 @@ If this PR does not meet those guidelines it will not be accepted, and everyone
|
|||||||
<!--
|
<!--
|
||||||
Please include a summary of the change. Screenshots and/or videos can also be helpful if appropriate.
|
Please include a summary of the change. Screenshots and/or videos can also be helpful if appropriate.
|
||||||
|
|
||||||
*** Please see the development guidelines for new widgets: https://gethomepage.dev/more/development/#service-widget-guidelines
|
|
||||||
*** If you do not follow these guidelines your PR will likely be closed without review.
|
|
||||||
|
|
||||||
New service widgets should include example(s) of relevant API output as well as updates to the docs for the new widget.
|
New service widgets should include example(s) of relevant API output as well as updates to the docs for the new widget.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -30,13 +28,13 @@ What type of change does your PR introduce to Homepage?
|
|||||||
|
|
||||||
- [ ] New service widget
|
- [ ] New service widget
|
||||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||||
- [ ] New feature (non-breaking change which adds functionality)
|
- [ ] New feature or enhancement (non-breaking change which adds functionality)
|
||||||
- [ ] Documentation only
|
- [ ] Documentation only
|
||||||
- [ ] Other (please explain)
|
- [ ] Other (please explain)
|
||||||
|
|
||||||
## Checklist:
|
## Checklist:
|
||||||
|
|
||||||
- [ ] If applicable, I have added corresponding documentation changes.
|
- [ ] If applicable, I have added corresponding documentation changes.
|
||||||
- [ ] If applicable, I have reviewed the [feature](https://gethomepage.dev/more/development/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/more/development/#service-widget-guidelines).
|
- [ ] If applicable, I have reviewed the [feature / enhancement](https://gethomepage.dev/more/development/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/more/development/#service-widget-guidelines).
|
||||||
- [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/more/development/#code-linting).
|
- [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/more/development/#code-linting).
|
||||||
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
|
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
|
||||||
|
|||||||
18
.github/workflows/docker-publish.yml
vendored
18
.github/workflows/docker-publish.yml
vendored
@ -46,6 +46,24 @@ jobs:
|
|||||||
-
|
-
|
||||||
name: Check files
|
name: Check files
|
||||||
uses: pre-commit/action@v3.0.1
|
uses: pre-commit/action@v3.0.1
|
||||||
|
-
|
||||||
|
name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
run_install: false
|
||||||
|
-
|
||||||
|
name: Install Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'pnpm'
|
||||||
|
-
|
||||||
|
name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
-
|
||||||
|
name: Lint frontend
|
||||||
|
run: pnpm run lint
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Docker Build & Push
|
name: Docker Build & Push
|
||||||
|
|||||||
@ -63,7 +63,7 @@ The homepage team appreciates all effort and interest from the community in fili
|
|||||||
- Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity.
|
- Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity.
|
||||||
- Discussions with a marked answer will be automatically closed.
|
- Discussions with a marked answer will be automatically closed.
|
||||||
- Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity.
|
- Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity.
|
||||||
- Feature requests that do not meet the following thresholds will be closed: 5 "up-votes" after 180 days of inactivity or 10 "up-votes" after 365 days.
|
- Feature requests that do not meet the following thresholds will be closed: 10 "up-votes" after 180 days of inactivity or 20 "up-votes" after 365 days.
|
||||||
|
|
||||||
In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns.
|
In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns.
|
||||||
Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features.
|
Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features.
|
||||||
|
|||||||
@ -134,7 +134,7 @@ Services may have descriptions,
|
|||||||
|
|
||||||
## Icons
|
## Icons
|
||||||
|
|
||||||
Services may have an icon attached to them, you can use icons from [Dashboard Icons](https://github.com/walkxcode/dashboard-icons) automatically, by passing the name of the icon, with, or without `.png` or with `.svg` to use the svg version.
|
Services may have an icon attached to them, you can use icons from [Dashboard Icons](https://github.com/homarr-labs/dashboard-icons) automatically, by passing the name of the icon, with, or without `.png`, `.webp` or `.svg` to specify the desired version.
|
||||||
|
|
||||||
You can also specify prefixed icons from:
|
You can also specify prefixed icons from:
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,14 @@ You can customize the title of the page if you'd like.
|
|||||||
title: My Awesome Homepage
|
title: My Awesome Homepage
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
You can customize the description of the page if you'd like.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
description: A description of my awesome homepage
|
||||||
|
```
|
||||||
|
|
||||||
## Start URL
|
## Start URL
|
||||||
|
|
||||||
You can customize the start_url as required for installable apps. The default is "/".
|
You can customize the start_url as required for installable apps. The default is "/".
|
||||||
|
|||||||
@ -23,3 +23,5 @@ Finally, run the server:
|
|||||||
```bash
|
```bash
|
||||||
pnpm start
|
pnpm start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When updating homepage versions you will need to re-build the static files i.e. repeat the process above.
|
||||||
|
|||||||
@ -46,9 +46,9 @@ See the [pre-commit documentation](https://pre-commit.com/#install) to get start
|
|||||||
In general, homepage is meant to be a dashboard for 'self-hosted' services and we believe it is a small way we can help showcase this kind of software. While exceptions are made, mostly when there is no viable
|
In general, homepage is meant to be a dashboard for 'self-hosted' services and we believe it is a small way we can help showcase this kind of software. While exceptions are made, mostly when there is no viable
|
||||||
self-hosted / open-source alternative, we ask that any widgets, etc. are developed primarily for a self-hosted tool.
|
self-hosted / open-source alternative, we ask that any widgets, etc. are developed primarily for a self-hosted tool.
|
||||||
|
|
||||||
## New Feature Guidelines
|
## New Feature or Enhancement Guidelines {#new-feature-guidelines}
|
||||||
|
|
||||||
- New features should usually be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users.
|
- New features or enhancements, **no matter how small**, must be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users.
|
||||||
- If you have ideas for a larger feature you may want to open a discussion first.
|
- If you have ideas for a larger feature you may want to open a discussion first.
|
||||||
|
|
||||||
## Service Widget Guidelines
|
## Service Widget Guidelines
|
||||||
|
|||||||
@ -7,7 +7,7 @@ Learn more about [Beszel](https://github.com/henrygd/beszel)
|
|||||||
|
|
||||||
The widget has two modes, a single system with detailed info if `systemId` is provided, or an overview of all systems if `systemId` is not provided.
|
The widget has two modes, a single system with detailed info if `systemId` is provided, or an overview of all systems if `systemId` is not provided.
|
||||||
|
|
||||||
The `systemID` in the `id` field on the collections page of Beszel.
|
The `systemID` is the `id` field on the collections page of Beszel under the PocketBase admin panel. You can also use the 'nice name' from the Beszel UI.
|
||||||
|
|
||||||
Allowed fields for 'overview' mode: `["systems", "up"]`
|
Allowed fields for 'overview' mode: `["systems", "up"]`
|
||||||
Allowed fields for a single system: `["name", "status", "updated", "cpu", "memory", "disk", "network"]`
|
Allowed fields for a single system: `["name", "status", "updated", "cpu", "memory", "disk", "network"]`
|
||||||
|
|||||||
@ -62,10 +62,12 @@ widget:
|
|||||||
format: size
|
format: size
|
||||||
```
|
```
|
||||||
|
|
||||||
Supported formats for the values are `text`, `number`, `float`, `percent`, `bytes`, `bitrate`, `size`, `date` and `relativeDate`.
|
Supported formats for the values are `text`, `number`, `float`, `percent`, `duration`, `bytes`, `bitrate`, `size`, `date` and `relativeDate`.
|
||||||
|
|
||||||
The `dateStyle` and `timeStyle` options of the `date` format are passed directly to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) and the `style` and `numeric` options of `relativeDate` are passed to [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat).
|
The `dateStyle` and `timeStyle` options of the `date` format are passed directly to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) and the `style` and `numeric` options of `relativeDate` are passed to [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat).
|
||||||
|
|
||||||
|
The `duration` format expects the duration to be specified in seconds. The `scale` transformation tool can be used if a conversion is required.
|
||||||
|
|
||||||
The `size` format will return the length of the array or string, or the number of keys in an object. This is then formatted as `number`.
|
The `size` format will return the length of the array or string, or the number of keys in an object. This is then formatted as `number`.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|||||||
@ -11,7 +11,7 @@ Learn more about [Gluetun](https://github.com/qdm12/gluetun).
|
|||||||
|
|
||||||
Allowed fields: `["public_ip", "region", "country"]`.
|
Allowed fields: `["public_ip", "region", "country"]`.
|
||||||
|
|
||||||
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication).
|
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). Note that to use the api key method, you must add the route `GET /v1/publicip/ip` to the `routes` array in your Gluetun config.toml.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
|
|||||||
@ -19,7 +19,7 @@ Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "w
|
|||||||
|
|
||||||
!!! hint
|
!!! hint
|
||||||
|
|
||||||
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache.
|
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container or restart the service to clear the cache.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
|
|||||||
932
package-lock.json
generated
932
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -32,11 +32,11 @@
|
|||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-i18next": "^11.18.6",
|
"react-i18next": "^11.18.6",
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^5.4.0",
|
||||||
"recharts": "^2.12.7",
|
"recharts": "^2.12.7",
|
||||||
"rrule": "^2.8.1",
|
"rrule": "^2.8.1",
|
||||||
"swr": "^1.3.0",
|
"swr": "^1.3.0",
|
||||||
"systeminformation": "^5.23.8",
|
"systeminformation": "^5.24.3",
|
||||||
"tough-cookie": "^4.1.4",
|
"tough-cookie": "^4.1.4",
|
||||||
"urbackup-server-api": "^0.8.9",
|
"urbackup-server-api": "^0.8.9",
|
||||||
"winston": "^3.13.0",
|
"winston": "^3.13.0",
|
||||||
@ -52,12 +52,12 @@
|
|||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.9.0",
|
"eslint-plugin-jsx-a11y": "^6.9.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.3",
|
||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"postcss": "^8.4.48",
|
"postcss": "^8.4.48",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.3.2",
|
||||||
"tailwind-scrollbar": "^3.0.5",
|
"tailwind-scrollbar": "^3.0.5",
|
||||||
"tailwindcss": "^3.4.14",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.6.3"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
|||||||
980
pnpm-lock.yaml
980
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -982,6 +982,9 @@
|
|||||||
"name": "Naam",
|
"name": "Naam",
|
||||||
"systems": "Stelsels",
|
"systems": "Stelsels",
|
||||||
"up": "Op",
|
"up": "Op",
|
||||||
|
"down": "Af",
|
||||||
|
"paused": "Onderbreek",
|
||||||
|
"pending": "Afwagtend",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Opgedateer",
|
"updated": "Opgedateer",
|
||||||
"cpu": "SVE",
|
"cpu": "SVE",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "الاسم",
|
"name": "الاسم",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "يعمل",
|
"up": "يعمل",
|
||||||
|
"down": "لا يعمل",
|
||||||
|
"paused": "متوقف",
|
||||||
|
"pending": "معلق",
|
||||||
"status": "الحالة",
|
"status": "الحالة",
|
||||||
"updated": "محدث",
|
"updated": "محدث",
|
||||||
"cpu": "المعالج",
|
"cpu": "المعالج",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Статус",
|
"status": "Статус",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "Процесор",
|
"cpu": "Процесор",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"systems": "Sistemes",
|
"systems": "Sistemes",
|
||||||
"up": "Actiu",
|
"up": "Actiu",
|
||||||
|
"down": "Inactiu",
|
||||||
|
"paused": "En pausa",
|
||||||
|
"pending": "Pendent",
|
||||||
"status": "Estat",
|
"status": "Estat",
|
||||||
"updated": "Actualitzat",
|
"updated": "Actualitzat",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Pozastaveno",
|
||||||
|
"pending": "Čeká",
|
||||||
"status": "Stav",
|
"status": "Stav",
|
||||||
"updated": "Aktualizováno",
|
"updated": "Aktualizováno",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Navn",
|
"name": "Navn",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Op",
|
"up": "Op",
|
||||||
|
"down": "Ned",
|
||||||
|
"paused": "Pause",
|
||||||
|
"pending": "Afventer",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Opdateret",
|
"updated": "Opdateret",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systeme",
|
"systems": "Systeme",
|
||||||
"up": "Senden",
|
"up": "Senden",
|
||||||
|
"down": "Empfangen",
|
||||||
|
"paused": "Pausiert",
|
||||||
|
"pending": "Ausstehend",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Aktualisiert",
|
"updated": "Aktualisiert",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Όνομα",
|
"name": "Όνομα",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Ping up",
|
"up": "Ping up",
|
||||||
|
"down": "Ping down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Σε εκκρεμότητα",
|
||||||
"status": "Κατάσταση",
|
"status": "Κατάσταση",
|
||||||
"updated": "Ενημερώθηκε",
|
"updated": "Ενημερώθηκε",
|
||||||
"cpu": "Επεξεργαστής",
|
"cpu": "Επεξεργαστής",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Stato",
|
"status": "Stato",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "Ĉefprocesoro",
|
"cpu": "Ĉefprocesoro",
|
||||||
|
|||||||
@ -311,13 +311,13 @@
|
|||||||
},
|
},
|
||||||
"suwayomi": {
|
"suwayomi": {
|
||||||
"download": "Descargado",
|
"download": "Descargado",
|
||||||
"nondownload": "Non-Downloaded",
|
"nondownload": "No descargado",
|
||||||
"read": "Leer",
|
"read": "Leer",
|
||||||
"unread": "Sin leer",
|
"unread": "Sin leer",
|
||||||
"downloadedread": "Downloaded & Read",
|
"downloadedread": "Descargado y leído",
|
||||||
"downloadedunread": "Downloaded & Unread",
|
"downloadedunread": "Descargado y no leído",
|
||||||
"nondownloadedread": "Non-Downloaded & Read",
|
"nondownloadedread": "No descargado y leído",
|
||||||
"nondownloadedunread": "Non-Downloaded & Unread"
|
"nondownloadedunread": "No descargado y no leído"
|
||||||
},
|
},
|
||||||
"tailscale": {
|
"tailscale": {
|
||||||
"address": "Dirección",
|
"address": "Dirección",
|
||||||
@ -980,32 +980,35 @@
|
|||||||
},
|
},
|
||||||
"beszel": {
|
"beszel": {
|
||||||
"name": "Nombre",
|
"name": "Nombre",
|
||||||
"systems": "Systems",
|
"systems": "Sistemas",
|
||||||
"up": "Activo",
|
"up": "Activo",
|
||||||
|
"down": "Inactivo",
|
||||||
|
"paused": "Pausado",
|
||||||
|
"pending": "Pendiente",
|
||||||
"status": "Estado",
|
"status": "Estado",
|
||||||
"updated": "Actualizado",
|
"updated": "Actualizado",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
"memory": "MEM",
|
"memory": "MEM",
|
||||||
"disk": "Disk",
|
"disk": "Disco",
|
||||||
"network": "NET"
|
"network": "RED"
|
||||||
},
|
},
|
||||||
"argocd": {
|
"argocd": {
|
||||||
"apps": "Apps",
|
"apps": "Apps",
|
||||||
"synced": "Synced",
|
"synced": "Sincronizado",
|
||||||
"outOfSync": "Out Of Sync",
|
"outOfSync": "Desincronizado",
|
||||||
"healthy": "Saludable",
|
"healthy": "Saludable",
|
||||||
"degraded": "Degraded",
|
"degraded": "Degradado",
|
||||||
"progressing": "Progressing",
|
"progressing": "Progresando",
|
||||||
"missing": "Faltantes",
|
"missing": "Faltantes",
|
||||||
"suspended": "Suspended"
|
"suspended": "Suspendido"
|
||||||
},
|
},
|
||||||
"spoolman": {
|
"spoolman": {
|
||||||
"loading": "Cargando"
|
"loading": "Cargando"
|
||||||
},
|
},
|
||||||
"gitlab": {
|
"gitlab": {
|
||||||
"groups": "Groups",
|
"groups": "Grupos",
|
||||||
"issues": "Números",
|
"issues": "Números",
|
||||||
"merges": "Merge Requests",
|
"merges": "Solicitudes de fusión",
|
||||||
"projects": "Projects"
|
"projects": "Proyectos"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Vireillä",
|
||||||
"status": "Tila",
|
"status": "Tila",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -58,7 +58,7 @@
|
|||||||
"wlan": "WLAN",
|
"wlan": "WLAN",
|
||||||
"devices": "Équipt.",
|
"devices": "Équipt.",
|
||||||
"lan_devices": "Équipt. LAN",
|
"lan_devices": "Équipt. LAN",
|
||||||
"wlan_devices": "Équipt. WLAN",
|
"wlan_devices": "Périphériques WLAN",
|
||||||
"lan_users": "Utilisateurs LAN",
|
"lan_users": "Utilisateurs LAN",
|
||||||
"wlan_users": "Utilisateurs WLAN",
|
"wlan_users": "Utilisateurs WLAN",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"systems": "Systèmes",
|
"systems": "Systèmes",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "En Pause",
|
||||||
|
"pending": "En attente",
|
||||||
"status": "Statut",
|
"status": "Statut",
|
||||||
"updated": "Mis à jour",
|
"updated": "Mis à jour",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
@ -990,22 +993,22 @@
|
|||||||
"network": "Réseau"
|
"network": "Réseau"
|
||||||
},
|
},
|
||||||
"argocd": {
|
"argocd": {
|
||||||
"apps": "Apps",
|
"apps": "Applications",
|
||||||
"synced": "Synced",
|
"synced": "Synchronisé",
|
||||||
"outOfSync": "Out Of Sync",
|
"outOfSync": "Désynchronisé",
|
||||||
"healthy": "Fonctionnel",
|
"healthy": "Fonctionnel",
|
||||||
"degraded": "Degraded",
|
"degraded": "Dégradé",
|
||||||
"progressing": "Progressing",
|
"progressing": "En cours",
|
||||||
"missing": "Manquant",
|
"missing": "Manquant",
|
||||||
"suspended": "Suspended"
|
"suspended": "Suspendu"
|
||||||
},
|
},
|
||||||
"spoolman": {
|
"spoolman": {
|
||||||
"loading": "Chargement"
|
"loading": "Chargement"
|
||||||
},
|
},
|
||||||
"gitlab": {
|
"gitlab": {
|
||||||
"groups": "Groups",
|
"groups": "Groupes",
|
||||||
"issues": "Anomalies",
|
"issues": "Anomalies",
|
||||||
"merges": "Merge Requests",
|
"merges": "Demandes de fusion de branches",
|
||||||
"projects": "Projects"
|
"projects": "Projets"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "ממתין",
|
||||||
"status": "סטטוס",
|
"status": "סטטוס",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Ime",
|
"name": "Ime",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Dostupno",
|
"up": "Dostupno",
|
||||||
|
"down": "Nedostupno",
|
||||||
|
"paused": "Zaustavljeno",
|
||||||
|
"pending": "U tijeku",
|
||||||
"status": "Stanje",
|
"status": "Stanje",
|
||||||
"updated": "Aktualizirano",
|
"updated": "Aktualizirano",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Név",
|
"name": "Név",
|
||||||
"systems": "Rendszerek",
|
"systems": "Rendszerek",
|
||||||
"up": "Fel",
|
"up": "Fel",
|
||||||
|
"down": "Le",
|
||||||
|
"paused": "Szünetel",
|
||||||
|
"pending": "Függőben",
|
||||||
"status": "Státusz",
|
"status": "Státusz",
|
||||||
"updated": "Frissített",
|
"updated": "Frissített",
|
||||||
"cpu": "Processzor",
|
"cpu": "Processzor",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nama",
|
"name": "Nama",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Hidup",
|
"up": "Hidup",
|
||||||
|
"down": "Mati",
|
||||||
|
"paused": "Pause",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Terbarui",
|
"updated": "Terbarui",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -335,7 +335,7 @@
|
|||||||
},
|
},
|
||||||
"technitium": {
|
"technitium": {
|
||||||
"totalQueries": "Richieste",
|
"totalQueries": "Richieste",
|
||||||
"totalNoError": "Success",
|
"totalNoError": "Successo",
|
||||||
"totalServerFailure": "Failures",
|
"totalServerFailure": "Failures",
|
||||||
"totalNxDomain": "NX Domains",
|
"totalNxDomain": "NX Domains",
|
||||||
"totalRefused": "Refused",
|
"totalRefused": "Refused",
|
||||||
@ -590,7 +590,7 @@
|
|||||||
"total": "Totale"
|
"total": "Totale"
|
||||||
},
|
},
|
||||||
"peanut": {
|
"peanut": {
|
||||||
"battery_charge": "Battery Charge",
|
"battery_charge": "Carica Batteria",
|
||||||
"ups_load": "Carico UPS",
|
"ups_load": "Carico UPS",
|
||||||
"ups_status": "Stato UPS",
|
"ups_status": "Stato UPS",
|
||||||
"online": "Online",
|
"online": "Online",
|
||||||
@ -854,7 +854,7 @@
|
|||||||
},
|
},
|
||||||
"romm": {
|
"romm": {
|
||||||
"platforms": "Piattaforme",
|
"platforms": "Piattaforme",
|
||||||
"totalRoms": "Games",
|
"totalRoms": "Giochi",
|
||||||
"saves": "Saves",
|
"saves": "Saves",
|
||||||
"states": "States",
|
"states": "States",
|
||||||
"screenshots": "Screenshots",
|
"screenshots": "Screenshots",
|
||||||
@ -890,7 +890,7 @@
|
|||||||
"sceneDuration": "Durata Delle Scene",
|
"sceneDuration": "Durata Delle Scene",
|
||||||
"images": "Immagini",
|
"images": "Immagini",
|
||||||
"imageSize": "Dimensioni immagine",
|
"imageSize": "Dimensioni immagine",
|
||||||
"galleries": "Galleries",
|
"galleries": "Gallerie",
|
||||||
"performers": "Esecutori",
|
"performers": "Esecutori",
|
||||||
"studios": "Studi",
|
"studios": "Studi",
|
||||||
"movies": "Film",
|
"movies": "Film",
|
||||||
@ -933,7 +933,7 @@
|
|||||||
},
|
},
|
||||||
"stocks": {
|
"stocks": {
|
||||||
"stocks": "Stocks",
|
"stocks": "Stocks",
|
||||||
"loading": "Loading",
|
"loading": "Caricamento",
|
||||||
"open": "Open - US Market",
|
"open": "Open - US Market",
|
||||||
"closed": "Closed - US Market",
|
"closed": "Closed - US Market",
|
||||||
"invalidConfiguration": "Invalid Configuration"
|
"invalidConfiguration": "Invalid Configuration"
|
||||||
@ -944,8 +944,8 @@
|
|||||||
"version": "Versione"
|
"version": "Versione"
|
||||||
},
|
},
|
||||||
"linkwarden": {
|
"linkwarden": {
|
||||||
"links": "Links",
|
"links": "Collegamenti",
|
||||||
"collections": "Collections",
|
"collections": "Raccolte",
|
||||||
"tags": "Tag"
|
"tags": "Tag"
|
||||||
},
|
},
|
||||||
"zabbix": {
|
"zabbix": {
|
||||||
@ -957,12 +957,12 @@
|
|||||||
"disaster": "Disaster"
|
"disaster": "Disaster"
|
||||||
},
|
},
|
||||||
"lubelogger": {
|
"lubelogger": {
|
||||||
"vehicle": "Vehicle",
|
"vehicle": "Veicolo",
|
||||||
"vehicles": "Vehicles",
|
"vehicles": "Veicoli",
|
||||||
"serviceRecords": "Service Records",
|
"serviceRecords": "Service Records",
|
||||||
"reminders": "Reminders",
|
"reminders": "Promemoria",
|
||||||
"nextReminder": "Next Reminder",
|
"nextReminder": "Promemoria Seguente",
|
||||||
"none": "None"
|
"none": "Nessuno"
|
||||||
},
|
},
|
||||||
"vikunja": {
|
"vikunja": {
|
||||||
"projects": "Active Projects",
|
"projects": "Active Projects",
|
||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "In Pausa",
|
||||||
|
"pending": "In attesa",
|
||||||
"status": "Stato",
|
"status": "Stato",
|
||||||
"updated": "Aggiornato",
|
"updated": "Aggiornato",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
@ -1000,7 +1003,7 @@
|
|||||||
"suspended": "Suspended"
|
"suspended": "Suspended"
|
||||||
},
|
},
|
||||||
"spoolman": {
|
"spoolman": {
|
||||||
"loading": "Loading"
|
"loading": "Caricamento"
|
||||||
},
|
},
|
||||||
"gitlab": {
|
"gitlab": {
|
||||||
"groups": "Groups",
|
"groups": "Groups",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "名前",
|
"name": "名前",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "稼働",
|
"up": "稼働",
|
||||||
|
"down": "下へ",
|
||||||
|
"paused": "一時停止中",
|
||||||
|
"pending": "保留中",
|
||||||
"status": "状態",
|
"status": "状態",
|
||||||
"updated": "更新済",
|
"updated": "更新済",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "이름",
|
"name": "이름",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "대기 중",
|
||||||
"status": "상태",
|
"status": "상태",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Statuss",
|
"status": "Statuss",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nama",
|
"name": "Nama",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Hidup",
|
"up": "Hidup",
|
||||||
|
"down": "Mati",
|
||||||
|
"paused": "Tangguh",
|
||||||
|
"pending": "Tertunda",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Dikemaskini",
|
"updated": "Dikemaskini",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -311,13 +311,13 @@
|
|||||||
},
|
},
|
||||||
"suwayomi": {
|
"suwayomi": {
|
||||||
"download": "Gedownload",
|
"download": "Gedownload",
|
||||||
"nondownload": "Non-Downloaded",
|
"nondownload": "Niet gedownload",
|
||||||
"read": "Gelezen",
|
"read": "Gelezen",
|
||||||
"unread": "Ongelezen",
|
"unread": "Ongelezen",
|
||||||
"downloadedread": "Downloaded & Read",
|
"downloadedread": "Gedownload & gelezen",
|
||||||
"downloadedunread": "Downloaded & Unread",
|
"downloadedunread": "Gedownload & ongelezen",
|
||||||
"nondownloadedread": "Non-Downloaded & Read",
|
"nondownloadedread": "Niet-gedownload & gelezen",
|
||||||
"nondownloadedunread": "Non-Downloaded & Unread"
|
"nondownloadedunread": "Niet-gedownload & ongelezen"
|
||||||
},
|
},
|
||||||
"tailscale": {
|
"tailscale": {
|
||||||
"address": "Adres",
|
"address": "Adres",
|
||||||
@ -980,32 +980,35 @@
|
|||||||
},
|
},
|
||||||
"beszel": {
|
"beszel": {
|
||||||
"name": "Naam",
|
"name": "Naam",
|
||||||
"systems": "Systems",
|
"systems": "Systemen",
|
||||||
"up": "Online",
|
"up": "Online",
|
||||||
|
"down": "Offline",
|
||||||
|
"paused": "Gepauzeerd",
|
||||||
|
"pending": "In afwachting",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Bijgewerkt",
|
"updated": "Bijgewerkt",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
"memory": "GEH",
|
"memory": "GEH",
|
||||||
"disk": "Disk",
|
"disk": "Schijf",
|
||||||
"network": "NET"
|
"network": "NET"
|
||||||
},
|
},
|
||||||
"argocd": {
|
"argocd": {
|
||||||
"apps": "Apps",
|
"apps": "Apps",
|
||||||
"synced": "Synced",
|
"synced": "Gesynchroniseerd",
|
||||||
"outOfSync": "Out Of Sync",
|
"outOfSync": "Niet gesynchroniseerd",
|
||||||
"healthy": "Gezond",
|
"healthy": "Gezond",
|
||||||
"degraded": "Degraded",
|
"degraded": "Gedegradeerd",
|
||||||
"progressing": "Progressing",
|
"progressing": "Doorvoeren",
|
||||||
"missing": "Ontbreekt",
|
"missing": "Ontbreekt",
|
||||||
"suspended": "Suspended"
|
"suspended": "Onderbroken"
|
||||||
},
|
},
|
||||||
"spoolman": {
|
"spoolman": {
|
||||||
"loading": "Laden"
|
"loading": "Laden"
|
||||||
},
|
},
|
||||||
"gitlab": {
|
"gitlab": {
|
||||||
"groups": "Groups",
|
"groups": "Groepen",
|
||||||
"issues": "Problemen",
|
"issues": "Problemen",
|
||||||
"merges": "Merge Requests",
|
"merges": "Merge Verzoeken",
|
||||||
"projects": "Projects"
|
"projects": "Projecten"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Navn",
|
"name": "Navn",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Oppe",
|
"up": "Oppe",
|
||||||
|
"down": "Nede",
|
||||||
|
"paused": "Pauset",
|
||||||
|
"pending": "Ventende",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Oppdatert",
|
"updated": "Oppdatert",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
"ms": "{{value, number}}",
|
"ms": "{{value, number}}",
|
||||||
"date": "{{value, date}}",
|
"date": "{{value, date}}",
|
||||||
"relativeDate": "{{value, relativeDate}}",
|
"relativeDate": "{{value, relativeDate}}",
|
||||||
"duration": "{value, duration}",
|
"duration": "{{value, duration}}",
|
||||||
"months": "mc",
|
"months": "mc",
|
||||||
"days": "d",
|
"days": "d",
|
||||||
"hours": "g",
|
"hours": "g",
|
||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nazwa",
|
"name": "Nazwa",
|
||||||
"systems": "Systemy",
|
"systems": "Systemy",
|
||||||
"up": "Dostępny",
|
"up": "Dostępny",
|
||||||
|
"down": "Niedostępny",
|
||||||
|
"paused": "Zatrzymane",
|
||||||
|
"pending": "Oczekiwane",
|
||||||
"status": "Stan",
|
"status": "Stan",
|
||||||
"updated": "Zaktualizowane",
|
"updated": "Zaktualizowane",
|
||||||
"cpu": "Procesor",
|
"cpu": "Procesor",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Pausa",
|
||||||
|
"pending": "Pendente",
|
||||||
"status": "Estado",
|
"status": "Estado",
|
||||||
"updated": "Atualizado",
|
"updated": "Atualizado",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Ativo",
|
"up": "Ativo",
|
||||||
|
"down": "Inativo",
|
||||||
|
"paused": "Pausado",
|
||||||
|
"pending": "Pendente",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Atualizado",
|
"updated": "Atualizado",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Sus",
|
"up": "Sus",
|
||||||
|
"down": "Jos",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "În așteptare",
|
||||||
"status": "Stare",
|
"status": "Stare",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "Procesor",
|
"cpu": "Procesor",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Имя",
|
"name": "Имя",
|
||||||
"systems": "Системы",
|
"systems": "Системы",
|
||||||
"up": "Онлайн",
|
"up": "Онлайн",
|
||||||
|
"down": "Офлайн",
|
||||||
|
"paused": "Приостановлено",
|
||||||
|
"pending": "В обработке",
|
||||||
"status": "Статус",
|
"status": "Статус",
|
||||||
"updated": "Обновленно",
|
"updated": "Обновленно",
|
||||||
"cpu": "ЦП",
|
"cpu": "ЦП",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Meno",
|
"name": "Meno",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Nahrávanie",
|
"up": "Nahrávanie",
|
||||||
|
"down": "Sťahovanie",
|
||||||
|
"paused": "Pozastavené",
|
||||||
|
"pending": "Čakajúce",
|
||||||
"status": "Stav",
|
"status": "Stav",
|
||||||
"updated": "Aktualizované",
|
"updated": "Aktualizované",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Naziv",
|
"name": "Naziv",
|
||||||
"systems": "Sistemi",
|
"systems": "Sistemi",
|
||||||
"up": "Povezan",
|
"up": "Povezan",
|
||||||
|
"down": "Nepovezan",
|
||||||
|
"paused": "Pavziran",
|
||||||
|
"pending": "V teku",
|
||||||
"status": "Stanje",
|
"status": "Stanje",
|
||||||
"updated": "Posodobljen",
|
"updated": "Posodobljen",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Avvaktar",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "పెండింగ్",
|
||||||
"status": "హోదా",
|
"status": "హోదా",
|
||||||
"updated": "నవీకరించబడింది",
|
"updated": "నవీకరించబడింది",
|
||||||
"cpu": "సీపియూ",
|
"cpu": "సీపియూ",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Pending",
|
||||||
"status": "สถานะ",
|
"status": "สถานะ",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "ซีพียู",
|
"cpu": "ซีพียู",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "İsim",
|
"name": "İsim",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Yükleme",
|
"up": "Yükleme",
|
||||||
|
"down": "İndirme",
|
||||||
|
"paused": "Duraklatıldı",
|
||||||
|
"pending": "Bekleyen",
|
||||||
"status": "Durum",
|
"status": "Durum",
|
||||||
"updated": "Güncellendi",
|
"updated": "Güncellendi",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Назва",
|
"name": "Назва",
|
||||||
"systems": "Системи",
|
"systems": "Системи",
|
||||||
"up": "Онлайн",
|
"up": "Онлайн",
|
||||||
|
"down": "Офлайн",
|
||||||
|
"paused": "Призупинено",
|
||||||
|
"pending": "В очікуванні",
|
||||||
"status": "Стан",
|
"status": "Стан",
|
||||||
"updated": "Оновлено",
|
"updated": "Оновлено",
|
||||||
"cpu": "ЦП",
|
"cpu": "ЦП",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "Paused",
|
||||||
|
"pending": "Đang xử lý",
|
||||||
"status": "Trạng thái",
|
"status": "Trạng thái",
|
||||||
"updated": "Updated",
|
"updated": "Updated",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "名稱",
|
"name": "名稱",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "在線",
|
"up": "在線",
|
||||||
|
"down": "離線",
|
||||||
|
"paused": "擱置中",
|
||||||
|
"pending": "待定",
|
||||||
"status": "狀況",
|
"status": "狀況",
|
||||||
"updated": "已更新",
|
"updated": "已更新",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
|
"down": "Down",
|
||||||
|
"paused": "暂停",
|
||||||
|
"pending": "待办的",
|
||||||
"status": "状态",
|
"status": "状态",
|
||||||
"updated": "已升级",
|
"updated": "已升级",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -982,6 +982,9 @@
|
|||||||
"name": "名稱",
|
"name": "名稱",
|
||||||
"systems": "Systems",
|
"systems": "Systems",
|
||||||
"up": "在線",
|
"up": "在線",
|
||||||
|
"down": "離線",
|
||||||
|
"paused": "擱置中",
|
||||||
|
"pending": "待下載",
|
||||||
"status": "狀態",
|
"status": "狀態",
|
||||||
"updated": "已更新",
|
"updated": "已更新",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
|
|||||||
@ -24,9 +24,9 @@ export default function BookmarksGroup({
|
|||||||
<div
|
<div
|
||||||
key={bookmarks.name}
|
key={bookmarks.name}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"bookmark-group",
|
"bookmark-group flex-1 overflow-hidden",
|
||||||
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6",
|
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6",
|
||||||
layout?.header === false ? "flex-1 px-1 -my-1 overflow-hidden" : "flex-1 p-1 overflow-hidden",
|
layout?.header === false ? "px-1" : "p-1 pb-0",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>
|
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>
|
||||||
|
|||||||
@ -5,15 +5,14 @@ import { columnMap } from "../../utils/layout/columns";
|
|||||||
import Item from "components/bookmarks/item";
|
import Item from "components/bookmarks/item";
|
||||||
|
|
||||||
export default function List({ bookmarks, layout, bookmarksStyle }) {
|
export default function List({ bookmarks, layout, bookmarksStyle }) {
|
||||||
let classes =
|
let classes = layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col bookmark-list";
|
||||||
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col mt-3 bookmark-list";
|
|
||||||
const style = {};
|
const style = {};
|
||||||
if (layout?.iconsOnly || bookmarksStyle === "icons") {
|
if (layout?.iconsOnly || bookmarksStyle === "icons") {
|
||||||
classes = "grid gap-3 mt-3 bookmark-list";
|
classes = "grid gap-2 bookmark-list";
|
||||||
style.gridTemplateColumns = "repeat(auto-fill, minmax(60px, 1fr))";
|
style.gridTemplateColumns = "repeat(auto-fill, minmax(60px, 1fr))";
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ul className={classNames(classes)} style={style}>
|
<ul className={classNames(classes, "mb-2", layout?.header === false ? "" : "mt-3")} style={style}>
|
||||||
{bookmarks.map((bookmark) => (
|
{bookmarks.map((bookmark) => (
|
||||||
<Item
|
<Item
|
||||||
key={`${bookmark.name}-${bookmark.href}`}
|
key={`${bookmark.name}-${bookmark.href}`}
|
||||||
|
|||||||
@ -14,8 +14,10 @@ export default class ErrorBoundary extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// You can also log error messages to an error reporting service here
|
// You can also log error messages to an error reporting service here
|
||||||
// eslint-disable-next-line no-console
|
if (error || errorInfo) {
|
||||||
console.error(error, errorInfo);
|
// eslint-disable-next-line no-console
|
||||||
|
console.error("component error: %s, info: %s", error, errorInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -101,7 +101,26 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
|
|||||||
const iconName = icon.replace(".svg", "");
|
const iconName = icon.replace(".svg", "");
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/${iconName}.svg`}
|
src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/${iconName}.svg`}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
style={{
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
objectFit: "contain",
|
||||||
|
maxHeight: "100%",
|
||||||
|
maxWidth: "100%",
|
||||||
|
}}
|
||||||
|
alt={alt}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon.endsWith(".webp")) {
|
||||||
|
const iconName = icon.replace(".webp", "");
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/webp/${iconName}.webp`}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={{
|
style={{
|
||||||
@ -119,7 +138,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
|
|||||||
const iconName = icon.replace(".png", "");
|
const iconName = icon.replace(".png", "");
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
|
src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/${iconName}.png`}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export default function ServicesGroup({
|
|||||||
disableCollapse,
|
disableCollapse,
|
||||||
useEqualHeights,
|
useEqualHeights,
|
||||||
groupsInitiallyCollapsed,
|
groupsInitiallyCollapsed,
|
||||||
|
isSubgroup,
|
||||||
}) {
|
}) {
|
||||||
const panel = useRef();
|
const panel = useRef();
|
||||||
|
|
||||||
@ -22,14 +23,18 @@ export default function ServicesGroup({
|
|||||||
if (layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) panel.current.style.height = `0`;
|
if (layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) panel.current.style.height = `0`;
|
||||||
}, [layout, groupsInitiallyCollapsed]);
|
}, [layout, groupsInitiallyCollapsed]);
|
||||||
|
|
||||||
|
let groupPadding = layout?.header === false ? "px-1" : "p-1 pb-0";
|
||||||
|
if (isSubgroup) groupPadding = "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={group.name}
|
key={group.name}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"services-group",
|
"services-group flex-1",
|
||||||
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
|
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
|
||||||
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
|
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
|
||||||
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1",
|
groupPadding,
|
||||||
|
isSubgroup ? "subgroup" : "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>
|
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>
|
||||||
@ -80,6 +85,7 @@ export default function ServicesGroup({
|
|||||||
services={group.services}
|
services={group.services}
|
||||||
layout={layout}
|
layout={layout}
|
||||||
useEqualHeights={useEqualHeights}
|
useEqualHeights={useEqualHeights}
|
||||||
|
header={layout?.header !== false}
|
||||||
/>
|
/>
|
||||||
{group.groups?.length > 0 && (
|
{group.groups?.length > 0 && (
|
||||||
<div
|
<div
|
||||||
@ -96,6 +102,7 @@ export default function ServicesGroup({
|
|||||||
disableCollapse={disableCollapse}
|
disableCollapse={disableCollapse}
|
||||||
useEqualHeights={useEqualHeights}
|
useEqualHeights={useEqualHeights}
|
||||||
groupsInitiallyCollapsed={groupsInitiallyCollapsed}
|
groupsInitiallyCollapsed={groupsInitiallyCollapsed}
|
||||||
|
isSubgroup
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -86,7 +86,7 @@ export default function Item({ service, groupName, useEqualHeights }) {
|
|||||||
<div
|
<div
|
||||||
className={`absolute top-0 right-0 flex flex-row justify-end ${
|
className={`absolute top-0 right-0 flex flex-row justify-end ${
|
||||||
statusStyle === "dot" ? "gap-0" : "gap-2 mr-2"
|
statusStyle === "dot" ? "gap-0" : "gap-2 mr-2"
|
||||||
} z-30 service-tags`}
|
} z-10 service-tags`}
|
||||||
>
|
>
|
||||||
{service.ping && (
|
{service.ping && (
|
||||||
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
|
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
|
||||||
|
|||||||
@ -4,12 +4,13 @@ import { columnMap } from "../../utils/layout/columns";
|
|||||||
|
|
||||||
import Item from "components/services/item";
|
import Item from "components/services/item";
|
||||||
|
|
||||||
export default function List({ groupName, services, layout, useEqualHeights }) {
|
export default function List({ groupName, services, layout, useEqualHeights, header }) {
|
||||||
return (
|
return (
|
||||||
<ul
|
<ul
|
||||||
className={classNames(
|
className={classNames(
|
||||||
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
|
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
|
||||||
"mt-3 services-list",
|
header ? "mt-3" : "",
|
||||||
|
"services-list",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{services.map((service) => (
|
{services.map((service) => (
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { useState, useEffect, Fragment } from "react";
|
import { useState, useEffect, Fragment } from "react";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { FiSearch } from "react-icons/fi";
|
import { FiSearch } from "react-icons/fi";
|
||||||
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
|
import { SiDuckduckgo, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
|
||||||
|
import { BiLogoBing } from "react-icons/bi";
|
||||||
import { Listbox, Transition, Combobox } from "@headlessui/react";
|
import { Listbox, Transition, Combobox } from "@headlessui/react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ export const searchProviders = {
|
|||||||
name: "Bing",
|
name: "Bing",
|
||||||
url: "https://www.bing.com/search?q=",
|
url: "https://www.bing.com/search?q=",
|
||||||
suggestionUrl: "https://api.bing.com/osjson.aspx?query=",
|
suggestionUrl: "https://api.bing.com/osjson.aspx?query=",
|
||||||
icon: SiMicrosoftbing,
|
icon: BiLogoBing,
|
||||||
},
|
},
|
||||||
baidu: {
|
baidu: {
|
||||||
name: "Baidu",
|
name: "Baidu",
|
||||||
|
|||||||
@ -4,10 +4,6 @@ export default function Document() {
|
|||||||
return (
|
return (
|
||||||
<Html>
|
<Html>
|
||||||
<Head>
|
<Head>
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations."
|
|
||||||
/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes" />
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
<link rel="manifest" href="/site.webmanifest?v=4" crossOrigin="use-credentials" />
|
<link rel="manifest" href="/site.webmanifest?v=4" crossOrigin="use-credentials" />
|
||||||
<link rel="preload" href="/api/config/custom.css" as="style" />
|
<link rel="preload" href="/api/config/custom.css" as="style" />
|
||||||
|
|||||||
@ -166,6 +166,18 @@ const headerStyles = {
|
|||||||
boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
|
boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getAllServices(services) {
|
||||||
|
function getServices(group) {
|
||||||
|
let nestedServices = [...group.services];
|
||||||
|
if (group.groups.length > 0) {
|
||||||
|
nestedServices = [...nestedServices, ...group.groups.map(getServices).flat()];
|
||||||
|
}
|
||||||
|
return nestedServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...services.map(getServices).flat()];
|
||||||
|
}
|
||||||
|
|
||||||
function Home({ initialSettings }) {
|
function Home({ initialSettings }) {
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const { theme, setTheme } = useContext(ThemeContext);
|
const { theme, setTheme } = useContext(ThemeContext);
|
||||||
@ -182,10 +194,9 @@ function Home({ initialSettings }) {
|
|||||||
const { data: bookmarks } = useSWR("/api/bookmarks");
|
const { data: bookmarks } = useSWR("/api/bookmarks");
|
||||||
const { data: widgets } = useSWR("/api/widgets");
|
const { data: widgets } = useSWR("/api/widgets");
|
||||||
|
|
||||||
const servicesAndBookmarks = [
|
const servicesAndBookmarks = [...bookmarks.map((bg) => bg.bookmarks).flat(), ...getAllServices(services)].filter(
|
||||||
...services.map((sg) => sg.services).flat(),
|
(i) => i?.href,
|
||||||
...bookmarks.map((bg) => bg.bookmarks).flat(),
|
);
|
||||||
].filter((i) => i?.href);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (settings.language) {
|
if (settings.language) {
|
||||||
@ -297,7 +308,6 @@ function Home({ initialSettings }) {
|
|||||||
disableCollapse={settings.disableCollapse}
|
disableCollapse={settings.disableCollapse}
|
||||||
useEqualHeights={settings.useEqualHeights}
|
useEqualHeights={settings.useEqualHeights}
|
||||||
groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed}
|
groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed}
|
||||||
bookmarksStyle={settings.bookmarksStyle}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<BookmarksGroup
|
<BookmarksGroup
|
||||||
@ -360,6 +370,13 @@ function Home({ initialSettings }) {
|
|||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>{initialSettings.title || "Homepage"}</title>
|
<title>{initialSettings.title || "Homepage"}</title>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content={
|
||||||
|
initialSettings.description ||
|
||||||
|
"A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations."
|
||||||
|
}
|
||||||
|
/>
|
||||||
{settings.base && <base href={settings.base} />}
|
{settings.base && <base href={settings.base} />}
|
||||||
{settings.favicon ? (
|
{settings.favicon ? (
|
||||||
<>
|
<>
|
||||||
@ -453,7 +470,7 @@ function Home({ initialSettings }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Wrapper({ initialSettings, fallback }) {
|
export default function Wrapper({ initialSettings, fallback }) {
|
||||||
const { theme } = useContext(ThemeContext);
|
const { themeContext } = useContext(ThemeContext);
|
||||||
const wrappedStyle = {};
|
const wrappedStyle = {};
|
||||||
let backgroundBlur = false;
|
let backgroundBlur = false;
|
||||||
let backgroundSaturate = false;
|
let backgroundSaturate = false;
|
||||||
@ -484,9 +501,9 @@ export default function Wrapper({ initialSettings, fallback }) {
|
|||||||
id="page_wrapper"
|
id="page_wrapper"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative",
|
"relative",
|
||||||
theme && theme,
|
initialSettings.theme && initialSettings.theme,
|
||||||
initialSettings.color && `theme-${initialSettings.color}`,
|
initialSettings.color && `theme-${initialSettings.color}`,
|
||||||
theme === "dark" ? "scheme-dark" : "scheme-light",
|
themeContext === "dark" ? "scheme-dark" : "scheme-light",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -65,5 +65,10 @@ dialog ::-webkit-scrollbar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chart + .chart {
|
.chart + .chart {
|
||||||
margin-top: 36px;
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-container + .chart {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: .5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,10 @@ function parseServicesToGroups(services) {
|
|||||||
const serviceGroupServices = [];
|
const serviceGroupServices = [];
|
||||||
serviceGroup[name].forEach((entries) => {
|
serviceGroup[name].forEach((entries) => {
|
||||||
const entryName = Object.keys(entries)[0];
|
const entryName = Object.keys(entries)[0];
|
||||||
|
if (!entries[entryName]) {
|
||||||
|
logger.warn(`Error parsing service "${entryName}" from config. Ensure required fields are present.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Array.isArray(entries[entryName])) {
|
if (Array.isArray(entries[entryName])) {
|
||||||
groups = groups.concat(parseServicesToGroups([{ [entryName]: entries[entryName] }]));
|
groups = groups.concat(parseServicesToGroups([{ [entryName]: entries[entryName] }]));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -79,7 +79,7 @@ export default async function genericProxyHandler(req, res, map) {
|
|||||||
error: {
|
error: {
|
||||||
message: "HTTP Error",
|
message: "HTTP Error",
|
||||||
url: sanitizeErrorURL(url),
|
url: sanitizeErrorURL(url),
|
||||||
resultData: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
|
data: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,8 +20,20 @@ export default function Component({ service }) {
|
|||||||
widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
|
widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (systemsError) {
|
let system = null;
|
||||||
return <Container service={service} error={systemsError} />;
|
let finalError = systemsError;
|
||||||
|
|
||||||
|
if (systems && !systems.items) {
|
||||||
|
finalError = { message: "No items returned from beszel API" };
|
||||||
|
} else if (systems && systems.items && systemId) {
|
||||||
|
system = systems.items.find((item) => item.id === systemId || item.name === systemId);
|
||||||
|
if (!system) {
|
||||||
|
finalError = { message: `System with id ${systemId} not found` };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalError) {
|
||||||
|
return <Container service={service} error={finalError} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!systems) {
|
if (!systems) {
|
||||||
@ -33,9 +45,7 @@ export default function Component({ service }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (systemId) {
|
if (system) {
|
||||||
const system = systems.items.find((item) => item.id === systemId);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="beszel.name" value={system.name} />
|
<Block label="beszel.name" value={system.name} />
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export default async function beszelProxyHandler(req, res) {
|
|||||||
if (!token) {
|
if (!token) {
|
||||||
[status, token] = await login(loginUrl, widget.username, widget.password, service);
|
[status, token] = await login(loginUrl, widget.username, widget.password, service);
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
logger.debug(`HTTP ${status} logging into Beszel: ${token}`);
|
logger.debug(`HTTP ${status} logging into Beszel: ${JSON.stringify(token)}`);
|
||||||
return res.status(status).send(token);
|
return res.status(status).send(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,13 +72,13 @@ export default async function beszelProxyHandler(req, res) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (status === 403) {
|
if ([400, 403].includes(status)) {
|
||||||
logger.debug(`HTTP ${status} retrieving data from Beszel, logging in and trying again.`);
|
logger.debug(`HTTP ${status} retrieving data from Beszel, logging in and trying again.`);
|
||||||
cache.del(`${tokenCacheKey}.${service}`);
|
cache.del(`${tokenCacheKey}.${service}`);
|
||||||
[status, token] = await login(loginUrl, widget.username, widget.password, service);
|
[status, token] = await login(loginUrl, widget.username, widget.password, service);
|
||||||
|
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
logger.debug(`HTTP ${status} logging into Beszel: ${data}`);
|
logger.debug(`HTTP ${status} logging into Beszel: ${JSON.stringify(data)}`);
|
||||||
return res.status(status).send(data);
|
return res.status(status).send(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const cellStyle = "relative w-10 flex items-center justify-center flex-col";
|
|||||||
const monthButton = "pl-6 pr-6 ml-2 mr-2 hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer";
|
const monthButton = "pl-6 pr-6 ml-2 mr-2 hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer";
|
||||||
|
|
||||||
export function Day({ weekNumber, weekday, events, colorVariants, showDate, setShowDate, currentDate }) {
|
export function Day({ weekNumber, weekday, events, colorVariants, showDate, setShowDate, currentDate }) {
|
||||||
const cellDate = showDate.set({ weekday, weekNumber }).startOf("day");
|
const cellDate = showDate.set({ weekday, weekNumber, weekYear: showDate.year }).startOf("day");
|
||||||
const filteredEvents = events?.filter((event) => compareDateTimezone(cellDate, event));
|
const filteredEvents = events?.filter((event) => compareDateTimezone(cellDate, event));
|
||||||
|
|
||||||
const dayStyles = (displayDate) => {
|
const dayStyles = (displayDate) => {
|
||||||
@ -35,7 +35,7 @@ export function Day({ weekNumber, weekday, events, colorVariants, showDate, setS
|
|||||||
// today style
|
// today style
|
||||||
style += "text-black-500 bg-theme-100/20 dark:bg-black/20 rounded-md ";
|
style += "text-black-500 bg-theme-100/20 dark:bg-black/20 rounded-md ";
|
||||||
} else {
|
} else {
|
||||||
style += "hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer ";
|
style += "hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer";
|
||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
|
|||||||
@ -78,6 +78,9 @@ function formatValue(t, mapping, rawValue) {
|
|||||||
case "percent":
|
case "percent":
|
||||||
value = t("common.percent", { value });
|
value = t("common.percent", { value });
|
||||||
break;
|
break;
|
||||||
|
case "duration":
|
||||||
|
value = t("common.duration", { value });
|
||||||
|
break;
|
||||||
case "bytes":
|
case "bytes":
|
||||||
value = t("common.bytes", { value });
|
value = t("common.bytes", { value });
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -29,10 +29,13 @@ export default function Component({ service }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// broken by evcc v0.133.0 https://github.com/evcc-io/evcc/commit/9dcb1fa0a7c08dd926b79309aa1f676a5fc6c8aa
|
||||||
|
const gridPower = stateData.result.gridPower ?? stateData.result.grid?.power ?? 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="evcc.pv_power" value={`${toKilowatts(t, stateData.result.pvPower)} ${t("evcc.kilowatt")}`} />
|
<Block label="evcc.pv_power" value={`${toKilowatts(t, stateData.result.pvPower)} ${t("evcc.kilowatt")}`} />
|
||||||
<Block label="evcc.grid_power" value={`${toKilowatts(t, stateData.result.gridPower)} ${t("evcc.kilowatt")}`} />
|
<Block label="evcc.grid_power" value={`${toKilowatts(t, gridPower)} ${t("evcc.kilowatt")}`} />
|
||||||
<Block label="evcc.home_power" value={`${toKilowatts(t, stateData.result.homePower)} ${t("evcc.kilowatt")}`} />
|
<Block label="evcc.home_power" value={`${toKilowatts(t, stateData.result.homePower)} ${t("evcc.kilowatt")}`} />
|
||||||
<Block
|
<Block
|
||||||
label="evcc.charge_power"
|
label="evcc.charge_power"
|
||||||
|
|||||||
@ -8,7 +8,7 @@ class Chart extends PureComponent {
|
|||||||
const { dataPoints, formatter, label } = this.props;
|
const { dataPoints, formatter, label } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute -top-1 -left-1 h-[120px] w-[calc(100%+0.5em)] z-0">
|
<div className="absolute -top-10 -left-2 h-[calc(100%+3em)] w-[calc(100%+1em)] z-0">
|
||||||
<div className="overflow-clip z-10 w-full h-full">
|
<div className="overflow-clip z-10 w-full h-full">
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
<AreaChart data={dataPoints}>
|
<AreaChart data={dataPoints}>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ class ChartDual extends PureComponent {
|
|||||||
const { dataPoints, formatter, stack, label, stackOffset } = this.props;
|
const { dataPoints, formatter, stack, label, stackOffset } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute -top-1 -left-1 h-[120px] w-[calc(100%+0.5em)] z-0">
|
<div className="absolute -top-10 -left-2 h-[calc(100%+3em)] w-[calc(100%+1em)] z-0">
|
||||||
<div className="overflow-clip z-10 w-full h-full">
|
<div className="overflow-clip z-10 w-full h-full">
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
<AreaChart data={dataPoints} stackOffset={stackOffset ?? "none"}>
|
<AreaChart data={dataPoints} stackOffset={stackOffset ?? "none"}>
|
||||||
|
|||||||
@ -18,10 +18,10 @@ export default function Container({ children, widget, error = null, chart = true
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames("service-container relative", chart ? "chart h-[84px]" : "")}>
|
<div className={classNames("service-container", chart ? "chart relative h-[68px]" : "")}>
|
||||||
{children}
|
{children}
|
||||||
<div className={`absolute top-0 right-0 bottom-0 left-0 overflow-clip pointer-events-none ${className}`} />
|
<div className={`absolute -top-10 right-0 bottom-0 left-0 overflow-clip pointer-events-none ${className}`} />
|
||||||
{chart && <div className="chart h-[68px] overflow-clip" />}
|
{chart && <div className="h-[68px] overflow-clip" />}
|
||||||
{!chart && <div className="h-[16px] overflow-clip" />}
|
{!chart && <div className="h-[16px] overflow-clip" />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -38,10 +38,16 @@ export default function Component({ service }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.splice(chart ? 5 : 1);
|
data.splice(chart ? 5 : 1);
|
||||||
|
let headerYPosition = "top-4";
|
||||||
|
let listYPosition = "bottom-4";
|
||||||
|
if (chart) {
|
||||||
|
headerYPosition = "-top-6";
|
||||||
|
listYPosition = "-top-3";
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container chart={chart}>
|
<Container chart={chart}>
|
||||||
<Block position="top-4 right-3 left-3">
|
<Block position={`${headerYPosition} right-3 left-3`}>
|
||||||
<div className="flex items-center text-xs">
|
<div className="flex items-center text-xs">
|
||||||
<div className="grow" />
|
<div className="grow" />
|
||||||
<div className="w-14 text-right italic">{t("resources.cpu")}</div>
|
<div className="w-14 text-right italic">{t("resources.cpu")}</div>
|
||||||
@ -49,7 +55,7 @@ export default function Component({ service }) {
|
|||||||
</div>
|
</div>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
<Block position="bottom-4 right-3 left-3">
|
<Block position={`${listYPosition} right-3 left-3`}>
|
||||||
<div className="pointer-events-none text-theme-900 dark:text-theme-200">
|
<div className="pointer-events-none text-theme-900 dark:text-theme-200">
|
||||||
{data.map((item) => (
|
{data.map((item) => (
|
||||||
<div key={item[idKey]} className="text-[0.75rem] h-[0.8rem]">
|
<div key={item[idKey]} className="text-[0.75rem] h-[0.8rem]">
|
||||||
|
|||||||
@ -43,10 +43,10 @@ export default function Component({ service }) {
|
|||||||
return (
|
return (
|
||||||
<Container chart={chart}>
|
<Container chart={chart}>
|
||||||
{chart && (
|
{chart && (
|
||||||
<div className="absolute top-0 left-0 right-0 bottom-0">
|
<div className="absolute -top-2 -left-2 -right-2 -bottom-2">
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
height: `${Math.max(20, fsData.size / fsData.free)}%`,
|
height: `${Math.max(20, (140 * (fsData.size - fsData.free)) / fsData.size)}px`,
|
||||||
}}
|
}}
|
||||||
className="absolute bottom-0 border-t border-t-theme-500 bg-gradient-to-b from-theme-500/40 to-theme-500/10 w-full"
|
className="absolute bottom-0 border-t border-t-theme-500 bg-gradient-to-b from-theme-500/40 to-theme-500/10 w-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -107,8 +107,12 @@ export default function Component({ service }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container chart={chart} className="bg-gradient-to-br from-theme-500/30 via-theme-600/20 to-theme-700/10">
|
<Container chart={chart}>
|
||||||
<Block position="top-3 right-3">
|
{chart && (
|
||||||
|
<div className="bg-gradient-to-br from-theme-500/30 via-theme-600/20 to-theme-700/10 absolute -top-10 -left-2 -right-2 -bottom-2 h-[calc(100%+3em)] w-[calc(100%+1em)]" />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Block position="-top-6 right-2">
|
||||||
{quicklookData && quicklookData.cpu_name && chart && (
|
{quicklookData && quicklookData.cpu_name && chart && (
|
||||||
<div className="text-[0.6rem] opacity-50">{quicklookData.cpu_name}</div>
|
<div className="text-[0.6rem] opacity-50">{quicklookData.cpu_name}</div>
|
||||||
)}
|
)}
|
||||||
@ -124,7 +128,7 @@ export default function Component({ service }) {
|
|||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
{chart && (
|
{chart && (
|
||||||
<Block position="bottom-3 left-3">
|
<Block position="bottom-3 left-2">
|
||||||
{systemData && systemData.linux_distro && <div className="text-xs opacity-50">{systemData.linux_distro}</div>}
|
{systemData && systemData.linux_distro && <div className="text-xs opacity-50">{systemData.linux_distro}</div>}
|
||||||
{systemData && systemData.os_version && <div className="text-xs opacity-50">{systemData.os_version}</div>}
|
{systemData && systemData.os_version && <div className="text-xs opacity-50">{systemData.os_version}</div>}
|
||||||
{systemData && systemData.hostname && <div className="text-xs opacity-75">{systemData.hostname}</div>}
|
{systemData && systemData.hostname && <div className="text-xs opacity-75">{systemData.hostname}</div>}
|
||||||
@ -137,7 +141,7 @@ export default function Component({ service }) {
|
|||||||
</Block>
|
</Block>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Block position="bottom-3 right-3 w-[4rem]">
|
<Block position="bottom-3 right-2 w-[4rem]">
|
||||||
{chart && <CPU quicklookData={quicklookData} className="opacity-50" />}
|
{chart && <CPU quicklookData={quicklookData} className="opacity-50" />}
|
||||||
|
|
||||||
{chart && <Mem quicklookData={quicklookData} className="opacity-50" />}
|
{chart && <Mem quicklookData={quicklookData} className="opacity-50" />}
|
||||||
|
|||||||
@ -42,10 +42,16 @@ export default function Component({ service }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.splice(chart ? 5 : 1);
|
data.splice(chart ? 5 : 1);
|
||||||
|
let headerYPosition = "top-4";
|
||||||
|
let listYPosition = "bottom-4";
|
||||||
|
if (chart) {
|
||||||
|
headerYPosition = "-top-6";
|
||||||
|
listYPosition = "-top-3";
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container chart={chart}>
|
<Container chart={chart}>
|
||||||
<Block position="top-0 right-3 left-3">
|
<Block position={`${headerYPosition} right-3 left-3`}>
|
||||||
<div className="flex items-center text-xs">
|
<div className="flex items-center text-xs">
|
||||||
<div className="grow" />
|
<div className="grow" />
|
||||||
<div className="w-14 text-right italic">{t("resources.cpu")}</div>
|
<div className="w-14 text-right italic">{t("resources.cpu")}</div>
|
||||||
@ -53,7 +59,7 @@ export default function Component({ service }) {
|
|||||||
</div>
|
</div>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
<Block position="bottom-2 right-3 left-3">
|
<Block position={`${listYPosition} right-3 left-3`}>
|
||||||
<div className="pointer-events-none text-theme-900 dark:text-theme-200">
|
<div className="pointer-events-none text-theme-900 dark:text-theme-200">
|
||||||
{data.map((item) => (
|
{data.map((item) => (
|
||||||
<div key={item.pid} className="text-[0.75rem] h-[0.8rem]">
|
<div key={item.pid} className="text-[0.75rem] h-[0.8rem]">
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const widget = {
|
|||||||
mappings: {
|
mappings: {
|
||||||
ip: {
|
ip: {
|
||||||
endpoint: "publicip/ip",
|
endpoint: "publicip/ip",
|
||||||
validate: ["public_ip", "region", "country"],
|
validate: ["public_ip", "country"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user