Compare commits

..

102 Commits
v0.9.13 ... dev

Author SHA1 Message Date
shamoon
e6a821ecc3 Bind all addreses in docker container 2025-01-27 10:50:44 -08:00
shamoon
49036a9738
Fix: fix semver detection bug 2025-01-27 00:23:20 -08:00
shamoon
0197b449ed
[BREAKING] Chore: update to next v15 (#4661) 2025-01-26 00:20:41 -08:00
shamoon
dc3382447c
Fix: fix overlap with glances charts in multi-widgets (#4653) 2025-01-24 16:53:14 -08:00
shamoon
6beaf665fb
Development: pnpm lint on ci (#4646) 2025-01-23 21:38:23 -08:00
shamoon
b9622f75b0 Fix: generic proxy error data display 2025-01-21 07:13:12 -08:00
shamoon
fe462a71d6
Fix: handle evcc breaking change (#4630) 2025-01-20 07:55:26 -08:00
Jesse Houston
1e556e105d
Documentation: add note about clearing UniFi cache non-docker (#4585) 2025-01-08 15:42:38 -08:00
shamoon
b5f4daa8ef
Fix: fix bing search logo (#4571) 2025-01-06 07:25:14 -08:00
shamoon
fd50241e2a
Update errorboundry.jsx 2025-01-06 00:53:10 -08:00
Bjorn Lammers
6a0fbba407
Chore: migrate dashboard-icons to homarr-labs (#4564) 2025-01-05 13:45:15 -08:00
shamoon
2ee5fd123b code style 2025-01-05 07:58:28 -08:00
shamoon
86a13817df Merge branch 'main' into dev 2025-01-05 07:57:05 -08:00
Adi Vaknin
2f7d948a5c
Fix: quick launch not showing nested services (#4561)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-01-05 07:56:12 -08:00
shamoon
1b79e51194
Update source.md 2025-01-04 22:13:28 -08:00
Martin Bjeldbak Madsen
2d98ac30f2
Documentation: update gluetun apikey config instructions (#4554)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-01-02 21:07:55 -08:00
shamoon
1a85175b15
Fix: toggle light / dark makes background white (#4553) 2025-01-02 19:13:14 -08:00
Peder Toftegaard Olsen
6f429a6a4b
Enhancement: add duration format to customapi widget (#4549)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-01-02 19:11:33 -08:00
shamoon
3020a2d1fd
Fix: better fs height (#4552) 2025-01-02 18:56:48 -08:00
shamoon
a6e85240c6 Update getting-started.md 2025-01-02 17:13:48 -08:00
shamoon
98e816204a Update getting-started.md 2025-01-02 17:13:36 -08:00
shamoon
a0b5ac318a
Update PULL_REQUEST_TEMPLATE.md 2025-01-02 16:34:24 -08:00
shamoon
101461b7b5 Update getting-started.md 2025-01-02 16:26:15 -08:00
shamoon
ba6f50f21d Merge branch 'main' into dev 2025-01-02 16:26:01 -08:00
shamoon
dd3a229559 Update getting-started.md 2025-01-02 16:25:32 -08:00
dependabot[bot]
630d5024ac
Chore(deps): Bump systeminformation from 5.23.8 to 5.24.3 (#4546)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 08:35:15 -08:00
dependabot[bot]
d239687e2e
Chore(deps): Bump react-icons from 4.12.0 to 5.4.0 (#4536)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 08:34:05 -08:00
dependabot[bot]
81a3dfbfe4
Chore(deps-dev): Bump tailwindcss from 3.4.14 to 3.4.17 (#4537)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 08:33:37 -08:00
dependabot[bot]
034720f47a
Chore(deps-dev): Bump eslint-plugin-react from 7.37.2 to 7.37.3 (#4534)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 08:33:23 -08:00
shamoon
0717607a97 Merge branch dev into main 2024-12-31 21:48:49 -08:00
github-actions[bot]
ee5442c15c
New Crowdin translations by GitHub Action (#4506) 2024-12-31 21:48:12 -08:00
shamoon
b2158b0921
Fix: incorrect weekyear for events (#4519) 2024-12-30 11:26:04 -08:00
shamoon
a158866ca1
Feature: meta description setting (#4513) 2024-12-28 21:12:20 -08:00
shamoon
4f27ffbe2d
Change: make region optional for gluetun api response (#4512) 2024-12-28 20:53:43 -08:00
shamoon
10bc8a15a9 Update support.yml 2024-12-28 16:50:23 -08:00
Per Mortensen
5d63b3d212
Fix: include all Beszel status localization strings (#4504) 2024-12-28 07:35:22 -08:00
shamoon
43decb0ed9
Fix: correct iconsOnly bookmark group spacing (#4502) 2024-12-27 16:11:47 -08:00
shamoon
e4d42b5393
FIx: glances containers header position (#4496) 2024-12-26 14:51:11 -08:00
shamoon
f717e59085
Enhancement: support 'nice name' for beszel system ID (#4495) 2024-12-26 11:07:33 -08:00
shamoon
fd05ae377c
Enhancement: Better handle some beszel errors (#4493) 2024-12-25 12:17:10 -08:00
shamoon
cc9b4782f2
Merge branch 'dev' 2024-12-24 22:20:20 -08:00
github-actions[bot]
14cda38dbb
New Crowdin translations by GitHub Action (#4481)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-12-24 22:19:23 -08:00
shamoon
27e3c9f1ed
Merge branch 'dev' 2024-12-24 22:18:55 -08:00
shamoon
607c4b7750
Fix: fun with padding and margins (#4489) 2024-12-24 12:22:06 -08:00
shamoon
1c6480586c
Fix: fix search overlay behind status indicators in 0.10.x (#4484) 2024-12-23 18:28:04 -08:00
shamoon
31c04006da Merge branch 'dev' 2024-12-23 14:02:38 -08:00
github-actions[bot]
499ab4d701
New Crowdin translations by GitHub Action (#4470)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-12-23 14:02:20 -08:00
shamoon
fbb35d3dc8 Merge branch 'dev' 2024-12-23 14:01:48 -08:00
shamoon
94936ed09d
Tweak: again trying to restore chart sizing in 0.10.x (#4479) 2024-12-23 13:37:48 -08:00
shamoon
31a511de02
Update getting-started.md 2024-12-23 09:27:25 -08:00
shamoon
2d91b2b748
Tweak: remove extra padding for nested groups (#4474) 2024-12-22 17:48:49 -08:00
shamoon
7dabd0335f
Remove service group bookmarksStyle 2024-12-22 17:37:46 -08:00
shamoon
96431c6085
Chore: warn and dont fail for invalid services (#4468) 2024-12-21 19:26:02 -08:00
shamoon
f64aa50cc0 Fix: metric heights in 0.10.x (#4467) 2024-12-21 19:14:00 -08:00
shamoon
ac39ffdc2f
Fix: dont discard service groups not included in layout (#4456) 2024-12-20 15:00:25 -08:00
dependabot[bot]
f4adebca92
Chore(deps): Bump systeminformation from 5.23.5 to 5.23.8 (#4450)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-20 11:40:25 -08:00
shamoon
b2d75a99e7 Merge branch 'dev' 2024-12-20 09:26:50 -08:00
github-actions[bot]
bda586b04e
New Crowdin translations by GitHub Action (#4330)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-12-20 09:02:04 -08:00
shamoon
4a4ca95fe5
Enhancement: beszel widget compatibility with v0.9.0 (#4439) 2024-12-18 13:04:18 -08:00
shamoon
6753843202 Fix: always parse version as a number 2024-12-18 12:51:12 -08:00
shamoon
6b77ae835b Update proxy.js 2024-12-18 12:12:08 -08:00
shamoon
d0eabf7adb Revert "Enhancement: encode uri params for synology proxy (#4414)"
This reverts commit 93c18a8077.

Revert "Fix synology param encoding"

This reverts commit bc3adf1f2a.

Revert "I think this will actually fix the synology handler"

This reverts commit 30fd42dba4.
2024-12-18 11:48:02 -08:00
shamoon
30fd42dba4 I think this will actually fix the synology handler 2024-12-18 11:06:07 -08:00
shamoon
7bcdba16c6 Fix: chart stacking with multiple widgets 2024-12-18 10:14:59 -08:00
Mindfreak9100
59ed5ed114
Enhancement: downloading torrents list for deluge (#4436) 2024-12-17 16:09:46 -08:00
Jesse Hills
6b2a3da7ee
Enhancement: support basic auth to ESPHome widget (#4429) 2024-12-16 20:35:15 -08:00
shamoon
b853c566b2 Some npm audit 2024-12-16 17:39:59 -08:00
shamoon
bc3adf1f2a Fix synology param encoding 2024-12-16 11:45:35 -08:00
shamoon
c437b414ab
Enhancement: better display of finnhub tickers with exchange (#4425) 2024-12-16 09:01:28 -08:00
shamoon
9aa46e4fdd
Use initial settings for title 2024-12-15 20:08:11 -08:00
shamoon
0c352b1843 Add a little debugging to stocks endpoint 2024-12-15 19:15:27 -08:00
shamoon
f229bca609 Update headscale.md 2024-12-15 19:02:29 -08:00
shamoon
93c18a8077
Enhancement: encode uri params for synology proxy (#4414) 2024-12-15 15:36:46 -08:00
shamoon
deff2f5506 Maybe this will make the requirements more obvious 2024-12-15 15:36:28 -08:00
shamoon
d0937fe6a8 Updated requirements 2024-12-14 23:02:11 -08:00
shamoon
a35c60f973
Update repo-maintenance.yml 2024-12-14 22:59:56 -08:00
shamoon
29928a9a5f
Update requirement 2024-12-14 22:57:36 -08:00
shamoon
191a95c55c Fix: maybe prevent unnecessary search suggestion calls 2024-12-14 15:53:15 -08:00
Epoch Philosophy
48e0a0e8ef
Documentation: update k8s.md to Reflect New Traefik V3 API (#4416) 2024-12-13 12:03:32 -08:00
shamoon
20445583cd Build feature images 2024-12-13 10:59:44 -08:00
shamoon
5bc67137f6
Fix: glances metric - different key for process list memory on windows host (#4410) 2024-12-12 20:53:20 -08:00
Mindfreak9100
22c02f4e45
Enhancement: downloading torrents list for qbittorrent (#4405) 2024-12-12 16:32:03 -08:00
shamoon
3c28e4af44 Fix empty groups with configured services 2024-12-12 15:42:06 -08:00
shamoon
01252c6193
Fix: correct evcc units (#4396) 2024-12-10 08:36:32 -08:00
shamoon
27f536c267 Fix: evcc docs name 2024-12-10 08:34:21 -08:00
shamoon
cb3248117f
Enhancement: icons-only bookmarks style (#4384) 2024-12-05 15:35:31 -08:00
shamoon
c58f59c105 Fix: add optional chaining for info widgets options 2024-12-02 14:38:55 -08:00
dependabot[bot]
8cc6640d04
Chore(deps-dev): Bump eslint-plugin-react from 7.37.1 to 7.37.2 (#4367)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 09:02:09 -08:00
dependabot[bot]
20df9a5e9c
Chore(deps): Bump gamedig from 5.1.3 to 5.1.4 (#4369)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 08:56:52 -08:00
shamoon
91e529f87a
Enhancement: glances containers metric widget (#4361) 2024-11-29 23:32:59 -08:00
shamoon
a28952ce69
Chore: move custom css loading, add letter-spacing (#4359) 2024-11-29 10:14:53 -08:00
shamoon
276a1c3ef4
Chore: better tailscale error handling 2024-11-28 21:54:22 -08:00
zombaru
5cc487a96d
Documentation: Add missing admonition type to UniFi docs (#4353) 2024-11-28 20:15:28 -08:00
shamoon
e626274f34
Documentation: doc updates for nesting, reorganizing, fixes 2024-11-27 23:02:55 -08:00
shamoon
6d829bce79
Enhancement: use css color-scheme (#4349) 2024-11-27 22:12:59 -08:00
DamitusThyYeetus123
230da3d2eb
Enhancement: support hrefs for info widgets (#4347)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-11-27 19:45:30 -08:00
shamoon
aaf4a3e92f Add note 2024-11-27 18:07:54 -08:00
shamoon
be8363cc35
Feature: nested groups (#4346) 2024-11-27 17:01:47 -08:00
shamoon
907abee1aa
Enhancement: multiple widgets per service (#4338) 2024-11-27 02:33:40 -08:00
shamoon
385511f773
Fix: resources network better startup behavior 2024-11-27 02:33:15 -08:00
shamoon
cbf304a4c8
Update README.md 2024-11-24 22:56:35 -08:00
shamoon
897309a47c
Enhancement: resources network widget (#4327) 2024-11-24 22:56:34 -08:00
169 changed files with 4940 additions and 3120 deletions

View File

@ -1,3 +0,0 @@
{
"presets": ["next/babel"]
}

View File

@ -54,3 +54,11 @@ body:
description: Please include output from your [troubleshooting tests](https://gethomepage.dev/more/troubleshooting/#service-widget-errors), if relevant.
validations:
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.*

View File

@ -1,11 +1,20 @@
<!--
==== STOP ====================
======== STOP ================
============ STOP ============
================ STOP ========
==================== STOP ====
⚠️ Before opening this pull request please review the guidelines in the checklist below.
If this PR does not meet those guidelines it will not be accepted, and everyone will be sad.
-->
## Proposed change
<!--
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.
-->
@ -19,13 +28,13 @@ What type of change does your PR introduce to Homepage?
- [ ] New service widget
- [ ] 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
- [ ] Other (please explain)
## Checklist:
- [ ] 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).
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.

View File

@ -46,6 +46,24 @@ jobs:
-
name: Check files
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:
name: Docker Build & Push
@ -118,7 +136,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.event_name != 'pull_request' && !(github.event_name == 'push' && startsWith(github.ref, 'refs/heads/feature')) }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
@ -127,7 +145,7 @@ jobs:
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
# https://github.com/docker/setup-qemu-action#about
# platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
platforms: linux/amd64,linux/arm64
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max

View File

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

View File

@ -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.
- Discussions with a marked answer will be automatically closed.
- 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.
Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features.

View File

@ -1,7 +1,7 @@
# syntax = docker/dockerfile:latest
# Install dependencies only when needed
FROM docker.io/node:18-alpine AS deps
FROM docker.io/node:22-alpine AS deps
WORKDIR /app
@ -17,7 +17,7 @@ RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm f
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline
# Rebuild the source code only when needed
FROM docker.io/node:18-alpine AS builder
FROM docker.io/node:22-alpine AS builder
WORKDIR /app
ARG BUILDTIME
@ -33,7 +33,7 @@ RUN npm run telemetry \
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
# Production image, copy all the files and run next
FROM docker.io/node:18-alpine AS runner
FROM docker.io/node:22-alpine AS runner
LABEL org.opencontainers.image.title "Homepage"
LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations."
LABEL org.opencontainers.image.url="https://github.com/gethomepage/homepage"
@ -41,7 +41,7 @@ LABEL org.opencontainers.image.documentation='https://github.com/gethomepage/hom
LABEL org.opencontainers.image.source='https://github.com/gethomepage/homepage'
LABEL org.opencontainers.image.licenses='Apache-2.0'
ENV NODE_ENV production
ENV NODE_ENV=production
WORKDIR /app
@ -56,7 +56,8 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
RUN apk add --no-cache su-exec
ENV PORT 3000
ENV HOSTNAME=::
ENV PORT=3000
EXPOSE $PORT
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \

View File

@ -38,7 +38,7 @@ With features like quick search, bookmarks, weather support, a wide range of int
- **Fast** - The site is statically generated at build time for instant load times.
- **Secure** - All API requests to backend services are proxied, keeping your API keys hidden. Constantly reviewed for security by the community.
- **For Everyone** - Images built for AMD64, ARM64, ARMv7, and ARMv6.
- **For Everyone** - Images built for AMD64, ARM64.
- **Full i18n** - Support for over 40 languages.
- **Service & Web Bookmarks** - Add custom links to the homepage.
- **Docker Integration** - Container status and stats. Automatic service discovery via labels.
@ -52,7 +52,7 @@ Homepage has built-in support for Docker, and can automatically discover and add
## Service Widgets
Homepage also has support for over 100 3rd party services, including all popular starr apps, and most popular self-hosted apps. Some examples include: Radarr, Sonarr, Lidarr, Bazarr, Ombi, Tautulli, Plex, Jellyfin, Emby, Transmission, qBittorrent, Deluge, Jackett, NZBGet, SABnzbd, etc. As well as service integrations, Homepage also has a number of information providers, sourcing information from a variety of external 3rd party APIs. See the [Service](https://gethomepage.dev/widgets/) page for more information.
Homepage also has support for hundreds of 3rd-party services, including all popular \*arr apps, and most popular self-hosted apps. Some examples include: Radarr, Sonarr, Lidarr, Bazarr, Ombi, Tautulli, Plex, Jellyfin, Emby, Transmission, qBittorrent, Deluge, Jackett, NZBGet, SABnzbd, etc. As well as service integrations, Homepage also has a number of information providers, sourcing information from a variety of external 3rd-party APIs. See the [Service](https://gethomepage.dev/widgets/) page for more information.
## Information Widgets

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,3 +23,5 @@ Finally, run the server:
```bash
pnpm start
```
When updating homepage versions you will need to re-build the static files i.e. repeat the process above.

View File

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

View File

@ -46,16 +46,16 @@ 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
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.
## Service Widget Guidelines
To ensure cohesiveness of various widgets, the following should be used as a guide for developing new widgets:
- Please only submit widgets that target a feature request discussion with at least 10 'up-votes'. The purpose of this requirement is to avoid the addition (and maintenance) of service widgets that might only benefit a small number of users.
- Please only submit widgets that target a feature request discussion with at least 20 'up-votes'. The purpose of this requirement is to avoid the addition (and maintenance) of service widgets that might only benefit a small number of users.
- Note that we reserve the right to decline widgets for projects that are very young (eg < ~1y) or those with a small reach (eg low GitHub stars). Again, this is in an effort to keep overall widget maintenance under control.
- Widgets should be only one row of blocks
- Widgets should be no more than 4 blocks wide and generally conform to the styling / design choices of other widgets

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,11 +7,16 @@ Learn more about [Beszel](https://github.com/henrygd/beszel)
The widget has two modes, a single system with detailed info if `systemId` is provided, or an overview of all systems if `systemId` is not provided.
The `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 a single system: `["name", "status", "updated", "cpu", "memory", "disk", "network"]`
| Beszel Version | Homepage Widget Version |
| -------------- | ----------------------- |
| < 0.9.0 | 1 (default) |
| >= 0.9.0 | 2 |
```yaml
widget:
type: beszel
@ -19,4 +24,5 @@ widget:
username: username # email
password: password
systemId: systemId # optional
version: 2 # optional, default is 1
```

View File

@ -62,10 +62,12 @@ widget:
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 `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`.
## Example

View File

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

View File

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

View File

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

View File

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

View File

@ -11,7 +11,7 @@ Learn more about [Gluetun](https://github.com/qdm12/gluetun).
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
widget:

View File

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

View File

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

View File

@ -9,7 +9,7 @@ _(Find the Unifi Controller information widget [here](../info/unifi_controller.m
You can display general connectivity status from your Unifi (Network) Controller.
!!!
!!! warning
When authenticating you will want to use a local account that has at least read privileges.
@ -19,7 +19,7 @@ Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "w
!!! 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
widget:

View File

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

3169
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,36 +10,36 @@
"telemetry": "next telemetry disable"
},
"dependencies": {
"@headlessui/react": "^1.7.18",
"@headlessui/react": "^1.7.19",
"@kubernetes/client-node": "^0.17.1",
"cal-parser": "^1.0.2",
"classnames": "^2.5.1",
"compare-versions": "^6.1.0",
"dockerode": "^4.0.2",
"follow-redirects": "^1.15.9",
"gamedig": "^5.1.2",
"gamedig": "^5.1.4",
"i18next": "^21.10.0",
"js-yaml": "^4.1.0",
"json-rpc-2.0": "^1.7.0",
"luxon": "^3.5.0",
"memory-cache": "^0.2.0",
"minecraft-ping-js": "^1.0.2",
"next": "^12.3.4",
"next": "^15.0.3",
"next-i18next": "^12.1.0",
"ping": "^0.4.4",
"pretty-bytes": "^6.1.1",
"raw-body": "^3.0.0",
"react": "^18.3.1",
"react-dom": "^18.2.0",
"react-dom": "^18.3.1",
"react-i18next": "^11.18.6",
"react-icons": "^4.12.0",
"recharts": "^2.12.6",
"react-icons": "^5.4.0",
"recharts": "^2.12.7",
"rrule": "^2.8.1",
"swr": "^1.3.0",
"systeminformation": "^5.23.2",
"tough-cookie": "^4.1.3",
"urbackup-server-api": "^0.52.1",
"winston": "^3.11.0",
"systeminformation": "^5.24.3",
"tough-cookie": "^4.1.4",
"urbackup-server-api": "^0.8.9",
"winston": "^3.13.0",
"xml-js": "^1.6.11"
},
"devDependencies": {
@ -47,17 +47,17 @@
"autoprefixer": "^10.4.20",
"eslint": "^8.57.1",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "^14.2.3",
"eslint-config-next": "^14.2.4",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-jsx-a11y": "^6.9.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.47",
"prettier": "^3.2.5",
"postcss": "^8.4.48",
"prettier": "^3.3.2",
"tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.4.14",
"tailwindcss": "^3.4.17",
"typescript": "^5.6.3"
},
"optionalDependencies": {

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,13 @@ import ErrorBoundary from "components/errorboundry";
import List from "components/bookmarks/list";
import ResolvedIcon from "components/resolvedicon";
export default function BookmarksGroup({ bookmarks, layout, disableCollapse, groupsInitiallyCollapsed }) {
export default function BookmarksGroup({
bookmarks,
layout,
disableCollapse,
groupsInitiallyCollapsed,
bookmarksStyle,
}) {
const panel = useRef();
useEffect(() => {
@ -18,9 +24,9 @@ export default function BookmarksGroup({ bookmarks, layout, disableCollapse, gro
<div
key={bookmarks.name}
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?.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}>
@ -64,7 +70,7 @@ export default function BookmarksGroup({ bookmarks, layout, disableCollapse, gro
>
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
<ErrorBoundary>
<List bookmarks={bookmarks.bookmarks} layout={layout} />
<List bookmarks={bookmarks.bookmarks} layout={layout} bookmarksStyle={bookmarksStyle} />
</ErrorBoundary>
</Disclosure.Panel>
</Transition>

View File

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

View File

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

View File

@ -14,8 +14,10 @@ export default class ErrorBoundary extends React.Component {
});
// You can also log error messages to an error reporting service here
// eslint-disable-next-line no-console
console.error(error, errorInfo);
if (error || errorInfo) {
// eslint-disable-next-line no-console
console.error("component error: %s, info: %s", error, errorInfo);
}
}
render() {

View File

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

View File

@ -1,5 +1,5 @@
import { useContext } from "react";
import Image from "next/future/image";
import Image from "next/image";
import { SettingsContext } from "utils/contexts/settings";
import { ThemeContext } from "utils/contexts/theme";
@ -101,7 +101,26 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
const iconName = icon.replace(".svg", "");
return (
<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}
height={height}
style={{
@ -119,7 +138,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
const iconName = icon.replace(".png", "");
return (
<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}
height={height}
style={{

View File

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

View File

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

View File

@ -4,19 +4,20 @@ import { columnMap } from "../../utils/layout/columns";
import Item from "components/services/item";
export default function List({ group, services, layout, useEqualHeights }) {
export default function List({ groupName, services, layout, useEqualHeights, header }) {
return (
<ul
className={classNames(
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) => (
<Item
key={[service.container, service.app, service.name].filter((s) => s).join("-")}
service={service}
group={group}
groupName={groupName}
useEqualHeights={layout?.useEqualHeights ?? useEqualHeights}
/>
))}

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import { useTranslation } from "next-i18next";
import useSWR from "swr";
import { compareVersions } from "compare-versions";
import { compareVersions, validate } from "compare-versions";
import { MdNewReleases } from "react-icons/md";
export default function Version() {
@ -44,7 +44,7 @@ export default function Version() {
</a>
)}
</span>
{version === "main" || version === "dev" || version === "nightly"
{!validate(version)
? null
: releaseData &&
latestRelease &&

View File

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

View File

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

View File

@ -1,7 +1,8 @@
import { useState, useEffect, Fragment } from "react";
import { useTranslation } from "next-i18next";
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 classNames from "classnames";
@ -25,7 +26,7 @@ export const searchProviders = {
name: "Bing",
url: "https://www.bing.com/search?q=",
suggestionUrl: "https://api.bing.com/osjson.aspx?query=",
icon: SiMicrosoftbing,
icon: BiLogoBing,
},
baidu: {
name: "Baidu",
@ -94,6 +95,7 @@ export default function Search({ options }) {
if (
options.showSearchSuggestions &&
(selectedProvider.suggestionUrl || options.suggestionUrl) && // custom providers pass url via options
query.trim().length > 0 &&
query.trim() !== searchSuggestions[0]
) {
fetch(`/api/search/searchSuggestion?query=${encodeURIComponent(query)}&providerName=${selectedProvider.name}`, {

View File

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

View File

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

View File

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

View File

@ -4,12 +4,10 @@ export default function Document() {
return (
<Html>
<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" />
<link rel="manifest" href="/site.webmanifest?v=4" crossOrigin="use-credentials" />
<link rel="preload" href="/api/config/custom.css" as="style" />
<link rel="stylesheet" href="/api/config/custom.css" /> {/* eslint-disable-line @next/next/no-css-tags */}
</Head>
<body>
<Main />

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