Compare commits

...

38 Commits
v0.10.5 ... 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
d0937fe6a8 Updated requirements 2024-12-14 23:02:11 -08:00
75 changed files with 3807 additions and 2527 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. description: Please include output from your [troubleshooting tests](https://gethomepage.dev/more/troubleshooting/#service-widget-errors), if relevant.
validations: validations:
required: true required: true
- type: markdown
attributes:
value: |
## ⚠️ STOP ⚠️
Before you submit this support request, please ensure you have entered your configuration files and actually followed the steps from the troubleshooting guide linked above, if relevant. The troubleshooting steps often help to solve the problem.
*Please remember that this project is maintained by regular people **just like you**, so if you don't take the time to fill out the requested information, don't expect a reply back.*

View File

@ -6,6 +6,7 @@
==================== STOP ==== ==================== STOP ====
⚠️ Before opening this pull request please review the guidelines in the checklist below. ⚠️ Before opening this pull request please review the guidelines in the checklist below.
If this PR does not meet those guidelines it will not be accepted, and everyone will be sad. If this PR does not meet those guidelines it will not be accepted, and everyone will be sad.
--> -->
@ -14,9 +15,6 @@ If this PR does not meet those guidelines it will not be accepted, and everyone
<!-- <!--
Please include a summary of the change. Screenshots and/or videos can also be helpful if appropriate. Please include a summary of the change. Screenshots and/or videos can also be helpful if appropriate.
*** Please see the development guidelines for new widgets: https://gethomepage.dev/more/development/#service-widget-guidelines
*** If you do not follow these guidelines your PR will likely be closed without review.
New service widgets should include example(s) of relevant API output as well as updates to the docs for the new widget. New service widgets should include example(s) of relevant API output as well as updates to the docs for the new widget.
--> -->
@ -30,13 +28,13 @@ What type of change does your PR introduce to Homepage?
- [ ] New service widget - [ ] New service widget
- [ ] Bug fix (non-breaking change which fixes an issue) - [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality) - [ ] New feature or enhancement (non-breaking change which adds functionality)
- [ ] Documentation only - [ ] Documentation only
- [ ] Other (please explain) - [ ] Other (please explain)
## Checklist: ## Checklist:
- [ ] If applicable, I have added corresponding documentation changes. - [ ] If applicable, I have added corresponding documentation changes.
- [ ] If applicable, I have reviewed the [feature](https://gethomepage.dev/more/development/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/more/development/#service-widget-guidelines). - [ ] If applicable, I have reviewed the [feature / enhancement](https://gethomepage.dev/more/development/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/more/development/#service-widget-guidelines).
- [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/more/development/#code-linting). - [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/more/development/#code-linting).
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers. - [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.

View File

@ -46,6 +46,24 @@ jobs:
- -
name: Check files name: Check files
uses: pre-commit/action@v3.0.1 uses: pre-commit/action@v3.0.1
-
name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
run_install: false
-
name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
-
name: Install dependencies
run: pnpm install
-
name: Lint frontend
run: pnpm run lint
build: build:
name: Docker Build & Push name: Docker Build & Push
@ -127,7 +145,7 @@ jobs:
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
# https://github.com/docker/setup-qemu-action#about # 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/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-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max

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. - Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity.
- Discussions with a marked answer will be automatically closed. - Discussions with a marked answer will be automatically closed.
- Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity. - Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity.
- Feature requests that do not meet the following thresholds will be closed: 5 "up-votes" after 180 days of inactivity or 10 "up-votes" after 365 days. - Feature requests that do not meet the following thresholds will be closed: 10 "up-votes" after 180 days of inactivity or 20 "up-votes" after 365 days.
In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns. In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns.
Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features. Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features.

View File

@ -1,7 +1,7 @@
# syntax = docker/dockerfile:latest # syntax = docker/dockerfile:latest
# Install dependencies only when needed # Install dependencies only when needed
FROM docker.io/node:18-alpine AS deps FROM docker.io/node:22-alpine AS deps
WORKDIR /app 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 RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline
# Rebuild the source code only when needed # 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 WORKDIR /app
ARG BUILDTIME 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 && NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
# Production image, copy all the files and run next # 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.title "Homepage"
LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations." 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" 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.source='https://github.com/gethomepage/homepage'
LABEL org.opencontainers.image.licenses='Apache-2.0' LABEL org.opencontainers.image.licenses='Apache-2.0'
ENV NODE_ENV production ENV NODE_ENV=production
WORKDIR /app WORKDIR /app
@ -56,7 +56,8 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
RUN apk add --no-cache su-exec RUN apk add --no-cache su-exec
ENV PORT 3000 ENV HOSTNAME=::
ENV PORT=3000
EXPOSE $PORT EXPOSE $PORT
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \ 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. - **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. - **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. - **Full i18n** - Support for over 40 languages.
- **Service & Web Bookmarks** - Add custom links to the homepage. - **Service & Web Bookmarks** - Add custom links to the homepage.
- **Docker Integration** - Container status and stats. Automatic service discovery via labels. - **Docker Integration** - Container status and stats. Automatic service discovery via labels.

View File

@ -134,7 +134,7 @@ Services may have descriptions,
## Icons ## Icons
Services may have an icon attached to them, you can use icons from [Dashboard Icons](https://github.com/walkxcode/dashboard-icons) automatically, by passing the name of the icon, with, or without `.png` or with `.svg` to use the svg version. Services may have an icon attached to them, you can use icons from [Dashboard Icons](https://github.com/homarr-labs/dashboard-icons) automatically, by passing the name of the icon, with, or without `.png`, `.webp` or `.svg` to specify the desired version.
You can also specify prefixed icons from: You can also specify prefixed icons from:

View File

@ -13,6 +13,14 @@ You can customize the title of the page if you'd like.
title: My Awesome Homepage title: My Awesome Homepage
``` ```
## Description
You can customize the description of the page if you'd like.
```yaml
description: A description of my awesome homepage
```
## Start URL ## Start URL
You can customize the start_url as required for installable apps. The default is "/". You can customize the start_url as required for installable apps. The default is "/".

View File

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

View File

@ -46,9 +46,9 @@ See the [pre-commit documentation](https://pre-commit.com/#install) to get start
In general, homepage is meant to be a dashboard for 'self-hosted' services and we believe it is a small way we can help showcase this kind of software. While exceptions are made, mostly when there is no viable In general, homepage is meant to be a dashboard for 'self-hosted' services and we believe it is a small way we can help showcase this kind of software. While exceptions are made, mostly when there is no viable
self-hosted / open-source alternative, we ask that any widgets, etc. are developed primarily for a self-hosted tool. self-hosted / open-source alternative, we ask that any widgets, etc. are developed primarily for a self-hosted tool.
## New Feature Guidelines ## New Feature or Enhancement Guidelines {#new-feature-guidelines}
- New features should be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users. - New features or enhancements, **no matter how small**, must be linked to an existing feature request. The purpose of this requirement is to avoid the addition (and maintenance) of features that might only benefit a small number of users.
- If you have ideas for a larger feature you may want to open a discussion first. - If you have ideas for a larger feature you may want to open a discussion first.
## Service Widget Guidelines ## Service Widget Guidelines

View File

@ -62,10 +62,12 @@ widget:
format: size format: size
``` ```
Supported formats for the values are `text`, `number`, `float`, `percent`, `bytes`, `bitrate`, `size`, `date` and `relativeDate`. Supported formats for the values are `text`, `number`, `float`, `percent`, `duration`, `bytes`, `bitrate`, `size`, `date` and `relativeDate`.
The `dateStyle` and `timeStyle` options of the `date` format are passed directly to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) and the `style` and `numeric` options of `relativeDate` are passed to [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat). The `dateStyle` and `timeStyle` options of the `date` format are passed directly to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) and the `style` and `numeric` options of `relativeDate` are passed to [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat).
The `duration` format expects the duration to be specified in seconds. The `scale` transformation tool can be used if a conversion is required.
The `size` format will return the length of the array or string, or the number of keys in an object. This is then formatted as `number`. The `size` format will return the length of the array or string, or the number of keys in an object. This is then formatted as `number`.
## Example ## Example

View File

@ -11,7 +11,7 @@ Learn more about [Gluetun](https://github.com/qdm12/gluetun).
Allowed fields: `["public_ip", "region", "country"]`. Allowed fields: `["public_ip", "region", "country"]`.
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). Note that to use the api key method, you must add the route `GET /v1/publicip/ip` to the `routes` array in your Gluetun config.toml.
```yaml ```yaml
widget: widget:

View File

@ -19,7 +19,7 @@ Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "w
!!! hint !!! hint
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache. If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container or restart the service to clear the cache.
```yaml ```yaml
widget: widget:

3132
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
"telemetry": "next telemetry disable" "telemetry": "next telemetry disable"
}, },
"dependencies": { "dependencies": {
"@headlessui/react": "^1.7.18", "@headlessui/react": "^1.7.19",
"@kubernetes/client-node": "^0.17.1", "@kubernetes/client-node": "^0.17.1",
"cal-parser": "^1.0.2", "cal-parser": "^1.0.2",
"classnames": "^2.5.1", "classnames": "^2.5.1",
@ -24,22 +24,22 @@
"luxon": "^3.5.0", "luxon": "^3.5.0",
"memory-cache": "^0.2.0", "memory-cache": "^0.2.0",
"minecraft-ping-js": "^1.0.2", "minecraft-ping-js": "^1.0.2",
"next": "^12.3.4", "next": "^15.0.3",
"next-i18next": "^12.1.0", "next-i18next": "^12.1.0",
"ping": "^0.4.4", "ping": "^0.4.4",
"pretty-bytes": "^6.1.1", "pretty-bytes": "^6.1.1",
"raw-body": "^3.0.0", "raw-body": "^3.0.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.2.0", "react-dom": "^18.3.1",
"react-i18next": "^11.18.6", "react-i18next": "^11.18.6",
"react-icons": "^4.12.0", "react-icons": "^5.4.0",
"recharts": "^2.12.6", "recharts": "^2.12.7",
"rrule": "^2.8.1", "rrule": "^2.8.1",
"swr": "^1.3.0", "swr": "^1.3.0",
"systeminformation": "^5.23.8", "systeminformation": "^5.24.3",
"tough-cookie": "^4.1.3", "tough-cookie": "^4.1.4",
"urbackup-server-api": "^0.52.1", "urbackup-server-api": "^0.8.9",
"winston": "^3.11.0", "winston": "^3.13.0",
"xml-js": "^1.6.11" "xml-js": "^1.6.11"
}, },
"devDependencies": { "devDependencies": {
@ -47,17 +47,17 @@
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"eslint": "^8.57.1", "eslint": "^8.57.1",
"eslint-config-airbnb": "^19.0.4", "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-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.31.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-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.2", "eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.47", "postcss": "^8.4.48",
"prettier": "^3.2.5", "prettier": "^3.3.2",
"tailwind-scrollbar": "^3.0.5", "tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.4.14", "tailwindcss": "^3.4.17",
"typescript": "^5.6.3" "typescript": "^5.6.3"
}, },
"optionalDependencies": { "optionalDependencies": {

File diff suppressed because it is too large Load Diff

View File

@ -982,6 +982,9 @@
"name": "Naam", "name": "Naam",
"systems": "Stelsels", "systems": "Stelsels",
"up": "Op", "up": "Op",
"down": "Af",
"paused": "Onderbreek",
"pending": "Afwagtend",
"status": "Status", "status": "Status",
"updated": "Opgedateer", "updated": "Opgedateer",
"cpu": "SVE", "cpu": "SVE",

View File

@ -982,6 +982,9 @@
"name": "الاسم", "name": "الاسم",
"systems": "Systems", "systems": "Systems",
"up": "يعمل", "up": "يعمل",
"down": "لا يعمل",
"paused": "متوقف",
"pending": "معلق",
"status": "الحالة", "status": "الحالة",
"updated": "محدث", "updated": "محدث",
"cpu": "المعالج", "cpu": "المعالج",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Статус", "status": "Статус",
"updated": "Updated", "updated": "Updated",
"cpu": "Процесор", "cpu": "Процесор",

View File

@ -982,6 +982,9 @@
"name": "Nom", "name": "Nom",
"systems": "Sistemes", "systems": "Sistemes",
"up": "Actiu", "up": "Actiu",
"down": "Inactiu",
"paused": "En pausa",
"pending": "Pendent",
"status": "Estat", "status": "Estat",
"updated": "Actualitzat", "updated": "Actualitzat",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Pozastaveno",
"pending": "Čeká",
"status": "Stav", "status": "Stav",
"updated": "Aktualizováno", "updated": "Aktualizováno",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Navn", "name": "Navn",
"systems": "Systems", "systems": "Systems",
"up": "Op", "up": "Op",
"down": "Ned",
"paused": "Pause",
"pending": "Afventer",
"status": "Status", "status": "Status",
"updated": "Opdateret", "updated": "Opdateret",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systeme", "systems": "Systeme",
"up": "Senden", "up": "Senden",
"down": "Empfangen",
"paused": "Pausiert",
"pending": "Ausstehend",
"status": "Status", "status": "Status",
"updated": "Aktualisiert", "updated": "Aktualisiert",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Όνομα", "name": "Όνομα",
"systems": "Systems", "systems": "Systems",
"up": "Ping up", "up": "Ping up",
"down": "Ping down",
"paused": "Paused",
"pending": "Σε εκκρεμότητα",
"status": "Κατάσταση", "status": "Κατάσταση",
"updated": "Ενημερώθηκε", "updated": "Ενημερώθηκε",
"cpu": "Επεξεργαστής", "cpu": "Επεξεργαστής",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Stato", "status": "Stato",
"updated": "Updated", "updated": "Updated",
"cpu": "Ĉefprocesoro", "cpu": "Ĉefprocesoro",

View File

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

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Vireillä",
"status": "Tila", "status": "Tila",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

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

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "ממתין",
"status": "סטטוס", "status": "סטטוס",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Ime", "name": "Ime",
"systems": "Systems", "systems": "Systems",
"up": "Dostupno", "up": "Dostupno",
"down": "Nedostupno",
"paused": "Zaustavljeno",
"pending": "U tijeku",
"status": "Stanje", "status": "Stanje",
"updated": "Aktualizirano", "updated": "Aktualizirano",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Név", "name": "Név",
"systems": "Rendszerek", "systems": "Rendszerek",
"up": "Fel", "up": "Fel",
"down": "Le",
"paused": "Szünetel",
"pending": "Függőben",
"status": "Státusz", "status": "Státusz",
"updated": "Frissített", "updated": "Frissített",
"cpu": "Processzor", "cpu": "Processzor",

View File

@ -982,6 +982,9 @@
"name": "Nama", "name": "Nama",
"systems": "Systems", "systems": "Systems",
"up": "Hidup", "up": "Hidup",
"down": "Mati",
"paused": "Pause",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Terbarui", "updated": "Terbarui",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Nome", "name": "Nome",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "In Pausa",
"pending": "In attesa",
"status": "Stato", "status": "Stato",
"updated": "Aggiornato", "updated": "Aggiornato",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "名前", "name": "名前",
"systems": "Systems", "systems": "Systems",
"up": "稼働", "up": "稼働",
"down": "下へ",
"paused": "一時停止中",
"pending": "保留中",
"status": "状態", "status": "状態",
"updated": "更新済", "updated": "更新済",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "이름", "name": "이름",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "대기 중",
"status": "상태", "status": "상태",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Statuss", "status": "Statuss",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Nama", "name": "Nama",
"systems": "Systems", "systems": "Systems",
"up": "Hidup", "up": "Hidup",
"down": "Mati",
"paused": "Tangguh",
"pending": "Tertunda",
"status": "Status", "status": "Status",
"updated": "Dikemaskini", "updated": "Dikemaskini",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Naam", "name": "Naam",
"systems": "Systemen", "systems": "Systemen",
"up": "Online", "up": "Online",
"down": "Offline",
"paused": "Gepauzeerd",
"pending": "In afwachting",
"status": "Status", "status": "Status",
"updated": "Bijgewerkt", "updated": "Bijgewerkt",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Navn", "name": "Navn",
"systems": "Systems", "systems": "Systems",
"up": "Oppe", "up": "Oppe",
"down": "Nede",
"paused": "Pauset",
"pending": "Ventende",
"status": "Status", "status": "Status",
"updated": "Oppdatert", "updated": "Oppdatert",
"cpu": "CPU", "cpu": "CPU",

View File

@ -13,7 +13,7 @@
"ms": "{{value, number}}", "ms": "{{value, number}}",
"date": "{{value, date}}", "date": "{{value, date}}",
"relativeDate": "{{value, relativeDate}}", "relativeDate": "{{value, relativeDate}}",
"duration": "{value, duration}", "duration": "{{value, duration}}",
"months": "mc", "months": "mc",
"days": "d", "days": "d",
"hours": "g", "hours": "g",
@ -982,6 +982,9 @@
"name": "Nazwa", "name": "Nazwa",
"systems": "Systemy", "systems": "Systemy",
"up": "Dostępny", "up": "Dostępny",
"down": "Niedostępny",
"paused": "Zatrzymane",
"pending": "Oczekiwane",
"status": "Stan", "status": "Stan",
"updated": "Zaktualizowane", "updated": "Zaktualizowane",
"cpu": "Procesor", "cpu": "Procesor",

View File

@ -982,6 +982,9 @@
"name": "Nome", "name": "Nome",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Pausa",
"pending": "Pendente",
"status": "Estado", "status": "Estado",
"updated": "Atualizado", "updated": "Atualizado",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Nome", "name": "Nome",
"systems": "Systems", "systems": "Systems",
"up": "Ativo", "up": "Ativo",
"down": "Inativo",
"paused": "Pausado",
"pending": "Pendente",
"status": "Status", "status": "Status",
"updated": "Atualizado", "updated": "Atualizado",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Sus", "up": "Sus",
"down": "Jos",
"paused": "Paused",
"pending": "În așteptare",
"status": "Stare", "status": "Stare",
"updated": "Updated", "updated": "Updated",
"cpu": "Procesor", "cpu": "Procesor",

View File

@ -982,6 +982,9 @@
"name": "Имя", "name": "Имя",
"systems": "Системы", "systems": "Системы",
"up": "Онлайн", "up": "Онлайн",
"down": "Офлайн",
"paused": "Приостановлено",
"pending": "В обработке",
"status": "Статус", "status": "Статус",
"updated": "Обновленно", "updated": "Обновленно",
"cpu": "ЦП", "cpu": "ЦП",

View File

@ -982,6 +982,9 @@
"name": "Meno", "name": "Meno",
"systems": "Systems", "systems": "Systems",
"up": "Nahrávanie", "up": "Nahrávanie",
"down": "Sťahovanie",
"paused": "Pozastavené",
"pending": "Čakajúce",
"status": "Stav", "status": "Stav",
"updated": "Aktualizované", "updated": "Aktualizované",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Naziv", "name": "Naziv",
"systems": "Sistemi", "systems": "Sistemi",
"up": "Povezan", "up": "Povezan",
"down": "Nepovezan",
"paused": "Pavziran",
"pending": "V teku",
"status": "Stanje", "status": "Stanje",
"updated": "Posodobljen", "updated": "Posodobljen",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Avvaktar",
"status": "Status", "status": "Status",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "పెండింగ్",
"status": "హోదా", "status": "హోదా",
"updated": "నవీకరించబడింది", "updated": "నవీకరించబడింది",
"cpu": "సీపియూ", "cpu": "సీపియూ",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Pending",
"status": "สถานะ", "status": "สถานะ",
"updated": "Updated", "updated": "Updated",
"cpu": "ซีพียู", "cpu": "ซีพียู",

View File

@ -982,6 +982,9 @@
"name": "İsim", "name": "İsim",
"systems": "Systems", "systems": "Systems",
"up": "Yükleme", "up": "Yükleme",
"down": "İndirme",
"paused": "Duraklatıldı",
"pending": "Bekleyen",
"status": "Durum", "status": "Durum",
"updated": "Güncellendi", "updated": "Güncellendi",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Назва", "name": "Назва",
"systems": "Системи", "systems": "Системи",
"up": "Онлайн", "up": "Онлайн",
"down": "Офлайн",
"paused": "Призупинено",
"pending": "В очікуванні",
"status": "Стан", "status": "Стан",
"updated": "Оновлено", "updated": "Оновлено",
"cpu": "ЦП", "cpu": "ЦП",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "Paused",
"pending": "Đang xử lý",
"status": "Trạng thái", "status": "Trạng thái",
"updated": "Updated", "updated": "Updated",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "名稱", "name": "名稱",
"systems": "Systems", "systems": "Systems",
"up": "在線", "up": "在線",
"down": "離線",
"paused": "擱置中",
"pending": "待定",
"status": "狀況", "status": "狀況",
"updated": "已更新", "updated": "已更新",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "Name", "name": "Name",
"systems": "Systems", "systems": "Systems",
"up": "Up", "up": "Up",
"down": "Down",
"paused": "暂停",
"pending": "待办的",
"status": "状态", "status": "状态",
"updated": "已升级", "updated": "已升级",
"cpu": "CPU", "cpu": "CPU",

View File

@ -982,6 +982,9 @@
"name": "名稱", "name": "名稱",
"systems": "Systems", "systems": "Systems",
"up": "在線", "up": "在線",
"down": "離線",
"paused": "擱置中",
"pending": "待下載",
"status": "狀態", "status": "狀態",
"updated": "已更新", "updated": "已更新",
"cpu": "CPU", "cpu": "CPU",

View File

@ -24,9 +24,9 @@ export default function BookmarksGroup({
<div <div
key={bookmarks.name} key={bookmarks.name}
className={classNames( className={classNames(
"bookmark-group", "bookmark-group flex-1 overflow-hidden",
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6",
layout?.header === false ? "flex-1 px-1 -my-1 overflow-hidden" : "flex-1 p-1 overflow-hidden", layout?.header === false ? "px-1" : "p-1 pb-0",
)} )}
> >
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}> <Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>

View File

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

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 // You can also log error messages to an error reporting service here
if (error || errorInfo) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(error, errorInfo); console.error("component error: %s, info: %s", error, errorInfo);
}
} }
render() { render() {

View File

@ -1,5 +1,5 @@
import { useContext } from "react"; import { useContext } from "react";
import Image from "next/future/image"; import Image from "next/image";
import { SettingsContext } from "utils/contexts/settings"; import { SettingsContext } from "utils/contexts/settings";
import { ThemeContext } from "utils/contexts/theme"; 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", ""); const iconName = icon.replace(".svg", "");
return ( return (
<Image <Image
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/${iconName}.svg`} src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/${iconName}.svg`}
width={width}
height={height}
style={{
width,
height,
objectFit: "contain",
maxHeight: "100%",
maxWidth: "100%",
}}
alt={alt}
/>
);
}
if (icon.endsWith(".webp")) {
const iconName = icon.replace(".webp", "");
return (
<Image
src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/webp/${iconName}.webp`}
width={width} width={width}
height={height} height={height}
style={{ style={{
@ -119,7 +138,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
const iconName = icon.replace(".png", ""); const iconName = icon.replace(".png", "");
return ( return (
<Image <Image
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`} src={`https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/${iconName}.png`}
width={width} width={width}
height={height} height={height}
style={{ style={{

View File

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

View File

@ -1,7 +1,8 @@
import { useState, useEffect, Fragment } from "react"; import { useState, useEffect, Fragment } from "react";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { FiSearch } from "react-icons/fi"; import { FiSearch } from "react-icons/fi";
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si"; import { SiDuckduckgo, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
import { BiLogoBing } from "react-icons/bi";
import { Listbox, Transition, Combobox } from "@headlessui/react"; import { Listbox, Transition, Combobox } from "@headlessui/react";
import classNames from "classnames"; import classNames from "classnames";
@ -25,7 +26,7 @@ export const searchProviders = {
name: "Bing", name: "Bing",
url: "https://www.bing.com/search?q=", url: "https://www.bing.com/search?q=",
suggestionUrl: "https://api.bing.com/osjson.aspx?query=", suggestionUrl: "https://api.bing.com/osjson.aspx?query=",
icon: SiMicrosoftbing, icon: BiLogoBing,
}, },
baidu: { baidu: {
name: "Baidu", name: "Baidu",

View File

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

View File

@ -166,6 +166,18 @@ const headerStyles = {
boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1", boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
}; };
function getAllServices(services) {
function getServices(group) {
let nestedServices = [...group.services];
if (group.groups.length > 0) {
nestedServices = [...nestedServices, ...group.groups.map(getServices).flat()];
}
return nestedServices;
}
return [...services.map(getServices).flat()];
}
function Home({ initialSettings }) { function Home({ initialSettings }) {
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const { theme, setTheme } = useContext(ThemeContext); const { theme, setTheme } = useContext(ThemeContext);
@ -182,10 +194,9 @@ function Home({ initialSettings }) {
const { data: bookmarks } = useSWR("/api/bookmarks"); const { data: bookmarks } = useSWR("/api/bookmarks");
const { data: widgets } = useSWR("/api/widgets"); const { data: widgets } = useSWR("/api/widgets");
const servicesAndBookmarks = [ const servicesAndBookmarks = [...bookmarks.map((bg) => bg.bookmarks).flat(), ...getAllServices(services)].filter(
...services.map((sg) => sg.services).flat(), (i) => i?.href,
...bookmarks.map((bg) => bg.bookmarks).flat(), );
].filter((i) => i?.href);
useEffect(() => { useEffect(() => {
if (settings.language) { if (settings.language) {
@ -359,6 +370,13 @@ function Home({ initialSettings }) {
<> <>
<Head> <Head>
<title>{initialSettings.title || "Homepage"}</title> <title>{initialSettings.title || "Homepage"}</title>
<meta
name="description"
content={
initialSettings.description ||
"A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations."
}
/>
{settings.base && <base href={settings.base} />} {settings.base && <base href={settings.base} />}
{settings.favicon ? ( {settings.favicon ? (
<> <>
@ -452,7 +470,7 @@ function Home({ initialSettings }) {
} }
export default function Wrapper({ initialSettings, fallback }) { export default function Wrapper({ initialSettings, fallback }) {
const { theme } = useContext(ThemeContext); const { themeContext } = useContext(ThemeContext);
const wrappedStyle = {}; const wrappedStyle = {};
let backgroundBlur = false; let backgroundBlur = false;
let backgroundSaturate = false; let backgroundSaturate = false;
@ -483,9 +501,9 @@ export default function Wrapper({ initialSettings, fallback }) {
id="page_wrapper" id="page_wrapper"
className={classNames( className={classNames(
"relative", "relative",
theme && theme, initialSettings.theme && initialSettings.theme,
initialSettings.color && `theme-${initialSettings.color}`, initialSettings.color && `theme-${initialSettings.color}`,
theme === "dark" ? "scheme-dark" : "scheme-light", themeContext === "dark" ? "scheme-dark" : "scheme-light",
)} )}
> >
<div <div

View File

@ -67,3 +67,8 @@ dialog ::-webkit-scrollbar {
.chart + .chart { .chart + .chart {
margin-top: 2em; margin-top: 2em;
} }
.service-container + .chart {
margin-top: 2.5rem;
margin-bottom: .5rem;
}

View File

@ -79,7 +79,7 @@ export default async function genericProxyHandler(req, res, map) {
error: { error: {
message: "HTTP Error", message: "HTTP Error",
url: sanitizeErrorURL(url), url: sanitizeErrorURL(url),
resultData: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData, data: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
}, },
}); });
} }

View File

@ -9,7 +9,7 @@ const cellStyle = "relative w-10 flex items-center justify-center flex-col";
const monthButton = "pl-6 pr-6 ml-2 mr-2 hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer"; const monthButton = "pl-6 pr-6 ml-2 mr-2 hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer";
export function Day({ weekNumber, weekday, events, colorVariants, showDate, setShowDate, currentDate }) { export function Day({ weekNumber, weekday, events, colorVariants, showDate, setShowDate, currentDate }) {
const cellDate = showDate.set({ weekday, weekNumber }).startOf("day"); const cellDate = showDate.set({ weekday, weekNumber, weekYear: showDate.year }).startOf("day");
const filteredEvents = events?.filter((event) => compareDateTimezone(cellDate, event)); const filteredEvents = events?.filter((event) => compareDateTimezone(cellDate, event));
const dayStyles = (displayDate) => { const dayStyles = (displayDate) => {

View File

@ -78,6 +78,9 @@ function formatValue(t, mapping, rawValue) {
case "percent": case "percent":
value = t("common.percent", { value }); value = t("common.percent", { value });
break; break;
case "duration":
value = t("common.duration", { value });
break;
case "bytes": case "bytes":
value = t("common.bytes", { value }); value = t("common.bytes", { value });
break; break;

View File

@ -29,10 +29,13 @@ export default function Component({ service }) {
); );
} }
// broken by evcc v0.133.0 https://github.com/evcc-io/evcc/commit/9dcb1fa0a7c08dd926b79309aa1f676a5fc6c8aa
const gridPower = stateData.result.gridPower ?? stateData.result.grid?.power ?? 0;
return ( return (
<Container service={service}> <Container service={service}>
<Block label="evcc.pv_power" value={`${toKilowatts(t, stateData.result.pvPower)} ${t("evcc.kilowatt")}`} /> <Block label="evcc.pv_power" value={`${toKilowatts(t, stateData.result.pvPower)} ${t("evcc.kilowatt")}`} />
<Block label="evcc.grid_power" value={`${toKilowatts(t, stateData.result.gridPower)} ${t("evcc.kilowatt")}`} /> <Block label="evcc.grid_power" value={`${toKilowatts(t, gridPower)} ${t("evcc.kilowatt")}`} />
<Block label="evcc.home_power" value={`${toKilowatts(t, stateData.result.homePower)} ${t("evcc.kilowatt")}`} /> <Block label="evcc.home_power" value={`${toKilowatts(t, stateData.result.homePower)} ${t("evcc.kilowatt")}`} />
<Block <Block
label="evcc.charge_power" label="evcc.charge_power"

View File

@ -46,7 +46,7 @@ export default function Component({ service }) {
<div className="absolute -top-2 -left-2 -right-2 -bottom-2"> <div className="absolute -top-2 -left-2 -right-2 -bottom-2">
<div <div
style={{ style={{
height: `${Math.max(20, fsData.size / fsData.free)}%`, height: `${Math.max(20, (140 * (fsData.size - fsData.free)) / fsData.size)}px`,
}} }}
className="absolute bottom-0 border-t border-t-theme-500 bg-gradient-to-b from-theme-500/40 to-theme-500/10 w-full" className="absolute bottom-0 border-t border-t-theme-500 bg-gradient-to-b from-theme-500/40 to-theme-500/10 w-full"
/> />

View File

@ -7,7 +7,7 @@ const widget = {
mappings: { mappings: {
ip: { ip: {
endpoint: "publicip/ip", endpoint: "publicip/ip",
validate: ["public_ip", "region", "country"], validate: ["public_ip", "country"],
}, },
}, },
}; };