Compare commits

..
Author SHA1 Message Date
Manuel 0db0c656b2 Merge branch 'dev' 2026-03-27 18:43:45 +01:00
Lorinc936 d48254fa57 Merge branch 'dev' into main 2026-03-24 20:41:22 +01:00
Lorinc936 b2fdab0418 defined notificationSchema outside of class 2026-03-24 18:11:10 +01:00
Lorinc936 e78dc86aa3 Update nextcloud.integration.ts 2026-03-24 14:44:24 +01:00
Lorinc936andManuel e70d804ab8 Update packages/integrations/src/nextcloud/nextcloud.integration.ts
Co-authored-by: Manuel <30572287+manuel-rw@users.noreply.github.com>
2026-03-23 19:12:42 +01:00
Lorinc936 b7c3a48377 feat: add Nextcloud notification provider
fix: resolve hydration error in add-board modal
2026-03-23 17:25:22 +01:00
101 changed files with 1373 additions and 1809 deletions

No files matched your search

-2
View File
@@ -33,8 +33,6 @@ body:
options:
# The below comment is used to insert a new version with on-release.yml
#NEXT_VERSION#
- 1.57.1
- 1.57.0
- 1.56.1
- 1.56.0
- 1.55.0
+2 -2
View File
@@ -15,11 +15,11 @@ runs:
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
- name: Build docker image for ${{ inputs.architecture }}
id: build
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
push: false
load: true
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@v6
- name: Obtain token
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.RENOVATE_APPROVE_PRIVATE_KEY }}
app-id: ${{ secrets.RENOVATE_APPROVE_APP_ID }}
+1 -1
View File
@@ -89,7 +89,7 @@ jobs:
uses: ./tooling/github/setup
- name: Build docker image
id: build-docker-image
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
platforms: linux/amd64
context: .
@@ -19,7 +19,7 @@ jobs:
- name: Obtain token
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.CROWDIN_APP_PRIVATE_KEY }}
app-id: ${{ secrets.CROWDIN_APP_ID }}
+10 -10
View File
@@ -50,7 +50,7 @@ jobs:
- name: Obtain token
if: env.SKIP_RELEASE == 'false'
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
app-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
@@ -60,12 +60,12 @@ jobs:
if: env.SKIP_RELEASE == 'false'
with:
persist-credentials: false
- uses: pnpm/action-setup@v5
- uses: pnpm/action-setup@v4
if: env.SKIP_RELEASE == 'false'
- uses: actions/setup-node@v6
if: env.SKIP_RELEASE == 'false'
with:
node-version: 24.14.1
node-version: 24.14.0
cache: "pnpm"
- run: npm i -g pnpm
if: env.SKIP_RELEASE == 'false'
@@ -123,7 +123,7 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: "${{ env.GHCR_REPO }}"
@@ -135,11 +135,11 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
network: host
@@ -162,7 +162,7 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: "${{ env.GHCR_REPO }}"
@@ -174,11 +174,11 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
network: host
@@ -231,7 +231,7 @@ jobs:
- name: Obtain token
if: needs.release.outputs.skipped == 'false'
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
app-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
@@ -50,7 +50,7 @@ jobs:
args: "Created a release PR ${{ steps.create-pull-request.outputs.url }} for version ${{ steps.semver.outputs.next }} (new behaviour: ${{ steps.semver.outputs.bump }})"
- name: Obtain token
id: obtainApprovalToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.RENOVATE_APPROVE_PRIVATE_KEY }}
app-id: ${{ secrets.RENOVATE_APPROVE_APP_ID }}
@@ -62,7 +62,7 @@ jobs:
gh pr review --approve --body "Automatically approved by GitHub Action"
- name: Obtain token
id: obtainMergeToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
app-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
+2 -2
View File
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Obtain token
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.HOMARR_DOCS_RELEASE_APP_PRIVATE_KEY }}
app-id: ${{ vars.HOMARR_DOCS_RELEASE_APP_ID }}
@@ -45,7 +45,7 @@ jobs:
steps:
- name: Obtain token
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
app-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
+2 -2
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Obtain token
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.HOMARR_UPDATE_CONTRIBUTORS_PRIVATE_KEY }}
app-id: ${{ vars.HOMARR_UPDATE_CONTRIBUTORS_APP_ID }}
@@ -33,7 +33,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
- uses: pnpm/action-setup@v5
- uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Obtain token
id: obtainToken
uses: actions/create-github-app-token@v3
uses: actions/create-github-app-token@v2
with:
private-key: ${{ secrets.HOMARR_UPDATE_CONTRIBUTORS_PRIVATE_KEY }}
app-id: ${{ vars.HOMARR_UPDATE_CONTRIBUTORS_APP_ID }}
+1 -1
View File
@@ -1 +1 @@
24.14.1
24.14.0
-50
View File
@@ -1,53 +1,3 @@
## [1.57.1](https://github.com/homarr-labs/homarr/compare/v1.57.0...v1.57.1) (2026-03-27)
### Bug Fixes
* dashdot gpu ([#5347](https://github.com/homarr-labs/homarr/issues/5347)) ([192a43a](https://github.com/homarr-labs/homarr/commit/192a43a031eb9431da2c11395eda69a6c7236b9b))
* **deps:** update dependency @t3-oss/env-nextjs to ^0.13.11 ([#5345](https://github.com/homarr-labs/homarr/issues/5345)) ([49d9394](https://github.com/homarr-labs/homarr/commit/49d9394cd78b2a1146c8dc00dd982215a2f9a580))
* **deps:** update dependency dockerode to ^4.0.10 ([#5327](https://github.com/homarr-labs/homarr/issues/5327)) ([42a3791](https://github.com/homarr-labs/homarr/commit/42a3791e6b5664a0f28d3ee4d29d5257ef3765f6))
* **deps:** update dependency fast-xml-parser to ^5.5.8 ([#5324](https://github.com/homarr-labs/homarr/issues/5324)) ([7982938](https://github.com/homarr-labs/homarr/commit/798293813cf82e38d7059069823f927b7cdfb3b8))
## [1.57.0](https://github.com/homarr-labs/homarr/compare/v1.56.1...v1.57.0) (2026-03-27)
### Features
* add "allowModals" option for iframe widget ([#5339](https://github.com/homarr-labs/homarr/issues/5339)) ([2fefd9d](https://github.com/homarr-labs/homarr/commit/2fefd9da01c827160fa5fd9b63a38615ea9969e2))
* add GPU monitoring support via Glances integration ([#5255](https://github.com/homarr-labs/homarr/issues/5255)) ([003dac4](https://github.com/homarr-labs/homarr/commit/003dac4744f2e23535f1cbb7494187201af4b164)), closes [#5102](https://github.com/homarr-labs/homarr/issues/5102)
* add nextcloud notification provider ([#5343](https://github.com/homarr-labs/homarr/issues/5343)) ([f88bf95](https://github.com/homarr-labs/homarr/commit/f88bf9582e1cf45a6b7fd898e12d227869a3849f))
### Bug Fixes
* **deps:** update dependency @immich/sdk to ^2.6.0 ([#5318](https://github.com/homarr-labs/homarr/issues/5318)) ([20a9b3d](https://github.com/homarr-labs/homarr/commit/20a9b3d556a15e6fdf7d1dbd78b677b5ce219c75))
* **deps:** update dependency @immich/sdk to ^2.6.1 ([#5319](https://github.com/homarr-labs/homarr/issues/5319)) ([feaf022](https://github.com/homarr-labs/homarr/commit/feaf022965cf4a27112c7e3bcb9ef3ad0dd5c281))
* **deps:** update dependency @next/eslint-plugin-next to v16.1.7 ([#5289](https://github.com/homarr-labs/homarr/issues/5289)) ([237d11d](https://github.com/homarr-labs/homarr/commit/237d11d2c021e28d58b0d627d2802d509d4c1b2b))
* **deps:** update dependency @tanstack/react-query to ^5.91.0 ([#5305](https://github.com/homarr-labs/homarr/issues/5305)) ([13b99d0](https://github.com/homarr-labs/homarr/commit/13b99d021b46fe0541ce9b42ba66756fafd26c30))
* **deps:** update dependency @tanstack/react-query to ^5.91.2 ([#5314](https://github.com/homarr-labs/homarr/issues/5314)) ([6fa6ba3](https://github.com/homarr-labs/homarr/commit/6fa6ba385e6691fefbb9f045a0ff976bcd85de16))
* **deps:** update dependency drizzle-kit to ^0.31.10 ([#5291](https://github.com/homarr-labs/homarr/issues/5291)) ([09227a3](https://github.com/homarr-labs/homarr/commit/09227a3884d291032f1012b59ce06babc3c87103))
* **deps:** update dependency fast-xml-parser to ^5.5.6 ([#5297](https://github.com/homarr-labs/homarr/issues/5297)) ([991044e](https://github.com/homarr-labs/homarr/commit/991044ebd78288bea7b441d3c14b159b5e66915b))
* **deps:** update dependency fast-xml-parser to ^5.5.7 ([#5315](https://github.com/homarr-labs/homarr/issues/5315)) ([2336f9e](https://github.com/homarr-labs/homarr/commit/2336f9ee5e35f7b610743dee55b91caf8434c1e4))
* **deps:** update dependency ioredis to v5.10.1 ([#5316](https://github.com/homarr-labs/homarr/issues/5316)) ([47b2d36](https://github.com/homarr-labs/homarr/commit/47b2d36f7a0933b6a6bbb61a449888be9304e1c5))
* **deps:** update dependency isomorphic-dompurify to ^3.4.0 ([#5292](https://github.com/homarr-labs/homarr/issues/5292)) ([6276449](https://github.com/homarr-labs/homarr/commit/62764499e7bbc9995ecf3de7351c9224d6aee4b6))
* **deps:** update dependency isomorphic-dompurify to ^3.5.0 ([#5299](https://github.com/homarr-labs/homarr/issues/5299)) ([b6b11c3](https://github.com/homarr-labs/homarr/commit/b6b11c39d2b4a33c5732ae239d7c1aaba6003cc6))
* **deps:** update dependency isomorphic-dompurify to ^3.5.1 ([#5300](https://github.com/homarr-labs/homarr/issues/5300)) ([94dfddf](https://github.com/homarr-labs/homarr/commit/94dfddf8bde2966b46bcd2d30e5e4f886ebe4605))
* **deps:** update dependency isomorphic-dompurify to ^3.6.0 ([#5334](https://github.com/homarr-labs/homarr/issues/5334)) ([8d64cb8](https://github.com/homarr-labs/homarr/commit/8d64cb8a5e276677b033774152c921aedc1e6c8a))
* **deps:** update dependency mysql2 to v3.20.0 ([#5283](https://github.com/homarr-labs/homarr/issues/5283)) ([4fb48c2](https://github.com/homarr-labs/homarr/commit/4fb48c23a2ccb1c047bab0d354933561e81cc3ed))
* **deps:** update dependency swagger-ui-react to ^5.32.1 ([#5296](https://github.com/homarr-labs/homarr/issues/5296)) ([63c55ce](https://github.com/homarr-labs/homarr/commit/63c55cec5711c41544c65ab83f24d09e63b10354))
* **deps:** update dependency trpc-to-openapi to ^3.2.0 ([#5320](https://github.com/homarr-labs/homarr/issues/5320)) ([22f5d3b](https://github.com/homarr-labs/homarr/commit/22f5d3b95959cf0a835c9750b41106eaafc4432e))
* **deps:** update dependency typescript-eslint to ^8.57.1 ([#5286](https://github.com/homarr-labs/homarr/issues/5286)) ([d4e4c96](https://github.com/homarr-labs/homarr/commit/d4e4c9669d648632a055b5ec0515821b50821142))
* **deps:** update dependency undici to v7.24.5 ([#5338](https://github.com/homarr-labs/homarr/issues/5338)) ([22bbef9](https://github.com/homarr-labs/homarr/commit/22bbef9d8e03215abddf6c6e26a5df45f252626d))
* **deps:** update dependency ws to ^8.20.0 ([#5337](https://github.com/homarr-labs/homarr/issues/5337)) ([d53c922](https://github.com/homarr-labs/homarr/commit/d53c922688606bd7d9494089e1ec43b930ad9923))
* **deps:** update mantine monorepo to ^8.3.18 ([#5298](https://github.com/homarr-labs/homarr/issues/5298)) ([6f8e629](https://github.com/homarr-labs/homarr/commit/6f8e62963a4eb47cb3095dff46ee0e759e1cbd3c))
* **deps:** update nextjs monorepo to v16.2.0 ([#5309](https://github.com/homarr-labs/homarr/issues/5309)) ([8831613](https://github.com/homarr-labs/homarr/commit/883161357dab4d94ff794f9444040d88074c464c))
* **deps:** update nextjs monorepo to v16.2.1 ([#5330](https://github.com/homarr-labs/homarr/issues/5330)) ([e23a397](https://github.com/homarr-labs/homarr/commit/e23a397a80e4409f5da50c737aeb26b295ce79fc))
* **deps:** update testcontainers-node monorepo to ^11.13.0 ([#5293](https://github.com/homarr-labs/homarr/issues/5293)) ([c009dd7](https://github.com/homarr-labs/homarr/commit/c009dd7de649bf24ab9bcf5ea25c65ebd18540bb))
* **deps:** update tiptap monorepo to v3.20.4 ([#5287](https://github.com/homarr-labs/homarr/issues/5287)) ([369b4d4](https://github.com/homarr-labs/homarr/commit/369b4d486327d0eaa04b70dd692c426f9a39afd7))
* **deps:** update trpc monorepo to ^11.14.1 ([#5328](https://github.com/homarr-labs/homarr/issues/5328)) ([d7f0596](https://github.com/homarr-labs/homarr/commit/d7f0596db8e44e2e79bb26095abd142b50675cc3))
* **deps:** update turbo monorepo to ^2.8.18 ([#5308](https://github.com/homarr-labs/homarr/issues/5308)) ([24694b9](https://github.com/homarr-labs/homarr/commit/24694b92411aae818b97a3a5c9add97d707a2f38))
* **deps:** update turbo monorepo to ^2.8.19 ([#5310](https://github.com/homarr-labs/homarr/issues/5310)) ([7537184](https://github.com/homarr-labs/homarr/commit/7537184a8168a4837d0a83a925a70c938555f199))
* **deps:** update turbo monorepo to ^2.8.20 ([#5317](https://github.com/homarr-labs/homarr/issues/5317)) ([5b4e6fc](https://github.com/homarr-labs/homarr/commit/5b4e6fcc11c877815c4730607de84ab70d630fb8))
* handle null ports in Docker container table ([#5313](https://github.com/homarr-labs/homarr/issues/5313)) ([1639da5](https://github.com/homarr-labs/homarr/commit/1639da57794d2555426e56030b4b34e2cc201aa9)), closes [#5311](https://github.com/homarr-labs/homarr/issues/5311)
* warnings in code ([4f2b821](https://github.com/homarr-labs/homarr/commit/4f2b8217f819b91ec4b05e32aebd6bc5473db155))
## [1.56.1](https://github.com/homarr-labs/homarr/compare/v1.56.0...v1.56.1) (2026-03-20)
### Bug Fixes
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:24.14.1-alpine AS base
FROM node:24.14.0-alpine AS base
FROM base AS builder
RUN apk add --no-cache libc6-compat
+11 -11
View File
@@ -56,13 +56,13 @@
"@mantine/tiptap": "^8.3.18",
"@million/lint": "1.0.14",
"@tabler/icons-react": "^3.40.0",
"@tanstack/react-query": "^5.95.2",
"@tanstack/react-query-devtools": "^5.95.2",
"@tanstack/react-query-next-experimental": "^5.95.2",
"@trpc/client": "^11.15.0",
"@trpc/next": "^11.15.0",
"@trpc/react-query": "^11.15.0",
"@trpc/server": "^11.15.0",
"@tanstack/react-query": "^5.91.2",
"@tanstack/react-query-devtools": "^5.91.3",
"@tanstack/react-query-next-experimental": "^5.91.0",
"@trpc/client": "^11.13.4",
"@trpc/next": "^11.13.4",
"@trpc/react-query": "^11.13.4",
"@trpc/server": "^11.13.4",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "0.11.0",
"@xterm/xterm": "^6.0.0",
@@ -73,10 +73,10 @@
"dotenv": "^17.3.1",
"flag-icons": "^7.5.0",
"glob": "^13.0.6",
"isomorphic-dompurify": "^3.7.1",
"jotai": "^2.19.0",
"isomorphic-dompurify": "^3.5.1",
"jotai": "^2.18.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.2.1",
"next": "16.2.0",
"postcss-preset-mantine": "^1.18.0",
"prismjs": "^1.30.0",
"react": "19.2.4",
@@ -87,7 +87,7 @@
"superjson": "2.2.6",
"swagger-ui-react": "^5.32.1",
"use-deep-compare-effect": "^1.8.1",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -2,7 +2,7 @@
import { useEffect, useRef } from "react";
import { Button, Grid, Group, Loader, Stack, TextInput } from "@mantine/core";
import { useDebouncedValue, useDocumentTitle } from "@mantine/hooks";
import { useDebouncedValue, useDocumentTitle, useFavicon } from "@mantine/hooks";
import { useUpdateBoard } from "@homarr/boards/updater";
import { useZodForm } from "@homarr/form";
@@ -10,7 +10,6 @@ import { IconPicker } from "@homarr/forms-collection";
import { useI18n } from "@homarr/translation/client";
import { boardSavePartialSettingsSchema } from "@homarr/validation/board";
import { homarrLogoPath } from "~/components/layout/logo/homarr-logo";
import { createMetaTitle } from "~/metadata";
import type { Board } from "../../_types";
import { useSavePartialSettingsMutation } from "./_shared";
@@ -54,6 +53,7 @@ export const GeneralSettingsContent = ({ board }: Props) => {
);
useLogoPreview(form.values.logoImageUrl);
useFaviconPreview(form.values.faviconImageUrl);
const metaTitleStatus = useMetaTitlePreview(form.values.metaTitle);
// Cleanup for not applied changes of the page title and logo image URL
@@ -75,7 +75,6 @@ export const GeneralSettingsContent = ({ board }: Props) => {
pageTitle: values.pageTitle,
logoImageUrl: values.logoImageUrl,
};
updateFavicon(values.faviconImageUrl ?? homarrLogoPath);
savePartialSettings({
id: board.id,
...values,
@@ -147,13 +146,7 @@ const useMetaTitlePreview = (title: string | null) => {
};
};
// Previously we used the useFavicon hook from Mantine
// However if the user tried to click on a link to a different page
// it caused an error "Cannot read properties of null (reading 'removeChild')"
// Probably because the head element was null (https://github.com/mantinedev/mantine/blob/b90d9b81031f45f5d15e75f25138ed6477f65bce/packages/%40mantine/hooks/src/use-favicon/use-favicon.ts#L21)
// See https://github.com/homarr-labs/homarr/issues/4905
const updateFavicon = (url: string) => {
const link: HTMLLinkElement | null = document.querySelector('link[rel="icon"]');
if (!link) return;
link.href = url;
const useFaviconPreview = (url: string | null) => {
const [faviconDebounced] = useDebouncedValue(url ?? "", 500);
useFavicon(faviconDebounced);
};
@@ -76,7 +76,6 @@ const createColumns = (
accessorKey: "ports",
header: t("docker.field.ports.label"),
Cell({ cell }) {
if (!cell.row.original.ports) return null;
if (!cell.row.original.ports.length) return null;
return (
<OverflowBadge overflowCount={1} data={cell.row.original.ports.map((port) => port.PrivatePort.toString())} />
+2 -2
View File
@@ -39,9 +39,9 @@
"@homarr/widgets": "workspace:^0.1.0",
"dayjs": "^1.11.20",
"dotenv": "^17.3.1",
"fastify": "^5.8.4",
"fastify": "^5.8.2",
"superjson": "2.2.6",
"undici": "7.24.6"
"undici": "7.24.5"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -27,7 +27,7 @@
"@homarr/validation": "workspace:^0.1.0",
"dotenv": "^17.3.1",
"tsx": "4.20.4",
"ws": "^8.20.0"
"ws": "^8.19.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:24.14.1-trixie AS base
FROM node:24.14.0-trixie AS base
WORKDIR /app
COPY package.json .
COPY pnpm-lock.yaml .
+4 -4
View File
@@ -2,12 +2,12 @@
"name": "homarr-prebuilt-debian",
"private": true,
"dependencies": {
"better-sqlite3": "^12.8.0"
"better-sqlite3": "^12.6.2"
},
"packageManager": "pnpm@10.33.0",
"packageManager": "pnpm@10.32.1",
"engines": {
"node": ">=24.14.1",
"pnpm": ">=10.33.0"
"node": ">=24.14.0",
"pnpm": ">=10.32.1"
},
"pnpm": {
"onlyBuiltDependencies": [
+5 -6
View File
@@ -9,16 +9,16 @@ importers:
.:
dependencies:
better-sqlite3:
specifier: ^12.8.0
version: 12.8.0
specifier: ^12.6.2
version: 12.6.2
packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
better-sqlite3@12.8.0:
resolution: {integrity: sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==}
better-sqlite3@12.6.2:
resolution: {integrity: sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==}
engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x}
bindings@1.5.0:
@@ -93,7 +93,6 @@ packages:
prebuild-install@7.1.3:
resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
engines: {node: '>=10'}
deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available.
hasBin: true
pump@3.0.3:
@@ -148,7 +147,7 @@ snapshots:
base64-js@1.5.1: {}
better-sqlite3@12.8.0:
better-sqlite3@12.6.2:
dependencies:
bindings: 1.5.0
prebuild-install: 7.1.3
+14 -14
View File
@@ -1,6 +1,6 @@
{
"name": "homarr",
"version": "1.57.1",
"version": "1.56.1",
"private": true,
"scripts": {
"build": "cross-env CI=true turbo build",
@@ -45,11 +45,11 @@
"@testcontainers/redis": "^11.13.0",
"@turbo/gen": "^2.8.20",
"@vitejs/plugin-react": "^5.2.0",
"@vitest/coverage-v8": "^4.1.2",
"@vitest/ui": "^4.1.2",
"@vitest/coverage-v8": "^4.1.0",
"@vitest/ui": "^4.1.0",
"conventional-changelog-conventionalcommits": "^9.3.0",
"cross-env": "^10.1.0",
"jsdom": "^29.0.1",
"jsdom": "^28.1.0",
"json5": "^2.2.3",
"prettier": "^3.8.1",
"semantic-release": "^25.0.3",
@@ -57,12 +57,12 @@
"turbo": "^2.8.20",
"typescript": "^5.9.3",
"vite-tsconfig-paths": "^6.1.1",
"vitest": "^4.1.2"
"vitest": "^4.1.0"
},
"packageManager": "pnpm@10.33.0",
"packageManager": "pnpm@10.32.1",
"engines": {
"node": ">=24.14.1",
"pnpm": ">=10.33.0"
"node": ">=24.14.0",
"pnpm": ">=10.32.1"
},
"pnpm": {
"onlyBuiltDependencies": [
@@ -80,22 +80,22 @@
"@babel/helpers@<7.26.10": ">=7.29.2",
"@babel/runtime@<7.26.10": ">=7.29.2",
"axios@>=1.0.0 <1.8.2": ">=1.13.6",
"brace-expansion@>=2.0.0 <=2.0.1": ">=5.0.5",
"brace-expansion@>=1.0.0 <=1.1.11": ">=5.0.5",
"brace-expansion@>=2.0.0 <=2.0.1": ">=5.0.4",
"brace-expansion@>=1.0.0 <=1.1.11": ">=5.0.4",
"esbuild@<=0.24.2": ">=0.27.4",
"form-data@>=4.0.0 <4.0.4": ">=4.0.5",
"hono@<4.6.5": ">=4.12.9",
"hono@<4.6.5": ">=4.12.8",
"linkifyjs@<4.3.2": ">=4.3.2",
"nanoid@>=4.0.0 <5.0.9": ">=5.1.7",
"prismjs@<1.30.0": ">=1.30.0",
"proxmox-api>undici": "7.24.6",
"proxmox-api>undici": "7.24.0",
"react-is": "^19.2.4",
"rollup@>=4.0.0 <4.22.4": ">=4.60.0",
"rollup@>=4.0.0 <4.22.4": ">=4.59.0",
"sha.js@<=2.4.11": ">=2.4.12",
"tar-fs@>=3.0.0 <3.0.9": ">=3.1.2",
"tar-fs@>=2.0.0 <2.1.3": ">=3.1.2",
"tmp@<=0.2.3": ">=0.2.5",
"vite@>=5.0.0 <=5.4.18": ">=8.0.3"
"vite@>=5.0.0 <=5.4.18": ">=8.0.1"
},
"patchedDependencies": {
"@types/node-unifi": "patches/@types__node-unifi.patch",
+8 -8
View File
@@ -41,18 +41,18 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@kubernetes/client-node": "^1.4.0",
"@tanstack/react-query": "^5.95.2",
"@trpc/client": "^11.15.0",
"@trpc/react-query": "^11.15.0",
"@trpc/server": "^11.15.0",
"@trpc/tanstack-react-query": "^11.15.0",
"@tanstack/react-query": "^5.91.2",
"@trpc/client": "^11.13.4",
"@trpc/react-query": "^11.13.4",
"@trpc/server": "^11.13.4",
"@trpc/tanstack-react-query": "^11.13.4",
"lodash.clonedeep": "^4.5.0",
"next": "16.2.1",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"superjson": "2.2.6",
"trpc-to-openapi": "^3.2.0",
"zod": "^4.3.6"
"trpc-to-openapi": "^3.1.0",
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -140,7 +140,7 @@ interface DockerContainer {
id: string;
state: ContainerState;
image: string;
ports: Port[] | undefined;
ports: Port[];
iconUrl: string | null;
cpuUsage: number;
memoryUsage: number;
+2 -2
View File
@@ -145,7 +145,7 @@ export const userRouter = createTRPCRouter({
create: permissionRequiredProcedure
.requiresPermission("admin")
.meta({ openapi: { method: "POST", path: "/api/users", tags: ["users"], protect: true } })
.input(convertIntersectionToZodObject(userCreateSchema))
.input(userCreateSchema)
.output(z.void())
.mutation(async ({ ctx, input }) => {
throwIfCredentialsDisabled();
@@ -376,7 +376,7 @@ export const userRouter = createTRPCRouter({
await ctx.db.delete(users).where(eq(users.id, input.userId));
}),
changePassword: protectedProcedure
.input(convertIntersectionToZodObject(userChangePasswordApiSchema))
.input(userChangePasswordApiSchema)
.output(z.void())
.meta({ openapi: { method: "PATCH", path: "/api/users/{userId}/changePassword", tags: ["users"], protect: true } })
.mutation(async ({ ctx, input }) => {
+2 -2
View File
@@ -34,11 +34,11 @@
"bcrypt": "^6.0.0",
"cookies": "^0.9.1",
"ldapts": "8.1.7",
"next": "16.2.1",
"next": "16.2.0",
"next-auth": "5.0.0-beta.30",
"react": "19.2.4",
"react-dom": "19.2.4",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+3 -3
View File
@@ -30,12 +30,12 @@
"@paralleldrive/cuid2": "^3.3.0",
"cookie": "1.1.1",
"dayjs": "^1.11.20",
"next": "16.2.1",
"next": "16.2.0",
"octokit": "^5.0.5",
"react": "19.2.4",
"react-dom": "19.2.4",
"undici": "7.24.6",
"zod": "^4.3.6",
"undici": "7.24.5",
"zod": "^4.2.1",
"zod-validation-error": "^5.0.0"
},
"devDependencies": {
+4 -4
View File
@@ -37,8 +37,8 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
"@t3-oss/env-nextjs": "^0.13.11",
"better-sqlite3": "^12.8.0",
"@t3-oss/env-nextjs": "^0.13.10",
"better-sqlite3": "^12.6.2",
"dns-caching": "^0.2.9",
"drizzle-orm": "^0.45.1",
"ioredis": "5.10.1",
@@ -46,14 +46,14 @@
"pg": "^8.20.0",
"superjson": "2.2.6",
"winston": "3.19.0",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/better-sqlite3": "7.6.13",
"@types/pg": "^8.20.0",
"@types/pg": "^8.18.0",
"eslint": "^9.39.4",
"typescript": "^5.9.3"
}
+5 -5
View File
@@ -28,13 +28,13 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/core": "workspace:^0.1.0",
"@homarr/cron-jobs": "workspace:^0.1.0",
"@tanstack/react-query": "^5.95.2",
"@trpc/client": "^11.15.0",
"@trpc/server": "^11.15.0",
"@trpc/tanstack-react-query": "^11.15.0",
"@tanstack/react-query": "^5.91.2",
"@trpc/client": "^11.13.4",
"@trpc/server": "^11.13.4",
"@trpc/tanstack-react-query": "^11.13.4",
"node-cron": "^4.2.1",
"react": "19.2.4",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+2 -2
View File
@@ -51,7 +51,7 @@
"@paralleldrive/cuid2": "^3.3.0",
"@testcontainers/mysql": "^11.13.0",
"@testcontainers/postgresql": "^11.13.0",
"better-sqlite3": "^12.8.0",
"better-sqlite3": "^12.6.2",
"dotenv": "^17.3.1",
"drizzle-kit": "^0.31.10",
"drizzle-orm": "^0.45.1",
@@ -65,7 +65,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/better-sqlite3": "7.6.13",
"@types/pg": "^8.20.0",
"@types/pg": "^8.18.0",
"dotenv-cli": "^11.0.0",
"esbuild": "^0.27.4",
"eslint": "^9.39.4",
+2 -2
View File
@@ -24,8 +24,8 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"fast-xml-parser": "^5.5.9",
"zod": "^4.3.6"
"fast-xml-parser": "^5.5.7",
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -26,7 +26,7 @@
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"@homarr/core": "workspace:^0.1.0",
"dockerode": "^4.0.10"
"dockerode": "^4.0.9"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -28,7 +28,7 @@
"@homarr/validation": "workspace:^0.1.0",
"@mantine/form": "^8.3.18",
"mantine-form-zod-resolver": "^1.3.0",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -32,7 +32,7 @@
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.18",
"react": "19.2.4",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+5 -5
View File
@@ -25,7 +25,7 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
"@ctrl/deluge": "^8.0.0",
"@ctrl/deluge": "^7.5.2",
"@ctrl/qbittorrent": "^9.11.2",
"@ctrl/transmission": "^7.4.0",
"@gitbeaker/rest": "^43.8.0",
@@ -38,18 +38,18 @@
"@homarr/redis": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@immich/sdk": "^2.6.3",
"@immich/sdk": "^2.6.1",
"@jellyfin/sdk": "^0.13.0",
"@octokit/auth-app": "^8.2.0",
"ical.js": "^2.2.1",
"maria2": "^0.4.1",
"node-ical": "^0.25.6",
"node-ical": "^0.22.1",
"octokit": "^5.0.5",
"proxmox-api": "1.1.1",
"tsdav": "^2.1.8",
"undici": "7.24.6",
"undici": "7.24.5",
"xml2js": "^0.6.2",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -33,7 +33,6 @@ export class DashDotIntegration extends Integration implements ISystemHealthMoni
const memoryLoad = await this.getCurrentMemoryLoadAsync();
const storageLoad = await this.getCurrentStorageLoadAsync();
const networkLoad = await this.getCurrentNetworkLoadAsync();
const gpuLoad = await this.getCurrentGpuLoadAsync();
const channel = this.getChannel();
const history = await channel.getSliceUntilTimeAsync(dayjs().subtract(15, "minutes").toDate());
@@ -57,14 +56,6 @@ export class DashDotIntegration extends Integration implements ISystemHealthMoni
availablePkgUpdates: 0,
rebootRequired: false,
smart: [], // API endpoint does not provide S.M.A.R.T data.
gpu: gpuLoad.map((gpu, index) => ({
gpuId: `gpu-${index}`,
name: info.gpuNames[index] ?? `GPU ${index}`,
memoryUtilization: gpu.memory ?? 0,
processorUtilization: gpu.load ?? 0,
temperature: null,
fanSpeed: null,
})),
uptime: info.uptime,
version: `${info.operatingSystemVersion}`,
loadAverage: {
@@ -85,7 +76,6 @@ export class DashDotIntegration extends Integration implements ISystemHealthMoni
cpuModel: serverInfo.cpu.model,
operatingSystemVersion: `${serverInfo.os.distro} ${serverInfo.os.release} (${serverInfo.os.kernel})`,
uptime: serverInfo.os.uptime,
gpuNames: serverInfo.gpu.layout.map((gpu) => gpu.brand),
};
}
@@ -160,17 +150,6 @@ export class DashDotIntegration extends Integration implements ISystemHealthMoni
return await networkLoadApi.parseAsync(JSON.parse(result));
}
private async getCurrentGpuLoadAsync() {
try {
const response = await fetchWithTrustedCertificatesAsync(this.url("/load/gpu"));
const result = await response.json();
const data = await gpuLoadApi.parseAsync(result);
return data.layout;
} catch {
return [];
}
}
private getChannel() {
return createChannelEventHistoryOld<z.infer<typeof cpuLoadPerCoreApiList>>(
`integration:${this.integration.id}:history:cpu`,
@@ -219,25 +198,6 @@ const internalServerInfoApi = z.object({
),
}),
),
gpu: z.object({
layout: z
.array(
z.object({
brand: z.string(),
model: z.string().optional(),
}),
)
.default([]),
}),
});
const cpuLoadPerCoreApiList = z.array(cpuLoadPerCoreApi);
const gpuLoadApi = z.object({
layout: z.array(
z.object({
load: z.number().min(0).optional(),
memory: z.number().min(0).optional(),
}),
),
});
@@ -59,14 +59,6 @@ export class GlancesIntegration extends Integration implements ISystemHealthMoni
loadAverage: null,
smart: [],
cpuTemp: undefined,
gpu: stats.gpu.map((gpu) => ({
gpuId: gpu.gpu_id,
name: gpu.name,
memoryUtilization: gpu.mem ?? 0,
processorUtilization: gpu.proc ?? 0,
temperature: gpu.temperature ?? null,
fanSpeed: gpu.fan_speed ?? null,
})),
};
}
@@ -158,16 +150,4 @@ const allSchema = z.object({
quicklook: z.object({
cpu_name: z.string(),
}),
gpu: z
.array(
z.object({
gpu_id: z.string(),
name: z.string(),
mem: z.number().nullable().optional(),
proc: z.number().nullable().optional(),
temperature: z.number().nullable().optional(),
fan_speed: z.number().nullable().optional(),
}),
)
.default([]),
});
@@ -1,6 +1,5 @@
import { getAlbumInfo, getAllAlbums, getMyUser, getServerStatistics, init, searchUsers } from "@immich/sdk";
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { ImageProxy } from "@homarr/image-proxy";
@@ -42,10 +41,7 @@ export class ImmichIntegration extends Integration {
public async getServerStatsAsync(): Promise<ImmichServerStats> {
this.initClient();
const [statistics, users] = await Promise.all([
getServerStatistics(this.getRequestOptions()),
searchUsers(this.getRequestOptions()),
]);
const [statistics, users] = await Promise.all([getServerStatistics(), searchUsers()]);
return {
photoCount: statistics.photos,
userCount: users.length,
@@ -56,7 +52,7 @@ export class ImmichIntegration extends Integration {
public async getAlbumAsync(albumId: string): Promise<ImmichAlbum> {
this.initClient();
const album = await getAlbumInfo({ id: albumId }, this.getRequestOptions());
const album = await getAlbumInfo({ id: albumId });
const imageProxy = new ImageProxy();
return {
albumName: album.albumName,
@@ -93,24 +89,17 @@ export class ImmichIntegration extends Integration {
}[]
> {
this.initClient();
const albums = await getAllAlbums({}, this.getRequestOptions());
const albums = await getAllAlbums({});
return albums.map((album) => ({ id: album.id, albumName: album.albumName, assetCount: album.assetCount }));
}
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
protected async testingAsync(_: IntegrationTestingInput): Promise<TestingResult> {
this.initClient();
const user = await getMyUser(this.getRequestOptions(input.fetchAsync));
const user = await getMyUser();
logger.debug(`Logged in as ${user.name} (${user.id})`);
return { success: true };
}
private getRequestOptions(fetchAsync = fetchWithTrustedCertificatesAsync) {
return {
// Undici and node types are not the same
fetch: fetchAsync as unknown as typeof fetch,
};
}
/**
* Sets the credentials and prepares the client for calls.
* Must be called before any other functions.
@@ -31,14 +31,6 @@ export interface SystemHealthMonitoring {
overallStatus: string;
healthy: boolean;
}[];
gpu: {
gpuId: string;
name: string;
memoryUtilization: number;
processorUtilization: number;
temperature: number | null;
fanSpeed: number | null;
}[];
}
// TODO: in the future decouple this from the Proxmox integration
@@ -36,16 +36,6 @@ export class SystemHealthMonitoringMockService implements ISystemHealthMonitorin
healthy: true,
},
],
gpu: [
{
gpuId: "mock0",
name: "Mock GPU RTX 4090",
memoryUtilization: Math.floor(Math.random() * 100),
processorUtilization: Math.floor(Math.random() * 100),
temperature: Math.floor(Math.random() * 90),
fanSpeed: Math.floor(Math.random() * 2000),
},
],
});
}
}
@@ -68,19 +68,15 @@ export class NextcloudIntegration extends Integration implements ICalendarIntegr
return calendarEvents
.map((event) => {
// @ts-expect-error the TypeScript definitions for this package are wrong
// @ts-expect-error the typescript definitions for this package are wrong
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
const icalData = ical.default.parseICS(event.data) as ical.CalendarResponse;
const veventObject = Object.values(icalData).find((data) => data?.type === "VEVENT");
const veventObject = Object.values(icalData).find((data) => data.type === "VEVENT");
if (!veventObject) {
throw new Error(`Invalid event data object: ${JSON.stringify(event.data)}. Unable to process the calendar.`);
}
if (!veventObject.end) {
throw new Error(`Event had no end date: ${JSON.stringify(event.data)}. Unable to process the calendar.`);
}
logger.debug(`Converting VEVENT event to ${event.etag} from Nextcloud: ${JSON.stringify(veventObject)}`);
const eventUrlWithoutHost = new URL(event.url).pathname;
@@ -91,18 +87,21 @@ export class NextcloudIntegration extends Integration implements ICalendarIntegr
const durationMs = veventObject.end.getTime() - veventObject.start.getTime();
return startDates.map((startDate) => {
const utcStartDate = dayjs(startDate).tz("UTC").toDate();
const timezoneOffsetMinutes = veventObject.rrule?.origOptions.tzid
? dayjs(startDate).tz(veventObject.rrule.origOptions.tzid).utcOffset()
: 0;
const utcStartDate = new Date(startDate.getTime() - timezoneOffsetMinutes * 60 * 1000);
const endDate = new Date(utcStartDate.getTime() + durationMs);
const dateInMillis = utcStartDate.valueOf();
return {
title: veventObject.summary as string,
title: veventObject.summary,
subTitle: null,
description: veventObject.description as string,
description: veventObject.description,
startDate: utcStartDate,
endDate,
image: null,
location: (veventObject.location as string | undefined) ?? null,
location: veventObject.location || null,
indicatorColor:
"color" in veventObject && typeof veventObject.color === "string" ? veventObject.color : "#ff8600",
links: [
@@ -86,7 +86,6 @@ export class OpenMediaVaultIntegration extends Integration implements ISystemHea
cpuTemp: cpuTempResult.success ? cpuTempResult.data.response.cputemp : undefined,
fileSystem,
smart,
gpu: [], // OpenMediaVault does not expose GPU monitoring via its RPC API.
};
}
@@ -297,7 +297,6 @@ export class TrueNasIntegration extends Integration implements ISystemHealthMoni
version: systemInformation.version,
cpuModelName: systemInformation.model,
rebootRequired: false,
gpu: [],
};
}
@@ -70,7 +70,6 @@ export class UnraidIntegration extends Integration implements ISystemHealthMonit
// See ArrayDiskStatus from https://studio.apollographql.com/public/Unraid-API/variant/current/explorer
healthy: disk.status === "DISK_OK",
})),
gpu: [],
};
}
+2 -2
View File
@@ -36,10 +36,10 @@
"@mantine/core": "^8.3.18",
"@tabler/icons-react": "^3.40.0",
"dayjs": "^1.11.20",
"next": "16.2.1",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -21,7 +21,7 @@ export const AddDockerAppToHomarrModal = createModal<AddDockerAppToHomarrProps>(
{
initialValues: {
containerUrls: innerProps.selectedContainers.map((container) => {
if (Array.isArray(container.ports) && container.ports[0]) {
if (container.ports[0]) {
return `http://${container.ports[0].IP}:${container.ports[0].PublicPort}`;
}
+2 -2
View File
@@ -40,11 +40,11 @@
"@mantine/core": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"adm-zip": "0.5.16",
"next": "16.2.1",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"superjson": "2.2.6",
"zod": "^4.3.6",
"zod": "^4.2.1",
"zod-form-data": "^3.0.1"
},
"devDependencies": {
@@ -162,7 +162,6 @@ const optionMapping: OptionMapping = {
sectionIndicatorRequirement: (oldOptions) =>
"sectionIndicatorColor" in oldOptions ? oldOptions.sectionIndicatorColor : undefined,
showUptime: () => undefined,
gpu: () => undefined,
visibleClusterSections: (oldOptions) => {
if (!("showNode" in oldOptions)) return undefined;
+1 -1
View File
@@ -23,7 +23,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+2 -2
View File
@@ -33,8 +33,8 @@
"dayjs": "^1.11.20",
"octokit": "^5.0.5",
"superjson": "2.2.6",
"undici": "7.24.6",
"zod": "^4.3.6"
"undici": "7.24.5",
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -2
View File
@@ -1,6 +1,5 @@
import dayjs from "dayjs";
import type { ContainerInfo, ContainerStats } from "dockerode";
import type Dockerode from "dockerode";
import { db, like, or } from "@homarr/db";
import { icons } from "@homarr/db/schema";
@@ -73,7 +72,7 @@ async function getContainersWithStatsAsync() {
cpuUsage,
memoryUsage,
image: container.Image,
ports: container.Ports as Dockerode.Port[] | undefined,
ports: container.Ports,
};
});
+1 -1
View File
@@ -26,7 +26,7 @@
"@homarr/db": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/dates": "^8.3.18",
"next": "16.2.1",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4"
},
+2 -2
View File
@@ -37,8 +37,8 @@
"@mantine/hooks": "^8.3.18",
"@mantine/spotlight": "^8.3.18",
"@tabler/icons-react": "^3.40.0",
"jotai": "^2.19.0",
"next": "16.2.1",
"jotai": "^2.18.1",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"use-deep-compare-effect": "^1.8.1"
+1 -1
View File
@@ -32,7 +32,7 @@
"dayjs": "^1.11.20",
"deepmerge": "4.3.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.2.1",
"next": "16.2.0",
"next-intl": "4.8.3",
"react": "19.2.4",
"react-dom": "19.2.4"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": ""
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": ""
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "允许地理位置"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "显示内存信息"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "显示运行时间"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "内存",
"gpu": "",
"network": "网络"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "内存",
"gpu": "",
"network": "网络",
"up": "上传",
"down": "下载"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "crwdns970:0crwdne970:0"
},
"allowModals": {
"label": "crwdns3992:0crwdne3992:0"
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "crwdns1080:0crwdne1080:0"
},
"gpu": {
"label": "crwdns3994:0crwdne3994:0"
},
"showUptime": {
"label": "crwdns3446:0crwdne3446:0"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "crwdns3700:0crwdne3700:0",
"memory": "crwdns3702:0crwdne3702:0",
"gpu": "crwdns3996:0crwdne3996:0",
"network": "crwdns3704:0crwdne3704:0"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "crwdns3604:0crwdne3604:0",
"memory": "crwdns3606:0crwdne3606:0",
"gpu": "crwdns3998:0crwdne3998:0",
"network": "crwdns3608:0crwdne3608:0",
"up": "crwdns3610:0crwdne3610:0",
"down": "crwdns3612:0crwdne3612:0"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Povolit polohu"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Zobrazit informace o paměti"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Tillad geolokalisering"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Vis hukommelsesoplysninger"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Vis Oppetid"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "Hukommelse",
"gpu": "",
"network": "Netværk"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "MEM",
"gpu": "",
"network": "NET",
"up": "OP",
"down": "NED"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Geolokalisierung zulassen"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Speicher-Info anzeigen"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Geolokalisierung zulassen"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Speicher-Info anzeigen"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Laufzeit anzeigen"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "Speicher",
"gpu": "",
"network": "Netzwerk"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "Arbeitsspeicher",
"gpu": "",
"network": "Netzwerk",
"up": "OBEN",
"down": "UNTEN"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Επιτρέπεται ο γεωεντοπισμός"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Εμφάνιση Πληροφοριών Μνήμης"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
+52 -60
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Allow geolocation"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1749,119 +1746,116 @@
"name": "Calendar",
"description": "Display events from your integrations in a calendar view within a certain relative time period",
"duration": {
"allDay": "All day"
"allDay": ""
},
"option": {
"releaseType": {
"label": "Radarr release type",
"label": "",
"options": {
"inCinemas": "In cinemas",
"digitalRelease": "Digital release",
"physicalRelease": "Physical release"
"inCinemas": "",
"digitalRelease": "",
"physicalRelease": ""
}
},
"filterPastMonths": {
"label": "Start from"
"label": ""
},
"filterFutureMonths": {
"label": "End at"
"label": ""
},
"showUnmonitored": {
"label": "Show unmonitored"
"label": ""
}
}
},
"weather": {
"name": "Weather",
"description": "Displays the current weather information of a set location.",
"name": "",
"description": "",
"option": {
"isFormatFahrenheit": {
"label": "Temperature in Fahrenheit"
"label": ""
},
"disableTemperatureDecimals": {
"label": "Disable temperature decimals"
"label": ""
},
"showCurrentWindSpeed": {
"label": "Show current wind speed",
"description": "Only on current weather"
"label": "",
"description": ""
},
"useImperialSpeed": {
"label": "Use mph for windspeed"
"label": ""
},
"location": {
"label": "Weather location"
"label": ""
},
"showCity": {
"label": "Show city"
"label": ""
},
"hasForecast": {
"label": "Show forecast"
"label": ""
},
"forecastDayCount": {
"label": "Amount of forecast days",
"description": "When the widget is not wide enough, less days are shown"
"label": "",
"description": ""
},
"dateFormat": {
"label": "Date Format",
"description": "How the date should look like"
"label": "",
"description": ""
}
},
"currentWindSpeed": "{currentWindSpeed} {unit}",
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "Sunrise",
"sunset": "Sunset",
"maxWindSpeed": "Max wind speed: {maxWindSpeed} {unit}",
"maxWindGusts": "Max wind gusts: {maxWindGusts} {unit}"
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": {
"clear": "Clear",
"mainlyClear": "Mainly clear",
"fog": "Fog",
"drizzle": "Drizzle",
"freezingDrizzle": "Freezing drizzle",
"clear": "",
"mainlyClear": "",
"fog": "",
"drizzle": "",
"freezingDrizzle": "",
"rain": "Rain",
"freezingRain": "Freezing rain",
"snowFall": "Snow fall",
"snowGrains": "Snow grains",
"rainShowers": "Rain showers",
"snowShowers": "Snow showers",
"thunderstorm": "Thunderstorm",
"thunderstormWithHail": "Thunderstorm with hail",
"unknown": "Unknown"
"snowGrains": "",
"rainShowers": "",
"snowShowers": "",
"thunderstorm": "",
"thunderstormWithHail": "",
"unknown": ""
}
},
"indexerManager": {
"name": "Indexer manager status",
"description": "Status of your indexers",
"name": "",
"description": "",
"option": {
"openIndexerSiteInNewTab": {
"label": "Open indexer site in new tab"
"label": ""
}
},
"title": "Indexer manager",
"testAll": "Test all",
"title": "",
"testAll": "",
"error": {
"internalServerError": "Failed to fetch indexers status"
"internalServerError": ""
}
},
"healthMonitoring": {
"name": "System Health Monitoring",
"description": "Displays information showing the health and status of your system(s).",
"name": "",
"description": "",
"tab": {
"system": "System",
"cluster": "Cluster"
"system": "",
"cluster": ""
},
"option": {
"fahrenheit": {
"label": "CPU Temp in Fahrenheit"
},
"cpu": {
"label": "Show CPU Info"
},
"memory": {
"label": ""
},
"gpu": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
},
"showUptime": {
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-5
View File
@@ -1861,9 +1861,6 @@
"memory": {
"label": "Show Memory Info"
},
"gpu": {
"label": "Show GPU Info"
},
"showUptime": {
"label": "Show Uptime"
},
@@ -2731,7 +2728,6 @@
"option": {
"cpu": "CPU",
"memory": "Memory",
"gpu": "GPU",
"network": "Network"
}
},
@@ -2748,7 +2744,6 @@
"card": {
"cpu": "CPU",
"memory": "MEM",
"gpu": "GPU",
"network": "NET",
"up": "UP",
"down": "DOWN"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Permitir geolocalización"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Mostrar información de la memoria"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Mostrar tiempo de actividad"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "Memoria",
"gpu": "",
"network": "Red"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "MEM",
"gpu": "",
"network": "RED",
"up": "ENCENDIDO",
"down": "APAGADO"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": ""
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": ""
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
+11 -19
View File
@@ -27,7 +27,7 @@
"description": "Configurer le comportement d'importation"
},
"boardSelection": {
"title": "{count} tableaux trouvés",
"title": "Tableaux {count} trouvés",
"description": "Choisissez tous les tableaux avec la taille que vous souhaitez importer",
"action": {
"selectAll": "Tout sélectionner",
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Autoriser la géolocalisation"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Afficher les infos de la mémoire"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Afficher le temps de disponibilité"
},
@@ -2003,20 +1997,20 @@
}
},
"tracearr": {
"name": "Tracearr",
"description": "Surveillance avancée du serveur multimédia avec des données détaillées de flux et de transcodage",
"name": "",
"description": "",
"option": {
"showStreams": {
"label": ""
},
"showStats": {
"label": "Afficher le résumé des statistiques"
"label": ""
},
"showRecentActivity": {
"label": "Afficher l'activité récente"
},
"showViolations": {
"label": "Afficher les violations"
"label": ""
}
},
"stats": {
@@ -2028,7 +2022,7 @@
"streams": {
"empty": "",
"user": "Utilisateur",
"media": "Média",
"media": "",
"state": "",
"quality": "Qualité",
"device": "Appareil",
@@ -2046,15 +2040,15 @@
"partial": ""
},
"violations": {
"title": "Violations",
"empty": "Aucune violation récente",
"title": "",
"empty": "",
"rule": "Règle",
"user": "Utilisateur"
},
"noSectionsEnabled": "",
"error": {
"noIntegration": "Aucune intégration Tracearr configurée",
"internalServerError": "Impossible de récupérer les données de Tracearr"
"noIntegration": "",
"internalServerError": ""
}
},
"common": {
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "Mémoire",
"gpu": "",
"network": "Réseau"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "RAM",
"gpu": "",
"network": "NET",
"up": "UP",
"down": "HORS SERVICE"
@@ -3583,7 +3575,7 @@
"label": "Météo"
},
"tracearr": {
"label": "Tracearr"
"label": ""
}
},
"interval": {
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "אפשר מיקום גיאוגרפי"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "הצג מידע זיכרון"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "הצג זמן פעולה"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "מעבד",
"memory": "זיכרון",
"gpu": "",
"network": "רשת"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "מעבד",
"memory": "זיכרון",
"gpu": "",
"network": "רשת",
"up": "העלאה",
"down": "הורדה"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Dopusti geolociranje"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": ""
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Geolokáció engedélyezése"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Memóriainformációk megjelenítése"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Consenti geo-localizzazione"
},
"allowModals": {
"label": "Consenti modali"
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Mostra Informazioni Memoria"
},
"gpu": {
"label": "Mostra informazioni sulla GPU"
},
"showUptime": {
"label": "Mostra Uptime"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "Memoria",
"gpu": "GPU",
"network": "Rete"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "MEM",
"gpu": "GPU",
"network": "NET",
"up": "SU",
"down": "DOWN"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "位置情報を許可する"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "メモリー情報を表示"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "稼働時間を表示"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "メモリ",
"gpu": "",
"network": "ネットワーク"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "MEM",
"gpu": "",
"network": "NET",
"up": "UP",
"down": "DOWN"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "지리적 위치 허용"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": ""
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Leisti nustatyti geografinę buvimo vietą"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": ""
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Atļaut ģeogrāfiskās atrašanās vietas noteikšanu"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Rādīt atmiņas informāciju"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Geolocatie toestaan"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Werkgeheugen info weergeven"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Uptime weergeven"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "Processor",
"memory": "Geheugen",
"gpu": "",
"network": "Netwerk"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "MEM",
"gpu": "",
"network": "NET",
"up": "OMHOOG",
"down": "OMLAAG"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Tillat geolokalisering"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Vis minneinfo"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Vis oppetid"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "Minne",
"gpu": "",
"network": "Nettverk"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "Minne",
"gpu": "",
"network": "NETT",
"up": "OPP",
"down": "NED"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Zezwalaj na geolokalizację"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Pokaż informacje o pamięci"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Pokaż czas pracy"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "Procesor",
"memory": "Pamięć",
"gpu": "",
"network": "Sieć"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "Procesor",
"memory": "Pamięć",
"gpu": "",
"network": "Sieć",
"up": "Aktywny",
"down": "Nieaktywny"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Permitir geolocalização"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Mostrar informações da memória"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Exibir tempo de atividade"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "CPU",
"memory": "Memória",
"gpu": "",
"network": "Rede"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "CPU",
"memory": "MEM",
"gpu": "",
"network": "REDE",
"up": "ENVIO",
"down": "RECEBIDO"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Permiteți geolocalizarea"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Afișare informații memorie"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Разрешить геолокацию"
},
"allowModals": {
"label": "Разрешить модальные окна"
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Показать информацию о памяти"
},
"gpu": {
"label": "Показать информацию о GPU"
},
"showUptime": {
"label": "Показывать время работы"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "ЦП",
"memory": "Память",
"gpu": "GPU",
"network": "Сеть"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "ЦП",
"memory": "ОЗУ",
"gpu": "GPU",
"network": "Сеть",
"up": "Исх.",
"down": "Вх."
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Povolenie geografickej lokalizácie"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Zobraziť informácie o pamäti"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Zobraziť Uptime"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Omogočanje zemljepisne lokacije"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": ""
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Tillåt geografisk lokalisering"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Visa minnesinformation"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Coğrafi konuma izin ver (geolocation)"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Bellek Bilgilerini Göster"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": "Çalışma Süresini Göster"
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "İşlemci",
"memory": "Bellek",
"gpu": "",
"network": "Ağ"
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "İşlemci",
"memory": "BELLEK",
"gpu": "",
"network": "AĞ",
"up": "YÜKLEME",
"down": "İNDİRME"
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Дозволити геолокацію"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "Показати інформацію про пам'ять"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "Cho phép định vị"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": ""
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
-8
View File
@@ -1625,9 +1625,6 @@
},
"allowGeolocation": {
"label": "允許地址位置"
},
"allowModals": {
"label": ""
}
},
"error": {
@@ -1861,9 +1858,6 @@
"memory": {
"label": "顯示記憶體訊息"
},
"gpu": {
"label": ""
},
"showUptime": {
"label": ""
},
@@ -2731,7 +2725,6 @@
"option": {
"cpu": "",
"memory": "",
"gpu": "",
"network": ""
}
},
@@ -2748,7 +2741,6 @@
"card": {
"cpu": "",
"memory": "",
"gpu": "",
"network": "",
"up": "",
"down": ""
+1 -1
View File
@@ -36,7 +36,7 @@
"@tabler/icons-react": "^3.40.0",
"crypto-js": "^4.2.0",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.2.1",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"svgson": "^5.3.1"
+1 -1
View File
@@ -24,7 +24,7 @@
"dependencies": {
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"zod": "^4.3.6",
"zod": "^4.2.1",
"zod-form-data": "^3.0.1"
},
"devDependencies": {
+6 -10
View File
@@ -57,13 +57,12 @@ export const userBaseCreateSchema = z.object({
password: userPasswordSchema,
confirmPassword: z.string(),
email: z.string().email().or(z.string().length(0)).optional(),
groupIds: z.array(z.string()),
});
export const userCreateSchema = addConfirmPasswordRefinement(userBaseCreateSchema).and(
z.object({ groupIds: z.array(z.string()) }),
);
export const userCreateSchema = addConfirmPasswordRefinement(userBaseCreateSchema);
export const userInitSchema = addConfirmPasswordRefinement(userBaseCreateSchema);
export const userInitSchema = addConfirmPasswordRefinement(userBaseCreateSchema.omit({ groupIds: true }));
export const userSignInSchema = z.object({
name: z.string().min(1),
@@ -112,15 +111,12 @@ const baseChangePasswordSchema = z.object({
previousPassword: z.string().min(1),
password: userPasswordSchema,
confirmPassword: z.string(),
userId: z.string(),
});
export const userChangePasswordSchema = addConfirmPasswordRefinement(baseChangePasswordSchema);
export const userChangePasswordSchema = addConfirmPasswordRefinement(baseChangePasswordSchema.omit({ userId: true }));
export const userChangePasswordApiSchema = addConfirmPasswordRefinement(baseChangePasswordSchema).and(
z.object({
userId: z.string(),
}),
);
export const userChangePasswordApiSchema = addConfirmPasswordRefinement(baseChangePasswordSchema);
export const userChangeHomeBoardsSchema = z.object({
homeBoardId: z.string().nullable(),
+18 -18
View File
@@ -52,33 +52,33 @@
"@mantine/core": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"@tabler/icons-react": "^3.40.0",
"@tiptap/extension-color": "3.20.5",
"@tiptap/extension-highlight": "3.20.5",
"@tiptap/extension-image": "3.20.5",
"@tiptap/extension-link": "^3.20.5",
"@tiptap/extension-placeholder": "^3.20.5",
"@tiptap/extension-table": "3.20.5",
"@tiptap/extension-table-cell": "3.20.5",
"@tiptap/extension-table-header": "3.20.5",
"@tiptap/extension-table-row": "3.20.5",
"@tiptap/extension-task-item": "3.20.5",
"@tiptap/extension-task-list": "3.20.5",
"@tiptap/extension-text-align": "3.20.5",
"@tiptap/extension-text-style": "3.20.5",
"@tiptap/extension-underline": "3.20.5",
"@tiptap/react": "^3.20.5",
"@tiptap/starter-kit": "^3.20.5",
"@tiptap/extension-color": "3.20.4",
"@tiptap/extension-highlight": "3.20.4",
"@tiptap/extension-image": "3.20.4",
"@tiptap/extension-link": "^3.20.4",
"@tiptap/extension-placeholder": "^3.20.4",
"@tiptap/extension-table": "3.20.4",
"@tiptap/extension-table-cell": "3.20.4",
"@tiptap/extension-table-header": "3.20.4",
"@tiptap/extension-table-row": "3.20.4",
"@tiptap/extension-task-item": "3.20.4",
"@tiptap/extension-task-list": "3.20.4",
"@tiptap/extension-text-align": "3.20.4",
"@tiptap/extension-text-style": "3.20.4",
"@tiptap/extension-underline": "3.20.4",
"@tiptap/react": "^3.20.4",
"@tiptap/starter-kit": "^3.20.4",
"clsx": "^2.1.1",
"dayjs": "^1.11.20",
"mantine-form-zod-resolver": "^1.3.0",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.2.1",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-markdown": "^10.1.0",
"recharts": "^2.15.4",
"video.js": "^8.23.7",
"zod": "^4.3.6"
"zod": "^4.2.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -19,9 +19,6 @@ export const { definition, componentLoader } = createWidgetDefinition("healthMon
memory: factory.switch({
defaultValue: true,
}),
gpu: factory.switch({
defaultValue: true,
}),
showUptime: factory.switch({
defaultValue: true,
}),
@@ -1,64 +0,0 @@
import { Center, RingProgress, Stack, Text, Tooltip } from "@mantine/core";
import { IconDeviceDesktop } from "@tabler/icons-react";
import { progressColor } from "../system-health";
interface GpuRingProps {
gpu: {
gpuId: string;
name: string;
memoryUtilization: number;
processorUtilization: number;
temperature: number | null;
fanSpeed: number | null;
};
isTiny: boolean;
fahrenheit: boolean;
}
export const GpuRing = ({ gpu, isTiny, fahrenheit }: GpuRingProps) => {
const tempDisplay =
gpu.temperature != null
? fahrenheit
? `${(gpu.temperature * 1.8 + 32).toFixed(0)}°F`
: `${gpu.temperature}°C`
: null;
return (
<Tooltip
label={
<Stack gap={2}>
<Text size="xs" fw={600}>
{gpu.name}
</Text>
<Text size="xs">VRAM: {gpu.memoryUtilization.toFixed(1)}%</Text>
{tempDisplay && <Text size="xs">Temp: {tempDisplay}</Text>}
{gpu.fanSpeed != null && <Text size="xs">Fan: {gpu.fanSpeed} RPM</Text>}
</Stack>
}
multiline
>
<RingProgress
className={`health-monitoring-gpu health-monitoring-gpu-${gpu.gpuId}`}
roundCaps
size={isTiny ? 50 : 100}
thickness={isTiny ? 4 : 8}
label={
<Center style={{ flexDirection: "column" }}>
<Text
className="health-monitoring-gpu-utilization-value"
size={isTiny ? "8px" : "xs"}
>{`${gpu.processorUtilization.toFixed(0)}%`}</Text>
<IconDeviceDesktop className="health-monitoring-gpu-utilization-icon" size={isTiny ? 8 : 16} />
</Center>
}
sections={[
{
value: Number(gpu.processorUtilization.toFixed(2)),
color: progressColor(Number(gpu.processorUtilization.toFixed(2))),
},
]}
/>
</Tooltip>
);
};
@@ -39,7 +39,6 @@ import { useI18n } from "@homarr/translation/client";
import type { WidgetComponentProps } from "../definition";
import { CpuRing } from "./rings/cpu-ring";
import { CpuTempRing } from "./rings/cpu-temp-ring";
import { GpuRing } from "./rings/gpu-ring";
import { formatMemoryUsage, MemoryRing } from "./rings/memory-ring";
import classes from "./system-health.module.css";
@@ -188,10 +187,6 @@ export const SystemHealthMonitoring = ({
isTiny={isTiny}
/>
)}
{options.gpu &&
healthInfo.gpu.map((gpu) => (
<GpuRing key={gpu.gpuId} gpu={gpu} isTiny={isTiny} fahrenheit={options.fahrenheit} />
))}
</Flex>
{
<Text className="health-monitoring-status-update-time" c="dimmed" size="xs" ta="center">
@@ -1,52 +0,0 @@
import { Paper, Text } from "@mantine/core";
import { IconDeviceDesktop } from "@tabler/icons-react";
import { useScopedI18n } from "@homarr/translation/client";
import type { LabelDisplayModeOption } from "..";
import { CommonChart } from "./common-chart";
export const SystemResourceGPUChart = ({
gpuUsageOverTime,
hasShadow,
labelDisplayMode,
}: {
gpuUsageOverTime: number[];
hasShadow: boolean;
labelDisplayMode: LabelDisplayModeOption;
}) => {
const chartData = gpuUsageOverTime.map((usage, index) => ({ index, usage }));
const t = useScopedI18n("widget.systemResources.card");
return (
<CommonChart
data={chartData}
dataKey={"index"}
series={[{ name: "usage", color: "grape.5" }]}
title={t("gpu")}
icon={IconDeviceDesktop}
lastValue={
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
gpuUsageOverTime.length > 0 ? `${Math.round(gpuUsageOverTime[gpuUsageOverTime.length - 1]!)}%` : undefined
}
chartType={hasShadow ? "area" : "line"}
yAxisProps={{ domain: [0, 100] }}
labelDisplayMode={labelDisplayMode}
tooltipProps={{
content: ({ payload }) => {
if (!payload) {
return null;
}
const value = payload[0] ? Number(payload[0].value) : 0;
return (
<Paper px={3} py={2} withBorder shadow="md" radius="md">
<Text c="dimmed" size="xs">
{value.toFixed(0)}%
</Text>
</Paper>
);
},
}}
/>
);
};
@@ -9,7 +9,6 @@ import { clientApi } from "@homarr/api/client";
import type { WidgetComponentProps } from "../definition";
import { CombinedNetworkTrafficChart } from "./chart/combined-network-traffic";
import { SystemResourceCPUChart } from "./chart/cpu-chart";
import { SystemResourceGPUChart } from "./chart/gpu-chart";
import { SystemResourceMemoryChart } from "./chart/memory-chart";
import { NetworkTrafficChart } from "./chart/network-traffic";
@@ -24,16 +23,10 @@ export default function SystemResources({ integrationIds, options }: WidgetCompo
const memoryCapacityInBytes =
(data[0]?.healthInfo.memAvailableInBytes ?? 0) + (data[0]?.healthInfo.memUsedInBytes ?? 0);
const [items, setItems] = useState<
{ cpu: number; memory: number; gpu: number; network: { up: number; down: number } | null }[]
>(
const [items, setItems] = useState<{ cpu: number; memory: number; network: { up: number; down: number } | null }[]>(
data.map((item) => ({
cpu: item.healthInfo.cpuUtilization,
memory: item.healthInfo.memUsedInBytes,
gpu:
item.healthInfo.gpu.length > 0
? item.healthInfo.gpu.reduce((acc, g) => acc + g.processorUtilization, 0) / item.healthInfo.gpu.length
: 0,
network: item.healthInfo.network,
})),
);
@@ -48,10 +41,6 @@ export default function SystemResources({ integrationIds, options }: WidgetCompo
const next = {
cpu: data.healthInfo.cpuUtilization,
memory: data.healthInfo.memUsedInBytes,
gpu:
data.healthInfo.gpu.length > 0
? data.healthInfo.gpu.reduce((acc, g) => acc + g.processorUtilization, 0) / data.healthInfo.gpu.length
: 0,
network: data.healthInfo.network,
};
@@ -86,15 +75,6 @@ export default function SystemResources({ integrationIds, options }: WidgetCompo
/>
</Box>
)}
{options.visibleCharts.includes("gpu") && (
<Box h={rowHeight}>
<SystemResourceGPUChart
gpuUsageOverTime={items.map((item) => item.gpu)}
hasShadow={options.hasShadow}
labelDisplayMode={options.labelDisplayMode}
/>
</Box>
)}
{showNetwork &&
(width > 256 ? (
<Group h={rowHeight} gap="xs" grow>
@@ -19,7 +19,7 @@ export const { definition, componentLoader } = createWidgetDefinition("systemRes
return optionsBuilder.from((factory) => ({
hasShadow: factory.switch({ defaultValue: true }),
visibleCharts: factory.multiSelect({
options: (["cpu", "memory", "gpu", "network"] as const).map((key) => ({
options: (["cpu", "memory", "network"] as const).map((key) => ({
value: key,
label: (t) => t(`widget.systemResources.option.visibleCharts.option.${key}`),
})),
+1147 -1010
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -17,14 +17,14 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
"@next/eslint-plugin-next": "16.2.1",
"@next/eslint-plugin-next": "16.2.0",
"eslint-config-prettier": "^10.1.8",
"eslint-config-turbo": "^2.8.20",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^6.1.1",
"typescript-eslint": "^8.57.2"
"typescript-eslint": "^8.57.1"
},
"devDependencies": {
"@homarr/prettier-config": "workspace:^0.1.0",
Loaded 100 of 101 files, more files were not shown because too many files have changed in this diff. Show more