Compare commits

...
71 Commits
Author SHA1 Message Date
Releases Homarr 0bba7be8d5 chore(release): 1.43.3 [skip ci] 2025-11-14 19:16:15 +00:00
homarr-releases[bot] 96b556f558 chore(release): automatic release v1.43.3 2025-11-14 19:15:12 +00:00
Manuel aaa23f3732 Merge commit from fork
* fix: sanitize user-media svg api endpoint using isomorphic dompurify

* fix: add iframe sandbox to prevent priviledge escalation
2025-11-14 18:00:15 +01:00
homarr-update-contributors[bot] d33cfe211a chore: update contributors (#4473)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2025-11-14 12:36:49 +00:00
homarr-renovate[bot] e7071bf2bf fix(deps): update dependency fastify to ^5.6.2 (#4471)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-14 10:35:22 +00:00
homarr-renovate[bot] 8a87dbad59 fix(deps): update mantine monorepo to ^8.3.7 (#4472)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-14 09:35:28 +00:00
homarr-renovate[bot] 6a5f069383 chore(deps): update dependency esbuild@&lt;&#x3d;0.24.2 to >=0.26.0 (#4470)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-14 04:37:00 +00:00
homarr-renovate[bot] d8e4255733 chore(deps): update dependency esbuild to ^0.26.0 (#4469)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-14 03:25:59 +00:00
homarr-crowdin[bot] 1916eacb4d chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-11-14 00:52:23 +00:00
AartSchinkelandMeier Lukas c30c98b153 fix(stock-price): ignore missing data points in price history (#4429)
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-11-13 22:07:23 +01:00
homarr-renovate[bot] 89aed57645 chore(deps): update semantic-release monorepo (#4464)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-13 14:33:37 +00:00
homarr-renovate[bot] 251d1d0da3 chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.53.1 (#4465)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-12 22:31:40 +00:00
homarr-renovate[bot] 51ce5da45b fix(deps): update dependency next-intl to v4.5.0 (#4462)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-12 17:33:22 +00:00
homarr-renovate[bot] eff2202e92 chore(deps): update vitest monorepo to ^4.0.8 (#4459)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-12 17:32:42 +00:00
homarr-renovate[bot] bb25410a40 chore(deps): update dependency vite@&gt;&#x3d;5.0.0 &lt;&#x3d;5.4.18 to >=7.2.2 (#4457)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-12 17:31:53 +00:00
homarr-renovate[bot] 1a56a56989 chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.53.0 (#4463)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-12 16:42:50 +00:00
homarr-renovate[bot] ddfed18acf fix(deps): update dependency @ctrl/qbittorrent to ^9.11.0 (#4456)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-11 07:32:42 +00:00
homarr-renovate[bot] 7bc2f87f31 fix(deps): update dependency @tanstack/react-query to ^5.90.7 (#4451)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-11 05:33:17 +00:00
homarr-renovate[bot] 05a9d26138 chore(deps): update dependency vite@&gt;&#x3d;5.0.0 &lt;&#x3d;5.4.18 to >=7.2.1 (#4454)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-11 04:37:45 +00:00
homarr-renovate[bot] 4f96cdf9f7 chore(deps): update dependency vite@&gt;&#x3d;5.0.0 &lt;&#x3d;5.4.18 to >=7.2.0 (#4449)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-10 15:13:48 +00:00
ManuelandMeier Lukas 1c1f8a48d2 fix(users): next button in create form always disabled (#4443)
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-11-10 16:02:14 +01:00
homarr-renovate[bot] f648af0e2b fix(deps): update testcontainers-node monorepo to ^11.8.0 (#4450)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-10 10:36:35 +00:00
homarr-crowdin[bot] 35ca0571ad chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-11-10 00:55:24 +00:00
homarr-renovate[bot] 92a91329c9 chore(deps): update dependency axios@&gt;&#x3d;1.0.0 &lt;1.8.2 to >=1.13.2 (#4447)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-09 20:31:57 +00:00
homarr-renovate[bot] 23edb55c67 chore(deps): update dependency eslint to ^9.39.1 (#4440)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-09 16:34:41 +00:00
homarr-renovate[bot] 8449d606d7 chore(deps): update vitest monorepo to ^4.0.7 (#4444)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-09 15:28:38 +00:00
homarr-renovate[bot] d3edfcf3dc fix(deps): update dependency swagger-ui-react to ^5.30.2 (#4442)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-09 10:30:28 +00:00
homarr-renovate[bot] 65f2e825fd fix(deps): update dependency fast-xml-parser to ^5.3.1 (#4435)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-08 19:36:33 +00:00
homarr-renovate[bot] 286f4e764a chore(deps): update dependency @types/node to ^24.10.0 (#4434)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-08 01:57:46 +00:00
Releases Homarr def87f36fd chore(release): 1.43.2 [skip ci] 2025-11-07 19:16:38 +00:00
homarr-releases[bot] 5adc2049cc chore(release): automatic release v1.43.2 2025-11-07 19:15:38 +00:00
homarr-renovate[bot] 5f9054b162 fix(deps): update dependency @tanstack/react-query to ^5.90.6 (#4427)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-07 03:23:11 +00:00
homarr-renovate[bot] b450ff6877 chore(deps): update dependency esbuild@&lt;&#x3d;0.24.2 to >=0.25.12 (#4431)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-07 02:04:23 +00:00
homarr-renovate[bot] 97052b8bff chore(deps): update dependency esbuild to ^0.25.12 (#4430)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-07 02:03:50 +00:00
homarr-renovate[bot] 07af9d8673 fix(deps): update dependency jotai to ^2.15.1 (#4426)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-06 06:44:55 +00:00
homarr-renovate[bot] 4516f27fa6 fix(deps): update dependency @gitbeaker/rest to ^43.8.0 (#4425)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-06 06:44:37 +00:00
homarr-renovate[bot] f2164272a5 fix(deps): update dependency sass to ^1.93.3 (#4421)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-06 02:05:33 +00:00
homarr-renovate[bot] 50caa1fcf9 chore(deps): update vitest monorepo to ^4.0.6 (#4420)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 23:30:24 +00:00
homarr-renovate[bot] 742ef66e3c fix(deps): update turbo monorepo to ^2.6.0 (#4422)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 22:34:14 +00:00
homarr-renovate[bot] 0d10b2b99a chore(deps): update dependency @semantic-release/github to ^12.0.1 (#4423)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 22:31:09 +00:00
homarr-renovate[bot] 2ff32627f4 chore(deps): update dependency eslint to ^9.39.0 (#4424)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 21:32:12 +00:00
homarr-renovate[bot] d9b14db6a1 fix(deps): update dependency swagger-ui-react to ^5.30.1 (#4418)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 09:36:37 +00:00
homarr-renovate[bot] 186e3e445d fix(deps): update dependency octokit to ^5.0.5 (#4413)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 09:35:58 +00:00
homarr-renovate[bot] 160c20a9a6 fix(deps): update dependency tsdav to ^2.1.6 (#4417)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 08:43:04 +00:00
homarr-renovate[bot] 97cbade713 fix(deps): update dependency dayjs to ^1.11.19 (#4414)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 07:32:10 +00:00
homarr-renovate[bot] 816c6a0329 chore(deps): update dependency jsdom to ^27.1.0 (#4416)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 06:44:28 +00:00
homarr-renovate[bot] 018a33b078 fix(deps): update dependency @octokit/auth-app to ^8.1.2 (#4412)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-05 02:04:46 +00:00
homarr-renovate[bot] 168458e9e1 chore(deps): update actions/setup-node action to v6 (#4320)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-04 22:15:15 +01:00
homarr-renovate[bot] ebc64f3090 chore(deps): update dependency dotenv-cli to v11 (#4402)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-04 22:13:26 +01:00
homarr-renovate[bot]andMeier Lukas d255492bb7 chore(deps): update vitest monorepo to v4 (major) (#4367)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-11-04 22:03:43 +01:00
homarr-renovate[bot]andMeier Lukas dcf960fa97 fix(deps): update dependency @gitbeaker/rest to ^43.7.0 (#4386)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-11-04 21:28:11 +01:00
homarr-renovate[bot]andMeier Lukas 6ce23a6e97 fix(deps): update nextjs monorepo to v16 (major) (#4363)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-11-04 21:26:44 +01:00
homarr-renovate[bot] a43ac18bef chore(deps): update node.js to v24 (#4395)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-04 21:14:13 +01:00
homarr-renovate[bot] 881d0d1219 chore(deps): update dependency hono@&lt;4.6.5 to >=4.10.4 (#4410)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-04 19:03:28 +00:00
homarr-crowdin[bot] 3fff8b88b3 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-11-04 00:50:14 +00:00
homarr-renovate[bot] 57d1a91866 fix(deps): update dependency @ctrl/deluge to ^7.5.0 (#4407)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-03 21:18:41 +00:00
homarr-renovate[bot] d34f9e5b3e fix(deps): update tiptap monorepo to v2.27.1 (#4405)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-03 16:37:13 +00:00
homarr-renovate[bot] cf89a03f0c chore(deps): update dependency axios@&gt;&#x3d;1.0.0 &lt;1.8.2 to >=1.13.1 (#4401)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-03 10:36:04 +00:00
homarr-renovate[bot] f4caddfd56 fix(deps): update tiptap monorepo to v2.27.0 (#4404)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-03 09:38:19 +00:00
homarr-renovate[bot] 9e2bbb8a3f fix(deps): update mantine monorepo to ^8.3.6 (#4403)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-03 06:45:35 +00:00
homarr-renovate[bot] 6dbd2802c9 chore(deps): update pnpm to v10.20.0 (#4400)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-02 18:37:28 +00:00
homarr-renovate[bot] 19e25a095f fix(deps): update dependency superjson to v2.2.5 (#4398)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-02 17:26:14 +00:00
homarr-renovate[bot] 4c4e901e7d fix(deps): update dependency @jellyfin/sdk to ^0.13.0 (#4399)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-02 16:34:38 +00:00
homarr-renovate[bot] 5aca5d1b0a fix(deps): update trpc monorepo to ^11.7.1 (#4396)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-02 14:27:23 +00:00
homarr-renovate[bot] 59434ee33a fix(deps): update dependency drizzle-kit to ^0.31.6 (#4397)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-02 13:34:04 +00:00
homarr-renovate[bot] b59ee77c28 chore(deps): update node.js to v22.21.1 (#4355)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-02 02:09:11 +00:00
homarr-renovate[bot] 5effee8148 chore(deps): update dependency @types/pg to ^8.15.6 (#4394)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-02 02:08:59 +00:00
homarr-renovate[bot] ba82853f5c chore(deps): update dependency @types/chroma-js to v3.1.2 (#4393)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-01 21:26:47 +00:00
homarr-renovate[bot] 1491b0fe0e chore(deps): update dependency axios@&gt;&#x3d;1.0.0 &lt;1.8.2 to >=1.13.0 (#4392)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-01 16:33:43 +00:00
homarr-renovate[bot] b51e285c92 fix(deps): update dependency swagger-ui-react to ^5.30.0 (#4391)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-11-01 12:51:55 +00:00
Meier Lukas 6d9726e19e chore: update bug report template 2025-10-31 23:35:49 +01:00
105 changed files with 3184 additions and 2712 deletions

No files matched your search

+1
View File
@@ -33,6 +33,7 @@ body:
options:
# The below comment is used to insert a new version with on-release.yml
#NEXT_VERSION#
- 1.43.1
- 1.43.0
- 1.42.1
- 1.42.0
@@ -61,10 +61,10 @@ jobs:
persist-credentials: false
- uses: pnpm/action-setup@v4
if: env.SKIP_RELEASE == 'false'
- uses: actions/setup-node@v5
- uses: actions/setup-node@v6
if: env.SKIP_RELEASE == 'false'
with:
node-version: 24.10.0
node-version: 24.11.0
cache: "pnpm"
- run: npm i -g pnpm
if: env.SKIP_RELEASE == 'false'
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
- uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
+1 -1
View File
@@ -1 +1 @@
22.21.0
24.11.0
+41
View File
@@ -1,3 +1,44 @@
## [1.43.3](https://github.com/homarr-labs/homarr/compare/v1.43.2...v1.43.3) (2025-11-14)
### Bug Fixes
* **deps:** update dependency @ctrl/qbittorrent to ^9.11.0 ([#4456](https://github.com/homarr-labs/homarr/issues/4456)) ([ddfed18](https://github.com/homarr-labs/homarr/commit/ddfed18acf44596dba15ea0ef56233c4936f9775))
* **deps:** update dependency @tanstack/react-query to ^5.90.7 ([#4451](https://github.com/homarr-labs/homarr/issues/4451)) ([7bc2f87](https://github.com/homarr-labs/homarr/commit/7bc2f87f31f1babe691fa4a086a3897977f2d871))
* **deps:** update dependency fast-xml-parser to ^5.3.1 ([#4435](https://github.com/homarr-labs/homarr/issues/4435)) ([65f2e82](https://github.com/homarr-labs/homarr/commit/65f2e825fdb9e5e79b814c9b49f663d1afac784d))
* **deps:** update dependency fastify to ^5.6.2 ([#4471](https://github.com/homarr-labs/homarr/issues/4471)) ([e7071bf](https://github.com/homarr-labs/homarr/commit/e7071bf2bf6a45ff760cd3e7bd06382d2ed66cdc))
* **deps:** update dependency next-intl to v4.5.0 ([#4462](https://github.com/homarr-labs/homarr/issues/4462)) ([51ce5da](https://github.com/homarr-labs/homarr/commit/51ce5da45bdccf061e593097ed751cf09d663437))
* **deps:** update dependency swagger-ui-react to ^5.30.2 ([#4442](https://github.com/homarr-labs/homarr/issues/4442)) ([d3edfcf](https://github.com/homarr-labs/homarr/commit/d3edfcf3dca3d34afd5ef8ec21599cd08fde5092))
* **deps:** update mantine monorepo to ^8.3.7 ([#4472](https://github.com/homarr-labs/homarr/issues/4472)) ([8a87dba](https://github.com/homarr-labs/homarr/commit/8a87dbad59786fa9789dd3efb8d9424bb950e977))
* **deps:** update testcontainers-node monorepo to ^11.8.0 ([#4450](https://github.com/homarr-labs/homarr/issues/4450)) ([f648af0](https://github.com/homarr-labs/homarr/commit/f648af0e2b2b5d5f8180402c2734ea0c04559daa))
* **stock-price:** ignore missing data points in price history ([#4429](https://github.com/homarr-labs/homarr/issues/4429)) ([c30c98b](https://github.com/homarr-labs/homarr/commit/c30c98b153fbec21551e45aedf83e0ae29d6e773))
* **users:** next button in create form always disabled ([#4443](https://github.com/homarr-labs/homarr/issues/4443)) ([1c1f8a4](https://github.com/homarr-labs/homarr/commit/1c1f8a48d259c65ebeeec6856e1fe339defb4aaf))
## [1.43.2](https://github.com/homarr-labs/homarr/compare/v1.43.1...v1.43.2) (2025-11-07)
### Bug Fixes
* **deps:** update dependency @ctrl/deluge to ^7.5.0 ([#4407](https://github.com/homarr-labs/homarr/issues/4407)) ([57d1a91](https://github.com/homarr-labs/homarr/commit/57d1a9186653dd4c327b360a3bdaa78fd8e1187b))
* **deps:** update dependency @gitbeaker/rest to ^43.7.0 ([#4386](https://github.com/homarr-labs/homarr/issues/4386)) ([dcf960f](https://github.com/homarr-labs/homarr/commit/dcf960fa97011c24475f303d587152b42eabec45))
* **deps:** update dependency @gitbeaker/rest to ^43.8.0 ([#4425](https://github.com/homarr-labs/homarr/issues/4425)) ([4516f27](https://github.com/homarr-labs/homarr/commit/4516f27fa69445e5aec16760e1f6ed8080bc8fff))
* **deps:** update dependency @jellyfin/sdk to ^0.13.0 ([#4399](https://github.com/homarr-labs/homarr/issues/4399)) ([4c4e901](https://github.com/homarr-labs/homarr/commit/4c4e901e7d38faf83a4725b7cee5526b0b223dc3))
* **deps:** update dependency @octokit/auth-app to ^8.1.2 ([#4412](https://github.com/homarr-labs/homarr/issues/4412)) ([018a33b](https://github.com/homarr-labs/homarr/commit/018a33b07812fa59f1469ce8b4baa7b1d55c6103))
* **deps:** update dependency @tanstack/react-query to ^5.90.6 ([#4427](https://github.com/homarr-labs/homarr/issues/4427)) ([5f9054b](https://github.com/homarr-labs/homarr/commit/5f9054b162daf974baafdbee9f844b3a860cbdd0))
* **deps:** update dependency dayjs to ^1.11.19 ([#4414](https://github.com/homarr-labs/homarr/issues/4414)) ([97cbade](https://github.com/homarr-labs/homarr/commit/97cbade7135cb06e0780dd1b448c78c8802794ea))
* **deps:** update dependency drizzle-kit to ^0.31.6 ([#4397](https://github.com/homarr-labs/homarr/issues/4397)) ([59434ee](https://github.com/homarr-labs/homarr/commit/59434ee33ae16e06f96e2f07cf85337c313c73f6))
* **deps:** update dependency jotai to ^2.15.1 ([#4426](https://github.com/homarr-labs/homarr/issues/4426)) ([07af9d8](https://github.com/homarr-labs/homarr/commit/07af9d8673ea9573bc436626cd84d11980d023bc))
* **deps:** update dependency octokit to ^5.0.5 ([#4413](https://github.com/homarr-labs/homarr/issues/4413)) ([186e3e4](https://github.com/homarr-labs/homarr/commit/186e3e445dfe6b4fb1aeda3830ae1f260b605882))
* **deps:** update dependency sass to ^1.93.3 ([#4421](https://github.com/homarr-labs/homarr/issues/4421)) ([f216427](https://github.com/homarr-labs/homarr/commit/f2164272a5ca9b51bdf9110664ed5a40b87b60f6))
* **deps:** update dependency superjson to v2.2.5 ([#4398](https://github.com/homarr-labs/homarr/issues/4398)) ([19e25a0](https://github.com/homarr-labs/homarr/commit/19e25a095fb0252e8f2a459e0a97d44a37d2188a))
* **deps:** update dependency swagger-ui-react to ^5.30.0 ([#4391](https://github.com/homarr-labs/homarr/issues/4391)) ([b51e285](https://github.com/homarr-labs/homarr/commit/b51e285c92ef707076f321f0ce1a15d5cbd5de7d))
* **deps:** update dependency swagger-ui-react to ^5.30.1 ([#4418](https://github.com/homarr-labs/homarr/issues/4418)) ([d9b14db](https://github.com/homarr-labs/homarr/commit/d9b14db6a1af515796951a1db670431d10f81eaf))
* **deps:** update dependency tsdav to ^2.1.6 ([#4417](https://github.com/homarr-labs/homarr/issues/4417)) ([160c20a](https://github.com/homarr-labs/homarr/commit/160c20a9a6f850f75537e246f42e93f9a2ed79a0))
* **deps:** update mantine monorepo to ^8.3.6 ([#4403](https://github.com/homarr-labs/homarr/issues/4403)) ([9e2bbb8](https://github.com/homarr-labs/homarr/commit/9e2bbb8a3f2db95c5598e5dca993bf6cd4ebc127))
* **deps:** update nextjs monorepo to v16 (major) ([#4363](https://github.com/homarr-labs/homarr/issues/4363)) ([6ce23a6](https://github.com/homarr-labs/homarr/commit/6ce23a6e971b064292970fc4df90cc69cdb59a95))
* **deps:** update tiptap monorepo to v2.27.0 ([#4404](https://github.com/homarr-labs/homarr/issues/4404)) ([f4caddf](https://github.com/homarr-labs/homarr/commit/f4caddfd564553014854347eb6dd14cc800eb027))
* **deps:** update tiptap monorepo to v2.27.1 ([#4405](https://github.com/homarr-labs/homarr/issues/4405)) ([d34f9e5](https://github.com/homarr-labs/homarr/commit/d34f9e5b3ef999559a4c5f1165488fe4f8828a83))
* **deps:** update trpc monorepo to ^11.7.1 ([#4396](https://github.com/homarr-labs/homarr/issues/4396)) ([5aca5d1](https://github.com/homarr-labs/homarr/commit/5aca5d1b0a76ab4cf0ed27dac62183c766ad398a))
* **deps:** update turbo monorepo to ^2.6.0 ([#4422](https://github.com/homarr-labs/homarr/issues/4422)) ([742ef66](https://github.com/homarr-labs/homarr/commit/742ef66e3cf56fd351c8dee2d3dd05cd639e51fa))
## [1.43.1](https://github.com/homarr-labs/homarr/compare/v1.43.0...v1.43.1) (2025-10-31)
### Bug Fixes
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:24.10.0-alpine AS base
FROM node:24.11.0-alpine AS base
FROM base AS builder
RUN apk add --no-cache libc6-compat
+11 -4
View File
@@ -20,19 +20,26 @@ const withNextIntl = createNextIntlPlugin({
const nextConfig: NextConfig = {
output: "standalone",
reactStrictMode: true,
/** We already do linting and typechecking as separate tasks in CI */
eslint: { ignoreDuringBuilds: true },
reactCompiler: true,
/** We already do typechecking as separate tasks in CI */
typescript: { ignoreBuildErrors: true },
/**
* dockerode is required in the external server packages because of https://github.com/homarr-labs/homarr/issues/612
* isomorphic-dompurify and jsdom are required, see https://github.com/kkomelin/isomorphic-dompurify/issues/356
*/
serverExternalPackages: ["dockerode"],
serverExternalPackages: ["dockerode", "isomorphic-dompurify", "jsdom"],
experimental: {
optimizePackageImports: ["@mantine/core", "@mantine/hooks", "@tabler/icons-react"],
turbopackFileSystemCacheForDev: true,
},
transpilePackages: ["@homarr/ui", "@homarr/notifications", "@homarr/modals", "@homarr/spotlight", "@homarr/widgets"],
images: {
domains: ["cdn.jsdelivr.net"],
localPatterns: [
{
pathname: "/**",
search: "",
},
],
},
// eslint-disable-next-line @typescript-eslint/require-await,no-restricted-syntax
async headers() {
+22 -20
View File
@@ -50,42 +50,44 @@
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@homarr/widgets": "workspace:^0.1.0",
"@mantine/colors-generator": "^8.3.5",
"@mantine/core": "^8.3.5",
"@mantine/dropzone": "^8.3.5",
"@mantine/hooks": "^8.3.5",
"@mantine/modals": "^8.3.5",
"@mantine/tiptap": "^8.3.5",
"@mantine/colors-generator": "^8.3.7",
"@mantine/core": "^8.3.7",
"@mantine/dropzone": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"@mantine/modals": "^8.3.7",
"@mantine/tiptap": "^8.3.7",
"@million/lint": "1.0.14",
"@tabler/icons-react": "^3.35.0",
"@tanstack/react-query": "^5.90.5",
"@tanstack/react-query": "^5.90.7",
"@tanstack/react-query-devtools": "^5.90.2",
"@tanstack/react-query-next-experimental": "^5.90.2",
"@trpc/client": "^11.7.0",
"@trpc/next": "^11.7.0",
"@trpc/react-query": "^11.7.0",
"@trpc/server": "^11.7.0",
"@trpc/client": "^11.7.1",
"@trpc/next": "^11.7.1",
"@trpc/react-query": "^11.7.1",
"@trpc/server": "^11.7.1",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "0.10.0",
"@xterm/xterm": "^5.5.0",
"babel-plugin-react-compiler": "^1.0.0",
"chroma-js": "^3.1.2",
"clsx": "^2.1.1",
"dayjs": "^1.11.18",
"dayjs": "^1.11.19",
"dotenv": "^17.2.3",
"flag-icons": "^7.5.0",
"glob": "^11.0.3",
"jotai": "^2.15.0",
"isomorphic-dompurify": "^2.32.0",
"jotai": "^2.15.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "15.5.6",
"next": "16.0.1",
"postcss-preset-mantine": "^1.18.0",
"prismjs": "^1.30.0",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-error-boundary": "^6.0.0",
"react-simple-code-editor": "^0.14.1",
"sass": "^1.93.2",
"superjson": "2.2.3",
"swagger-ui-react": "^5.29.5",
"sass": "^1.93.3",
"superjson": "2.2.5",
"swagger-ui-react": "^5.30.2",
"use-deep-compare-effect": "^1.8.1",
"zod": "^4.1.12"
},
@@ -93,14 +95,14 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/chroma-js": "3.1.1",
"@types/node": "^24.9.1",
"@types/chroma-js": "3.1.2",
"@types/node": "^24.10.0",
"@types/prismjs": "^1.26.5",
"@types/react": "19.2.2",
"@types/react-dom": "19.2.2",
"@types/swagger-ui-react": "^5.18.0",
"concurrently": "^9.2.1",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"node-loader": "^2.1.0",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
@@ -1,7 +1,6 @@
"use client";
import { useCallback, useEffect } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { Group, Menu, ScrollArea } from "@mantine/core";
import { useHotkeys } from "@mantine/hooks";
@@ -29,6 +28,7 @@ import { useConfirmModal, useModalAction } from "@homarr/modals";
import { AppSelectModal } from "@homarr/modals-collection";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { useItemActions } from "~/components/board/items/item-actions";
import { ItemSelectModal } from "~/components/board/items/item-select-modal";
@@ -1,4 +1,3 @@
import Link from "next/link";
import type { MantineColor } from "@mantine/core";
import { Button, Card, Stack, Text } from "@mantine/core";
import { IconBook2, IconCategoryPlus, IconLayoutDashboard, IconMailForward } from "@tabler/icons-react";
@@ -8,6 +7,7 @@ import { getMantineColor } from "@homarr/common";
import { db } from "@homarr/db";
import { createDocumentationLink } from "@homarr/definitions";
import { getScopedI18n } from "@homarr/translation/server";
import { Link } from "@homarr/ui";
import type { TablerIcon } from "@homarr/ui";
export const InitFinish = async () => {
@@ -1,5 +1,4 @@
import { Fragment } from "react";
import Link from "next/link";
import { redirect } from "next/navigation";
import { ActionIcon, ActionIconGroup, Anchor, Avatar, Card, Group, Stack, Text, Title } from "@mantine/core";
import { IconBox, IconPencil } from "@tabler/icons-react";
@@ -10,7 +9,7 @@ import { api } from "@homarr/api/server";
import { auth } from "@homarr/auth/next";
import type { inferSearchParamsFromSchema } from "@homarr/common/types";
import { getI18n, getScopedI18n } from "@homarr/translation/server";
import { SearchInput, TablePagination } from "@homarr/ui";
import { Link, SearchInput, TablePagination } from "@homarr/ui";
import { ManageContainer } from "~/components/manage/manage-container";
import { MobileAffixButton } from "~/components/manage/mobile-affix-button";
@@ -1,7 +1,6 @@
"use client";
import { useCallback } from "react";
import Link from "next/link";
import { Menu } from "@mantine/core";
import { IconCopy, IconDeviceMobile, IconHome, IconSettings, IconTrash } from "@tabler/icons-react";
@@ -12,6 +11,7 @@ import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal, useModalAction } from "@homarr/modals";
import { DuplicateBoardModal } from "@homarr/modals-collection";
import { useScopedI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { useBoardPermissions } from "~/components/board/permissions/client";
@@ -1,4 +1,3 @@
import Link from "next/link";
import {
ActionIcon,
Badge,
@@ -21,7 +20,7 @@ import type { RouterOutputs } from "@homarr/api";
import { api } from "@homarr/api/server";
import { auth } from "@homarr/auth/next";
import { getScopedI18n } from "@homarr/translation/server";
import { UserAvatar } from "@homarr/ui";
import { Link, UserAvatar } from "@homarr/ui";
import { getBoardPermissionsAsync } from "~/components/board/permissions/server";
import { ManageContainer } from "~/components/manage/manage-container";
@@ -1,7 +1,6 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { Alert, Anchor, Button, ButtonGroup, Fieldset, Group, Stack, Text, TextInput } from "@mantine/core";
import { IconInfoCircle, IconPencil, IconPlus, IconUnlink } from "@tabler/icons-react";
@@ -17,6 +16,7 @@ import { useConfirmModal, useModalAction } from "@homarr/modals";
import { AppSelectModal } from "@homarr/modals-collection";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { integrationUpdateSchema } from "@homarr/validation/integration";
import { SecretCard } from "../../_components/secrets/integration-secret-card";
@@ -2,13 +2,12 @@
import type { ChangeEvent } from "react";
import React, { useMemo, useState } from "react";
import Link from "next/link";
import { Flex, Group, Menu, ScrollArea, Text, TextInput } from "@mantine/core";
import { IconSearch } from "@tabler/icons-react";
import { getIntegrationName, integrationKinds } from "@homarr/definitions";
import { useI18n } from "@homarr/translation/client";
import { IntegrationAvatar } from "@homarr/ui";
import { IntegrationAvatar, Link } from "@homarr/ui";
interface IntegrationCreateDropdownContentProps {
enableMockIntegration: boolean;
@@ -1,7 +1,6 @@
"use client";
import { startTransition, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import {
Alert,
@@ -36,6 +35,7 @@ import type { GetInputPropsReturnType, UseFormReturnType } from "@homarr/form";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { appHrefSchema } from "@homarr/validation/app";
import { integrationCreateSchema } from "@homarr/validation/integration";
@@ -1,6 +1,5 @@
import { Fragment } from "react";
import type { PropsWithChildren } from "react";
import Link from "next/link";
import { redirect } from "next/navigation";
import {
AccordionControl,
@@ -36,7 +35,7 @@ import { objectEntries } from "@homarr/common";
import type { IntegrationKind } from "@homarr/definitions";
import { getIntegrationName } from "@homarr/definitions";
import { getScopedI18n } from "@homarr/translation/server";
import { CountBadge, IntegrationAvatar } from "@homarr/ui";
import { CountBadge, IntegrationAvatar, Link } from "@homarr/ui";
import { ManageContainer } from "~/components/manage/manage-container";
import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
@@ -1,4 +1,3 @@
import Link from "next/link";
import { notFound } from "next/navigation";
import {
ActionIcon,
@@ -25,7 +24,7 @@ import { humanFileSize } from "@homarr/common";
import type { inferSearchParamsFromSchema } from "@homarr/common/types";
import { createLocalImageUrl } from "@homarr/icons/local";
import { getI18n } from "@homarr/translation/server";
import { SearchInput, TablePagination, UserAvatar } from "@homarr/ui";
import { Link, SearchInput, TablePagination, UserAvatar } from "@homarr/ui";
import { ManageContainer } from "~/components/manage/manage-container";
import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
+1 -1
View File
@@ -1,10 +1,10 @@
import type { Metadata } from "next";
import Link from "next/link";
import { Card, Group, SimpleGrid, Space, Stack, Text } from "@mantine/core";
import { IconArrowRight } from "@tabler/icons-react";
import { api } from "@homarr/api/server";
import { getScopedI18n } from "@homarr/translation/server";
import { Link } from "@homarr/ui";
import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
import { createMetaTitle } from "~/metadata";
@@ -1,6 +1,5 @@
"use client";
import Link from "next/link";
import type { SegmentedControlItem } from "@mantine/core";
import { Button, Fieldset, Grid, Group, SegmentedControl, Stack, Textarea, TextInput } from "@mantine/core";
import { WidgetIntegrationSelect } from "node_modules/@homarr/widgets/src/widget-integration-select";
@@ -12,6 +11,7 @@ import { useZodForm } from "@homarr/form";
import { IconPicker } from "@homarr/forms-collection";
import type { TranslationFunction } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { searchEngineManageSchema } from "@homarr/validation/search-engine";
type FormType = z.infer<typeof searchEngineManageSchema>;
@@ -1,4 +1,3 @@
import Link from "next/link";
import { redirect } from "next/navigation";
import { ActionIcon, ActionIconGroup, Anchor, Avatar, Card, Group, Stack, Text, Title } from "@mantine/core";
import { IconPencil, IconSearch } from "@tabler/icons-react";
@@ -9,7 +8,7 @@ import { api } from "@homarr/api/server";
import { auth } from "@homarr/auth/next";
import type { inferSearchParamsFromSchema } from "@homarr/common/types";
import { getI18n, getScopedI18n } from "@homarr/translation/server";
import { SearchInput, TablePagination } from "@homarr/ui";
import { Link, SearchInput, TablePagination } from "@homarr/ui";
import { ManageContainer } from "~/components/manage/manage-container";
import { MobileAffixButton } from "~/components/manage/mobile-affix-button";
@@ -1,5 +1,4 @@
import { X509Certificate } from "node:crypto";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
Button,
@@ -19,6 +18,7 @@ import { IconCertificateOff } from "@tabler/icons-react";
import { auth } from "@homarr/auth/next";
import { getTrustedCertificateHostnamesAsync } from "@homarr/certificates/server";
import { getI18n } from "@homarr/translation/server";
import { Link } from "@homarr/ui";
import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
import { NoResults } from "~/components/no-results";
@@ -1,5 +1,4 @@
import { X509Certificate } from "node:crypto";
import Link from "next/link";
import { notFound } from "next/navigation";
import { Button, Card, Group, SimpleGrid, Stack, Text, Title } from "@mantine/core";
import { IconAlertTriangle, IconCertificate, IconCertificateOff } from "@tabler/icons-react";
@@ -10,6 +9,7 @@ import { loadCustomRootCertificatesAsync } from "@homarr/certificates/server";
import { getMantineColor } from "@homarr/common";
import type { SupportedLanguage } from "@homarr/translation";
import { getI18n } from "@homarr/translation/server";
import { Link } from "@homarr/ui";
import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
import { NoResults } from "~/components/no-results";
@@ -1,10 +1,10 @@
"use client";
import Link from "next/link";
import { Anchor, Center, Stack, Text } from "@mantine/core";
import { IconShipOff } from "@tabler/icons-react";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
export default function DockerErrorPage() {
const t = useI18n();
@@ -1,10 +1,10 @@
"use client";
import Link from "next/link";
import { Anchor, Center, Stack, Text } from "@mantine/core";
import { IconCubeOff } from "@tabler/icons-react";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
export default function KubernetesErrorPage() {
const t = useI18n();
@@ -1,11 +1,11 @@
import React from "react";
import Image from "next/image";
import Link from "next/link";
import { Card, Group, Text } from "@mantine/core";
import { IconArrowRight } from "@tabler/icons-react";
import type { KubernetesLabelResourceType } from "@homarr/definitions";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import classes from "./resource-tile.module.css";
@@ -1,7 +1,6 @@
"use client";
import { useMemo } from "react";
import Link from "next/link";
import { Anchor, Button, Group, Text, Title, Tooltip } from "@mantine/core";
import { IconCheck } from "@tabler/icons-react";
import type { MRT_ColumnDef } from "mantine-react-table";
@@ -10,7 +9,7 @@ import { MantineReactTable } from "mantine-react-table";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { UserAvatar } from "@homarr/ui";
import { Link, UserAvatar } from "@homarr/ui";
import { useTranslatedMantineReactTable } from "@homarr/ui/hooks";
interface UserListComponentProps {
@@ -1,6 +1,6 @@
"use client";
import { startTransition, useCallback, useMemo, useState } from "react";
import { startTransition, useCallback, useState } from "react";
import {
Badge,
Button,
@@ -20,8 +20,9 @@ import { IconPlus, IconUserCheck } from "@tabler/icons-react";
import { z } from "zod/v4";
import { clientApi } from "@homarr/api/client";
import { everyoneGroup, groupPermissions } from "@homarr/definitions";
import type { GroupPermissionKey } from "@homarr/definitions";
import { everyoneGroup, groupPermissions } from "@homarr/definitions";
import type { IsValid } from "@homarr/form";
import { useZodForm } from "@homarr/form";
import { useModalAction } from "@homarr/modals";
import { showErrorNotification } from "@homarr/notifications";
@@ -113,11 +114,9 @@ export const UserCreateStepperComponent = ({ initialGroups }: UserCreateStepperC
},
);
const allForms = useMemo(() => [generalForm, securityForm, groupsForm], [generalForm, securityForm, groupsForm]);
const activeForm = allForms[active];
const isCurrentFormValid = activeForm ? activeForm.isValid : () => true;
const canNavigateToNextStep = isCurrentFormValid();
const allForms = [generalForm, securityForm, groupsForm];
const isValidCallback: IsValid<unknown> | undefined = allForms[active]?.isValid;
const currentFormValid = isValidCallback?.() ?? true;
const controlledGoToNextStep = useCallback(async () => {
if (active + 1 === stepperMax) {
@@ -218,7 +217,7 @@ export const UserCreateStepperComponent = ({ initialGroups }: UserCreateStepperC
</Stepper.Completed>
</Stepper>
<StepperNavigationComponent
hasNext={hasNext && canNavigateToNextStep}
hasNext={hasNext && currentFormValid}
hasPrevious={hasPrevious}
isComplete={active === stepperMax}
isLoadingNextStep={isPending}
@@ -1,8 +1,8 @@
import Link from "next/link";
import { Button, Card, Group } from "@mantine/core";
import { IconArrowBackUp, IconArrowLeft, IconArrowRight, IconRotate } from "@tabler/icons-react";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
interface StepperNavigationComponentProps {
hasPrevious: boolean;
@@ -1,10 +1,11 @@
"use client";
import type { ReactNode } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { NavLink } from "@mantine/core";
import { Link } from "@homarr/ui";
interface NavigationLinkProps {
href: string;
label: string;
@@ -1,11 +1,11 @@
"use client";
import Link from "next/link";
import { Alert, Anchor } from "@mantine/core";
import { IconExclamationCircle } from "@tabler/icons-react";
import { createDocumentationLink } from "@homarr/definitions";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
export const ReservedGroupAlert = () => {
const t = useI18n();
@@ -1,10 +1,10 @@
import type { PropsWithChildren } from "react";
import Link from "next/link";
import { Button, Grid, GridCol, Group, Stack, Text, Title } from "@mantine/core";
import { IconId, IconLock, IconSettings, IconUsersGroup } from "@tabler/icons-react";
import { api } from "@homarr/api/server";
import { getI18n, getScopedI18n } from "@homarr/translation/server";
import { Link } from "@homarr/ui";
import { ManageContainer } from "~/components/manage/manage-container";
import { NavigationLink } from "./_navigation";
@@ -1,4 +1,3 @@
import Link from "next/link";
import { notFound } from "next/navigation";
import { Alert, Anchor, Center, Group, Stack, Table, TableTbody, TableTd, TableTr, Text, Title } from "@mantine/core";
import { IconExclamationCircle } from "@tabler/icons-react";
@@ -10,7 +9,7 @@ import { auth } from "@homarr/auth/next";
import { isProviderEnabled } from "@homarr/auth/server";
import { everyoneGroup } from "@homarr/definitions";
import { getI18n, getScopedI18n } from "@homarr/translation/server";
import { SearchInput, UserAvatar } from "@homarr/ui";
import { Link, SearchInput, UserAvatar } from "@homarr/ui";
import { ReservedGroupAlert } from "../_reserved-group-alert";
import { AddGroupMember } from "./_add-group-member";
@@ -2,7 +2,6 @@
import type { ReactNode } from "react";
import { useMemo, useState } from "react";
import Link from "next/link";
import type { DragEndEvent, DraggableAttributes, DragStartEvent } from "@dnd-kit/core";
import {
closestCenter,
@@ -41,7 +40,7 @@ import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { UserAvatarGroup } from "@homarr/ui";
import { Link, UserAvatarGroup } from "@homarr/ui";
interface GroupsTableProps {
initialGroupIds: string[];
@@ -1,4 +1,3 @@
import Link from "next/link";
import { notFound } from "next/navigation";
import { Card, Group, Stack, Text, ThemeIcon, Title, UnstyledButton } from "@mantine/core";
import { IconChevronRight, IconUsersGroup } from "@tabler/icons-react";
@@ -7,6 +6,7 @@ import { api } from "@homarr/api/server";
import { auth } from "@homarr/auth/next";
import { everyoneGroup } from "@homarr/definitions";
import { getI18n } from "@homarr/translation/server";
import { Link } from "@homarr/ui";
import { ManageContainer } from "~/components/manage/manage-container";
import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb";
@@ -1,6 +1,7 @@
import { notFound } from "next/navigation";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import DOMPurify from "isomorphic-dompurify";
import { db, eq } from "@homarr/db";
import { medias } from "@homarr/db/schema";
@@ -19,11 +20,24 @@ export async function GET(_req: NextRequest, props: { params: Promise<{ id: stri
notFound();
}
let content = new Uint8Array(image.content);
// Sanitize SVG content to prevent XSS attacks
if (image.contentType === "image/svg+xml" || image.contentType === "image/svg") {
const svgText = new TextDecoder().decode(content);
const sanitized = DOMPurify.sanitize(svgText, {
USE_PROFILES: { svg: true, svgFilters: true },
});
content = new TextEncoder().encode(sanitized);
}
const headers = new Headers();
headers.set("Content-Type", image.contentType);
headers.set("Content-Length", image.content.length.toString());
headers.set("Content-Length", content.length.toString());
headers.set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox");
headers.set("X-Content-Type-Options", "nosniff");
return new NextResponse(new Uint8Array(image.content), {
return new NextResponse(content, {
status: 200,
headers,
});
@@ -1,10 +1,10 @@
import { useState } from "react";
import Link from "next/link";
import { Anchor, Button, Group, Stack, Table, TableTbody, TableTh, TableThead, TableTr } from "@mantine/core";
import { IconPlus } from "@tabler/icons-react";
import { useModalAction } from "@homarr/modals";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import type { AccessQueryData } from "./access-settings";
import { AccessSelectRow } from "./access-table-rows";
@@ -1,11 +1,10 @@
import { useState } from "react";
import Link from "next/link";
import { Anchor, Box, Button, Group, Stack, Table, TableTbody, TableTh, TableThead, TableTr } from "@mantine/core";
import { IconPlus } from "@tabler/icons-react";
import { useModalAction } from "@homarr/modals";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { UserAvatar } from "@homarr/ui";
import { Link, UserAvatar } from "@homarr/ui";
import type { AccessQueryData } from "./access-settings";
import { AccessDisplayRow, AccessSelectRow } from "./access-table-rows";
+1 -1
View File
@@ -1,8 +1,8 @@
import type { ReactNode } from "react";
import Link from "next/link";
import { AppShellHeader, Group, UnstyledButton } from "@mantine/core";
import { Spotlight } from "@homarr/spotlight";
import { Link } from "@homarr/ui";
import { ClientBurger } from "./header/burger";
import { DesktopSearchInput, MobileSearchButton } from "./header/search";
@@ -1,9 +1,10 @@
import type { ForwardedRef, ReactNode } from "react";
import { forwardRef } from "react";
import Link from "next/link";
import type { ActionIconProps } from "@mantine/core";
import { ActionIcon } from "@mantine/core";
import { Link } from "@homarr/ui";
type HeaderButtonProps = (
| {
onClick?: () => void;
@@ -1,10 +1,11 @@
"use client";
import type { ReactNode } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { NavLink } from "@mantine/core";
import { Link } from "@homarr/ui";
export const CommonNavLink = (props: ClientNavigationLink) =>
"href" in props ? <NavLinkHref {...props} /> : <NavLinkWithItems {...props} />;
@@ -2,7 +2,6 @@
import type { ReactNode } from "react";
import { useCallback, useEffect } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { Center, Menu, Stack, Text, useMantineColorScheme } from "@mantine/core";
import { useHotkeys, useTimeout } from "@mantine/hooks";
@@ -22,6 +21,7 @@ import { signOut, useSession } from "@homarr/auth/client";
import { hotkeys } from "@homarr/definitions";
import { createModal, useModalAction } from "@homarr/modals";
import { useScopedI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { useAuthContext } from "~/app/[locale]/_client-providers/session";
import { CurrentLanguageCombobox } from "./language/current-language-combobox";
@@ -1,10 +1,7 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { createTRPCClient, httpLink } from "@trpc/client";
import SuperJSON from "superjson";
import { NextResponse } from "next/server";
import type { AppRouter } from "@homarr/api";
import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared";
import { api } from "@homarr/api/server";
import { localeCookieKey } from "@homarr/definitions";
import type { SupportedLanguage } from "@homarr/translation";
import { supportedLanguages } from "@homarr/translation";
@@ -12,12 +9,12 @@ import { createI18nMiddleware } from "@homarr/translation/middleware";
let isOnboardingFinished = false;
export async function middleware(request: NextRequest) {
export async function proxy(request: NextRequest) {
// Redirect to onboarding if it's not finished yet
const pathname = request.nextUrl.pathname;
if (!isOnboardingFinished && !pathname.endsWith("/init")) {
const currentOnboardingStep = await serverFetchApi.onboard.currentStep.query();
const currentOnboardingStep = await api.onboard.currentStep();
if (currentOnboardingStep.current !== "finish") {
return NextResponse.redirect(new URL("/init", request.url));
}
@@ -29,11 +26,12 @@ export async function middleware(request: NextRequest) {
const currentLocale = request.cookies.get(localeCookieKey)?.value;
let defaultLocale: SupportedLanguage = "en";
if (!currentLocale || !supportedLanguages.includes(currentLocale as SupportedLanguage)) {
defaultLocale = await serverFetchApi.serverSettings.getCulture.query().then((culture) => culture.defaultLocale);
defaultLocale = await api.serverSettings.getCulture().then((culture) => culture.defaultLocale);
}
// We don't want to fallback to accept-language header so we clear it
request.headers.set("accept-language", "");
const next = createI18nMiddleware(defaultLocale);
return next(request);
}
@@ -41,13 +39,3 @@ export async function middleware(request: NextRequest) {
export const config = {
matcher: ["/((?!api|static|.*\\..*|_next|favicon.ico|robots.txt).*)"],
};
export const serverFetchApi = createTRPCClient<AppRouter>({
links: [
httpLink({
url: getTrpcUrl(),
transformer: SuperJSON,
headers: createHeadersCallbackForSource("server-fetch"),
}),
],
});
+7 -7
View File
@@ -37,20 +37,20 @@
"@homarr/server-settings": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@homarr/widgets": "workspace:^0.1.0",
"dayjs": "^1.11.18",
"dayjs": "^1.11.19",
"dotenv": "^17.2.3",
"fastify": "^5.6.1",
"superjson": "2.2.3",
"fastify": "^5.6.2",
"superjson": "2.2.5",
"undici": "7.16.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^24.9.1",
"dotenv-cli": "^10.0.0",
"esbuild": "^0.25.11",
"eslint": "^9.38.0",
"@types/node": "^24.10.0",
"dotenv-cli": "^11.0.0",
"esbuild": "^0.26.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"tsx": "4.20.4",
"typescript": "^5.9.3"
+2 -2
View File
@@ -34,8 +34,8 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.18.1",
"esbuild": "^0.25.11",
"eslint": "^9.38.0",
"esbuild": "^0.26.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
}
+18 -18
View File
@@ -1,6 +1,6 @@
{
"name": "homarr",
"version": "1.43.1",
"version": "1.43.3",
"private": true,
"scripts": {
"build": "cross-env CI=true turbo build",
@@ -39,28 +39,28 @@
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^13.0.1",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^12.0.0",
"@semantic-release/github": "^12.0.2",
"@semantic-release/npm": "^13.1.1",
"@semantic-release/release-notes-generator": "^14.1.0",
"@testcontainers/redis": "^11.7.2",
"@turbo/gen": "^2.5.8",
"@testcontainers/redis": "^11.8.0",
"@turbo/gen": "^2.6.0",
"@vitejs/plugin-react": "^5.1.0",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"@vitest/coverage-v8": "^4.0.8",
"@vitest/ui": "^4.0.8",
"conventional-changelog-conventionalcommits": "^9.1.0",
"cross-env": "^10.1.0",
"jsdom": "^27.0.1",
"jsdom": "^27.1.0",
"prettier": "^3.6.2",
"semantic-release": "^25.0.1",
"testcontainers": "^11.7.2",
"turbo": "^2.5.8",
"semantic-release": "^25.0.2",
"testcontainers": "^11.8.0",
"turbo": "^2.6.0",
"typescript": "^5.9.3",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.4"
"vitest": "^4.0.8"
},
"packageManager": "pnpm@10.19.0",
"packageManager": "pnpm@10.20.0",
"engines": {
"node": ">=22.21.0"
"node": ">=24.11.0"
},
"pnpm": {
"onlyBuiltDependencies": [
@@ -77,23 +77,23 @@
"overrides": {
"@babel/helpers@<7.26.10": ">=7.28.4",
"@babel/runtime@<7.26.10": ">=7.28.4",
"axios@>=1.0.0 <1.8.2": ">=1.12.2",
"axios@>=1.0.0 <1.8.2": ">=1.13.2",
"brace-expansion@>=2.0.0 <=2.0.1": ">=4.0.1",
"brace-expansion@>=1.0.0 <=1.1.11": ">=4.0.1",
"esbuild@<=0.24.2": ">=0.25.11",
"esbuild@<=0.24.2": ">=0.26.0",
"form-data@>=4.0.0 <4.0.4": ">=4.0.4",
"hono@<4.6.5": ">=4.10.3",
"hono@<4.6.5": ">=4.10.4",
"linkifyjs@<4.3.2": ">=4.3.2",
"nanoid@>=4.0.0 <5.0.9": ">=5.1.6",
"prismjs@<1.30.0": ">=1.30.0",
"proxmox-api>undici": "7.16.0",
"react-is": "^19.2.0",
"rollup@>=4.0.0 <4.22.4": ">=4.52.5",
"rollup@>=4.0.0 <4.22.4": ">=4.53.1",
"sha.js@<=2.4.11": ">=2.4.12",
"tar-fs@>=3.0.0 <3.0.9": ">=3.1.1",
"tar-fs@>=2.0.0 <2.1.3": ">=3.1.1",
"tmp@<=0.2.3": ">=0.2.5",
"vite@>=5.0.0 <=5.4.18": ">=7.1.12"
"vite@>=5.0.0 <=5.4.18": ">=7.2.2"
},
"patchedDependencies": {
"@types/node-unifi": "patches/@types__node-unifi.patch",
+2 -2
View File
@@ -26,13 +26,13 @@
"@homarr/log": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@umami/node": "^0.4.0",
"superjson": "2.2.3"
"superjson": "2.2.5"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+8 -8
View File
@@ -43,16 +43,16 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@kubernetes/client-node": "^1.4.0",
"@tanstack/react-query": "^5.90.5",
"@trpc/client": "^11.7.0",
"@trpc/react-query": "^11.7.0",
"@trpc/server": "^11.7.0",
"@trpc/tanstack-react-query": "^11.7.0",
"@tanstack/react-query": "^5.90.7",
"@trpc/client": "^11.7.1",
"@trpc/react-query": "^11.7.1",
"@trpc/server": "^11.7.1",
"@trpc/tanstack-react-query": "^11.7.1",
"lodash.clonedeep": "^4.5.0",
"next": "15.5.6",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"superjson": "2.2.3",
"superjson": "2.2.5",
"trpc-to-openapi": "^3.1.0",
"zod": "^4.1.12"
},
@@ -60,7 +60,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
}
+2 -2
View File
@@ -35,7 +35,7 @@
"bcrypt": "^6.0.0",
"cookies": "^0.9.1",
"ldapts": "8.0.9",
"next": "15.5.6",
"next": "16.0.1",
"next-auth": "5.0.0-beta.30",
"react": "19.2.0",
"react-dom": "19.2.0",
@@ -47,7 +47,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/bcrypt": "6.0.0",
"@types/cookies": "0.9.2",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
}
@@ -23,12 +23,11 @@ describe("authorizeWithLdapCredentials", () => {
test("should fail when wrong ldap base credentials", async () => {
// Arrange
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn(() => Promise.reject(new Error("bindAsync"))),
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn(() => Promise.reject(new Error("bindAsync"))),
} as unknown as ldapClient.LdapClient;
});
// Act
const act = () =>
@@ -44,13 +43,12 @@ describe("authorizeWithLdapCredentials", () => {
test("should fail when user not found", async () => {
// Arrange
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() => Promise.resolve([])),
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() => Promise.resolve([])),
} as unknown as ldapClient.LdapClient;
});
// Act
const act = () =>
@@ -66,20 +64,19 @@ describe("authorizeWithLdapCredentials", () => {
test("should fail when user has invalid email", async () => {
// Arrange
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test",
mail: "test",
},
]),
),
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test",
mail: "test",
},
]),
),
} as unknown as ldapClient.LdapClient;
});
// Act
const act = () =>
@@ -103,15 +100,14 @@ describe("authorizeWithLdapCredentials", () => {
]),
);
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn((props: ldapClient.BindOptions) =>
props.distinguishedName === "test" ? Promise.reject(new Error("bindAsync")) : Promise.resolve(),
),
searchAsync: searchSpy,
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn((props: ldapClient.BindOptions) =>
props.distinguishedName === "test" ? Promise.reject(new Error("bindAsync")) : Promise.resolve(),
),
searchAsync: searchSpy,
} as unknown as ldapClient.LdapClient;
});
// Act
const act = () =>
@@ -129,21 +125,20 @@ describe("authorizeWithLdapCredentials", () => {
// Arrange
const db = createDb();
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
} as unknown as ldapClient.LdapClient;
});
// Act
const result = await authorizeWithLdapCredentialsAsync(db, {
@@ -168,21 +163,20 @@ describe("authorizeWithLdapCredentials", () => {
// Arrange
const db = createDb();
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
} as unknown as ldapClient.LdapClient;
});
await db.insert(users).values({
id: createId(),
name: "test",
@@ -220,21 +214,20 @@ describe("authorizeWithLdapCredentials", () => {
test("should authorize user with correct credentials and return updated name", async () => {
// Arrange
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test55",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn(() =>
Promise.resolve([
{
dn: "test55",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
} as unknown as ldapClient.LdapClient;
});
const userId = createId();
const db = createDb();
@@ -268,27 +261,26 @@ describe("authorizeWithLdapCredentials", () => {
test("should authorize user with correct credentials and return his groups", async () => {
// Arrange
const spy = vi.spyOn(ldapClient, "LdapClient");
spy.mockImplementation(
() =>
({
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn((argument: { options: { filter: string } }) =>
argument.options.filter.includes("group")
? Promise.resolve([
{
cn: "homarr_example",
},
])
: Promise.resolve([
{
dn: "test55",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
}) as unknown as ldapClient.LdapClient,
);
spy.mockImplementation(function () {
return {
bindAsync: vi.fn(() => Promise.resolve()),
searchAsync: vi.fn((argument: { options: { filter: string } }) =>
argument.options.filter.includes("group")
? Promise.resolve([
{
cn: "homarr_example",
},
])
: Promise.resolve([
{
dn: "test55",
mail: "test@gmail.com",
},
]),
),
disconnectAsync: vi.fn(),
} as unknown as ldapClient.LdapClient;
});
const db = createDb();
const userId = createId();
await db.insert(users).values({
+1 -1
View File
@@ -32,7 +32,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -30,7 +30,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+2 -2
View File
@@ -34,8 +34,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"esbuild": "^0.25.11",
"eslint": "^9.38.0",
"esbuild": "^0.26.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+4 -4
View File
@@ -30,10 +30,10 @@
"@homarr/core": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@paralleldrive/cuid2": "^3.1.0",
"dayjs": "^1.11.18",
"dayjs": "^1.11.19",
"dns-caching": "^0.2.7",
"next": "15.5.6",
"octokit": "^5.0.4",
"next": "16.0.1",
"octokit": "^5.0.5",
"react": "19.2.0",
"react-dom": "19.2.0",
"undici": "7.16.0",
@@ -44,7 +44,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -32,7 +32,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+5 -5
View File
@@ -29,10 +29,10 @@
"@homarr/core": "workspace:^0.1.0",
"@homarr/cron-jobs": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@tanstack/react-query": "^5.90.5",
"@trpc/client": "^11.7.0",
"@trpc/server": "^11.7.0",
"@trpc/tanstack-react-query": "^11.7.0",
"@tanstack/react-query": "^5.90.7",
"@trpc/client": "^11.7.1",
"@trpc/server": "^11.7.1",
"@trpc/tanstack-react-query": "^11.7.1",
"node-cron": "^4.2.1",
"react": "19.2.0",
"zod": "^4.1.12"
@@ -43,7 +43,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node-cron": "^3.0.11",
"@types/react": "19.2.2",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -29,7 +29,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -33,7 +33,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node-cron": "^3.0.11",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -44,7 +44,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+9 -9
View File
@@ -49,28 +49,28 @@
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.3.5",
"@mantine/core": "^8.3.7",
"@paralleldrive/cuid2": "^3.1.0",
"@testcontainers/mysql": "^11.7.2",
"@testcontainers/postgresql": "^11.7.2",
"@testcontainers/mysql": "^11.8.0",
"@testcontainers/postgresql": "^11.8.0",
"better-sqlite3": "^12.4.1",
"dotenv": "^17.2.3",
"drizzle-kit": "^0.31.5",
"drizzle-kit": "^0.31.6",
"drizzle-orm": "^0.44.7",
"drizzle-zod": "^0.8.3",
"mysql2": "3.15.3",
"pg": "^8.16.3",
"superjson": "2.2.3"
"superjson": "2.2.5"
},
"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.15.5",
"dotenv-cli": "^10.0.0",
"esbuild": "^0.25.11",
"eslint": "^9.38.0",
"@types/pg": "^8.15.6",
"dotenv-cli": "^11.0.0",
"esbuild": "^0.26.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"tsx": "4.20.4",
"typescript": "^5.9.3"
+2 -2
View File
@@ -24,14 +24,14 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"fast-xml-parser": "^5.3.0",
"fast-xml-parser": "^5.3.1",
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"tsx": "4.20.4",
"typescript": "^5.9.3"
}
+1 -1
View File
@@ -33,7 +33,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/dockerode": "^3.3.45",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+2 -2
View File
@@ -26,7 +26,7 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/form": "^8.3.5",
"@mantine/form": "^8.3.7",
"mantine-form-zod-resolver": "^1.3.0",
"zod": "^4.1.12"
},
@@ -34,7 +34,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+3 -2
View File
@@ -28,8 +28,9 @@
"@homarr/form": "workspace:^0.1.0",
"@homarr/notifications": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.5",
"@mantine/core": "^8.3.7",
"react": "19.2.0",
"zod": "^4.1.12"
},
@@ -37,7 +38,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
@@ -2,7 +2,6 @@
import type { ChangeEventHandler } from "react";
import { useEffect, useRef } from "react";
import Link from "next/link";
import { Button, Checkbox, Collapse, Group, Stack, Textarea, TextInput } from "@mantine/core";
import { useDebouncedValue, useDisclosure } from "@mantine/hooks";
import type { z } from "zod/v4";
@@ -10,6 +9,7 @@ import type { z } from "zod/v4";
import { clientApi } from "@homarr/api/client";
import { useZodForm } from "@homarr/form";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import { appManageSchema } from "@homarr/validation/app";
import { IconPicker } from "../icon-picker/icon-picker";
+1 -1
View File
@@ -31,7 +31,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -33,7 +33,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/bcrypt": "6.0.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+8 -8
View File
@@ -25,10 +25,10 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
"@ctrl/deluge": "^7.4.0",
"@ctrl/qbittorrent": "^9.10.0",
"@ctrl/deluge": "^7.5.0",
"@ctrl/qbittorrent": "^9.11.0",
"@ctrl/transmission": "^7.4.0",
"@gitbeaker/rest": "^43.5.0",
"@gitbeaker/rest": "^43.8.0",
"@homarr/certificates": "workspace:^0.1.0",
"@homarr/common": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
@@ -39,14 +39,14 @@
"@homarr/redis": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@jellyfin/sdk": "^0.12.0",
"@octokit/auth-app": "^8.1.1",
"@jellyfin/sdk": "^0.13.0",
"@octokit/auth-app": "^8.1.2",
"ical.js": "^2.2.1",
"maria2": "^0.4.1",
"node-ical": "^0.22.1",
"octokit": "^5.0.4",
"octokit": "^5.0.5",
"proxmox-api": "1.1.1",
"tsdav": "^2.1.5",
"tsdav": "^2.1.6",
"undici": "7.16.0",
"xml2js": "^0.6.2",
"zod": "^4.1.12"
@@ -57,7 +57,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node-unifi": "^2.5.1",
"@types/xml2js": "^0.4.14",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
@@ -108,7 +108,7 @@ export class GitlabIntegration extends Integration implements ReleasesProviderIn
return {
projectUrl: response.web_url,
projectDescription: response.description,
projectDescription: response.description ?? undefined,
isFork: response.forked_from_project !== null,
isArchived: response.archived,
createdAt: new Date(response.created_at),
+2 -2
View File
@@ -25,7 +25,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/core": "workspace:^0.1.0",
"superjson": "2.2.3",
"superjson": "2.2.5",
"winston": "3.18.3",
"zod": "^4.1.12"
},
@@ -33,7 +33,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+4 -4
View File
@@ -33,10 +33,10 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.5",
"@mantine/core": "^8.3.7",
"@tabler/icons-react": "^3.35.0",
"dayjs": "^1.11.18",
"next": "15.5.6",
"dayjs": "^1.11.19",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"zod": "^4.1.12"
@@ -45,7 +45,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
@@ -1,10 +1,10 @@
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Button, CopyButton, Mark, Stack, Text } from "@mantine/core";
import type { RouterOutputs } from "@homarr/api";
import { createModal } from "@homarr/modals";
import { useScopedI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
export const InviteCopyModal = createModal<RouterOutputs["invite"]["createInvite"]>(({ actions, innerProps }) => {
const t = useScopedI18n("management.page.user.invite");
+3 -3
View File
@@ -24,15 +24,15 @@
"dependencies": {
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.5",
"@mantine/hooks": "^8.3.5",
"@mantine/core": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"react": "19.2.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+2 -2
View File
@@ -24,14 +24,14 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/ui": "workspace:^0.1.0",
"@mantine/notifications": "^8.3.5",
"@mantine/notifications": "^8.3.7",
"@tabler/icons-react": "^3.35.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+5 -5
View File
@@ -37,13 +37,13 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.5",
"@mantine/hooks": "^8.3.5",
"@mantine/core": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"adm-zip": "0.5.16",
"next": "15.5.6",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"superjson": "2.2.3",
"superjson": "2.2.5",
"zod": "^4.1.12",
"zod-form-data": "^3.0.1"
},
@@ -52,7 +52,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/adm-zip": "0.5.7",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -29,7 +29,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -30,7 +30,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+2 -2
View File
@@ -28,13 +28,13 @@
"@homarr/definitions": "workspace:^",
"@homarr/log": "workspace:^",
"ioredis": "5.8.2",
"superjson": "2.2.3"
"superjson": "2.2.5"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+4 -4
View File
@@ -29,9 +29,9 @@
"@homarr/integrations": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/redis": "workspace:^0.1.0",
"dayjs": "^1.11.18",
"octokit": "^5.0.4",
"superjson": "2.2.3",
"dayjs": "^1.11.19",
"octokit": "^5.0.5",
"superjson": "2.2.5",
"undici": "7.16.0",
"zod": "^4.1.12"
},
@@ -39,7 +39,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+12 -4
View File
@@ -20,11 +20,19 @@ export const fetchStockPriceHandler = createCachedWidgetRequestHandler({
if (data.chart.result.length !== 1) {
throw new Error("Received multiple results");
}
if (!data.chart.result[0]) {
const firstResult = data.chart.result[0];
if (!firstResult) {
throw new Error("Received invalid data");
}
return data.chart.result[0];
return {
priceHistory:
firstResult.indicators.quote[0]?.close.filter(
// Filter out null values from price arrays (Yahoo Finance returns null for missing data points)
(value) => value !== null && value !== undefined,
) ?? [],
symbol: firstResult.meta.symbol,
shortName: firstResult.meta.shortName,
};
},
cacheDuration: dayjs.duration(5, "minutes"),
});
@@ -43,7 +51,7 @@ const dataSchema = z
indicators: z.object({
quote: z.array(
z.object({
close: z.array(z.number()),
close: z.array(z.number().nullish()),
}),
),
}),
+1 -1
View File
@@ -29,7 +29,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+3 -3
View File
@@ -26,8 +26,8 @@
"@homarr/api": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/dates": "^8.3.5",
"next": "15.5.6",
"@mantine/dates": "^8.3.7",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0"
},
@@ -35,7 +35,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+6 -6
View File
@@ -33,12 +33,12 @@
"@homarr/settings": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.5",
"@mantine/hooks": "^8.3.5",
"@mantine/spotlight": "^8.3.5",
"@mantine/core": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"@mantine/spotlight": "^8.3.7",
"@tabler/icons-react": "^3.35.0",
"jotai": "^2.15.0",
"next": "15.5.6",
"jotai": "^2.15.1",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"use-deep-compare-effect": "^1.8.1"
@@ -47,7 +47,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
@@ -1,6 +1,7 @@
import Link from "next/link";
import { Spotlight } from "@mantine/spotlight";
import { Link } from "@homarr/ui";
import type { inferSearchInteractionOptions } from "../../../lib/interaction";
import classes from "./action-item.module.css";
@@ -1,7 +1,7 @@
import Link from "next/link";
import { Spotlight } from "@mantine/spotlight";
import type { TranslationObject } from "@homarr/translation";
import { Link } from "@homarr/ui";
import type { SearchGroup } from "../../../lib/group";
import type { inferSearchInteractionOptions } from "../../../lib/interaction";
+4 -4
View File
@@ -29,11 +29,11 @@
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
"dayjs": "^1.11.18",
"dayjs": "^1.11.19",
"deepmerge": "4.3.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "15.5.6",
"next-intl": "4.4.0",
"next": "16.0.1",
"next-intl": "4.5.0",
"react": "19.2.0",
"react-dom": "19.2.0"
},
@@ -41,7 +41,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+21 -21
View File
@@ -649,14 +649,14 @@
"app": {
"option": {
"existing": {
"title": "",
"label": ""
"title": "Vorhanden",
"label": "Vorhandene App auswählen"
},
"new": {
"title": "",
"title": "Neu",
"url": {
"label": "",
"description": ""
"label": "App URL",
"description": "Die URL, welche die App öffnet, sobald sie vom Dashboard aus aufgerufen wird"
}
}
}
@@ -676,9 +676,9 @@
},
"app": {
"action": {
"add": "",
"remove": "",
"select": ""
"add": "Eine App verknüpfen",
"remove": "Verknüpfung aufheben",
"select": "Wählen Sie eine App zum Verknüpfen aus"
}
}
},
@@ -709,7 +709,7 @@
"description": "Integration \"{kind}\" kann mit den Suchmaschinen verwendet werden. Wählen Sie dies, um die Suchmaschine automatisch zu konfigurieren."
},
"app": {
"sectionTitle": ""
"sectionTitle": "Verknüpfte App"
},
"createApp": {
"label": "App erstellen",
@@ -1051,7 +1051,7 @@
"add": "Hinzufügen",
"apply": "Übernehmen",
"backToOverview": "Zurück zur Übersicht",
"change": "",
"change": "Verändern",
"create": "Erstellen",
"createAnother": "Erstellen und neu starten",
"edit": "Bearbeiten",
@@ -1174,8 +1174,8 @@
},
"unit": {
"speed": {
"kilometersPerHour": "",
"milesPerHour": ""
"kilometersPerHour": "km/h",
"milesPerHour": "mph"
}
}
},
@@ -1190,7 +1190,7 @@
"label": "Titel"
},
"customCssClasses": {
"label": ""
"label": "Benutzerdefinierte CSS Klassen"
},
"borderColor": {
"label": "Rahmenfarbe"
@@ -1780,7 +1780,7 @@
"description": "Nur bei aktuellem Wetter"
},
"useImperialSpeed": {
"label": ""
"label": "Verwende miles per hour für die Windgeschwindigkeit"
},
"location": {
"label": "Wetterstandort"
@@ -1800,12 +1800,12 @@
"description": "Wie das Datum aussehen sollte"
}
},
"currentWindSpeed": "{currentWindSpeed} km/h",
"currentWindSpeed": "{currentWindSpeed} {unit}",
"dailyForecast": {
"sunrise": "Sonnenaufgang",
"sunset": "Sonnenuntergang",
"maxWindSpeed": "Maximale Windgeschwindigkeit: {maxWindSpeed} km/h",
"maxWindGusts": "Maximale Windböen: {maxWindGusts} km/h"
"maxWindSpeed": "Maximale Windgeschwindigkeit: {maxWindSpeed} {unit}",
"maxWindGusts": "Maximale Windböen: {maxWindGusts} {unit}"
},
"kind": {
"clear": "Klar",
@@ -3013,8 +3013,8 @@
"integration": "Integrationen",
"app": "Apps",
"group": "Gruppen",
"searchEngine": "",
"media": ""
"searchEngine": "Suchmaschinen",
"media": "Medien"
},
"statisticLabel": {
"boards": "Boards",
@@ -3023,8 +3023,8 @@
"authorization": "Autorisierung"
},
"heroBanner": {
"title": "",
"subtitle": ""
"title": "Willkommen zurück zu Ihrem",
"subtitle": "{app} Board"
}
},
"board": {
+56 -56
View File
@@ -754,86 +754,86 @@
"notFound": "Not found",
"tooManyRequests": "Too many requests",
"internalServerError": "Internal server error",
"serviceUnavailable": "",
"gatewayTimeout": ""
"serviceUnavailable": "Service unavailable",
"gatewayTimeout": "Gateway timeout"
}
},
"certificate": {
"title": "",
"title": "Certificate error",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
"expired": "The certificate has expired.",
"notYetValid": "The certificate is not yet valid.",
"untrusted": "The certificate is not trusted.",
"hostnameMismatch": "The certificate hostname does not match the URL."
},
"alert": {
"permission": {
"title": "",
"message": ""
"title": "Not enough permissions",
"message": "You are not allowed to trust or upload certificates. Please contact your administrator to upload the necessary root certificate."
},
"hostnameMismatch": {
"title": "",
"message": ""
"title": "Hostname mismatch",
"message": "The hostname in the certificate does not match the hostname you are connecting to. This could indicate a security risk, but you can still choose to trust this certificate."
},
"extract": {
"title": "",
"message": ""
"title": "CA certificate extraction failed",
"message": "Only self-signed certificates without a chain can be fetched automatically. If you are using a self-signed certificate, please make sure to upload the CA certificate manually. You can find instructions on how to do this <docsLink></docsLink>."
}
},
"action": {
"retry": {
"label": ""
"label": "Retry creation"
},
"trust": {
"label": ""
"label": "Trust certificate"
},
"upload": {
"label": ""
"label": "Upload certificate"
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
"title": "Trust hostname mismatch",
"message": "Are you sure you want to trust the certificate with a hostname mismatch?"
},
"notification": {
"success": {
"title": "",
"message": ""
"title": "Trusted certificate",
"message": "Added hostname to trusted certificate list"
},
"error": {
"title": "",
"message": ""
"title": "Failed to trust certificate",
"message": "The certificate with a hostname mismatch could not be trusted"
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
"title": "Trust self-signed certificate",
"message": "Are you sure you want to trust this self-signed certificate?"
},
"notification": {
"success": {
"title": "",
"message": ""
"title": "Trusted certificate",
"message": "Added certificate to trusted certificate list"
},
"error": {
"title": "",
"message": ""
"title": "Failed to trust certificate",
"message": "Failed to add certificate to trusted certificate list"
}
}
},
"details": {
"title": "",
"description": "",
"title": "Details",
"description": "Review the certificate information before deciding to trust it.",
"content": {
"action": "",
"title": ""
"action": "Show content",
"title": "PEM Certificate"
}
}
},
"request": {
"title": "",
"title": "Request error",
"description": {
"connection": {
"hostUnreachable": "",
@@ -4456,50 +4456,50 @@
"title": "",
"description": "",
"noResults": {
"title": ""
"title": "There are no hostnames yet"
},
"toCertificates": ""
"toCertificates": "Certificates"
}
},
"action": {
"create": {
"label": "",
"label": "Add certificate",
"notification": {
"success": {
"title": "",
"message": ""
"title": "Certificate added",
"message": "The certificate was added successfully"
},
"error": {
"title": "",
"message": ""
"title": "Failed to add certificate",
"message": "The certificate could not be added"
}
}
},
"remove": {
"label": "",
"confirm": "",
"label": "Remove certificate",
"confirm": "Are you sure you want to remove the certificate?",
"notification": {
"success": {
"title": "",
"message": ""
"title": "Certificate removed",
"message": "The certificate was removed successfully"
},
"error": {
"title": "",
"message": ""
"title": "Certificate not removed",
"message": "The certificate could not be removed"
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"label": "Remove trusted hostname",
"confirm": "Are you sure you want to remove this trusted hostname? This can cause some integrations to stop working.",
"notification": {
"success": {
"title": "",
"message": ""
"title": "Hostname removed",
"message": "The hostname was removed successfully"
},
"error": {
"title": "",
"message": ""
"title": "Hostname not removed",
"message": "The hostname could not be removed"
}
}
}
@@ -4508,10 +4508,10 @@
"log": {
"level": {
"option": {
"debug": "",
"info": "",
"warn": "",
"error": ""
"debug": "Debug",
"info": "Info",
"warn": "Warn",
"error": "Error"
}
}
}
+15 -15
View File
@@ -653,10 +653,10 @@
"label": "Seleziona app esistente"
},
"new": {
"title": "",
"title": "Nuovo",
"url": {
"label": "Url app",
"description": ""
"description": "L'Url che l'app aprirà quando vi si accede dalla dashboard"
}
}
}
@@ -676,9 +676,9 @@
},
"app": {
"action": {
"add": "",
"remove": "",
"select": ""
"add": "Collega un'app",
"remove": "Scollega",
"select": "Seleziona un'app da collegare"
}
}
},
@@ -709,7 +709,7 @@
"description": "Integrazione \"{kind}\" può essere utilizzato con i motori di ricerca. Selezionare questa opzione per configurare automaticamente il motore di ricerca."
},
"app": {
"sectionTitle": ""
"sectionTitle": "App Collegata"
},
"createApp": {
"label": "Crea app",
@@ -1051,7 +1051,7 @@
"add": "Aggiungi",
"apply": "Applica",
"backToOverview": "Torna alla panoramica",
"change": "",
"change": "Cambia",
"create": "Crea",
"createAnother": "",
"edit": "Modifica",
@@ -2103,7 +2103,7 @@
},
"index": {
"columnTitle": "#",
"detailsTitle": ""
"detailsTitle": "Indice corrente all'interno del client"
},
"id": {
"columnTitle": "Id"
@@ -2949,7 +2949,7 @@
},
"breakpoint": {
"label": "",
"description": ""
"description": "Il layout verrà utilizzato su tutti gli schermi più grandi di questo breakpoint fino al breakpoint più grande successivo."
}
}
},
@@ -3013,7 +3013,7 @@
"integration": "Integrazioni",
"app": "Applicazioni",
"group": "Gruppi",
"searchEngine": "",
"searchEngine": "Motori di ricerca",
"media": "Media"
},
"statisticLabel": {
@@ -3023,8 +3023,8 @@
"authorization": "Autorizzazione"
},
"heroBanner": {
"title": "",
"subtitle": ""
"title": "Bentornato sulla tua",
"subtitle": "{app} Board"
}
},
"board": {
@@ -3358,7 +3358,7 @@
"label": "Controllo aggiornamenti"
},
"mediaTranscoding": {
"label": ""
"label": "Transcodifica del media"
},
"networkController": {
"label": "Controller di rete"
@@ -3510,7 +3510,7 @@
"subtitle": "{count} utilizzato nel Codice di Homarr"
},
"hotkeys": {
"title": "",
"title": "Tasti di scelta rapida",
"subtitle": "Scorciatoie da tastiera per migliorare il flusso di lavoro",
"field": {
"shortcut": "Scorciatoia",
@@ -3520,7 +3520,7 @@
"toggleBoardEdit": "",
"toggleColorScheme": "",
"saveNotebook": "",
"openSpotlight": ""
"openSpotlight": "Apri ricerca"
},
"note": ""
}
File diff suppressed because it is too large. Load diff
+5 -5
View File
@@ -30,12 +30,12 @@
"@homarr/log": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.5",
"@mantine/dates": "^8.3.5",
"@mantine/hooks": "^8.3.5",
"@mantine/core": "^8.3.7",
"@mantine/dates": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"@tabler/icons-react": "^3.35.0",
"mantine-react-table": "2.0.0-beta.9",
"next": "15.5.6",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"svgson": "^5.3.1"
@@ -45,7 +45,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/css-modules": "^1.0.5",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+1
View File
@@ -15,3 +15,4 @@ export { BetaBadge } from "./beta-badge";
export { MaskedImage } from "./masked-image";
export { MaskedOrNormalImage } from "./masked-or-normal-image";
export { LanguageIcon } from "./language-icon";
export { Link } from "./link";
+5
View File
@@ -0,0 +1,5 @@
"use client";
import NextLink from "next/link";
export const Link = NextLink;
@@ -1,11 +1,12 @@
"use client";
import { useCallback } from "react";
import Link from "next/link";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import type { PaginationProps } from "@mantine/core";
import { Pagination } from "@mantine/core";
import { Link } from "@homarr/ui";
interface TablePaginationProps {
total: number;
}
+1 -1
View File
@@ -31,7 +31,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
+22 -22
View File
@@ -48,31 +48,31 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/charts": "^8.3.5",
"@mantine/core": "^8.3.5",
"@mantine/hooks": "^8.3.5",
"@mantine/charts": "^8.3.7",
"@mantine/core": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"@tabler/icons-react": "^3.35.0",
"@tiptap/extension-color": "2.26.4",
"@tiptap/extension-highlight": "2.26.4",
"@tiptap/extension-image": "2.26.4",
"@tiptap/extension-link": "^2.26.4",
"@tiptap/extension-placeholder": "^2.26.4",
"@tiptap/extension-table": "2.26.4",
"@tiptap/extension-table-cell": "2.26.4",
"@tiptap/extension-table-header": "2.26.4",
"@tiptap/extension-table-row": "2.26.4",
"@tiptap/extension-task-item": "2.26.4",
"@tiptap/extension-task-list": "2.26.4",
"@tiptap/extension-text-align": "2.26.4",
"@tiptap/extension-text-style": "2.26.4",
"@tiptap/extension-underline": "2.26.4",
"@tiptap/react": "^2.26.4",
"@tiptap/starter-kit": "^2.26.4",
"@tiptap/extension-color": "2.27.1",
"@tiptap/extension-highlight": "2.27.1",
"@tiptap/extension-image": "2.27.1",
"@tiptap/extension-link": "^2.27.1",
"@tiptap/extension-placeholder": "^2.27.1",
"@tiptap/extension-table": "2.27.1",
"@tiptap/extension-table-cell": "2.27.1",
"@tiptap/extension-table-header": "2.27.1",
"@tiptap/extension-table-row": "2.27.1",
"@tiptap/extension-task-item": "2.27.1",
"@tiptap/extension-task-list": "2.27.1",
"@tiptap/extension-text-align": "2.27.1",
"@tiptap/extension-text-style": "2.27.1",
"@tiptap/extension-underline": "2.27.1",
"@tiptap/react": "^2.27.1",
"@tiptap/starter-kit": "^2.27.1",
"clsx": "^2.1.1",
"dayjs": "^1.11.18",
"dayjs": "^1.11.19",
"mantine-form-zod-resolver": "^1.3.0",
"mantine-react-table": "2.0.0-beta.9",
"next": "15.5.6",
"next": "16.0.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-markdown": "^10.1.0",
@@ -85,7 +85,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/video.js": "^7.3.58",
"eslint": "^9.38.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
}
@@ -1,7 +1,6 @@
"use client";
import { memo, useMemo } from "react";
import Link from "next/link";
import type { SelectProps } from "@mantine/core";
import { Anchor, Button, Group, Loader, Select, SimpleGrid, Text } from "@mantine/core";
import { IconCheck, IconRocket } from "@tabler/icons-react";
@@ -12,6 +11,7 @@ import { useSession } from "@homarr/auth/client";
import { useModalAction } from "@homarr/modals";
import { QuickAddAppModal } from "@homarr/modals-collection";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import type { CommonWidgetInputProps } from "./common";
import { useWidgetInputTranslation } from "./common";
@@ -1,9 +1,9 @@
import Link from "next/link";
import { Anchor, Button, Stack, Text } from "@mantine/core";
import type { stringOrTranslation } from "@homarr/translation";
import { translateIfNecessary } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
import { Link } from "@homarr/ui";
import type { TablerIcon } from "@homarr/ui";
export interface BaseWidgetErrorProps {
+20 -2
View File
@@ -11,8 +11,9 @@ import classes from "./component.module.css";
export default function IFrameWidget({ options, isEditMode }: WidgetComponentProps<"iframe">) {
const t = useI18n();
const { embedUrl, ...permissions } = options;
const { embedUrl, allowScrolling, ...permissions } = options;
const allowedPermissions = getAllowedPermissions(permissions);
const sandboxFlags = getSandboxFlags(permissions);
if (embedUrl.trim() === "") return <NoUrl />;
if (!isSupportedProtocol(embedUrl)) {
@@ -27,7 +28,8 @@ export default function IFrameWidget({ options, isEditMode }: WidgetComponentPro
src={embedUrl}
title="widget iframe"
allow={allowedPermissions.join(" ")}
scrolling={options.allowScrolling ? "yes" : "no"}
scrolling={allowScrolling ? "yes" : "no"}
sandbox={sandboxFlags.join(" ")}
>
<Text>{t("widget.iframe.error.noBrowerSupport")}</Text>
</iframe>
@@ -80,6 +82,22 @@ const getAllowedPermissions = (
.map(([key]) => permissionMapping[key]);
};
const getSandboxFlags = (
permissions: Omit<WidgetComponentProps<"iframe">["options"], "embedUrl" | "allowScrolling">,
) => {
const baseSandbox = ["allow-scripts", "allow-same-origin", "allow-forms", "allow-popups"];
if (permissions.allowFullScreen) {
baseSandbox.push("allow-presentation");
}
if (permissions.allowPayment) {
baseSandbox.push("allow-popups-to-escape-sandbox");
}
return baseSandbox;
};
const permissionMapping = {
allowAutoPlay: "autoplay",
allowCamera: "camera",
+9 -11
View File
@@ -26,15 +26,13 @@ export default function StockPriceWidget({ options, width, height }: WidgetCompo
const theme = useMantineTheme();
const [{ data }] = clientApi.widget.stockPrice.getPriceHistory.useSuspenseQuery(options);
const stockValues = data.indicators.quote[0]?.close ?? [];
const stockValuesChange = round(calculateChange(stockValues[stockValues.length - 1] ?? 0, stockValues[0] ?? 0));
const stockValuesChange = round(calculateChange(data.priceHistory.at(-1) ?? 0, data.priceHistory[0] ?? 0));
const stockValuesChangePercentage = round(
calculateChangePercentage(stockValues[stockValues.length - 1] ?? 0, stockValues[0] ?? 0),
calculateChangePercentage(data.priceHistory.at(-1) ?? 0, data.priceHistory[0] ?? 0),
);
const stockValuesMin = Math.min(...stockValues);
const stockGraphValues = stockValues.map((value) => value - stockValuesMin + 50);
const stockValuesMin = Math.min(...data.priceHistory);
const stockGraphValues = data.priceHistory.map((value) => value - stockValuesMin + 50);
return (
<Flex h="100%" w="100%">
@@ -57,17 +55,17 @@ export default function StockPriceWidget({ options, width, height }: WidgetCompo
) : (
<IconTrendingDown size="1.5rem" color={theme.colors.red[7]} />
)}
{data.meta.symbol}
{data.symbol}
</Text>
{width > 280 && height > 280 && (
<Text size="md" lh="1">
{data.meta.shortName}
{data.shortName}
</Text>
)}
</Stack>
<Title pos="absolute" bottom={10} right={10} order={width > 280 ? 1 : 2} fw={700}>
{new Intl.NumberFormat().format(round(stockValues[stockValues.length - 1] ?? 0))}
{new Intl.NumberFormat().format(round(data.priceHistory.at(-1) ?? 0))}
</Title>
{width > 280 && (
@@ -90,11 +88,11 @@ export default function StockPriceWidget({ options, width, height }: WidgetCompo
) : (
<IconTrendingDown size="1.5rem" color={theme.colors.red[7]} />
)}
{data.meta.symbol}
{data.symbol}
</Text>
{width > 280 && height > 280 && (
<Text size="md" lh="1">
{data.meta.shortName}
{data.shortName}
</Text>
)}
</Stack>
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff. Show more