Compare commits

...
117 Commits
Author SHA1 Message Date
Releases Homarr 6b76d55de2 chore(release): 1.22.0 [skip ci] 2025-05-30 19:17:12 +00:00
homarr-releases[bot] 09f821b95d chore(release): automatic release v1.22.0 2025-05-30 19:14:45 +00:00
Meier Lukas 11149348fc fix(cluster-health): storage items multiply (#3206) 2025-05-30 20:52:51 +02:00
homarr-renovate[bot] c8202ab3c6 fix(deps): update turbo monorepo to ^2.5.4 (#3279)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-30 16:24:36 +00:00
homarr-renovate[bot] 7a50829b6a chore(deps): update dependency @types/node to ^22.15.28 (#3277)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-30 15:21:51 +00:00
homarr-update-contributors[bot] 778cf861cf chore: update contributors (#3275)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2025-05-30 12:35:10 +00:00
homarr-renovate[bot] 6b8ffdfbc0 chore(deps): update dependency @types/node to ^22.15.27 (#3273)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-30 09:22:10 +00:00
homarr-renovate[bot] 608280e670 fix(deps): update dependency zod to ^3.25.42 (#3274)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-30 08:26:24 +00:00
homarr-renovate[bot] 5bf20aa353 fix(deps): update dependency zod to ^3.25.41 (#3272)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-30 03:15:18 +00:00
homarr-renovate[bot] 3ba9502b26 chore(deps): update dependency @types/node to ^22.15.26 (#3271)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 23:20:36 +00:00
homarr-renovate[bot] 862d07db68 fix(deps): update dependency zod to ^3.25.39 (#3270)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 22:21:03 +00:00
homarr-renovate[bot] d72a804ad9 fix(deps): update nextjs monorepo to v15.3.3 (#3269)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 20:24:32 +00:00
homarr-renovate[bot] 2320d3c567 fix(deps): update dependency flag-icons to ^7.5.0 (#3268)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 18:27:12 +00:00
homarr-renovate[bot] a0eda74fa4 fix(deps): update dependency flag-icons to ^7.4.0 (#3265)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 17:19:46 +00:00
homarr-renovate[bot] bac4f64257 fix(deps): update dependency ldapts to v8.0.1 (#3264)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 17:19:30 +00:00
homarr-renovate[bot] 1f9983f16d fix(deps): update tanstack-query monorepo to ^5.79.0 (#3263)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 12:23:07 +00:00
homarr-renovate[bot] 48ce2af4c1 fix(deps): update dependency zod to ^3.25.36 (#3262)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 08:26:55 +00:00
homarr-renovate[bot] 635c9a2687 fix(deps): update dependency @kubernetes/client-node to ^1.3.0 (#3261)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-29 01:15:13 +00:00
homarr-renovate[bot] c1324eab76 fix(deps): update dependency zod to ^3.25.34 (#3259)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-28 23:20:41 +00:00
homarr-renovate[bot] bfd7b70618 fix(deps): update trpc monorepo to ^11.1.4 (#3260)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-28 22:20:43 +00:00
homarr-renovate[bot] ad5f985645 chore(deps): update dependency @types/node to ^22.15.24 (#3257)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-28 21:20:37 +00:00
homarr-renovate[bot] 4a184d23f2 fix(deps): update dependency @ianvs/prettier-plugin-sort-imports to ^4.4.2 (#3258)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-28 20:23:40 +00:00
homarr-renovate[bot] 09b49a242d fix(deps): update dependency drizzle-orm to ^0.44.0 (#3256)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-28 15:22:07 +00:00
Meier Lukas 10f720d74c fix(search): removing server search engine causes loading error (#3252) 2025-05-28 07:57:37 +02:00
homarr-renovate[bot] 9c3a46c071 fix(deps): update dependency zod to ^3.25.32 (#3255)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-28 03:20:53 +00:00
homarr-renovate[bot] e2e4656001 fix(deps): update dependency zod to ^3.25.31 (#3254)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 22:20:28 +00:00
homarr-renovate[bot] 3253b2f138 fix(deps): update dependency octokit to ^5.0.3 (#3249)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 20:22:31 +00:00
homarr-renovate[bot] f9c7e7711a chore(deps): update dependency @types/node to ^22.15.23 (#3248)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 19:18:31 +00:00
homarr-renovate[bot] 8b553b80e6 fix(deps): update dependency typescript-eslint to ^8.33.0 (#3247)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 18:26:02 +00:00
homarr-renovate[bot] 75ebf075a5 chore(deps): update dependency @types/node to ^22.15.22 (#3246)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 18:25:39 +00:00
homarr-crowdin[bot] 1575716f41 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-27 17:02:51 +00:00
homarr-renovate[bot] 8966e2ad8a fix(deps): update dependency @t3-oss/env-nextjs to ^0.13.6 (#3244)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 12:36:02 +00:00
homarr-renovate[bot] 816544a996 fix(deps): update mantine monorepo to ^8.0.2 (#3245)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 11:19:17 +00:00
homarr-renovate[bot] 9c323850bc fix(deps): update dependency jotai to ^2.12.5 (#3243)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 09:21:29 +00:00
homarr-renovate[bot] c3936237c0 chore(deps): update dependency @types/react to v19.1.6 (#3242)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 08:26:07 +00:00
homarr-renovate[bot] 9b8d1cbb66 chore(deps): update dependency esbuild to ^0.25.5 (#3241)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 04:27:15 +00:00
homarr-renovate[bot] 3062948939 fix(deps): update dependency zod to ^3.25.30 (#3239)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 03:13:49 +00:00
homarr-renovate[bot] 78f98edc41 fix(deps): update trpc monorepo to ^11.1.3 (#3240)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-27 01:14:03 +00:00
homarr-renovate[bot] 81ca6ef7b2 fix(deps): update dependency zod to ^3.25.29 (#3237)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-26 23:20:16 +00:00
homarr-renovate[bot] 71186908b9 fix(deps): update tanstack-query monorepo to ^5.77.2 (#3232)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-26 12:34:40 +00:00
Meier Lukas cbbf0c8dcf fix: navigating back results in navigation back to first page opened (#3224) 2025-05-26 11:41:09 +02:00
Meier Lukas 1d27da2230 fix(calendar): remove scrollbar for 2x2 (#3227) 2025-05-26 11:40:42 +02:00
homarr-crowdin[bot] d4ef212042 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-26 00:53:16 +00:00
homarr-renovate[bot] 5ea7a20677 fix(deps): update tanstack-query monorepo to ^5.77.1 (#3229)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-25 22:19:07 +00:00
Meier Lukas 05e159f566 fix: csp prevents fonts to load (#3225) 2025-05-25 16:39:20 +02:00
homarr-renovate[bot] 6d9e42cf5d chore(deps): update dependency @semantic-release/github to ^11.0.3 (#3226)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-25 13:28:48 +00:00
Meier Lukas 437ecd1023 fix(calendar): load events for all visible days of calendar month (#3216) 2025-05-25 14:51:26 +02:00
Meier Lukas 85e98d2b60 fix(boards): app select modal images rendering issue (#3218) 2025-05-25 14:51:13 +02:00
homarr-crowdin[bot] 8e24d8362e chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-25 07:49:01 +00:00
Manuel c367f8ac23 docs: add pika pods (#3215) 2025-05-24 18:53:04 +02:00
Meier Lukas c67916f72e fix(downloads): upspeed font size wrong (#3214) 2025-05-24 18:52:55 +02:00
Meier Lukas 25bd3879db fix(media-request-stats): users squeezed together (#3213) 2025-05-24 18:52:45 +02:00
Meier Lukas 939df8f6d1 feat(cluster-health): add visibility options (#3210) 2025-05-24 17:49:49 +02:00
Meier Lukas 2dc871e531 feat(downloads): add option to limit amount of items (#3205) 2025-05-24 17:49:39 +02:00
Meier Lukas f7e5e823d5 fix(visual): check for creator board permission is wrong (#3212) 2025-05-24 17:49:08 +02:00
homarr-renovate[bot] 240bf16806 chore(deps): update dependency conventional-changelog-conventionalcommits to v9 (#3151)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-24 11:17:16 +02:00
homarr-renovate[bot] 640bf7b939 fix(deps): update dependency trpc-to-openapi to ^2.3.1 (#3046)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-24 09:14:40 +00:00
homarr-renovate[bot] ec42f265a0 fix(deps): update tanstack-query monorepo to ^5.77.0 (#3204)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-24 08:22:43 +00:00
homarr-crowdin[bot] ea5a763046 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-24 00:49:31 +00:00
homarr-renovate[bot] e0a9e4f97c fix(deps): update dependency zod to ^3.25.28 (#3201)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-23 23:20:33 +00:00
homarr-renovate[bot] 581746b2c2 chore(deps): update dependency semantic-release to ^24.2.5 (#3202)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-23 22:20:55 +00:00
ManuelandMeier Lukas be8b332f94 fix: reduce logging (#3200)
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-05-23 22:36:23 +02:00
homarr-renovate[bot]andManuel 109f9e7979 fix(deps): update dependency node-cron to v4 (#3075)
Co-authored-by: Manuel <30572287+manuel-rw@users.noreply.github.com>
2025-05-23 22:20:47 +02:00
Meier Lukas 2afa9b6727 perf: cache middleware onboarding and language checks (#3197) 2025-05-23 22:20:21 +02:00
09af0a76f6 feat: allow custom protocols for app href (#2575)
Co-authored-by: Manuel <30572287+manuel-rw@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-05-23 20:19:59 +00:00
Manuel 71516e02c0 ci: ignore auto gen and build files eslint (#3198) 2025-05-23 19:47:44 +00:00
Meier Lukas a5f7565468 chore(issue-template): add version 1.21.0 2025-05-23 21:19:35 +02:00
homarr-renovate[bot] 0b224e8835 fix(deps): update dependency zod to ^3.25.24 (#3195)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-23 19:18:29 +00:00
Releases Homarr f748a12b58 chore(release): 1.21.0 [skip ci] 2025-05-23 19:17:12 +00:00
homarr-releases[bot] 6b746b09b5 chore(release): automatic release v1.21.0 2025-05-23 19:15:16 +00:00
e1eda534da feat: docker widget (#2288)
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: homarr-crowdin[bot] <190541745+homarr-crowdin[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-05-23 18:35:04 +00:00
Meier Lukas 09f4e6785b fix(downloads): reordering columns in widget does not work (#3194) 2025-05-23 18:33:35 +00:00
Meier Lukas 09f3989483 fix(items): resize handle overlaps header (#3193) 2025-05-23 18:33:02 +00:00
Andre Silva 4cb004fce0 fix(releases-widget): add hardcoded css classNames(#3181) 2025-05-23 18:17:06 +02:00
homarr-renovate[bot] 0ef2310776 chore(deps): update node.js to v22.16.0 (#3180)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-23 18:11:43 +02:00
homarr-update-contributors[bot] b5bc8379ae chore: update contributors (#3192)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2025-05-23 12:55:50 +00:00
homarr-renovate[bot] 43b82419e9 fix(deps): update testcontainers-node monorepo to ^10.28.0 (#3191)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-23 10:23:03 +00:00
homarr-renovate[bot] 329d4727f1 chore(deps): update dependency @vitejs/plugin-react to ^4.5.0 (#3189)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-23 01:16:09 +00:00
homarr-renovate[bot] 9840644ca5 fix(deps): update dependency zod to ^3.25.23 (#3188)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-22 23:20:48 +00:00
homarr-renovate[bot] 37d637dcae fix(deps): update dependency zod to ^3.25.21 (#3187)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-22 21:20:03 +00:00
homarr-renovate[bot] 1584114e72 fix(deps): update tanstack-query monorepo to ^5.76.2 (#3186)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-22 16:24:12 +00:00
homarr-renovate[bot] 49498c870e fix(deps): update dependency zod to ^3.25.20 (#3183)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 23:20:30 +00:00
homarr-renovate[bot] 5466ff5047 chore(deps): update node.js to v22.16.0 (#3179)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 16:25:29 +00:00
homarr-renovate[bot] 1e7b2e617b fix(deps): update dependency swagger-ui-react to ^5.22.0 (#3178)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 13:34:52 +00:00
homarr-renovate[bot] 371803ac50 fix(deps): update dependency zod to ^3.25.17 (#3177)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 12:35:21 +00:00
homarr-renovate[bot] 746ada97be chore(deps): update dependency @types/react to v19.1.5 (#3176)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 11:19:20 +00:00
homarr-renovate[bot] 5080f51a8d fix(deps): update dependency zod to ^3.25.16 (#3175)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 10:22:29 +00:00
homarr-renovate[bot] 23404a27f1 fix(deps): update dependency zod to ^3.25.14 (#3174)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 09:23:12 +00:00
homarr-renovate[bot] dae6dedde5 fix(deps): update dependency zod to ^3.25.13 (#3173)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 04:25:16 +00:00
homarr-renovate[bot] caaee503c1 fix(deps): update dependency zod to ^3.25.12 (#3172)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-21 03:15:38 +00:00
homarr-crowdin[bot] a356d61808 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-21 00:52:08 +00:00
homarr-renovate[bot] 72bcbe8eff fix(deps): update dependency zod to ^3.25.8 (#3170)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 23:20:46 +00:00
homarr-renovate[bot] 145365fab7 chore(deps): update dependency @types/node to ^22.15.21 (#3169)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 23:20:28 +00:00
homarr-renovate[bot] 8c59abdde3 fix(deps): update dependency octokit to v5 (#3156)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 21:36:43 +02:00
homarr-renovate[bot] 47869a3af4 chore(deps): update dependency @types/dockerode to ^3.3.39 (#3166)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 19:18:32 +00:00
homarr-renovate[bot] 5403b9c95e chore(deps): update dependency @types/node to ^22.15.20 (#3167)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 18:27:17 +00:00
homarr-renovate[bot] 50445b560e fix(deps): update dependency octokit to ^4.1.4 (#3165)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 16:24:19 +00:00
homarr-renovate[bot] 18c465e81e fix(deps): update testcontainers-node monorepo to ^10.27.0 (#3159)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 09:23:43 +00:00
homarr-renovate[bot] eb5d5f8260 fix(deps): update dependency undici to v7.10.0 (#3158)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 08:27:45 +00:00
homarr-renovate[bot] 096d37be37 chore(deps): update dependency proxmox-api&gt;undici to v7.10.0 (#3157)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-20 08:26:49 +00:00
homarr-crowdin[bot] 279a4b6add chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-20 00:52:28 +00:00
homarr-renovate[bot] 22954b8d26 fix(deps): update dependency zod to ^3.25.7 (#3154)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 23:20:23 +00:00
homarr-renovate[bot] 92ebc05fbf fix(deps): update dependency zod to ^3.25.6 (#3153)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 22:20:45 +00:00
homarr-renovate[bot] 79755c95d3 fix(deps): update dependency zod to ^3.25.5 (#3152)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 21:20:22 +00:00
homarr-renovate[bot] 49b7080415 fix(deps): update dependency zod to ^3.25.4 (#3150)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 20:22:49 +00:00
homarr-renovate[bot] 5b9f75eb45 chore(deps): update vitest monorepo to ^3.1.4 (#3149)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 17:20:34 +00:00
homarr-renovate[bot] 6e2aa87102 fix(deps): update dependency zod to ^3.25.3 (#3148)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 16:25:04 +00:00
homarr-renovate[bot] 17fbb0fc41 chore(deps): update dependency prettier-plugin-packagejson to ^2.5.14 (#3147)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 12:36:05 +00:00
homarr-renovate[bot] 28be77b9c3 chore(deps): update dependency @types/node to ^22.15.19 (#3145)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-19 01:18:27 +00:00
homarr-crowdin[bot] adddae6430 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-18 08:06:41 +00:00
Meier Lukas ef540e980f fix: esbuild not part of dependencies (#3139) 2025-05-17 20:04:05 +02:00
homarr-renovate[bot] 15675d95bd chore(deps): update dependency semantic-release to ^24.2.4 (#3134)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-17 01:13:09 +00:00
homarr-crowdin[bot] 16e2f3f1e4 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-05-17 00:50:13 +00:00
homarr-renovate[bot] bf6b7912f9 chore(deps): update dependency eslint to ^9.27.0 (#3128)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-16 20:24:10 +00:00
homarr-renovate[bot] ee8870b66b fix(deps): update dependency @tabler/icons-react to ^3.33.0 (#3132)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-16 20:23:22 +00:00
Meier Lukas c6464e582e chore(issue-template): add version 1.20.0 2025-05-16 21:27:28 +02:00
homarr-renovate[bot] 886e95d517 fix(deps): update dependency zod-validation-error to ^3.4.1 (#3127)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-05-16 19:19:41 +00:00
140 changed files with 9930 additions and 2671 deletions

No files matched your search

+2
View File
@@ -31,6 +31,8 @@ body:
label: Version
description: What version of Homarr are you running?
options:
- 1.21.0
- 1.20.0
- 1.19.1
- 1.19.0
- 1.18.0
+1 -1
View File
@@ -1 +1 @@
22.15.1
22.16.0
+94
View File
@@ -1,3 +1,97 @@
## [1.22.0](https://github.com/homarr-labs/homarr/compare/v1.21.0...v1.22.0) (2025-05-30)
### Features
* allow custom protocols for app href ([#2575](https://github.com/homarr-labs/homarr/issues/2575)) ([09af0a7](https://github.com/homarr-labs/homarr/commit/09af0a76f64c2fec512ba30726827208d5c3ad95))
* **cluster-health:** add visibility options ([#3210](https://github.com/homarr-labs/homarr/issues/3210)) ([939df8f](https://github.com/homarr-labs/homarr/commit/939df8f6d11bb36f71854425e4fdc4ca0724da31))
* **downloads:** add option to limit amount of items ([#3205](https://github.com/homarr-labs/homarr/issues/3205)) ([2dc871e](https://github.com/homarr-labs/homarr/commit/2dc871e531b58aee25db26ab7c5e94626517db36))
### Bug Fixes
* **boards:** app select modal images rendering issue ([#3218](https://github.com/homarr-labs/homarr/issues/3218)) ([85e98d2](https://github.com/homarr-labs/homarr/commit/85e98d2b603abe18b37fa74bf50836422b72c9e1))
* **calendar:** load events for all visible days of calendar month ([#3216](https://github.com/homarr-labs/homarr/issues/3216)) ([437ecd1](https://github.com/homarr-labs/homarr/commit/437ecd10239c70e5a8c4d34119076ab155a2159e))
* **calendar:** remove scrollbar for 2x2 ([#3227](https://github.com/homarr-labs/homarr/issues/3227)) ([1d27da2](https://github.com/homarr-labs/homarr/commit/1d27da22303b2133bb1a7c59102b7c292bc34833))
* **cluster-health:** storage items multiply ([#3206](https://github.com/homarr-labs/homarr/issues/3206)) ([1114934](https://github.com/homarr-labs/homarr/commit/11149348fcbe9002bba33763e0b03aed50d20f71))
* csp prevents fonts to load ([#3225](https://github.com/homarr-labs/homarr/issues/3225)) ([05e159f](https://github.com/homarr-labs/homarr/commit/05e159f5662f04dd298eb13816fe1768d7ef9312))
* **deps:** update dependency @ianvs/prettier-plugin-sort-imports to ^4.4.2 ([#3258](https://github.com/homarr-labs/homarr/issues/3258)) ([4a184d2](https://github.com/homarr-labs/homarr/commit/4a184d23f25a8a06b36cd8c6d9b2a65118399d9f))
* **deps:** update dependency @kubernetes/client-node to ^1.3.0 ([#3261](https://github.com/homarr-labs/homarr/issues/3261)) ([635c9a2](https://github.com/homarr-labs/homarr/commit/635c9a2687cf2b9a09a3093eb638ef772eddfb03))
* **deps:** update dependency @t3-oss/env-nextjs to ^0.13.6 ([#3244](https://github.com/homarr-labs/homarr/issues/3244)) ([8966e2a](https://github.com/homarr-labs/homarr/commit/8966e2ad8a2025dfc91934ccf825bd76c08dc333))
* **deps:** update dependency drizzle-orm to ^0.44.0 ([#3256](https://github.com/homarr-labs/homarr/issues/3256)) ([09b49a2](https://github.com/homarr-labs/homarr/commit/09b49a242dd5d3d34bab758f190ab948b6fc7566))
* **deps:** update dependency flag-icons to ^7.4.0 ([#3265](https://github.com/homarr-labs/homarr/issues/3265)) ([a0eda74](https://github.com/homarr-labs/homarr/commit/a0eda74fa472446c5b93c1b65829e65670620ab6))
* **deps:** update dependency flag-icons to ^7.5.0 ([#3268](https://github.com/homarr-labs/homarr/issues/3268)) ([2320d3c](https://github.com/homarr-labs/homarr/commit/2320d3c5674413e18e9bb42fd004ada016c5e605))
* **deps:** update dependency jotai to ^2.12.5 ([#3243](https://github.com/homarr-labs/homarr/issues/3243)) ([9c32385](https://github.com/homarr-labs/homarr/commit/9c323850bc49df5f6fc3437678faab0c7eab2e53))
* **deps:** update dependency ldapts to v8.0.1 ([#3264](https://github.com/homarr-labs/homarr/issues/3264)) ([bac4f64](https://github.com/homarr-labs/homarr/commit/bac4f642574caf5f170d20353c036396698e5963))
* **deps:** update dependency node-cron to v4 ([#3075](https://github.com/homarr-labs/homarr/issues/3075)) ([109f9e7](https://github.com/homarr-labs/homarr/commit/109f9e79793b36b46ab1987a56f7c206e21d32e4))
* **deps:** update dependency octokit to ^5.0.3 ([#3249](https://github.com/homarr-labs/homarr/issues/3249)) ([3253b2f](https://github.com/homarr-labs/homarr/commit/3253b2f138a9e911b50c952e37fb4afb1f71446d))
* **deps:** update dependency trpc-to-openapi to ^2.3.1 ([#3046](https://github.com/homarr-labs/homarr/issues/3046)) ([640bf7b](https://github.com/homarr-labs/homarr/commit/640bf7b939b201d9905f5119af0dc0da6120b98c))
* **deps:** update dependency typescript-eslint to ^8.33.0 ([#3247](https://github.com/homarr-labs/homarr/issues/3247)) ([8b553b8](https://github.com/homarr-labs/homarr/commit/8b553b80e61ab608d01d890d26a8ea5bae3f38b8))
* **deps:** update dependency zod to ^3.25.24 ([#3195](https://github.com/homarr-labs/homarr/issues/3195)) ([0b224e8](https://github.com/homarr-labs/homarr/commit/0b224e8835d4fc5a292a624c8af8d874216b703a))
* **deps:** update dependency zod to ^3.25.28 ([#3201](https://github.com/homarr-labs/homarr/issues/3201)) ([e0a9e4f](https://github.com/homarr-labs/homarr/commit/e0a9e4f97c9dddb95fbc0b2a65acfd802dac9c19))
* **deps:** update dependency zod to ^3.25.29 ([#3237](https://github.com/homarr-labs/homarr/issues/3237)) ([81ca6ef](https://github.com/homarr-labs/homarr/commit/81ca6ef7b2767fb0bc285ffa53998e2c586225ec))
* **deps:** update dependency zod to ^3.25.30 ([#3239](https://github.com/homarr-labs/homarr/issues/3239)) ([3062948](https://github.com/homarr-labs/homarr/commit/30629489396668125dec7d93fcb0e733099c35fe))
* **deps:** update dependency zod to ^3.25.31 ([#3254](https://github.com/homarr-labs/homarr/issues/3254)) ([e2e4656](https://github.com/homarr-labs/homarr/commit/e2e46560010a94603852ea90a0fc63fabd473198))
* **deps:** update dependency zod to ^3.25.32 ([#3255](https://github.com/homarr-labs/homarr/issues/3255)) ([9c3a46c](https://github.com/homarr-labs/homarr/commit/9c3a46c071e169459ec7b8c9ba1647b4b354cbea))
* **deps:** update dependency zod to ^3.25.34 ([#3259](https://github.com/homarr-labs/homarr/issues/3259)) ([c1324ea](https://github.com/homarr-labs/homarr/commit/c1324eab76795dabc0a41315191f9ab6a73ba501))
* **deps:** update dependency zod to ^3.25.36 ([#3262](https://github.com/homarr-labs/homarr/issues/3262)) ([48ce2af](https://github.com/homarr-labs/homarr/commit/48ce2af4c182985a7721b65535bcf1b41f1cdcba))
* **deps:** update dependency zod to ^3.25.39 ([#3270](https://github.com/homarr-labs/homarr/issues/3270)) ([862d07d](https://github.com/homarr-labs/homarr/commit/862d07db68e7624342cb81241ef9924e6407fda8))
* **deps:** update dependency zod to ^3.25.41 ([#3272](https://github.com/homarr-labs/homarr/issues/3272)) ([5bf20aa](https://github.com/homarr-labs/homarr/commit/5bf20aa3538503de1d4f4d04f9de3e3b92442d75))
* **deps:** update dependency zod to ^3.25.42 ([#3274](https://github.com/homarr-labs/homarr/issues/3274)) ([608280e](https://github.com/homarr-labs/homarr/commit/608280e670432098ce466cfb8fa2b315bf35ead2))
* **deps:** update mantine monorepo to ^8.0.2 ([#3245](https://github.com/homarr-labs/homarr/issues/3245)) ([816544a](https://github.com/homarr-labs/homarr/commit/816544a996656ccf7cbacf76aff83d013ba21ad1))
* **deps:** update nextjs monorepo to v15.3.3 ([#3269](https://github.com/homarr-labs/homarr/issues/3269)) ([d72a804](https://github.com/homarr-labs/homarr/commit/d72a804ad9feb24a2b067712128a6566930990a6))
* **deps:** update tanstack-query monorepo to ^5.77.0 ([#3204](https://github.com/homarr-labs/homarr/issues/3204)) ([ec42f26](https://github.com/homarr-labs/homarr/commit/ec42f265a04f0f96105d6b1318becd5cc94aa8fb))
* **deps:** update tanstack-query monorepo to ^5.77.1 ([#3229](https://github.com/homarr-labs/homarr/issues/3229)) ([5ea7a20](https://github.com/homarr-labs/homarr/commit/5ea7a206772924faf1f842c80033954c853b3a02))
* **deps:** update tanstack-query monorepo to ^5.77.2 ([#3232](https://github.com/homarr-labs/homarr/issues/3232)) ([7118690](https://github.com/homarr-labs/homarr/commit/71186908b96f717c6f8c528b0f983e1792a7a885))
* **deps:** update tanstack-query monorepo to ^5.79.0 ([#3263](https://github.com/homarr-labs/homarr/issues/3263)) ([1f9983f](https://github.com/homarr-labs/homarr/commit/1f9983f16db8677b8c244b63306ea4afd2195d94))
* **deps:** update trpc monorepo to ^11.1.3 ([#3240](https://github.com/homarr-labs/homarr/issues/3240)) ([78f98ed](https://github.com/homarr-labs/homarr/commit/78f98edc4145e27e2daa269121173905c642c139))
* **deps:** update trpc monorepo to ^11.1.4 ([#3260](https://github.com/homarr-labs/homarr/issues/3260)) ([bfd7b70](https://github.com/homarr-labs/homarr/commit/bfd7b706182340eaa1db70a3c6cdcc935aee8df4))
* **deps:** update turbo monorepo to ^2.5.4 ([#3279](https://github.com/homarr-labs/homarr/issues/3279)) ([c8202ab](https://github.com/homarr-labs/homarr/commit/c8202ab3c676bf796c6e7aff2ebfef224a0124c8))
* **downloads:** upspeed font size wrong ([#3214](https://github.com/homarr-labs/homarr/issues/3214)) ([c67916f](https://github.com/homarr-labs/homarr/commit/c67916f72eded64133fd458184a599f32d8fc63c))
* **media-request-stats:** users squeezed together ([#3213](https://github.com/homarr-labs/homarr/issues/3213)) ([25bd387](https://github.com/homarr-labs/homarr/commit/25bd3879db9260bbd24a1338cc5f26652ed78d72))
* navigating back results in navigation back to first page opened ([#3224](https://github.com/homarr-labs/homarr/issues/3224)) ([cbbf0c8](https://github.com/homarr-labs/homarr/commit/cbbf0c8dcf685e31e70bb62f04b1065dab90e18d))
* reduce logging ([#3200](https://github.com/homarr-labs/homarr/issues/3200)) ([be8b332](https://github.com/homarr-labs/homarr/commit/be8b332f942beb3af181ee6f39558882ed640a0e))
* **search:** removing server search engine causes loading error ([#3252](https://github.com/homarr-labs/homarr/issues/3252)) ([10f720d](https://github.com/homarr-labs/homarr/commit/10f720d74c6cc70cbf217e8daf8cc7878ac6d712))
* **visual:** check for creator board permission is wrong ([#3212](https://github.com/homarr-labs/homarr/issues/3212)) ([f7e5e82](https://github.com/homarr-labs/homarr/commit/f7e5e823d5dee36ea11f243a0da7d84a1f363419))
### Performance Improvements
* cache middleware onboarding and language checks ([#3197](https://github.com/homarr-labs/homarr/issues/3197)) ([2afa9b6](https://github.com/homarr-labs/homarr/commit/2afa9b67274edd79b52598dc0d22437048a67e2c))
## [1.21.0](https://github.com/homarr-labs/homarr/compare/v1.20.0...v1.21.0) (2025-05-23)
### Features
* docker widget ([#2288](https://github.com/homarr-labs/homarr/issues/2288)) ([e1eda53](https://github.com/homarr-labs/homarr/commit/e1eda534da6d97655546f3140f9e36eca8817db3))
### Bug Fixes
* **deps:** update dependency @tabler/icons-react to ^3.33.0 ([#3132](https://github.com/homarr-labs/homarr/issues/3132)) ([ee8870b](https://github.com/homarr-labs/homarr/commit/ee8870b66bbcb8eeeef359ece9391a496198be0d))
* **deps:** update dependency octokit to ^4.1.4 ([#3165](https://github.com/homarr-labs/homarr/issues/3165)) ([50445b5](https://github.com/homarr-labs/homarr/commit/50445b560edc3af2631f8d8d9aa81f3387d848f7))
* **deps:** update dependency octokit to v5 ([#3156](https://github.com/homarr-labs/homarr/issues/3156)) ([8c59abd](https://github.com/homarr-labs/homarr/commit/8c59abdde3d8034f22a2b926b3291b55a0d492ea))
* **deps:** update dependency swagger-ui-react to ^5.22.0 ([#3178](https://github.com/homarr-labs/homarr/issues/3178)) ([1e7b2e6](https://github.com/homarr-labs/homarr/commit/1e7b2e617b1437f0f98bc791e763bc49b6589b9e))
* **deps:** update dependency undici to v7.10.0 ([#3158](https://github.com/homarr-labs/homarr/issues/3158)) ([eb5d5f8](https://github.com/homarr-labs/homarr/commit/eb5d5f8260cc9795806ecdb56fbb3f8d19858ed7))
* **deps:** update dependency zod to ^3.25.12 ([#3172](https://github.com/homarr-labs/homarr/issues/3172)) ([caaee50](https://github.com/homarr-labs/homarr/commit/caaee503c128ff2a0b2a7de7a7c353484e4741a5))
* **deps:** update dependency zod to ^3.25.13 ([#3173](https://github.com/homarr-labs/homarr/issues/3173)) ([dae6ded](https://github.com/homarr-labs/homarr/commit/dae6dedde544bf28fcdf87c71a9d585078527b82))
* **deps:** update dependency zod to ^3.25.14 ([#3174](https://github.com/homarr-labs/homarr/issues/3174)) ([23404a2](https://github.com/homarr-labs/homarr/commit/23404a27f1a9dfec4e9126750f8d97e7c5eda572))
* **deps:** update dependency zod to ^3.25.16 ([#3175](https://github.com/homarr-labs/homarr/issues/3175)) ([5080f51](https://github.com/homarr-labs/homarr/commit/5080f51a8dbe1b82571f356f7ae29ed7be69e18e))
* **deps:** update dependency zod to ^3.25.17 ([#3177](https://github.com/homarr-labs/homarr/issues/3177)) ([371803a](https://github.com/homarr-labs/homarr/commit/371803ac509efd246367c812a6c0143e7aeda03f))
* **deps:** update dependency zod to ^3.25.20 ([#3183](https://github.com/homarr-labs/homarr/issues/3183)) ([49498c8](https://github.com/homarr-labs/homarr/commit/49498c870e494b417e6c63d8547a4c0ffd93768b))
* **deps:** update dependency zod to ^3.25.21 ([#3187](https://github.com/homarr-labs/homarr/issues/3187)) ([37d637d](https://github.com/homarr-labs/homarr/commit/37d637dcae6cbf62efda25a8dc01eedba66f2c74))
* **deps:** update dependency zod to ^3.25.23 ([#3188](https://github.com/homarr-labs/homarr/issues/3188)) ([9840644](https://github.com/homarr-labs/homarr/commit/9840644ca50d3157223e7da0cf895f2e750afc58))
* **deps:** update dependency zod to ^3.25.3 ([#3148](https://github.com/homarr-labs/homarr/issues/3148)) ([6e2aa87](https://github.com/homarr-labs/homarr/commit/6e2aa87102b72319236483b9a1d3e5ddd6fe2c82))
* **deps:** update dependency zod to ^3.25.4 ([#3150](https://github.com/homarr-labs/homarr/issues/3150)) ([49b7080](https://github.com/homarr-labs/homarr/commit/49b7080415aaeee576507d48e8cda18acc9943a8))
* **deps:** update dependency zod to ^3.25.5 ([#3152](https://github.com/homarr-labs/homarr/issues/3152)) ([79755c9](https://github.com/homarr-labs/homarr/commit/79755c95d3cf58680e434f0113c130db9f649d96))
* **deps:** update dependency zod to ^3.25.6 ([#3153](https://github.com/homarr-labs/homarr/issues/3153)) ([92ebc05](https://github.com/homarr-labs/homarr/commit/92ebc05fbfded6d20d242ad477cb0dc30243e8cc))
* **deps:** update dependency zod to ^3.25.7 ([#3154](https://github.com/homarr-labs/homarr/issues/3154)) ([22954b8](https://github.com/homarr-labs/homarr/commit/22954b8d2637cdea9a6502cab2d3d40359fa098f))
* **deps:** update dependency zod to ^3.25.8 ([#3170](https://github.com/homarr-labs/homarr/issues/3170)) ([72bcbe8](https://github.com/homarr-labs/homarr/commit/72bcbe8effe47fdfb6a94de8defc0d3c12e7c754))
* **deps:** update dependency zod-validation-error to ^3.4.1 ([#3127](https://github.com/homarr-labs/homarr/issues/3127)) ([886e95d](https://github.com/homarr-labs/homarr/commit/886e95d51714ce20e03d32b4c2cfb673e7e4c218))
* **deps:** update tanstack-query monorepo to ^5.76.2 ([#3186](https://github.com/homarr-labs/homarr/issues/3186)) ([1584114](https://github.com/homarr-labs/homarr/commit/1584114e72246a018b9f49a859e49f7fb985009d))
* **deps:** update testcontainers-node monorepo to ^10.27.0 ([#3159](https://github.com/homarr-labs/homarr/issues/3159)) ([18c465e](https://github.com/homarr-labs/homarr/commit/18c465e81e92cf58b7e32bcb70f1ab404a03a135))
* **deps:** update testcontainers-node monorepo to ^10.28.0 ([#3191](https://github.com/homarr-labs/homarr/issues/3191)) ([43b8241](https://github.com/homarr-labs/homarr/commit/43b82419e9396f0b80bafa0a707d575c3732dc5b))
* **downloads:** reordering columns in widget does not work ([#3194](https://github.com/homarr-labs/homarr/issues/3194)) ([09f4e67](https://github.com/homarr-labs/homarr/commit/09f4e6785b2ce38da3b52003e9c9300cdd0feb85))
* esbuild not part of dependencies ([#3139](https://github.com/homarr-labs/homarr/issues/3139)) ([ef540e9](https://github.com/homarr-labs/homarr/commit/ef540e980f90f730020ef081dd105e33b0671232))
* **items:** resize handle overlaps header ([#3193](https://github.com/homarr-labs/homarr/issues/3193)) ([09f3989](https://github.com/homarr-labs/homarr/commit/09f398948348fb402600506571a967ba405fbafb))
* **releases-widget:** add hardcoded css classNames([#3181](https://github.com/homarr-labs/homarr/issues/3181)) ([4cb004f](https://github.com/homarr-labs/homarr/commit/4cb004fce0750da339f603b944de55135faa4bfa))
## [1.20.0](https://github.com/homarr-labs/homarr/compare/v1.19.1...v1.20.0) (2025-05-16)
### Features
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:22.15.1-alpine AS base
FROM node:22.16.0-alpine AS base
FROM base AS builder
RUN apk add --no-cache libc6-compat
+27
View File
@@ -49,6 +49,33 @@ const nextConfig: NextConfig = {
images: {
domains: ["cdn.jsdelivr.net"],
},
// eslint-disable-next-line @typescript-eslint/require-await,no-restricted-syntax
async headers() {
return [
{
source: "/(.*)", // Apply CSP to all routes
headers: [
{
key: "Content-Security-Policy",
value: `
default-src 'self';
script-src * 'unsafe-inline' 'unsafe-eval';
base-uri 'self';
connect-src *;
style-src 'self' 'unsafe-inline';
frame-ancestors *;
frame-src *;
form-action 'self';
img-src * data:;
font-src * data:;
`
.replace(/\s{2,}/g, " ")
.trim(),
},
],
},
];
},
};
// Skip transform is used because of webpack loader, without it for example 'Tooltip.Floating' will not work and show an error
+22 -22
View File
@@ -48,21 +48,21 @@
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@homarr/widgets": "workspace:^0.1.0",
"@mantine/colors-generator": "^8.0.1",
"@mantine/core": "^8.0.1",
"@mantine/dropzone": "^8.0.1",
"@mantine/hooks": "^8.0.1",
"@mantine/modals": "^8.0.1",
"@mantine/tiptap": "^8.0.1",
"@mantine/colors-generator": "^8.0.2",
"@mantine/core": "^8.0.2",
"@mantine/dropzone": "^8.0.2",
"@mantine/hooks": "^8.0.2",
"@mantine/modals": "^8.0.2",
"@mantine/tiptap": "^8.0.2",
"@million/lint": "1.0.14",
"@tabler/icons-react": "^3.31.0",
"@tanstack/react-query": "^5.76.1",
"@tanstack/react-query-devtools": "^5.76.1",
"@tanstack/react-query-next-experimental": "^5.76.1",
"@trpc/client": "^11.1.2",
"@trpc/next": "^11.1.2",
"@trpc/react-query": "^11.1.2",
"@trpc/server": "^11.1.2",
"@tabler/icons-react": "^3.33.0",
"@tanstack/react-query": "^5.79.0",
"@tanstack/react-query-devtools": "^5.79.0",
"@tanstack/react-query-next-experimental": "^5.79.0",
"@trpc/client": "^11.1.4",
"@trpc/next": "^11.1.4",
"@trpc/react-query": "^11.1.4",
"@trpc/server": "^11.1.4",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "0.10.0",
"@xterm/xterm": "^5.5.0",
@@ -70,11 +70,11 @@
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"dotenv": "^16.5.0",
"flag-icons": "^7.3.2",
"flag-icons": "^7.5.0",
"glob": "^11.0.2",
"jotai": "^2.12.4",
"jotai": "^2.12.5",
"mantine-react-table": "2.0.0-beta.9",
"next": "15.3.2",
"next": "15.3.3",
"postcss-preset-mantine": "^1.17.0",
"prismjs": "^1.30.0",
"react": "19.1.0",
@@ -83,22 +83,22 @@
"react-simple-code-editor": "^0.14.1",
"sass": "^1.89.0",
"superjson": "2.2.2",
"swagger-ui-react": "^5.21.0",
"swagger-ui-react": "^5.22.0",
"use-deep-compare-effect": "^1.8.1",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@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": "^22.15.18",
"@types/node": "^22.15.28",
"@types/prismjs": "^1.26.5",
"@types/react": "19.1.4",
"@types/react": "19.1.6",
"@types/react-dom": "19.1.5",
"@types/swagger-ui-react": "^5.18.0",
"concurrently": "^9.1.2",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"node-loader": "^2.1.0",
"prettier": "^3.5.3",
"typescript": "^5.8.3"
@@ -1,6 +1,5 @@
"use client";
import type { MouseEvent } from "react";
import { useCallback, useEffect } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
@@ -204,17 +203,22 @@ const SelectBoardsMenu = () => {
);
};
const anchorSelector = "a[href]:not([target='_blank'])";
const usePreventLeaveWithDirty = (isDirty: boolean) => {
const t = useI18n();
const { openConfirmModal } = useConfirmModal();
const router = useRouter();
useEffect(() => {
const handleClick = (event: MouseEvent<HTMLElement>) => {
if (!isDirty) return;
const handleClick = (event: Event) => {
const target = (event.target as HTMLElement).closest("a");
if (!target) return;
if (!isDirty) return;
if (!target) {
console.warn("No anchor element found for click event", event);
return;
}
event.preventDefault();
@@ -231,33 +235,29 @@ const usePreventLeaveWithDirty = (isDirty: boolean) => {
};
const handlePopState = (event: Event) => {
if (isDirty) {
window.history.pushState(null, document.title, window.location.href);
event.preventDefault();
} else {
window.history.back();
}
window.history.pushState(null, document.title, window.location.href);
event.preventDefault();
};
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
if (!isDirty) return;
if (env.NODE_ENV === "development") return; // Allow to reload in development
event.preventDefault();
event.returnValue = true;
};
document.querySelectorAll("a").forEach((link) => {
link.addEventListener("click", handleClick as never);
const anchors = document.querySelectorAll(anchorSelector);
anchors.forEach((link) => {
link.addEventListener("click", handleClick);
});
window.addEventListener("popstate", handlePopState);
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
document.querySelectorAll("a").forEach((link) => {
link.removeEventListener("click", handleClick as never);
window.removeEventListener("popstate", handlePopState);
anchors.forEach((link) => {
link.removeEventListener("click", handleClick);
});
window.removeEventListener("popstate", handlePopState);
window.removeEventListener("beforeunload", handleBeforeUnload);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -17,6 +17,7 @@ import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useTimeAgo } from "@homarr/common";
import type { ContainerState } from "@homarr/docker";
import { containerStateColorMap } from "@homarr/docker/shared";
import { useModalAction } from "@homarr/modals";
import { AddDockerAppToHomarr } from "@homarr/modals-collection";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
@@ -244,21 +245,11 @@ const ContainerActionBarButton = (props: ContainerActionBarButtonProps) => {
);
};
const containerStates = {
created: "cyan",
running: "green",
paused: "yellow",
restarting: "orange",
exited: "red",
removing: "pink",
dead: "dark",
} satisfies Record<ContainerState, MantineColor>;
const ContainerStateBadge = ({ state }: { state: ContainerState }) => {
const t = useScopedI18n("docker.field.state.option");
return (
<Badge size="lg" radius="sm" variant="light" w={120} color={containerStates[state]}>
<Badge size="lg" radius="sm" variant="light" w={120} color={containerStateColorMap[state]}>
{t(state)}
</Badge>
);
@@ -125,8 +125,8 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => {
setOptions={(partialNewOptions) =>
updateOptions({
newOptions: {
...partialNewOptions.newOptions,
...options,
...partialNewOptions.newOptions,
},
})
}
+17 -6
View File
@@ -5,25 +5,36 @@ import SuperJSON from "superjson";
import type { AppRouter } from "@homarr/api";
import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared";
import { localeCookieKey } from "@homarr/definitions";
import type { SupportedLanguage } from "@homarr/translation";
import { supportedLanguages } from "@homarr/translation";
import { createI18nMiddleware } from "@homarr/translation/middleware";
export async function middleware(request: NextRequest) {
// fetch api does not work because window is not defined and we need to construct the url from the headers
// In next 15 we will be able to use node apis and such the db directly
const culture = await serverFetchApi.serverSettings.getCulture.query();
let isOnboardingFinished = false;
export async function middleware(request: NextRequest) {
// Redirect to onboarding if it's not finished yet
const pathname = request.nextUrl.pathname;
if (!pathname.endsWith("/init")) {
if (!isOnboardingFinished && !pathname.endsWith("/init")) {
const currentOnboardingStep = await serverFetchApi.onboard.currentStep.query();
if (currentOnboardingStep.current !== "finish") {
return NextResponse.redirect(new URL("/init", request.url));
}
isOnboardingFinished = true;
}
// Only run this if the user has not already configured their language
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);
}
// We don't want to fallback to accept-language header so we clear it
request.headers.set("accept-language", "");
const next = createI18nMiddleware(culture.defaultLocale);
const next = createI18nMiddleware(defaultLocale);
return next(request);
}
+6
View File
@@ -6,6 +6,12 @@
--gridstack-cell-size: 0;
}
.ui-resizable-handle {
// Override default z-index of 100 to prevent it from being on top of the header.
// See https://github.com/homarr-labs/homarr/issues/1999
z-index: 1 !important;
}
.grid-stack-placeholder > .placeholder-content {
background-color: rgb(248, 249, 250) !important;
border-radius: 12px;
+5 -4
View File
@@ -10,7 +10,7 @@
"main": "./src/main.ts",
"types": "./src/main.ts",
"scripts": {
"build": "esbuild src/main.ts --bundle --platform=node --loader:.scss=text --external:@opentelemetry/api --external:deasync --outfile=tasks.cjs",
"build": "esbuild src/main.ts --bundle --platform=node --loader:.scss=text --external:*.node --external:@opentelemetry/api --external:deasync --outfile=tasks.cjs",
"clean": "rm -rf .turbo node_modules",
"dev": "pnpm with-env tsx ./src/main.ts",
"format": "prettier --check . --ignore-path ../../.gitignore",
@@ -38,15 +38,16 @@
"dayjs": "^1.11.13",
"dotenv": "^16.5.0",
"superjson": "2.2.2",
"undici": "7.9.0"
"undici": "7.10.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^22.15.18",
"@types/node": "^22.15.28",
"dotenv-cli": "^8.0.0",
"eslint": "^9.26.0",
"esbuild": "^0.25.5",
"eslint": "^9.27.0",
"prettier": "^3.5.3",
"tsx": "4.19.4",
"typescript": "^5.8.3"
+2 -1
View File
@@ -34,7 +34,8 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.18.1",
"eslint": "^9.26.0",
"esbuild": "^0.25.5",
"eslint": "^9.27.0",
"prettier": "^3.5.3",
"typescript": "^5.8.3"
}
+3 -1
View File
@@ -120,4 +120,6 @@ You can also support us by helping with [translating the entire project](https:/
Thanks to your generous sponsors we can continue to build Homarr. Check them out for high quality and easy to use development tools.
Feel free to contact us at homarr-labs@proton.me if you wish to become a sponsor.
[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](https://argos-ci.com?utm_source=%5Bhomarr%5D&utm_campaign=oss)
[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](https://argos-ci.com?utm_source=%5Bhomarr%5D&utm_campaign=oss) \
[![Supported by PikaPods](https://www.pikapods.com/static/run-button.svg)](https://www.pikapods.com/pods?run=homarr-v1)
+13 -13
View File
@@ -1,6 +1,6 @@
{
"name": "homarr",
"version": "1.20.0",
"version": "1.22.0",
"private": true,
"scripts": {
"build": "cross-env CI=true turbo build",
@@ -35,27 +35,27 @@
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^13.0.1",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^11.0.2",
"@semantic-release/github": "^11.0.3",
"@semantic-release/npm": "^12.0.1",
"@semantic-release/release-notes-generator": "^14.0.3",
"@turbo/gen": "^2.5.3",
"@vitejs/plugin-react": "^4.4.1",
"@vitest/coverage-v8": "^3.1.3",
"@vitest/ui": "^3.1.3",
"conventional-changelog-conventionalcommits": "^8.0.0",
"@turbo/gen": "^2.5.4",
"@vitejs/plugin-react": "^4.5.0",
"@vitest/coverage-v8": "^3.1.4",
"@vitest/ui": "^3.1.4",
"conventional-changelog-conventionalcommits": "^9.0.0",
"cross-env": "^7.0.3",
"jsdom": "^26.1.0",
"prettier": "^3.5.3",
"semantic-release": "^24.2.3",
"testcontainers": "^10.26.0",
"turbo": "^2.5.3",
"semantic-release": "^24.2.5",
"testcontainers": "^10.28.0",
"turbo": "^2.5.4",
"typescript": "^5.8.3",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.1.3"
"vitest": "^3.1.4"
},
"packageManager": "pnpm@10.11.0",
"engines": {
"node": ">=22.15.1"
"node": ">=22.16.0"
},
"pnpm": {
"onlyBuiltDependencies": [
@@ -70,7 +70,7 @@
"tree-sitter-json"
],
"overrides": {
"proxmox-api>undici": "7.9.0"
"proxmox-api>undici": "7.10.0"
},
"allowUnusedPatches": true,
"ignoredBuiltDependencies": [
+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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+10 -10
View File
@@ -40,25 +40,25 @@
"@homarr/request-handler": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@kubernetes/client-node": "^1.2.0",
"@tanstack/react-query": "^5.76.1",
"@trpc/client": "^11.1.2",
"@trpc/react-query": "^11.1.2",
"@trpc/server": "^11.1.2",
"@trpc/tanstack-react-query": "^11.1.2",
"@kubernetes/client-node": "^1.3.0",
"@tanstack/react-query": "^5.79.0",
"@trpc/client": "^11.1.4",
"@trpc/react-query": "^11.1.4",
"@trpc/server": "^11.1.4",
"@trpc/tanstack-react-query": "^11.1.4",
"lodash.clonedeep": "^4.5.0",
"next": "15.3.2",
"next": "15.3.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"superjson": "2.2.2",
"trpc-to-openapi": "^2.2.0",
"zod": "^3.24.4"
"trpc-to-openapi": "^2.3.1",
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"prettier": "^3.5.3",
"typescript": "^5.8.3"
}
+31 -83
View File
@@ -1,90 +1,48 @@
import { TRPCError } from "@trpc/server";
import { observable } from "@trpc/server/observable";
import { z } from "zod";
import { db, like, or } from "@homarr/db";
import { icons } from "@homarr/db/schema";
import type { Container, ContainerState, Docker, Port } from "@homarr/docker";
import { DockerSingleton } from "@homarr/docker";
import type { Container, ContainerInfo, ContainerState, Docker, Port } from "@homarr/docker";
import { logger } from "@homarr/log";
import { createCacheChannel } from "@homarr/redis";
import { dockerContainersRequestHandler } from "@homarr/request-handler/docker";
import { dockerMiddleware } from "../../middlewares/docker";
import { createTRPCRouter, permissionRequiredProcedure } from "../../trpc";
const dockerCache = createCacheChannel<{
containers: (ContainerInfo & { instance: string; iconUrl: string | null })[];
}>("docker-containers", 5 * 60 * 1000);
export const dockerRouter = createTRPCRouter({
getContainers: permissionRequiredProcedure
.requiresPermission("admin")
.concat(dockerMiddleware())
.query(async () => {
const result = await dockerCache
.consumeAsync(async () => {
const dockerInstances = DockerSingleton.getInstances();
const containers = await Promise.all(
// Return all the containers of all the instances into only one item
dockerInstances.map(({ instance, host: key }) =>
instance.listContainers({ all: true }).then((containers) =>
containers.map((container) => ({
...container,
instance: key,
})),
),
),
).then((containers) => containers.flat());
const extractImage = (container: ContainerInfo) => container.Image.split("/").at(-1)?.split(":").at(0) ?? "";
const likeQueries = containers.map((container) => like(icons.name, `%${extractImage(container)}%`));
const dbIcons =
likeQueries.length >= 1
? await db.query.icons.findMany({
where: or(...likeQueries),
})
: [];
return {
containers: containers.map((container) => ({
...container,
iconUrl:
dbIcons.find((icon) => {
const extractedImage = extractImage(container);
if (!extractedImage) return false;
return icon.name.toLowerCase().includes(extractedImage.toLowerCase());
})?.url ?? null,
})),
};
})
.catch((error) => {
logger.error(error);
return {
isError: true,
error: error as unknown,
};
});
if ("isError" in result) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "An error occurred while fetching the containers",
cause: result.error,
});
}
const innerHandler = dockerContainersRequestHandler.handler({});
const result = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
const { data, timestamp } = result;
return {
containers: sanitizeContainers(data.containers),
containers: data satisfies DockerContainer[],
timestamp,
};
}),
subscribeContainers: permissionRequiredProcedure
.requiresPermission("admin")
.concat(dockerMiddleware())
.subscription(() => {
return observable<DockerContainer[]>((emit) => {
const innerHandler = dockerContainersRequestHandler.handler({});
const unsubscribe = innerHandler.subscribe((data) => {
emit.next(data);
});
return unsubscribe;
});
}),
invalidate: permissionRequiredProcedure
.requiresPermission("admin")
.concat(dockerMiddleware())
.mutation(async () => {
await dockerCache.invalidateAsync();
return;
const innerHandler = dockerContainersRequestHandler.handler({});
await innerHandler.invalidateAsync();
}),
startAll: permissionRequiredProcedure
.requiresPermission("admin")
@@ -98,7 +56,8 @@ export const dockerRouter = createTRPCRouter({
}),
);
await dockerCache.invalidateAsync();
const innerHandler = dockerContainersRequestHandler.handler({});
await innerHandler.invalidateAsync();
}),
stopAll: permissionRequiredProcedure
.requiresPermission("admin")
@@ -112,7 +71,8 @@ export const dockerRouter = createTRPCRouter({
}),
);
await dockerCache.invalidateAsync();
const innerHandler = dockerContainersRequestHandler.handler({});
await innerHandler.invalidateAsync();
}),
restartAll: permissionRequiredProcedure
.requiresPermission("admin")
@@ -126,7 +86,8 @@ export const dockerRouter = createTRPCRouter({
}),
);
await dockerCache.invalidateAsync();
const innerHandler = dockerContainersRequestHandler.handler({});
await innerHandler.invalidateAsync();
}),
removeAll: permissionRequiredProcedure
.requiresPermission("admin")
@@ -140,7 +101,8 @@ export const dockerRouter = createTRPCRouter({
}),
);
await dockerCache.invalidateAsync();
const innerHandler = dockerContainersRequestHandler.handler({});
await innerHandler.invalidateAsync();
}),
});
@@ -180,20 +142,6 @@ interface DockerContainer {
image: string;
ports: Port[];
iconUrl: string | null;
}
function sanitizeContainers(
containers: (ContainerInfo & { instance: string; iconUrl: string | null })[],
): DockerContainer[] {
return containers.map((container) => {
return {
name: container.Names[0]?.split("/")[1] ?? "Unknown",
id: container.Id,
instance: container.instance,
state: container.State as ContainerState,
image: container.Image,
ports: container.Ports,
iconUrl: container.iconUrl,
};
});
cpuUsage: number;
memoryUsage: number;
}
@@ -2,9 +2,10 @@ import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { asc, createId, eq, like } from "@homarr/db";
import { getServerSettingByKeyAsync } from "@homarr/db/queries";
import { getServerSettingByKeyAsync, updateServerSettingByKeyAsync } from "@homarr/db/queries";
import { searchEngines, users } from "@homarr/db/schema";
import { createIntegrationAsync } from "@homarr/integrations";
import { logger } from "@homarr/log";
import { byIdSchema, paginatedSchema, searchSchema } from "@homarr/validation/common";
import { searchEngineEditSchema, searchEngineManageSchema } from "@homarr/validation/search-engine";
import { mediaRequestOptionsSchema, mediaRequestRequestSchema } from "@homarr/validation/widgets/media-request";
@@ -96,23 +97,35 @@ export const searchEngineRouter = createTRPCRouter({
});
}
const serverDefaultId = await getServerSettingByKeyAsync(ctx.db, "search").then(
(setting) => setting.defaultSearchEngineId,
);
const searchSettings = await getServerSettingByKeyAsync(ctx.db, "search");
if (serverDefaultId) {
return await ctx.db.query.searchEngines.findFirst({
where: eq(searchEngines.id, serverDefaultId),
with: {
integration: {
columns: {
kind: true,
url: true,
id: true,
},
if (!searchSettings.defaultSearchEngineId) return null;
const serverDefault = await ctx.db.query.searchEngines.findFirst({
where: eq(searchEngines.id, searchSettings.defaultSearchEngineId),
with: {
integration: {
columns: {
kind: true,
url: true,
id: true,
},
},
},
});
if (serverDefault) return serverDefault;
// Remove the default search engine ID from settings if it does not longer exist
try {
await updateServerSettingByKeyAsync(ctx.db, "search", {
...searchSettings,
defaultSearchEngineId: null,
});
} catch (error) {
logger.warn(
new Error("Failed to update search settings after default search engine not found", { cause: error }),
);
}
return null;
@@ -4,14 +4,26 @@ import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import { objectKeys } from "@homarr/common";
import type { Database } from "@homarr/db";
import { getPermissionsWithChildren } from "@homarr/definitions";
import type { GroupPermissionKey } from "@homarr/definitions";
import { getPermissionsWithChildren } from "@homarr/definitions";
import type { RouterInputs } from "../../..";
import { dockerRouter } from "../../docker/docker-router";
// Mock the auth module to return an empty session
vi.mock("@homarr/auth", () => ({ auth: () => ({}) as Session }));
vi.mock("@homarr/request-handler/docker", () => ({
dockerContainersRequestHandler: {
handler: () => ({
getCachedOrUpdatedDataAsync: async () => {
return await Promise.resolve({ containers: [] });
},
invalidateAsync: async () => {
return await Promise.resolve();
},
}),
},
}));
vi.mock("@homarr/redis", () => ({
createCacheChannel: () => ({
// eslint-disable-next-line @typescript-eslint/require-await
@@ -22,6 +34,7 @@ vi.mock("@homarr/redis", () => ({
// eslint-disable-next-line @typescript-eslint/no-empty-function
invalidateAsync: async () => {},
}),
createWidgetOptionsChannel: () => ({}),
}));
vi.mock("@homarr/docker/env", () => ({
@@ -46,6 +59,7 @@ const validInputs: {
[key in (typeof procedureKeys)[number]]: RouterInputs["docker"][key];
} = {
getContainers: undefined,
subscribeContainers: undefined,
startAll: { ids: ["1"] },
stopAll: { ids: ["1"] },
restartAll: { ids: ["1"] },
+8 -4
View File
@@ -19,10 +19,11 @@ const createDownloadClientIntegrationMiddleware = (action: IntegrationAction) =>
export const downloadsRouter = createTRPCRouter({
getJobsAndStatuses: publicProcedure
.concat(createDownloadClientIntegrationMiddleware("query"))
.query(async ({ ctx }) => {
.input(z.object({ limitPerIntegration: z.number().default(50) }))
.query(async ({ ctx, input }) => {
return await Promise.all(
ctx.integrations.map(async (integration) => {
const innerHandler = downloadClientRequestHandler.handler(integration, {});
const innerHandler = downloadClientRequestHandler.handler(integration, { limit: input.limitPerIntegration });
const { data, timestamp } = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
@@ -40,7 +41,8 @@ export const downloadsRouter = createTRPCRouter({
}),
subscribeToJobsAndStatuses: publicProcedure
.concat(createDownloadClientIntegrationMiddleware("query"))
.subscription(({ ctx }) => {
.input(z.object({ limitPerIntegration: z.number().default(50) }))
.subscription(({ ctx, input }) => {
return observable<{
integration: Modify<Integration, { kind: IntegrationKindByCategory<"downloadClient"> }>;
data: DownloadClientJobsAndStatus;
@@ -48,7 +50,9 @@ export const downloadsRouter = createTRPCRouter({
const unsubscribes: (() => void)[] = [];
for (const integrationWithSecrets of ctx.integrations) {
const { decryptedSecrets: _, ...integration } = integrationWithSecrets;
const innerHandler = downloadClientRequestHandler.handler(integrationWithSecrets, {});
const innerHandler = downloadClientRequestHandler.handler(integrationWithSecrets, {
limit: input.limitPerIntegration,
});
const unsubscribe = innerHandler.subscribe((data) => {
emit.next({
integration,
+4 -4
View File
@@ -34,12 +34,12 @@
"@homarr/validation": "workspace:^0.1.0",
"bcrypt": "^6.0.0",
"cookies": "^0.9.1",
"ldapts": "8.0.0",
"next": "15.3.2",
"ldapts": "8.0.1",
"next": "15.3.3",
"next-auth": "5.0.0-beta.28",
"react": "19.1.0",
"react-dom": "19.1.0",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -47,7 +47,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/bcrypt": "5.0.2",
"@types/cookies": "0.9.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"prettier": "^3.5.3",
"typescript": "^5.8.3"
}
@@ -23,21 +23,22 @@ export type BoardPermissionsProps = (
export const constructBoardPermissions = (board: BoardPermissionsProps, session: Session | null) => {
const creatorId = "creator" in board ? board.creator?.id : board.creatorId;
const isCreator = session !== null && session.user.id === creatorId;
return {
hasFullAccess:
session?.user.id === creatorId ||
isCreator ||
board.userPermissions.some(({ permission }) => permission === "full") ||
board.groupPermissions.some(({ permission }) => permission === "full") ||
(session?.user.permissions.includes("board-full-all") ?? false),
hasChangeAccess:
session?.user.id === creatorId ||
isCreator ||
board.userPermissions.some(({ permission }) => permission === "modify" || permission === "full") ||
board.groupPermissions.some(({ permission }) => permission === "modify" || permission === "full") ||
(session?.user.permissions.includes("board-modify-all") ?? false) ||
(session?.user.permissions.includes("board-full-all") ?? false),
hasViewAccess:
session?.user.id === creatorId ||
isCreator ||
board.userPermissions.length >= 1 ||
board.groupPermissions.length >= 1 ||
board.isPublic ||
@@ -286,4 +286,22 @@ describe("constructBoardPermissions", () => {
expect(result.hasChangeAccess).toBe(false);
expect(result.hasViewAccess).toBe(true);
});
test("should return all false when creator is null and session is null", () => {
// Arrange
const board = {
creator: null,
userPermissions: [],
groupPermissions: [],
isPublic: false,
};
const session = null;
// Act
const result = constructBoardPermissions(board, session);
// Assert
expect(result.hasFullAccess).toBe(false);
expect(result.hasChangeAccess).toBe(false);
expect(result.hasViewAccess).toBe(false);
});
});
+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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+2 -2
View File
@@ -24,13 +24,13 @@
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"undici": "7.9.0"
"undici": "7.10.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+2 -1
View File
@@ -34,7 +34,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"esbuild": "^0.25.5",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+5 -5
View File
@@ -30,18 +30,18 @@
"@homarr/env": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"dayjs": "^1.11.13",
"next": "15.3.2",
"next": "15.3.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"undici": "7.9.0",
"zod": "^3.24.4",
"zod-validation-error": "^3.4.0"
"undici": "7.10.0",
"zod": "^3.25.42",
"zod-validation-error": "^3.4.1"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ export class LoggingAgent extends Agent {
url.searchParams.set(key, "REDACTED");
});
logger.info(
logger.debug(
`Dispatching request ${url.toString().replaceAll("=&", "&")} (${Object.keys(options.headers ?? {}).length} headers)`,
);
return super.dispatch(options, handler);
+4 -4
View File
@@ -21,7 +21,7 @@ const REDACTED = "REDACTED";
describe("LoggingAgent should log all requests", () => {
test("should log all requests", () => {
// Arrange
const infoLogSpy = vi.spyOn(logger, "info");
const infoLogSpy = vi.spyOn(logger, "debug");
const agent = new LoggingAgent();
// Act
@@ -33,7 +33,7 @@ describe("LoggingAgent should log all requests", () => {
test("should show amount of headers", () => {
// Arrange
const infoLogSpy = vi.spyOn(logger, "info");
const infoLogSpy = vi.spyOn(logger, "debug");
const agent = new LoggingAgent();
// Act
@@ -68,7 +68,7 @@ describe("LoggingAgent should log all requests", () => {
[`/?stringWith13Chars=${"a".repeat(13)}`, `/?stringWith13Chars=${REDACTED}`],
])("should redact sensitive data in url https://homarr.dev%s", (path, expected) => {
// Arrange
const infoLogSpy = vi.spyOn(logger, "info");
const infoLogSpy = vi.spyOn(logger, "debug");
const agent = new LoggingAgent();
// Act
@@ -87,7 +87,7 @@ describe("LoggingAgent should log all requests", () => {
["date times", "/?datetime=2022-01-01T00:00:00.000Z"],
])("should not redact values that are %s", (_reason, path) => {
// Arrange
const infoLogSpy = vi.spyOn(logger, "info");
const infoLogSpy = vi.spyOn(logger, "debug");
const agent = new LoggingAgent();
// Act
+1 -1
View File
@@ -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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+1
View File
@@ -24,6 +24,7 @@ export const cronJobs = {
mediaTranscoding: { preventManualExecution: false },
minecraftServerStatus: { preventManualExecution: false },
networkController: { preventManualExecution: false },
dockerContainers: { preventManualExecution: false },
} satisfies Record<JobGroupKeys, { preventManualExecution?: boolean }>;
/**
+1 -1
View File
@@ -7,6 +7,6 @@ import { cronJobRunnerChannel } from ".";
*/
export const registerCronJobRunner = () => {
cronJobRunnerChannel.subscribe((jobName) => {
jobGroup.runManually(jobName);
void jobGroup.runManuallyAsync(jobName);
});
};
+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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+2 -2
View File
@@ -25,14 +25,14 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"node-cron": "^3.0.3"
"node-cron": "^4.0.7"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node-cron": "^3.0.11",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+7 -7
View File
@@ -1,5 +1,6 @@
import { AxiosError } from "axios";
import cron from "node-cron";
import type { ScheduledTask } from "node-cron";
import { schedule, validate } from "node-cron";
import { Stopwatch } from "@homarr/common";
import type { MaybePromise } from "@homarr/common/types";
@@ -27,7 +28,7 @@ const createCallback = <TAllowedNames extends string, TName extends TAllowedName
options: CreateCronJobOptions,
creatorOptions: CreateCronJobCreatorOptions<TAllowedNames>,
) => {
const expectedMaximumDurationInMillis = options.expectedMaximumDurationInMillis ?? 1000;
const expectedMaximumDurationInMillis = options.expectedMaximumDurationInMillis ?? 2500;
return (callback: () => MaybePromise<void>) => {
const catchingCallbackAsync = async () => {
try {
@@ -64,12 +65,11 @@ const createCallback = <TAllowedNames extends string, TName extends TAllowedName
/**
* We are not using the runOnInit method as we want to run the job only once we start the cron job schedule manually.
* This allows us to always run it once we start it. Additionally it will not run the callback if only the cron job file is imported.
* This allows us to always run it once we start it. Additionally, it will not run the callback if only the cron job file is imported.
*/
let scheduledTask: cron.ScheduledTask | null = null;
let scheduledTask: ScheduledTask | null = null;
if (cronExpression !== "never") {
scheduledTask = cron.schedule(cronExpression, () => void catchingCallbackAsync(), {
scheduled: false,
scheduledTask = schedule(cronExpression, () => void catchingCallbackAsync(), {
name,
timezone: creatorOptions.timezone,
});
@@ -110,7 +110,7 @@ export const createCronJobCreator = <TAllowedNames extends string = string>(
options: CreateCronJobOptions = { runOnStart: false },
) => {
creatorOptions.logger.logDebug(`Validating cron expression '${cronExpression}' for job: ${name}`);
if (cronExpression !== "never" && !cron.validate(cronExpression)) {
if (cronExpression !== "never" && !validate(cronExpression)) {
throw new Error(`Invalid cron expression '${cronExpression}' for job '${name}'`);
}
creatorOptions.logger.logDebug(`Cron job expression '${cronExpression}' for job ${name} is valid`);
+8 -8
View File
@@ -34,33 +34,33 @@ export const createJobGroupCreator = <TAllowedNames extends string = string>(
options.logger.logInfo(`Starting schedule cron job ${job.name}.`);
await job.onStartAsync();
job.scheduledTask?.start();
await job.scheduledTask?.start();
},
startAllAsync: async () => {
for (const job of jobRegistry.values()) {
options.logger.logInfo(`Starting schedule of cron job ${job.name}.`);
await job.onStartAsync();
job.scheduledTask?.start();
await job.scheduledTask?.start();
}
},
runManually: (name: keyof TJobs) => {
runManuallyAsync: async (name: keyof TJobs) => {
const job = jobRegistry.get(name as string);
if (!job) return;
options.logger.logInfo(`Running schedule cron job ${job.name} manually.`);
job.scheduledTask?.now();
await job.scheduledTask?.execute();
},
stop: (name: keyof TJobs) => {
stopAsync: async (name: keyof TJobs) => {
const job = jobRegistry.get(name as string);
if (!job) return;
options.logger.logInfo(`Stopping schedule cron job ${job.name}.`);
job.scheduledTask?.stop();
await job.scheduledTask?.stop();
},
stopAll: () => {
stopAllAsync: async () => {
for (const job of jobRegistry.values()) {
options.logger.logInfo(`Stopping schedule cron job ${job.name}.`);
job.scheduledTask?.stop();
await job.scheduledTask?.stop();
}
},
getJobRegistry() {
+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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+2
View File
@@ -1,4 +1,5 @@
import { analyticsJob } from "./jobs/analytics";
import { dockerContainersJob } from "./jobs/docker";
import { iconsUpdaterJob } from "./jobs/icons-updater";
import { dnsHoleJob } from "./jobs/integrations/dns-hole";
import { downloadsJob } from "./jobs/integrations/downloads";
@@ -35,6 +36,7 @@ export const jobGroup = createCronJobGroup({
updateChecker: updateCheckerJob,
mediaTranscoding: mediaTranscodingJob,
minecraftServerStatus: minecraftServerStatusJob,
dockerContainers: dockerContainersJob,
networkController: networkControllerJob,
});
+28
View File
@@ -0,0 +1,28 @@
import SuperJSON from "superjson";
import { EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions";
import { db, eq } from "@homarr/db";
import { items } from "@homarr/db/schema";
import { logger } from "@homarr/log";
import { dockerContainersRequestHandler } from "@homarr/request-handler/docker";
import type { WidgetComponentProps } from "../../../widgets";
import { createCronJob } from "../lib";
export const dockerContainersJob = createCronJob("dockerContainers", EVERY_MINUTE).withCallback(async () => {
const dockerItems = await db.query.items.findMany({
where: eq(items.kind, "dockerContainers"),
});
await Promise.allSettled(
dockerItems.map(async (item) => {
try {
const options = SuperJSON.parse<WidgetComponentProps<"dockerContainers">["options"]>(item.options);
const innerHandler = dockerContainersRequestHandler.handler(options);
await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true });
} catch (error) {
logger.error("Failed to update Docker container status", { item, error });
}
}),
);
});
@@ -8,7 +8,9 @@ export const downloadsJob = createCronJob("downloads", EVERY_5_SECONDS).withCall
createRequestIntegrationJobHandler(downloadClientRequestHandler.handler, {
widgetKinds: ["downloads"],
getInput: {
downloads: () => ({}),
downloads: (options) => ({
limit: options.limitPerIntegration,
}),
},
}),
);
+5 -4
View File
@@ -44,13 +44,13 @@
"@homarr/env": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.0.1",
"@mantine/core": "^8.0.2",
"@paralleldrive/cuid2": "^2.2.2",
"@testcontainers/mysql": "^10.26.0",
"@testcontainers/mysql": "^10.28.0",
"better-sqlite3": "^11.10.0",
"dotenv": "^16.5.0",
"drizzle-kit": "^0.31.1",
"drizzle-orm": "^0.43.1",
"drizzle-orm": "^0.44.0",
"drizzle-zod": "^0.7.1",
"mysql2": "3.14.1"
},
@@ -60,7 +60,8 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/better-sqlite3": "7.6.13",
"dotenv-cli": "^8.0.0",
"eslint": "^9.26.0",
"esbuild": "^0.25.5",
"eslint": "^9.27.0",
"prettier": "^3.5.3",
"tsx": "4.19.4",
"typescript": "^5.8.3"
+2 -2
View File
@@ -25,13 +25,13 @@
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"fast-xml-parser": "^5.2.3",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"tsx": "4.19.4",
"typescript": "^5.8.3"
}
+1
View File
@@ -24,5 +24,6 @@ export const widgetKinds = [
"indexerManager",
"healthMonitoring",
"releases",
"dockerContainers",
] as const;
export type WidgetKind = (typeof widgetKinds)[number];
+3 -2
View File
@@ -6,6 +6,7 @@
"type": "module",
"exports": {
".": "./index.ts",
"./shared": "./src/shared.ts",
"./env": "./src/env.ts"
},
"typesVersions": {
@@ -31,8 +32,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/dockerode": "^3.3.38",
"eslint": "^9.26.0",
"@types/dockerode": "^3.3.39",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+13
View File
@@ -0,0 +1,13 @@
import type { MantineColor } from "@mantine/core";
import type { ContainerState } from ".";
export const containerStateColorMap = {
created: "cyan",
running: "green",
paused: "yellow",
restarting: "orange",
exited: "red",
removing: "pink",
dead: "dark",
} satisfies Record<ContainerState, MantineColor>;
+3 -3
View File
@@ -23,14 +23,14 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
"@t3-oss/env-nextjs": "^0.13.4",
"zod": "^3.24.4"
"@t3-oss/env-nextjs": "^0.13.6",
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+3 -3
View File
@@ -26,14 +26,14 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/form": "^8.0.1",
"zod": "^3.24.4"
"@mantine/form": "^8.0.2",
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+3 -3
View File
@@ -29,15 +29,15 @@
"@homarr/notifications": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.0.1",
"@mantine/core": "^8.0.2",
"react": "19.1.0",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+3 -3
View File
@@ -42,9 +42,9 @@
"node-ical": "^0.20.1",
"proxmox-api": "1.1.1",
"tsdav": "^2.1.4",
"undici": "7.9.0",
"undici": "7.10.0",
"xml2js": "^0.6.2",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -52,7 +52,7 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node-unifi": "^2.5.1",
"@types/xml2js": "^0.4.14",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
@@ -12,7 +12,7 @@ import type { DownloadClientItem } from "../../interfaces/downloads/download-cli
import type { Aria2Download, Aria2GetClient } from "./aria2-types";
export class Aria2Integration extends DownloadClientIntegration {
public async getClientJobsAndStatusAsync(): Promise<DownloadClientJobsAndStatus> {
public async getClientJobsAndStatusAsync(input: { limit: number }): Promise<DownloadClientJobsAndStatus> {
const client = this.getClient();
const keys: (keyof Aria2Download)[] = [
"bittorrent",
@@ -27,12 +27,12 @@ export class Aria2Integration extends DownloadClientIntegration {
];
const [activeDownloads, waitingDownloads, stoppedDownloads, globalStats] = await Promise.all([
client.tellActive(),
client.tellWaiting(0, 1000, keys),
client.tellStopped(0, 1000, keys),
client.tellWaiting(0, input.limit, keys),
client.tellStopped(0, input.limit, keys),
client.getGlobalStat(),
]);
const downloads = [...activeDownloads, ...waitingDownloads, ...stoppedDownloads];
const downloads = [...activeDownloads, ...waitingDownloads, ...stoppedDownloads].slice(0, input.limit);
const allPaused = downloads.every((download) => download.status === "paused");
return {
@@ -29,9 +29,10 @@ export class DelugeIntegration extends DownloadClientIntegration {
};
}
public async getClientJobsAndStatusAsync(): Promise<DownloadClientJobsAndStatus> {
public async getClientJobsAndStatusAsync(input: { limit: number }): Promise<DownloadClientJobsAndStatus> {
const type = "torrent";
const client = await this.getClientAsync();
// Currently there is no way to limit the number of returned torrents
const {
stats: { download_rate, upload_rate },
torrents: rawTorrents,
@@ -49,27 +50,29 @@ export class DelugeIntegration extends DownloadClientIntegration {
},
types: [type],
};
const items = torrents.map((torrent): DownloadClientItem => {
const state = DelugeIntegration.getTorrentState(torrent.state);
return {
type,
id: torrent.id,
index: torrent.queue,
name: torrent.name,
size: torrent.total_wanted,
sent: torrent.total_uploaded,
downSpeed: torrent.progress !== 100 ? torrent.download_payload_rate : undefined,
upSpeed: torrent.upload_payload_rate,
time:
torrent.progress === 100
? Math.min((torrent.completed_time - dayjs().unix()) * 1000, -1)
: Math.max(torrent.eta * 1000, 0),
added: torrent.time_added * 1000,
state,
progress: torrent.progress / 100,
category: torrent.label,
};
});
const items = torrents
.map((torrent): DownloadClientItem => {
const state = DelugeIntegration.getTorrentState(torrent.state);
return {
type,
id: torrent.id,
index: torrent.queue,
name: torrent.name,
size: torrent.total_wanted,
sent: torrent.total_uploaded,
downSpeed: torrent.progress !== 100 ? torrent.download_payload_rate : undefined,
upSpeed: torrent.upload_payload_rate,
time:
torrent.progress === 100
? Math.min((torrent.completed_time - dayjs().unix()) * 1000, -1)
: Math.max(torrent.eta * 1000, 0),
added: torrent.time_added * 1000,
state,
progress: torrent.progress / 100,
category: torrent.label,
};
})
.slice(0, input.limit);
return { status, items };
}
@@ -20,7 +20,7 @@ export class NzbGetIntegration extends DownloadClientIntegration {
};
}
public async getClientJobsAndStatusAsync(): Promise<DownloadClientJobsAndStatus> {
public async getClientJobsAndStatusAsync(input: { limit: number }): Promise<DownloadClientJobsAndStatus> {
const type = "usenet";
const queue = await this.nzbGetApiCallAsync("listgroups");
const history = await this.nzbGetApiCallAsync("history");
@@ -65,7 +65,8 @@ export class NzbGetIntegration extends DownloadClientIntegration {
category: file.Category,
};
}),
);
)
.slice(0, input.limit);
return { status, items };
}
@@ -26,10 +26,10 @@ export class QBitTorrentIntegration extends DownloadClientIntegration {
};
}
public async getClientJobsAndStatusAsync(): Promise<DownloadClientJobsAndStatus> {
public async getClientJobsAndStatusAsync(input: { limit: number }): Promise<DownloadClientJobsAndStatus> {
const type = "torrent";
const client = await this.getClientAsync();
const torrents = await client.listTorrents();
const torrents = await client.listTorrents({ limit: input.limit });
const rates = torrents.reduce(
({ down, up }, { dlspeed, upspeed }) => ({ down: down + dlspeed, up: up + upspeed }),
{ down: 0, up: 0 },
@@ -22,10 +22,14 @@ export class SabnzbdIntegration extends DownloadClientIntegration {
return { success: true };
}
public async getClientJobsAndStatusAsync(): Promise<DownloadClientJobsAndStatus> {
public async getClientJobsAndStatusAsync(input: { limit: number }): Promise<DownloadClientJobsAndStatus> {
const type = "usenet";
const { queue } = await queueSchema.parseAsync(await this.sabNzbApiCallAsync("queue"));
const { history } = await historySchema.parseAsync(await this.sabNzbApiCallAsync("history"));
const { queue } = await queueSchema.parseAsync(
await this.sabNzbApiCallAsync("queue", { limit: input.limit.toString() }),
);
const { history } = await historySchema.parseAsync(
await this.sabNzbApiCallAsync("history", { limit: input.limit.toString() }),
);
const status: DownloadClientStatus = {
paused: queue.paused,
rates: { down: Math.floor(Number(queue.kbpersec) * 1024) }, //Actually rounded kiBps ()
@@ -73,7 +77,8 @@ export class SabnzbdIntegration extends DownloadClientIntegration {
category: slot.category,
};
}),
);
)
.slice(0, input.limit);
return { status, items };
}
@@ -23,9 +23,10 @@ export class TransmissionIntegration extends DownloadClientIntegration {
};
}
public async getClientJobsAndStatusAsync(): Promise<DownloadClientJobsAndStatus> {
public async getClientJobsAndStatusAsync(input: { limit: number }): Promise<DownloadClientJobsAndStatus> {
const type = "torrent";
const client = await this.getClientAsync();
// Currently there is no way to limit the number of returned torrents
const { torrents } = (await client.listTorrents()).arguments;
const rates = torrents.reduce(
({ down, up }, { rateDownload, rateUpload }) => ({ down: down + rateDownload, up: up + rateUpload }),
@@ -34,27 +35,29 @@ export class TransmissionIntegration extends DownloadClientIntegration {
const paused =
torrents.find(({ status }) => TransmissionIntegration.getTorrentState(status) !== "paused") === undefined;
const status: DownloadClientStatus = { paused, rates, types: [type] };
const items = torrents.map((torrent): DownloadClientItem => {
const state = TransmissionIntegration.getTorrentState(torrent.status);
return {
type,
id: torrent.hashString,
index: torrent.queuePosition,
name: torrent.name,
size: torrent.totalSize,
sent: torrent.uploadedEver,
downSpeed: torrent.percentDone !== 1 ? torrent.rateDownload : undefined,
upSpeed: torrent.rateUpload,
time:
torrent.percentDone === 1
? Math.min(torrent.doneDate * 1000 - dayjs().valueOf(), -1)
: Math.max(torrent.eta * 1000, 0),
added: torrent.addedDate * 1000,
state,
progress: torrent.percentDone,
category: torrent.labels,
};
});
const items = torrents
.map((torrent): DownloadClientItem => {
const state = TransmissionIntegration.getTorrentState(torrent.status);
return {
type,
id: torrent.hashString,
index: torrent.queuePosition,
name: torrent.name,
size: torrent.totalSize,
sent: torrent.uploadedEver,
downSpeed: torrent.percentDone !== 1 ? torrent.rateDownload : undefined,
upSpeed: torrent.rateUpload,
time:
torrent.percentDone === 1
? Math.min(torrent.doneDate * 1000 - dayjs().valueOf(), -1)
: Math.max(torrent.eta * 1000, 0),
added: torrent.addedDate * 1000,
state,
progress: torrent.percentDone,
category: torrent.labels,
};
})
.slice(0, input.limit);
return { status, items };
}
@@ -4,7 +4,7 @@ import type { DownloadClientItem } from "./download-client-items";
export abstract class DownloadClientIntegration extends Integration {
/** Get download client's status and list of all of it's items */
public abstract getClientJobsAndStatusAsync(): Promise<DownloadClientJobsAndStatus>;
public abstract getClientJobsAndStatusAsync(input: { limit: number }): Promise<DownloadClientJobsAndStatus>;
/** Pauses the client or all of it's items */
public abstract pauseQueueAsync(): Promise<void>;
/** Pause a single item using it's ID */
@@ -69,6 +69,7 @@ const mapResource = (resource: Proxmox.clusterResourcesResources): Resource | nu
const mapComputeResource = (resource: Proxmox.clusterResourcesResources): Omit<ComputeResourceBase<string>, "type"> => {
return {
id: resource.id,
cpu: {
utilization: resource.cpu ?? 0,
cores: resource.maxcpu ?? 0,
@@ -114,6 +115,7 @@ const mapVmResource = (resource: Proxmox.clusterResourcesResources): LxcResource
const mapStorageResource = (resource: Proxmox.clusterResourcesResources): StorageResource => {
return {
id: resource.id,
type: "storage",
name: resource.storage ?? "",
node: resource.node ?? "",
@@ -7,6 +7,7 @@ interface ResourceBase<TType extends string> {
}
export interface ComputeResourceBase<TType extends string> extends ResourceBase<TType> {
id: string;
cpu: {
utilization: number; // previously cpu (0-1)
cores: number; // previously cpuCores
@@ -40,6 +41,7 @@ export interface QemuResource extends ComputeResourceBase<"qemu"> {
}
export interface StorageResource extends ResourceBase<"storage"> {
id: string;
storagePlugin: string;
used: number; // previously disk
total: number; // previously maxDisk
+5 -5
View File
@@ -46,7 +46,7 @@ describe("Aria2 integration", () => {
// Acts
const actAsync = async () => await aria2Integration.pauseQueueAsync();
const getAsync = async () => await aria2Integration.getClientJobsAndStatusAsync();
const getAsync = async () => await aria2Integration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(actAsync()).resolves.not.toThrow();
@@ -62,7 +62,7 @@ describe("Aria2 integration", () => {
const aria2Integration = createAria2Intergration(startedContainer, API_KEY);
// Act
const getAsync = async () => await aria2Integration.getClientJobsAndStatusAsync();
const getAsync = async () => await aria2Integration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.not.toThrow();
@@ -81,7 +81,7 @@ describe("Aria2 integration", () => {
await aria2AddItemAsync(startedContainer, API_KEY, aria2Integration);
// Act
const getAsync = async () => await aria2Integration.getClientJobsAndStatusAsync();
const getAsync = async () => await aria2Integration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.not.toThrow();
@@ -104,7 +104,7 @@ describe("Aria2 integration", () => {
await expect(actAsync()).resolves.not.toThrow();
// NzbGet is slow and we wait for a second before querying the items. Test was flaky without this.
await new Promise((resolve) => setTimeout(resolve, 1000));
const result = await aria2Integration.getClientJobsAndStatusAsync();
const result = await aria2Integration.getClientJobsAndStatusAsync({ limit: 99 });
expect(result.items).toHaveLength(0);
// Cleanup
@@ -153,7 +153,7 @@ const aria2AddItemAsync = async (container: StartedTestContainer, apiKey: string
const {
items: [item],
} = await integration.getClientJobsAndStatusAsync();
} = await integration.getClientJobsAndStatusAsync({ limit: 99 });
if (!item) {
throw new Error("No item found");
+6 -6
View File
@@ -69,7 +69,7 @@ describe("Nzbget integration", () => {
// Acts
const actAsync = async () => await nzbGetIntegration.pauseQueueAsync();
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(actAsync()).resolves.not.toThrow();
@@ -87,7 +87,7 @@ describe("Nzbget integration", () => {
// Acts
const actAsync = async () => await nzbGetIntegration.resumeQueueAsync();
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(actAsync()).resolves.not.toThrow();
@@ -105,7 +105,7 @@ describe("Nzbget integration", () => {
const nzbGetIntegration = createNzbGetIntegration(startedContainer, username, password);
// Act
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.not.toThrow();
@@ -124,7 +124,7 @@ describe("Nzbget integration", () => {
await nzbGetAddItemAsync(startedContainer, username, password, nzbGetIntegration);
// Act
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.not.toThrow();
@@ -147,7 +147,7 @@ describe("Nzbget integration", () => {
await expect(actAsync()).resolves.not.toThrow();
// NzbGet is slow and we wait for a second before querying the items. Test was flaky without this.
await new Promise((resolve) => setTimeout(resolve, 1000));
const result = await nzbGetIntegration.getClientJobsAndStatusAsync();
const result = await nzbGetIntegration.getClientJobsAndStatusAsync({ limit: 99 });
expect(result.items).toHaveLength(0);
// Cleanup
@@ -209,7 +209,7 @@ const nzbGetAddItemAsync = async (
const {
items: [item],
} = await integration.getClientJobsAndStatusAsync();
} = await integration.getClientJobsAndStatusAsync({ limit: 99 });
if (!item) {
throw new Error("No item found");
+8 -8
View File
@@ -67,7 +67,7 @@ describe("Sabnzbd integration", () => {
// Acts
const actAsync = async () => await sabnzbdIntegration.pauseQueueAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(actAsync()).resolves.not.toThrow();
@@ -85,7 +85,7 @@ describe("Sabnzbd integration", () => {
// Acts
const actAsync = async () => await sabnzbdIntegration.resumeQueueAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(actAsync()).resolves.not.toThrow();
@@ -103,7 +103,7 @@ describe("Sabnzbd integration", () => {
const sabnzbdIntegration = createSabnzbdIntegration(startedContainer, DEFAULT_API_KEY);
// Act
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.not.toThrow();
@@ -122,7 +122,7 @@ describe("Sabnzbd integration", () => {
await sabNzbdAddItemAsync(startedContainer, DEFAULT_API_KEY, sabnzbdIntegration);
// Act
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.not.toThrow();
@@ -140,7 +140,7 @@ describe("Sabnzbd integration", () => {
// Act
const actAsync = async () => await sabnzbdIntegration.pauseItemAsync(item);
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.toMatchObject({ items: [{ ...item, state: "downloading" }] });
@@ -160,7 +160,7 @@ describe("Sabnzbd integration", () => {
// Act
const actAsync = async () => await sabnzbdIntegration.resumeItemAsync(item);
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(getAsync()).resolves.toMatchObject({ items: [{ ...item, state: "paused" }] });
@@ -180,7 +180,7 @@ describe("Sabnzbd integration", () => {
// Act - fromDisk already doesn't work for sabnzbd, so only test deletion itself.
const actAsync = async () =>
await sabnzbdIntegration.deleteItemAsync({ ...item, progress: 0 } as DownloadClientItem, false);
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync();
const getAsync = async () => await sabnzbdIntegration.getClientJobsAndStatusAsync({ limit: 99 });
// Assert
await expect(actAsync()).resolves.not.toThrow();
@@ -242,7 +242,7 @@ const sabNzbdAddItemAsync = async (
for (let i = 0; i < 5; i++) {
const {
items: [item],
} = await integration.getClientJobsAndStatusAsync();
} = await integration.getClientJobsAndStatusAsync({ limit: 99 });
if (item) return item;
}
// Throws if it can't find the item
+2 -2
View File
@@ -27,13 +27,13 @@
"ioredis": "5.6.1",
"superjson": "2.2.2",
"winston": "3.17.0",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+5 -5
View File
@@ -33,19 +33,19 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.0.1",
"@tabler/icons-react": "^3.31.0",
"@mantine/core": "^8.0.2",
"@tabler/icons-react": "^3.33.0",
"dayjs": "^1.11.13",
"next": "15.3.2",
"next": "15.3.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
@@ -1,5 +1,4 @@
import { useMemo, useState } from "react";
import Image from "next/image";
import { Button, Card, Center, Grid, Input, Stack, Text } from "@mantine/core";
import { IconPlus, IconSearch } from "@tabler/icons-react";
@@ -23,7 +22,7 @@ export const AppSelectModal = createModal<AppSelectModalProps>(({ actions, inner
() =>
apps
.filter((app) => app.name.toLowerCase().includes(search.toLowerCase()))
.sort((a, b) => a.name.localeCompare(b.name)),
.sort((appA, appB) => appA.name.localeCompare(appB.name)),
[apps, search],
);
@@ -88,7 +87,7 @@ export const AppSelectModal = createModal<AppSelectModalProps>(({ actions, inner
<Stack justify="space-between" h="100%">
<Stack gap="xs">
<Center>
<Image src={app.iconUrl || ""} alt={app.name} width={24} height={24} />
<img src={app.iconUrl} alt={app.name} width={24} height={24} />
</Center>
<Text lh={1.2} style={{ whiteSpace: "normal" }} ta="center">
{app.name}
+3 -3
View File
@@ -24,15 +24,15 @@
"dependencies": {
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.0.1",
"@mantine/hooks": "^8.0.1",
"@mantine/core": "^8.0.2",
"@mantine/hooks": "^8.0.2",
"react": "19.1.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+3 -3
View File
@@ -24,14 +24,14 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/ui": "workspace:^0.1.0",
"@mantine/notifications": "^8.0.1",
"@tabler/icons-react": "^3.31.0"
"@mantine/notifications": "^8.0.2",
"@tabler/icons-react": "^3.33.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+5 -5
View File
@@ -37,14 +37,14 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.0.1",
"@mantine/hooks": "^8.0.1",
"@mantine/core": "^8.0.2",
"@mantine/hooks": "^8.0.2",
"adm-zip": "0.5.16",
"next": "15.3.2",
"next": "15.3.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"superjson": "2.2.2",
"zod": "^3.24.4",
"zod": "^3.25.42",
"zod-form-data": "^2.0.7"
},
"devDependencies": {
@@ -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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
@@ -77,6 +77,7 @@ const optionMapping: OptionMapping = {
descendingDefaultSort: () => false,
showCompletedUsenet: () => true,
showCompletedHttp: () => true,
limitPerIntegration: () => undefined,
},
weather: {
forecastDayCount: (oldOptions) => oldOptions.forecastDays,
@@ -156,6 +157,21 @@ const optionMapping: OptionMapping = {
defaultTab: (oldOptions) => ("defaultTabState" in oldOptions ? oldOptions.defaultTabState : undefined),
sectionIndicatorRequirement: (oldOptions) =>
"sectionIndicatorColor" in oldOptions ? oldOptions.sectionIndicatorColor : undefined,
showUptime: () => undefined,
visibleClusterSections: (oldOptions) => {
if (!("showNode" in oldOptions)) return undefined;
const oldKeys = {
showNode: "node" as const,
showLXCs: "lxc" as const,
showVM: "qemu" as const,
showStorage: "storage" as const,
} satisfies Partial<Record<keyof typeof oldOptions, string>>;
return objectEntries(oldKeys)
.filter(([key]) => oldOptions[key])
.map(([_, section]) => section);
},
},
mediaTranscoding: {
defaultView: (oldOptions) => oldOptions.defaultView,
+2 -2
View File
@@ -23,13 +23,13 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"zod": "^3.24.4"
"zod": "^3.25.42"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+1 -1
View File
@@ -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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+2 -2
View File
@@ -30,14 +30,14 @@
"@homarr/log": "workspace:^0.1.0",
"@homarr/redis": "workspace:^0.1.0",
"dayjs": "^1.11.13",
"octokit": "^4.1.3",
"octokit": "^5.0.3",
"superjson": "2.2.2"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+4 -2
View File
@@ -13,8 +13,10 @@ export const calendarMonthRequestHandler = createCachedIntegrationRequestHandler
>({
async requestAsync(integration, input) {
const integrationInstance = await createIntegrationAsync(integration);
const startDate = dayjs().year(input.year).month(input.month).startOf("month");
const endDate = startDate.clone().endOf("month");
// Calendar component shows up to 6 days before and after the month, for example if 1. of january is sunday, it shows the last 6 days of december.
const startDate = dayjs().year(input.year).month(input.month).startOf("month").subtract(6, "days");
const endDate = dayjs().year(input.year).month(input.month).endOf("month").add(6, "days");
return await integrationInstance.getCalendarEventsAsync(
startDate.toDate(),
endDate.toDate(),
+80
View File
@@ -0,0 +1,80 @@
import dayjs from "dayjs";
import type { ContainerInfo, ContainerStats } from "dockerode";
import { db, like, or } from "@homarr/db";
import { icons } from "@homarr/db/schema";
import type { ContainerState } from "../../docker/src";
import { DockerSingleton } from "../../docker/src";
import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler";
export const dockerContainersRequestHandler = createCachedWidgetRequestHandler({
queryKey: "dockerContainersResult",
widgetKind: "dockerContainers",
async requestAsync() {
const containers = await getContainersWithStatsAsync();
return containers;
},
cacheDuration: dayjs.duration(20, "seconds"),
});
const dockerInstances = DockerSingleton.getInstances();
const extractImage = (container: ContainerInfo) => container.Image.split("/").at(-1)?.split(":").at(0) ?? "";
async function getContainersWithStatsAsync() {
const containers = await Promise.all(
dockerInstances.map(async ({ instance, host }) => {
const instanceContainers = await instance.listContainers({ all: true });
return instanceContainers.map((container) => ({
...container,
instance: host,
}));
}),
).then((res) => res.flat());
const likeQueries = containers.map((container) => like(icons.name, `%${extractImage(container)}%`));
const dbIcons =
likeQueries.length > 0
? await db.query.icons.findMany({
where: or(...likeQueries),
})
: [];
const containerStatsPromises = containers.map(async (container) => {
const instance = dockerInstances.find(({ host }) => host === container.instance)?.instance;
if (!instance) return null;
const stats = await instance.getContainer(container.Id).stats({ stream: false });
return {
id: container.Id,
name: container.Names[0]?.split("/")[1] ?? "Unknown",
state: container.State as ContainerState,
iconUrl:
dbIcons.find((icon) => {
const extractedImage = extractImage(container);
if (!extractedImage) return false;
return icon.name.toLowerCase().includes(extractedImage.toLowerCase());
})?.url ?? null,
cpuUsage: calculateCpuUsage(stats),
memoryUsage: stats.memory_stats.usage,
image: container.Image,
ports: container.Ports,
};
});
return (await Promise.all(containerStatsPromises)).filter((container) => container !== null);
}
function calculateCpuUsage(stats: ContainerStats): number {
const cpuDelta = stats.cpu_stats.cpu_usage.total_usage - stats.precpu_stats.cpu_usage.total_usage;
const systemDelta = stats.cpu_stats.system_cpu_usage - stats.precpu_stats.system_cpu_usage;
const numberOfCpus = stats.cpu_stats.online_cpus || 1;
if (systemDelta === 0) return 0;
return (cpuDelta / systemDelta) * numberOfCpus * 100;
}
+3 -3
View File
@@ -9,11 +9,11 @@ import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-
export const downloadClientRequestHandler = createCachedIntegrationRequestHandler<
DownloadClientJobsAndStatus,
IntegrationKindByCategory<"downloadClient">,
Record<string, never>
{ limit: number }
>({
async requestAsync(integration, _input) {
async requestAsync(integration, input) {
const integrationInstance = await createIntegrationAsync(integration);
return await integrationInstance.getClientJobsAndStatusAsync();
return await integrationInstance.getClientJobsAndStatusAsync(input);
},
cacheDuration: dayjs.duration(5, "seconds"),
queryKey: "downloadClientJobStatus",
+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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.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.0.1",
"next": "15.3.2",
"@mantine/dates": "^8.0.2",
"next": "15.3.3",
"react": "19.1.0",
"react-dom": "19.1.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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+7 -7
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.0.1",
"@mantine/hooks": "^8.0.1",
"@mantine/spotlight": "^8.0.1",
"@tabler/icons-react": "^3.31.0",
"jotai": "^2.12.4",
"next": "15.3.2",
"@mantine/core": "^8.0.2",
"@mantine/hooks": "^8.0.2",
"@mantine/spotlight": "^8.0.2",
"@tabler/icons-react": "^3.33.0",
"jotai": "^2.12.5",
"next": "15.3.3",
"react": "19.1.0",
"react-dom": "19.1.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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+2 -2
View File
@@ -32,7 +32,7 @@
"dayjs": "^1.11.13",
"deepmerge": "4.3.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "15.3.2",
"next": "15.3.3",
"next-intl": "4.1.0",
"react": "19.1.0",
"react-dom": "19.1.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.26.0",
"eslint": "^9.27.0",
"typescript": "^5.8.3"
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "Comprova la connexió i crea",
"edit": "Comprova la connexió i desa"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "El botó \"Desa\" s'habilita quan la connexió s'estableix correctament",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "",
"delete": "",
"discard": "",
"close": "",
"confirm": "",
"continue": "",
"previous": "",
@@ -1630,12 +1757,18 @@
"memory": {
"label": ""
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": ""
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": ""
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "测试连接并创建",
"edit": "测试连接并保存"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "成功建立连接后保存按钮将启用",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "取消",
"delete": "删除",
"discard": "Discard",
"close": "",
"confirm": "确认",
"continue": "继续",
"previous": "上一步",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "显示内存信息"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "显示文件系统信息"
},
"defaultTab": {
"label": "默认标签"
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": "部分指标要求"
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "城市/邮编",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": "使用过滤器来计算比率"
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": "网络控制器"
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "已更新 {when}",
"search": "搜索 {count} 容器",
"selected": "{totalCount} 容器的 {selectCount}"
"selected": "{totalCount} 容器的 {selectCount}",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": "废弃"
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "镜像"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "开始",
"notification": {
@@ -3496,7 +3654,10 @@
"label": "日志"
},
"certificates": {
"label": "证书"
"label": "证书",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "可信证书",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": "到期时间 {when}"
"expires": "到期时间 {when}",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": "无法删除证书"
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "Otestovat připojení a vytvořit",
"edit": "Otestovat připojení a uložit"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Zrušit",
"delete": "Odstranit",
"discard": "Zahodit",
"close": "",
"confirm": "Potvrdit",
"continue": "Pokračovat",
"previous": "Zpět",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Zobrazit informace o paměti"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Zobrazit informace o souborovém systému"
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Obraz"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Spustit",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+258 -51
View File
@@ -702,6 +702,132 @@
"create": "Test forbindelse og opret",
"edit": "Test forbindelse og gem"
},
"error": {
"common": {
"cause": {
"title": "Årsag med flere detaljer"
}
},
"unknown": {
"title": "Ukendt fejl",
"description": "En ukendt fejl opstod, åbn årsagen nedenfor for at se flere detaljer"
},
"parse": {
"title": "Parsingfejl",
"description": "Svaret kunne ikke fortolkes. Kontroller, at URL'en peger på tjenestens grundlæggende URL."
},
"authorization": {
"title": "Godkendelsesfejl",
"description": "Anmodningen blev ikke godkendt. Kontroller, at legitimationsoplysningerne er korrekte og at du har dem konfigureret med nok tilladelser."
},
"statusCode": {
"title": "Svar fejl",
"description": "Modtaget uventet {statusCode} ({reason}) svar fra <url></url>. Kontroller, at URL'en peger på basis-URL'en for integrationen.",
"otherDescription": "Modtaget uventet {statusCode} svar fra <url></url>. Kontroller, at URLen peger på den grundlæggende URL for integrationen.",
"reason": {
"badRequest": "Ugyldig forespørgsel",
"notFound": "Ikke fundet",
"tooManyRequests": "For mange forespørgsler",
"internalServerError": "Intern serverfejl",
"serviceUnavailable": "Tjeneste ikke tilgængelig",
"gatewayTimeout": "Gateway-timeout"
}
},
"certificate": {
"title": "Certifikatfejl",
"description": {
"expired": "Certifikatet er udløbet.",
"notYetValid": "Certifikatet er ikke gyldigt endnu.",
"untrusted": "Der er ikke tillid til certifikatet.",
"hostnameMismatch": "Certifikatets værtsnavn matcher ikke URL'en."
},
"alert": {
"permission": {
"title": "Ikke tilstrækkelige tilladelser",
"message": "Du har ikke tilladelse til at stole på eller uploade certifikater. Kontakt venligst din administrator for at uploade det nødvendige rodcertifikat."
},
"hostnameMismatch": {
"title": "Værtsnavn matcher ikke",
"message": "Værtsnavnet i certifikatet matcher ikke det værtsnavn du forbinder til. Dette kan indikere en sikkerhedsrisiko, men du kan stadig vælge at stole på dette certifikat."
},
"extract": {
"title": "Ekstraktion af CA-certifikat mislykkedes",
"message": "Kun selvsignerede certifikater uden kæde kan hentes automatisk. Hvis du bruger et selvsigneret certifikat, skal du sørge for at uploade CA-certifikatet manuelt. Du kan finde instruktioner om, hvordan du gør dette <docsLink></docsLink>."
}
},
"action": {
"retry": {
"label": "Gentag oprettelse"
},
"trust": {
"label": "Stol på certifikat"
},
"upload": {
"label": "Upload certifikat"
}
},
"hostnameMismatch": {
"confirm": {
"title": "Stol på uoverensstemmelse mellem værtsnavn",
"message": "Er du sikker på du vil have tillid til certifikatet med et værtsnavn uoverensstemmelse?"
},
"notification": {
"success": {
"title": "Betroet certifikat",
"message": "Tilføjet værtsnavn til liste over betroede certifikater"
},
"error": {
"title": "Kunne ikke stole på certifikat",
"message": "Certifikatet med et værtsnavn mismatch kunne ikke stoles på"
}
}
},
"selfSigned": {
"confirm": {
"title": "Stol på selvsigneret certifikat",
"message": "Er du sikker på, at du vil stole på dette selvsignerede certifikat?"
},
"notification": {
"success": {
"title": "Betroet certifikat",
"message": "Tilføjet certifikat til liste over betroede certifikater"
},
"error": {
"title": "Kunne ikke stole på certifikat",
"message": "Kunne ikke tilføje certifikat til listen over betroede certifikater"
}
}
},
"details": {
"title": "Detaljer",
"description": "Gennemgå certifikatoplysningerne, før du beslutter dig for at stole på den.",
"content": {
"action": "Vis indhold",
"title": "PEM Certifikat"
}
}
},
"request": {
"title": "Anmodningsfejl",
"description": {
"connection": {
"hostUnreachable": "Serveren kunne ikke nås. Dette betyder normalt, at værten er offline eller ikke kan nås fra dit netværk.",
"networkUnreachable": "Netværket er ikke tilgængeligt. Tjek venligst din internetforbindelse eller netværkskonfiguration.",
"refused": "Serveren nægtede forbindelsen. Den kører muligvis ikke eller afviser forespørgsler på den angivne port.",
"reset": "Forbindelsen blev uventet lukket af serveren. Dette kan ske hvis serveren er ustabil eller genstartet."
},
"dns": {
"notFound": "Serveradressen kunne ikke findes. Tjek venligst URL'en for stave eller ugyldige domænenavne.",
"timeout": "DNS-opslag fik timeout. Dette kan være et midlertidigt problem - prøv igen om et øjeblik.",
"noAnswer": "DNS-serveren returnerede ikke et gyldigt svar. Domænet findes måske men har ingen gyldige poster."
},
"timeout": {
"aborted": "Anmodningen blev afbrudt før den kunne fuldføres. Dette kan skyldes en bruger handling eller system timeout.",
"timeout": "Forespørgslen tog for lang tid at fuldføre og fik timeout. Tjek dit netværk eller prøv igen senere."
}
}
}
},
"alertNotice": "Gem-knappen er aktiveret, når en vellykket forbindelse er etableret",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Annuller",
"delete": "Slet",
"discard": "Kassér",
"close": "Luk",
"confirm": "Bekræft",
"continue": "Forsæt",
"previous": "Forrige",
@@ -1093,7 +1220,7 @@
"label": "Integrationer"
},
"title": {
"label": ""
"label": "Titel"
},
"customCssClasses": {
"label": "Brugerdefinerede CSS-klasser"
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Vis hukommelsesoplysninger"
},
"showUptime": {
"label": "Vis Oppetid"
},
"fileSystem": {
"label": "Vis information om filsystemet"
},
"defaultTab": {
"label": "Standard fane"
},
"visibleClusterSections": {
"label": "Synlige klynge sektioner"
},
"sectionIndicatorRequirement": {
"label": "Sektion indikator er et krav"
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "Docker statistik",
"description": "Statistik for dine containere (Denne widget kan kun tilføjes med administratorrettigheder)",
"option": {},
"error": {
"internalServerError": "Kunne ikke hente containerstatistik"
}
},
"common": {
"location": {
"query": "By / Postnummer",
@@ -1771,8 +1912,8 @@
"description": "Vis de aktuelle streams på dine medieservere",
"option": {
"showOnlyPlaying": {
"label": "",
"description": ""
"label": "Vis kun hvad der aktuelt afspilles",
"description": "Deaktivering af dette vil ikke virke for plex"
}
},
"items": {
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": "Brug filteret til at beregne forholdet"
},
"limitPerIntegration": {
"label": "Begræns elementer pr. integration",
"description": "Dette vil begrænse antallet af elementer vist pr. integration, ikke globalt"
}
},
"errors": {
@@ -1950,7 +2095,7 @@
"approved": "Godkendt",
"declined": "Afvist",
"failed": "Mislykket",
"completed": ""
"completed": "Fuldført"
},
"toBeDetermined": "TBD"
},
@@ -2054,94 +2199,94 @@
}
},
"releases": {
"name": "",
"description": "",
"name": "Udgivelser",
"description": "Viser en liste over den aktuelle version af de givne depoter med den givne version regex.",
"option": {
"newReleaseWithin": {
"label": "",
"description": ""
"label": "Ny Udgivelse Inden",
"description": "Anvendelseseksempel: 1w (1 uge), 10M (10 måneder). Accepterede enhedstyper h (timer), d (dage), w (uger), M (måneder), y (år). Lad være tom for ingen fremhævning af nye udgivelser."
},
"staleReleaseWithin": {
"label": "",
"description": ""
"label": "Gamle Udgivelse Indenfor",
"description": "Anvendelseseksempel: 1w (1 uge), 10M (10 måneder). Accepterede enhedstyper h (timer), d (dage), w (uger), M (måneder), y (år). Lad være tom for ingen fremhævning af forældede udgivelser."
},
"showOnlyHighlighted": {
"label": "",
"description": ""
"label": "Vis Kun Fremhævede",
"description": "Vis kun nye eller forældede udgivelser. Som pr ovenfor."
},
"showDetails": {
"label": ""
"label": "Vis detaljer"
},
"topReleases": {
"label": "",
"description": ""
"label": "Top Udgivelser",
"description": "Det maksimale antal seneste udgivelser at vise. Nul betyder ingen grænse."
},
"repositories": {
"label": "",
"label": "Repositories",
"addRRepository": {
"label": ""
"label": "Tilføj repository"
},
"provider": {
"label": ""
"label": "Udbyder"
},
"identifier": {
"label": "",
"placeholder": ""
"label": "Identifikator",
"placeholder": "Navn eller ejer/navn"
},
"name": {
"label": ""
"label": "Navn"
},
"versionFilter": {
"label": "",
"label": "Versionsfilter",
"prefix": {
"label": ""
"label": "Præfiks"
},
"precision": {
"label": "",
"label": "Præcision",
"options": {
"none": ""
"none": "Ingen"
}
},
"suffix": {
"label": ""
"label": "Suffiks"
},
"regex": {
"label": ""
"label": "Regulært Udtryk"
}
},
"edit": {
"label": ""
"label": "Rediger"
},
"editForm": {
"title": "",
"title": "Rediger Repository",
"cancel": {
"label": ""
"label": "Annuller"
},
"confirm": {
"label": ""
"label": "Bekræft"
}
},
"example": {
"label": ""
"label": "Eksempel"
},
"invalid": ""
"invalid": "Ugyldig repository definition, tjek venligst værdierne"
}
},
"not-found": "",
"pre-release": "",
"archived": "",
"forked": "",
"starsCount": "",
"forksCount": "",
"issuesCount": "",
"openProjectPage": "",
"openReleasePage": "",
"releaseDescription": "",
"created": "",
"not-found": "Ikke fundet",
"pre-release": "Pre-Release",
"archived": "Arkiveret",
"forked": "Forked",
"starsCount": "Stjerner",
"forksCount": "Forks",
"issuesCount": "Åbne Problemer",
"openProjectPage": "Åbn Projektside",
"openReleasePage": "Åbn Udgivelsesside",
"releaseDescription": "Udgivelse Beskrivelse",
"created": "Oprettet",
"error": {
"label": "",
"label": "Fejl",
"options": {
"noMatchingVersion": ""
"noMatchingVersion": "Ingen matchende version fundet"
}
}
},
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": "Netværkskontroller"
},
"dockerContainers": {
"label": "Docker containers"
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "Opdateret {when}",
"search": "Søg {count} containere",
"selected": "{selectCount} af {totalCount} containere valgt"
"selected": "{selectCount} af {totalCount} containere valgt",
"footer": "Total {count} containere"
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": "Død"
}
},
"stats": {
"cpu": {
"label": "CPU"
},
"memory": {
"label": "Hukommelse"
}
},
"containerImage": {
"label": "Billede"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "Handlinger",
"start": {
"label": "Start",
"notification": {
@@ -3496,7 +3654,10 @@
"label": "Logs"
},
"certificates": {
"label": "Certifikater"
"label": "Certifikater",
"hostnames": {
"label": "Værtsnavne"
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": "Værtsnavn"
},
"subject": {
"label": "Emne"
},
"issuer": {
"label": "Udsteder"
},
"validFrom": {
"label": "Gyldig fra"
},
"validTo": {
"label": "Gyldig til"
},
"serialNumber": {
"label": "Serienummer"
},
"fingerprint": {
"label": "Fingeraftryk"
}
},
"page": {
"list": {
"title": "Betroede certifikater",
@@ -3902,10 +4086,19 @@
"title": "Der er endnu ingen certifikater"
},
"invalid": {
"title": "",
"description": ""
"title": "Ugyldigt certifikat",
"description": "Kunne ikke fortolke certifikat"
},
"expires": "Udløber {when}"
"expires": "Udløber {when}",
"toHostnames": "Betroede værtsnavne"
},
"hostnames": {
"title": "Betroet certifikat værtsnavne",
"description": "Nogle certifikater tillader ikke det specifikke domæne Homarr bruger til at anmode om dem, på grund af dette alle betroede værtsnavne med deres certifikat thumbprints bruges til at omgå disse restriktioner.",
"noResults": {
"title": "Der er endnu ingen værtsnavne"
},
"toCertificates": "Certifikater"
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": "Certifikatet kunne ikke slettes"
}
}
},
"removeHostname": {
"label": "Fjern betroet værtsnavn",
"confirm": "Er du sikker på du vil fjerne dette betroede værtsnavn? Dette kan få nogle integrationer til at stoppe med at virke.",
"notification": {
"success": {
"title": "Værtsnavn fjernet",
"message": "Værtsnavnet blev fjernet korrekt"
},
"error": {
"title": "Værtsnavn ikke fjernet",
"message": "Værtsnavnet kunne ikke fjernes"
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "Verbindig teste und erstäue",
"edit": "Verbinding teste und spichere"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "Dr Spicherknopf isch aktiv sobald d Verbindig het chönne hergstellt werde",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Abbrechen",
"delete": "Löschen",
"discard": "Verwerfen",
"close": "",
"confirm": "Bestätigen",
"continue": "Fortfahren",
"previous": "Zurück",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Speicher-Info anzeigen"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Dateisystem Info anzeigen"
},
"defaultTab": {
"label": "Standard Tab"
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": "Anforderung der Sektionsindikatoren"
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "Stadt / Postleitzahl",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": "Filter zur Berechnung des Verhältnisses verwenden"
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "Aktualisiert {when}",
"search": "{count} Container durchsuchen",
"selected": "{selectCount} von {totalCount} ausgewählten Containern"
"selected": "{selectCount} von {totalCount} ausgewählten Containern",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": "Tot"
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": ""
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Starten",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": "Zertifikate"
"label": "Zertifikate",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "Vertrauenswürdige Zertifikate",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": "Gültig bis {when}"
"expires": "Gültig bis {when}",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": "Das Zertifikat konnte nicht entfernt werden"
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+311 -104
View File
@@ -612,15 +612,15 @@
"select": {
"label": "App auswählen",
"notFound": "Keine App gefunden",
"search": "",
"noResults": "",
"action": "",
"title": ""
"search": "Nach einer App suchen",
"noResults": "Keine Ergebnisse",
"action": "{app} auswählen",
"title": "Wählen Sie eine App, die diesem Board hinzugefügt werden soll"
},
"create": {
"title": "Neue App erstellen",
"description": "",
"action": ""
"description": "Eine neue App erstellen",
"action": "App-Erstellung öffnen"
},
"add": "App hinzufügen"
}
@@ -702,6 +702,132 @@
"create": "Verbindung erstellen und testen",
"edit": "Verbindung erstellen und speichern"
},
"error": {
"common": {
"cause": {
"title": "Fall mit mehr Details"
}
},
"unknown": {
"title": "Unbekannter Fehler",
"description": "Ein unbekannter Fehler ist aufgetreten, den Fall unten für mehr Details öffnen"
},
"parse": {
"title": "Fehler beim Parsen",
"description": "Die Antwort konnte nicht analysiert werden. Bitte stellen Sie sicher, dass die URL auf die Basis-URL des Dienstes zeigt."
},
"authorization": {
"title": "Autorisierungsfehler",
"description": "Die Anfrage wurde nicht autorisiert. Bitte überprüfen Sie, ob die Anmeldedaten korrekt sind und Sie diese mit mit den entsprechenden Berechtigungen konfiguriert haben."
},
"statusCode": {
"title": "Antwort Fehler",
"description": "Unerwartete {statusCode} ({reason}) Antwort von <url></url>erhalten. Bitte überprüfen Sie, ob die URL auf die Basis-URL der Integration verweist.",
"otherDescription": "Unerwartete {statusCode} Antwort von <url></url>erhalten. Bitte stellen Sie sicher, dass die URL auf die Basis-URL der Integration zeigt.",
"reason": {
"badRequest": "Fehlerhafte Anfrage",
"notFound": "Nicht gefunden",
"tooManyRequests": "Zu viele Anfragen",
"internalServerError": "Interner Serverfehler",
"serviceUnavailable": "Dienst nicht verfügbar",
"gatewayTimeout": "Gateway-Zeitüberschreitung"
}
},
"certificate": {
"title": "Zertifikatfehler",
"description": {
"expired": "Das Zertifikat ist abgelaufen.",
"notYetValid": "Das Zertifikat ist noch nicht gültig.",
"untrusted": "Dem Zertifikat wird nicht vertraut.",
"hostnameMismatch": "Der Hostname des Zertifikats entspricht nicht der URL."
},
"alert": {
"permission": {
"title": "Nicht genügend Berechtigungen",
"message": "Sie sind nicht berechtigt Zertifikate zu vertrauen oder hochzuladen. Bitte kontaktieren Sie Ihren Administrator, um das notwendige Root-Zertifikat hochzuladen."
},
"hostnameMismatch": {
"title": "Hostname stimmt nicht überein",
"message": "Der Hostname im Zertifikat stimmt nicht mit dem Hostnamen überein, mit dem Sie probieren sich zu verbinden. Dies könnte auf ein Sicherheitsrisiko hindeuten, Sie können trotzdem diesem Zertifikat vertrauen."
},
"extract": {
"title": "CA-Zertifikatextraktion fehlgeschlagen",
"message": "Nur selbstsignierte Zertifikate ohne Kette können automatisch abgerufen werden. Falls Sie ein selbst signiertes Zertifikat verwenden, stellen Sie bitte sicher, dass Sie das CA-Zertifikat manuell hochladen. Hier finden Sie Anweisungen, wie man das <docsLink></docsLink> macht."
}
},
"action": {
"retry": {
"label": "Erstellung wiederholen"
},
"trust": {
"label": "Zertifikat vertrauen"
},
"upload": {
"label": "Zertifikat hochladen"
}
},
"hostnameMismatch": {
"confirm": {
"title": "Der Nichtübereinstimmung der Hostnamen zustimmen",
"message": "Sind Sie sicher, dass Sie dem Zertifikat mit einer Nichtübereinstimmung des Hostnamens vertrauen möchten?"
},
"notification": {
"success": {
"title": "Vertrauenswürdige Zertifikate",
"message": "Hostname zu vertrauenswürdiger Zertifikatsliste hinzugefügt"
},
"error": {
"title": "Ein Fehler ist beim vertrauen des Zertifikats aufgetreten",
"message": "Dem Zertifikat mit einer Nichtübereinstimmung des Hostnamens konnte nicht vertraut werden"
}
}
},
"selfSigned": {
"confirm": {
"title": "Selbstsigniertem Zertifikat vertrauen",
"message": "Sind Sie sicher, dass Sie diesem selbst signierten Zertifikat vertrauen möchten?"
},
"notification": {
"success": {
"title": "Vertrauenswürdige Zertifikate",
"message": "Zertifikat zur vertrauenswürdigen Zertifikatsliste hinzugefügt"
},
"error": {
"title": "Ein Fehler ist beim vertrauen des Zertifikats aufgetreten",
"message": "Das Zertifikat konnte nicht zur vertrauenswürdigen Zertifikatsliste hinzugefügt werden"
}
}
},
"details": {
"title": "Details",
"description": "Überprüfen Sie die Zertifikatsinformationen, bevor Sie sich dazu entschließen, ihr zu vertrauen.",
"content": {
"action": "Inhalt anzeigen",
"title": "PEM Zertifikat"
}
}
},
"request": {
"title": "Anfrage Fehler",
"description": {
"connection": {
"hostUnreachable": "Der Server konnte nicht erreicht werden. Dies bedeutet in der Regel, dass der Host offline oder nicht von Ihrem Netzwerk aus erreichbar ist.",
"networkUnreachable": "Das Netzwerk ist nicht erreichbar. Bitte überprüfen Sie Ihre Internetverbindung oder die Netzwerkkonfiguration.",
"refused": "Der Server hat die Verbindung abgelehnt. Er läuft möglicherweise nicht oder lehnt Anfragen auf dem angegebenen Port ab.",
"reset": "Die Verbindung wurde unerwartet vom Server getrennt. Dies kann passieren, wenn der Server instabil ist oder neu gestartet wurde."
},
"dns": {
"notFound": "Die Serveradresse konnte nicht gefunden werden. Bitte überprüfen Sie die URL auf Tippfehler oder ungültige Domainnamen.",
"timeout": "Zeitüberschreitung bei der DNS Anfrage. Dies kann ein temporäres Problem sein – bitte versuchen Sie es in ein paar Augenblicken erneut.",
"noAnswer": "Der DNS-Server hat keine gültige Antwort zurückgegeben. Die Domain existiert vielleicht, hat jedoch keine gültigen Datensätze."
},
"timeout": {
"aborted": "Die Anfrage wurde abgebrochen, bevor sie abgeschlossen werden konnte. Dies könnte auf eine Benutzeraktion oder einen System Timeout zurückzuführen sein.",
"timeout": "Die Anfrage zu bearbeiten hat zu lange gedauert, sie ist damit abgelaufen. Überprüfe dein Netzwerk oder versuche es später erneut."
}
}
}
},
"alertNotice": "Der Speichern Button ist verfügbar, sobald eine erfolgreiche Verbindung hergestellt wurde",
"notification": {
"success": {
@@ -769,8 +895,8 @@
"message": "Der Pfad ist vermutlich nicht korrekt"
},
"tooManyRequests": {
"title": "",
"message": ""
"title": "Zu viele Anfragen innerhalb einer bestimmten Zeit",
"message": "Es gab zu viele Anfragen. Sie werden wahrscheinlich vom Zielsystem begrenzt oder abgelehnt"
}
}
},
@@ -878,6 +1004,7 @@
"cancel": "Abbrechen",
"delete": "Löschen",
"discard": "Verwerfen",
"close": "Schließen",
"confirm": "Bestätigen",
"continue": "Fortfahren",
"previous": "Zurück",
@@ -1093,7 +1220,7 @@
"label": "Integrationen"
},
"title": {
"label": ""
"label": "Titel"
},
"customCssClasses": {
"label": "Benutzerdefinierte CSS Klassen"
@@ -1445,76 +1572,76 @@
}
},
"stockPrice": {
"name": "",
"description": "",
"name": "Aktienpreis",
"description": "Zeigt den aktuellen Aktienkurs einer Firma an",
"option": {
"stock": {
"label": ""
"label": "Aktiensymbol"
},
"timeRange": {
"label": "",
"label": "Zeitraum",
"option": {
"1d": {
"label": ""
"label": "1 Tag"
},
"5d": {
"label": ""
"label": "5 Tage"
},
"1mo": {
"label": ""
"label": "1 Monat"
},
"3mo": {
"label": ""
"label": "3 Monate"
},
"6mo": {
"label": ""
"label": "6 Monate"
},
"ytd": {
"label": ""
"label": "Bisheriger Jahresverlauf"
},
"1y": {
"label": ""
"label": "1 Jahr"
},
"2y": {
"label": ""
"label": "2 Jahre"
},
"5y": {
"label": ""
"label": "5 Jahre"
},
"10y": {
"label": ""
"label": "10 Jahre"
},
"max": {
"label": ""
"label": "Max"
}
}
},
"timeInterval": {
"label": "",
"label": "Zeitintervall",
"option": {
"5m": {
"label": ""
"label": "5 Minuten"
},
"15m": {
"label": ""
"label": "15 Minuten"
},
"30m": {
"label": ""
"label": "30 Minuten"
},
"1h": {
"label": ""
"label": "1 Stunde"
},
"1d": {
"label": ""
"label": "1 Tag"
},
"5d": {
"label": ""
"label": "5 Tage"
},
"1wk": {
"label": ""
"label": "1 Woche"
},
"1mo": {
"label": ""
"label": "1 Monat"
}
}
}
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Speicher-Info anzeigen"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Dateisystem Info anzeigen"
},
"defaultTab": {
"label": "Standard Tab"
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": "Anforderung der Sektionsindikatoren"
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "Stadt / Postleitzahl",
@@ -1771,8 +1912,8 @@
"description": "Zeige die aktuellen Streams auf deinen Medienservern an",
"option": {
"showOnlyPlaying": {
"label": "",
"description": ""
"label": "Nur aktuelle Wiedergabe anzeigen",
"description": "Diese Einstellung zu deaktivieren wird für Plex nicht funktionieren"
}
},
"items": {
@@ -1805,7 +1946,7 @@
"label": "Torrent Einträge anzeigen die abgeschlossen wurden"
},
"showCompletedHttp": {
"label": ""
"label": "Andere Einträge als abgeschlossen anzeigen"
},
"activeTorrentThreshold": {
"label": "Abgeschlossene Torrents unter diesem Schwellenwert ausblenden (in kiB/s)"
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": "Filter zur Berechnung des Verhältnisses verwenden"
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -1950,7 +2095,7 @@
"approved": "Bestätigt",
"declined": "Abgelehnt",
"failed": "Fehlgeschlagen",
"completed": ""
"completed": "Abgeschlossen"
},
"toBeDetermined": "Noch Festzulegen"
},
@@ -2054,94 +2199,94 @@
}
},
"releases": {
"name": "",
"description": "",
"name": "Veröffentlichungen",
"description": "Zeigt eine Liste der aktuellen Version der angegebenen Repositories mit der angegebenen Version regex an.",
"option": {
"newReleaseWithin": {
"label": "",
"description": ""
"label": "Neue Version innerhalb",
"description": "Anwendungsbeispiel: 1w (1 Woche), 10M (10 Monate). Akzeptierte Einheiten h (Stunden), d (Tage), w (Wochen), M (Monate), y (Jahre). Leer lassen für keine Hervorhebung neuer Releases."
},
"staleReleaseWithin": {
"label": "",
"description": ""
"label": "Veraltete Version innerhalb",
"description": "Anwendungsbeispiel: 1w (1 Woche), 10M (10 Monate). Akzeptierte Einheiten h (Stunden), d (Tage), w (Wochen), M (Monate), y (Jahre). Leer lassen für keine Hervorhebung von veralteten Releases."
},
"showOnlyHighlighted": {
"label": "",
"description": ""
"label": "Nur markierte anzeigen",
"description": "Nur neue oder veraltete Versionen anzeigen. Wie oben beschrieben."
},
"showDetails": {
"label": ""
"label": "Details anzeigen"
},
"topReleases": {
"label": "",
"description": ""
"label": "Top Releases",
"description": "Die maximale Anzahl der neuesten Versionen, die angezeigt werden sollen. Null bedeutet kein Limit."
},
"repositories": {
"label": "",
"label": "Repositories",
"addRRepository": {
"label": ""
"label": "Repository hinzufügen"
},
"provider": {
"label": ""
"label": "Anbieter"
},
"identifier": {
"label": "",
"placeholder": ""
"label": "Identifier",
"placeholder": "Name oder Eigentümer/Name"
},
"name": {
"label": ""
"label": "Name"
},
"versionFilter": {
"label": "",
"label": "Versionsfilter",
"prefix": {
"label": ""
"label": "Präfix"
},
"precision": {
"label": "",
"label": "Präzision",
"options": {
"none": ""
"none": "Keine"
}
},
"suffix": {
"label": ""
"label": "Suffix"
},
"regex": {
"label": ""
"label": "Regulärer Ausdruck"
}
},
"edit": {
"label": ""
"label": "Bearbeiten"
},
"editForm": {
"title": "",
"title": "Repository bearbeiten",
"cancel": {
"label": ""
"label": "Abbrechen"
},
"confirm": {
"label": ""
"label": "Bestätigen"
}
},
"example": {
"label": ""
"label": "Beispiel"
},
"invalid": ""
"invalid": "Ungültige Repository Definition, bitte überprüfen Sie die Werte"
}
},
"not-found": "",
"pre-release": "",
"archived": "",
"forked": "",
"starsCount": "",
"forksCount": "",
"issuesCount": "",
"openProjectPage": "",
"openReleasePage": "",
"releaseDescription": "",
"created": "",
"not-found": "Nicht gefunden",
"pre-release": "Vorveröffentlichung",
"archived": "Archiviert",
"forked": "Forked",
"starsCount": "Sterne",
"forksCount": "Ableger",
"issuesCount": "Offene Tickets",
"openProjectPage": "Projektseite öffnen",
"openReleasePage": "Release Seite öffnen",
"releaseDescription": "Release Beschreibung",
"created": "Erstellt",
"error": {
"label": "",
"label": "Fehler",
"options": {
"noMatchingVersion": ""
"noMatchingVersion": "Keine passende Version gefunden"
}
}
},
@@ -2149,56 +2294,56 @@
"option": {},
"card": {
"vpn": {
"countConnected": ""
"countConnected": "{count} verbunden"
}
},
"error": {
"integrationsDisconnected": "",
"unknownContentOption": ""
"integrationsDisconnected": "Keine Daten verfügbar, alle Integrationen getrennt",
"unknownContentOption": "Unbekannte Inhaltsoption für das Widget der Netzwerk Controller Zusammenfassung: "
},
"name": "",
"description": ""
"name": "Netzwerk Controller Zusammenfassung",
"description": "Zeigt die Zusammenfassung eines Netzwerk Controller (wie UniFi-Controller) an"
},
"networkControllerStatus": {
"card": {
"variants": {
"wired": {
"name": ""
"name": "Kabel"
},
"wifi": {
"name": ""
"name": "WLAN"
}
},
"users": {
"label": ""
"label": "Benutzer"
},
"guests": {
"label": ""
"label": "Gäste"
}
},
"option": {
"content": {
"option": {
"wifi": {
"label": ""
"label": "WLAN"
},
"wired": {
"label": ""
"label": "Kabel"
}
},
"label": ""
"label": "Widget Inhalt"
}
},
"error": {
"integrationsDisconnected": "",
"unknownContentOption": ""
"integrationsDisconnected": "Keine Daten verfügbar, alle Integrationen getrennt",
"unknownContentOption": "Unbekannte Inhaltsoption für das Netzwerkstatus Widget: "
},
"name": "",
"description": ""
"name": "Netzwerkstatus",
"description": "Angeschlossene Geräte in einem Netzwerk anzeigen"
},
"networkController": {
"error": {
"internalServerError": ""
"internalServerError": "Fehler beim Abrufen der Netzwerk Controller Zusammenfassung"
}
}
},
@@ -2321,10 +2466,10 @@
},
"backgroundImageUrl": {
"label": "URL des Hintergrundbildes",
"placeholder": "",
"placeholder": "Tippen, um nach lokale Bilder zu suchen",
"group": {
"your": "",
"other": ""
"your": "Ihre Bilder",
"other": "Andere Bilder"
}
},
"backgroundImageAttachment": {
@@ -2963,6 +3108,9 @@
"label": "Medien Transkodierung"
},
"networkController": {
"label": "Netzwerk Controller"
},
"dockerContainers": {
"label": ""
}
}
@@ -3028,7 +3176,8 @@
"table": {
"updated": "Aktualisiert {when}",
"search": "{count} Container durchsuchen",
"selected": "{selectCount} von {totalCount} ausgewählten Containern"
"selected": "{selectCount} von {totalCount} ausgewählten Containern",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": "Tot"
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Image"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Starten",
"notification": {
@@ -3496,7 +3654,10 @@
"label": "Logs"
},
"certificates": {
"label": "Zertifikate"
"label": "Zertifikate",
"hostnames": {
"label": "Hostnamen"
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": "Hostname"
},
"subject": {
"label": "Thema"
},
"issuer": {
"label": "Ersteller"
},
"validFrom": {
"label": "Gültig ab"
},
"validTo": {
"label": "Gültig bis"
},
"serialNumber": {
"label": "Seriennummer"
},
"fingerprint": {
"label": "Fingerabdruck"
}
},
"page": {
"list": {
"title": "Vertrauenswürdige Zertifikate",
@@ -3902,10 +4086,19 @@
"title": "Es gibt noch keine Zertifikate"
},
"invalid": {
"title": "",
"description": ""
"title": "Ungültiges Zertifikat",
"description": "Fehler beim Analysieren des Zertifikats"
},
"expires": "Gültig bis {when}"
"expires": "Gültig bis {when}",
"toHostnames": "Vertrauenswürdige Hostnamen"
},
"hostnames": {
"title": "Hostnamen der vertrauten Zertifikate",
"description": "Einige Zertifikate erlauben es der spezifischen Domäne von Homarr nicht, sie anzufordern. Um diese Einschränkungen zu umgehen werden alle vertrauenswürdigen Hostnamen mit ihrem Zertifikats Fingerabdruck verwendet.",
"noResults": {
"title": "Noch keine Hostnamen vorhanden"
},
"toCertificates": "Zertifikate"
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": "Das Zertifikat konnte nicht entfernt werden"
}
}
},
"removeHostname": {
"label": "Vertrauenswürdigen Hostnamen entfernen",
"confirm": "Sind Sie sicher, dass Sie diesen vertrauenswürdigen Hostnamen entfernen wollen? Dies kann dazu führen, dass einige Integrationen nicht mehr funktionieren.",
"notification": {
"success": {
"title": "Hostname entfernt",
"message": "Der Hostname wurde erfolgreich entfernt"
},
"error": {
"title": "Hostname nicht entfernt",
"message": "Der Hostname konnte nicht entfernt werden"
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "",
"edit": ""
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Ακύρωση",
"delete": "Διαγραφή",
"discard": "",
"close": "",
"confirm": "Επιβεβαίωση",
"continue": "",
"previous": "Προηγούμενο",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Εμφάνιση Πληροφοριών Μνήμης"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Εμφάνιση Πληροφοριών Συστήματος Αρχείων"
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Εικόνα"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Έναρξη",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "Test the connection and create integration",
"edit": "Test the connection and save"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "The save button is enabled once the connection is successfully established",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Cancel",
"delete": "Delete",
"discard": "Discard",
"close": "",
"confirm": "Confirm",
"continue": "Continue",
"previous": "Previous",
@@ -1630,12 +1757,18 @@
"memory": {
"label": ""
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": ""
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": ""
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+33 -2
View File
@@ -1757,12 +1757,18 @@
"memory": {
"label": "Show Memory Info"
},
"showUptime": {
"label": "Show Uptime"
},
"fileSystem": {
"label": "Show Filesystem Info"
},
"defaultTab": {
"label": "Default tab"
},
"visibleClusterSections": {
"label": "Visible cluster sections"
},
"sectionIndicatorRequirement": {
"label": "Section indicator requirement"
}
@@ -1832,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "Docker stats",
"description": "Stats of your containers (This widget can only be added with administrator privileges)",
"option": {},
"error": {
"internalServerError": "Failed to fetch containers stats"
}
},
"common": {
"location": {
"query": "City / Postal code",
@@ -1945,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": "Use filter to calculate Ratio"
},
"limitPerIntegration": {
"label": "Limit items per integration",
"description": "This will limit the number of items shown per integration, not globally"
}
},
"errors": {
@@ -3091,6 +3109,9 @@
},
"networkController": {
"label": "Network Controller"
},
"dockerContainers": {
"label": "Docker containers"
}
}
},
@@ -3154,8 +3175,9 @@
"title": "Containers",
"table": {
"updated": "Updated {when}",
"search": "Search {count} containers",
"selected": "{selectCount} of {totalCount} containers selected"
"search": "Seach {count} containers",
"selected": "{selectCount} of {totalCount} containers selected",
"footer": "Total {count} containers"
},
"field": {
"name": {
@@ -3173,6 +3195,14 @@
"dead": "Dead"
}
},
"stats": {
"cpu": {
"label": "CPU"
},
"memory": {
"label": "Memory"
}
},
"containerImage": {
"label": "Image"
},
@@ -3181,6 +3211,7 @@
}
},
"action": {
"title": "Actions",
"start": {
"label": "Start",
"notification": {
+214 -7
View File
@@ -3,7 +3,7 @@
"step": {
"start": {
"title": "Bienvenido a Homarr",
"subtitle": "Comencemos con la configuración de tu instancia de Homar.",
"subtitle": "Comencemos con la configuración de tu instancia de Homarr.",
"description": "Para empezar, por favor, seleccione cómo desea configurar su instancia de Homarr.",
"action": {
"scratch": "Empezar de cero",
@@ -35,7 +35,7 @@
}
},
"summary": {
"title": "Importar resumen",
"title": "Resumen de importación",
"description": "",
"action": {
"import": "Confirmar la importación y continuar"
@@ -160,7 +160,7 @@
}
},
"error": {
"usernameTaken": "Nombre de usuario ya está ocupado"
"usernameTaken": ""
},
"action": {
"login": {
@@ -172,7 +172,7 @@
"message": ""
},
"error": {
"title": "",
"title": "Inicio de sesión fallido",
"message": ""
}
},
@@ -702,6 +702,132 @@
"create": "",
"edit": ""
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Cancelar",
"delete": "Eliminar",
"discard": "",
"close": "",
"confirm": "Confirmar",
"continue": "",
"previous": "Anterior",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Mostrar información de la memoria"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Mostrar información del sistema de archivos"
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Imagen"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Iniciar",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "",
"edit": ""
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "",
"delete": "",
"discard": "",
"close": "",
"confirm": "",
"continue": "",
"previous": "",
@@ -1630,12 +1757,18 @@
"memory": {
"label": ""
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": ""
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": ""
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "Tester la connexion et créer",
"edit": "Tester la connexion et enregistrer"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "Le bouton Enregistrer est activé une fois qu'une connexion est établie avec succès",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Annuler",
"delete": "Supprimer",
"discard": "Abandonner",
"close": "",
"confirm": "Confirmer",
"continue": "Continuer",
"previous": "Précédent",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Afficher les infos de la mémoire"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Afficher les infos sur le système de fichiers"
},
"defaultTab": {
"label": "Onglet par défaut"
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": "Exigence de l'indicateur de section"
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "Ville / Code Postal",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": "Utiliser le filtre pour calculer le ratio"
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "Mis à jour {when}",
"search": "Rechercher dans {count} conteneurs",
"selected": "{selectCount} sur {totalCount} conteneurs sélectionnés"
"selected": "{selectCount} sur {totalCount} conteneurs sélectionnés",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": "Mort"
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Image"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Début",
"notification": {
@@ -3496,7 +3654,10 @@
"label": "Journaux"
},
"certificates": {
"label": "Certificats"
"label": "Certificats",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "Certificats de confiance",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": "Expire le {when}"
"expires": "Expire le {when}",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": "Le certificat n'a pas pu être supprimé"
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+217 -10
View File
@@ -702,6 +702,132 @@
"create": "בדוק חיבור וצור",
"edit": "בדוק את החיבור ושמור"
},
"error": {
"common": {
"cause": {
"title": "סיבה עם פרטים נוספים"
}
},
"unknown": {
"title": "שגיאה לא ידועה",
"description": "אירעה שגיאה לא ידועה, פתח את הסיבה למטה כדי לראות פרטים נוספים"
},
"parse": {
"title": "שגיאת ניתוח",
"description": "לא ניתן היה לנתח את התגובה. אנא ודא שכתובת האתר מפנה לכתובת האתר הבסיסית של השירות."
},
"authorization": {
"title": "שגיאת הרשאה",
"description": "הבקשה לא אושרה. אנא ודא שהאישורים נכונים ושהוגדרו לך הרשאות מספיקות."
},
"statusCode": {
"title": "שגיאת תגובה",
"description": "התקבלה תגובה בלתי צפויה של {statusCode} ({reason}) מ-<url></url>. אנא ודא שכתובת האתר מפנה לכתובת האתר הבסיסית של האינטגרציה.",
"otherDescription": "התקבלה תגובה בלתי צפויה של {statusCode} מ-<url></url>. אנא ודא שכתובת האתר מפנה לכתובת האתר הבסיסית של האינטגרציה.",
"reason": {
"badRequest": "בקשה שגויה",
"notFound": "לא נמצא",
"tooManyRequests": "בקשות רבות מדי",
"internalServerError": "שגיאת שרת פנימית",
"serviceUnavailable": "השירות אינו זמין",
"gatewayTimeout": "פסק זמן של השער"
}
},
"certificate": {
"title": "שגיאת תעודה",
"description": {
"expired": "פג תוקפה של תעודה זו.",
"notYetValid": "התעודה עדיין אינה בתוקף.",
"untrusted": "התעודה אינה מהימנה.",
"hostnameMismatch": "שם המארח של האישור אינו תואם לכתובת ה-URL."
},
"alert": {
"permission": {
"title": "אין מספיק הרשאות",
"message": "אינך רשאי לתת אמון באישורים או להעלות אותם. אנא צור קשר עם מנהל המערכת שלך כדי להעלות את אישור הבסיס הדרוש."
},
"hostnameMismatch": {
"title": "שם השרת לא תואם",
"message": "שם המארח בתעודה אינו תואם לשם המארח שאליו אתה מתחבר. זה יכול להצביע על סיכון אבטחה, אך עדיין תוכל לבחור לתת אמון בתעודה זו."
},
"extract": {
"title": "חילוץ תעודת CA נכשל",
"message": "ניתן לאחזר באופן אוטומטי רק אישורים חתומים עצמית ללא שרשרת. אם אתם משתמשים באישור חתום עצמית, אנא ודאו שאתם מעלים את אישור רשות האישור באופן ידני. תוכלו למצוא הוראות כיצד לעשות זאת <docsLink></docsLink>."
}
},
"action": {
"retry": {
"label": "נסה ליצור שוב"
},
"trust": {
"label": "תעודה מהימנה"
},
"upload": {
"label": "העלאת תעודת אבטחה"
}
},
"hostnameMismatch": {
"confirm": {
"title": "אי התאמה בשם המארח",
"message": "האם אתה בטוח שאתה רוצה לסמוך על האישור עם אי התאמה בשם המארח?"
},
"notification": {
"success": {
"title": "תעודה מהימנה",
"message": "נוסף שם מארח לרשימת האישורים המהימנים"
},
"error": {
"title": "נכשל בהוספת תעודת אבטחה",
"message": "לא ניתן היה לסמוך על האישור עם אי-התאמה בשם המארח"
}
}
},
"selfSigned": {
"confirm": {
"title": "תעודת אמון חתומה עצמית",
"message": "האם אתה בטוח שאתה רוצה לסמוך על אישור חתום עצמי זה?"
},
"notification": {
"success": {
"title": "תעודה מהימנה",
"message": "נוסף שם מארח לרשימת האישורים המהימנים"
},
"error": {
"title": "נכשל בהוספת תעודת אבטחה",
"message": "נכשל בהוספת האישור לרשימת האישורים המהימנים"
}
}
},
"details": {
"title": "פרטים",
"description": "בדוק את פרטי האישור לפני שתחליט לסמוך עליו.",
"content": {
"action": "הצג תוכן",
"title": "תעודת PEM"
}
}
},
"request": {
"title": "שגיאת בקשה",
"description": {
"connection": {
"hostUnreachable": "לא ניתן היה להגיע לשרת. משמעות הדבר בדרך כלל היא שהמארח לא מקוון או שאינו ניתן להשגה מהרשת שלך.",
"networkUnreachable": "הרשת אינה נגישה. אנא בדוק את חיבור האינטרנט או את תצורת הרשת שלך.",
"refused": "השרת דחה את החיבור. ייתכן שהוא אינו פועל או דוחה בקשות בפורט שצוין.",
"reset": "החיבור נסגר באופן בלתי צפוי על ידי השרת. זה יכול לקרות אם השרת אינו יציב או שהופעל מחדש."
},
"dns": {
"notFound": "לא ניתן היה למצוא את כתובת השרת. אנא בדוק את כתובת ה-URL עבור שגיאות הקלדה או שמות דומיין לא חוקיים.",
"timeout": "בדיקת DNS הסתיימה. ייתכן שמדובר בבעיה זמנית - אנא נסה שוב בעוד מספר רגעים.",
"noAnswer": "שרת ה-DNS לא החזיר תגובה תקפה. ייתכן שהדומיין קיים אך אין לו רשומות תקפות."
},
"timeout": {
"aborted": "הבקשה בוטלה לפני שהספיקה להשלים אותה. ייתכן שהדבר נובע מפעולת משתמש או מפסק זמן של המערכת.",
"timeout": "הבקשה ארכה זמן רב מדי להשלמה ופג תוקפו. בדוק את הרשת שלך או נסה שוב מאוחר יותר."
}
}
}
},
"alertNotice": "הלחצן שמור מופעל לאחר יצירת חיבור מוצלח",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "בטל",
"delete": "מחיקה",
"discard": "ביטול",
"close": "סגור",
"confirm": "לאשר",
"continue": "המשך",
"previous": "הקודם",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "הצג מידע זיכרון"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "הצג מידע על מערכת הקבצים"
},
"defaultTab": {
"label": "כרטיסיית ברירת מחדל"
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": "דרישת מציין מקטע"
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "סטטיסטיקות דוקר",
"description": "סטטיסטיקות של המכולות שלך (ניתן להוסיף ווידג'ט זה רק עם הרשאות מנהל)",
"option": {},
"error": {
"internalServerError": "נכשל באחזור סטטיסטיקות המכולות"
}
},
"common": {
"location": {
"query": "עיר / מיקוד",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": "השתמש במסנן כדי לחשב יחס"
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2059,11 +2204,11 @@
"option": {
"newReleaseWithin": {
"label": "מהדורה חדשה בתוך",
"description": ""
"description": "דוגמת שימוש: שבוע אחד (1), חודש אחד (10 חודשים). סוגי יחידות מקובלים: h (שעות), d (ימים), w (שבועות), M (חודשים), y (שנים). השאר ריק כדי לא להדגיש מהדורות חדשות."
},
"staleReleaseWithin": {
"label": "מהדורה חדשה בתוך",
"description": ""
"description": "דוגמת שימוש: 1w (שבוע אחד), 10M (10 חודשים). סוגי יחידות מקובלים h (שעות), d (ימים), w (שבועות), M (חודשים), y (שנים). השאר ריק כדי לא להדגיש גרסאות ישנות."
},
"showOnlyHighlighted": {
"label": "הצג רק את המודגשים",
@@ -2073,8 +2218,8 @@
"label": "הצג פרטים"
},
"topReleases": {
"label": "",
"description": ""
"label": "מהדורות מובילות",
"description": "המספר המרבי של מהדורות אחרונות להצגה. אפס פירושו שאין הגבלה."
},
"repositories": {
"label": "מאגרים",
@@ -2089,7 +2234,7 @@
"placeholder": "שם או בעלים/שם"
},
"name": {
"label": ""
"label": "שם"
},
"versionFilter": {
"label": "מסנן גירסאות",
@@ -2139,9 +2284,9 @@
"releaseDescription": "תיאור הגרסה",
"created": "נוצר",
"error": {
"label": "",
"label": "שגיאה",
"options": {
"noMatchingVersion": ""
"noMatchingVersion": "לא נמצאה גרסה תואמת"
}
}
},
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": "בקר רשת"
},
"dockerContainers": {
"label": "מכולות דוקר"
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "עודכן ב- {when}",
"search": "חפש {count} קונטיינרים",
"selected": "{selectCount} מ- {totalCount} קונטיינרים נבחרו"
"selected": "{selectCount} מ- {totalCount} קונטיינרים נבחרו",
"footer": "סה״כ {count} קונטיינרים"
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": "מת"
}
},
"stats": {
"cpu": {
"label": "מעבד"
},
"memory": {
"label": "זיכרון"
}
},
"containerImage": {
"label": "קובץ תמונה"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "פעולות",
"start": {
"label": "התחל",
"notification": {
@@ -3496,7 +3654,10 @@
"label": "קבצי לוג"
},
"certificates": {
"label": "אישורי אבטחה"
"label": "אישורי אבטחה",
"hostnames": {
"label": "שמות מארחים"
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": "שם מארח"
},
"subject": {
"label": "נושא"
},
"issuer": {
"label": "מנפיק"
},
"validFrom": {
"label": "בתוקף מ: "
},
"validTo": {
"label": "בתוקף מ: "
},
"serialNumber": {
"label": "מספר סידורי"
},
"fingerprint": {
"label": "טביעת אצבע"
}
},
"page": {
"list": {
"title": "תעודות מהימנות",
@@ -3905,7 +4089,16 @@
"title": "אישור לא חוקי",
"description": "נכשל בהוספת תעודת אבטחה"
},
"expires": "פג ב- {when}"
"expires": "פג ב- {when}",
"toHostnames": "שמות מארחים מאושרים"
},
"hostnames": {
"title": "שמות מארחים של תעודות מהימנות",
"description": "חלק מהאישורים אינם מאפשרים לדומיין הספציפי בו Homarr משתמש לבקש אותם, מסיבה זו כל שמות המארח המהימנים עם טביעות האצבע של האישור שלהם משמשים כדי לעקוף את ההגבלות הללו.",
"noResults": {
"title": "אין עדיין שמות מארחים"
},
"toCertificates": "אישורי אבטחה"
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": "לא היה ניתן להסיר את תעודת האבטחה"
}
}
},
"removeHostname": {
"label": "הסר שם מארח מהימן",
"confirm": "האם אתה בטוח שברצונך להסיר את שם המארח המהימן הזה? זה עלול לגרום לחלק מהאינטגרציות להפסיק לפעול.",
"notification": {
"success": {
"title": "שם המארח הוסר",
"message": "שם המארח הוסר בהצלחה"
},
"error": {
"title": "שם המארח לא הוסר",
"message": "לא היה ניתן להסיר את שם המארח"
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "",
"edit": ""
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Otkaži",
"delete": "Obriši",
"discard": "",
"close": "",
"confirm": "Potvrdi",
"continue": "",
"previous": "Prethodno",
@@ -1630,12 +1757,18 @@
"memory": {
"label": ""
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": ""
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Slika"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Pokreni",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "Tesztelje a kapcsolatot és hozzon létre",
"edit": "Tesztelje a kapcsolatot és mentsen"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "A Mentés gomb a sikeres kapcsolat létrehozása után aktiválódik",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Mégse",
"delete": "Törlés",
"discard": "Elvetés",
"close": "",
"confirm": "Megerősít",
"continue": "Folytatás",
"previous": "Előző",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Memóriainformációk megjelenítése"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Fájlrendszer-információk megjelenítése"
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Kép"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Indítás",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "Prova la connessione e crea",
"edit": "Prova la connessione e salva"
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "Il pulsante Salva è abilitato una volta stabilita una connessione con successo",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Annulla",
"delete": "Elimina",
"discard": "",
"close": "",
"confirm": "Conferma",
"continue": "",
"previous": "Precedente",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "Mostra Informazioni Memoria"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "Mostra Informazioni Filesystem"
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Immagine"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Avvia",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "",
"edit": ""
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "キャンセル",
"delete": "削除",
"discard": "",
"close": "",
"confirm": "確認",
"continue": "次へ",
"previous": "前へ",
@@ -1630,12 +1757,18 @@
"memory": {
"label": "メモリー情報を表示"
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": "ファイルシステム情報を表示"
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "画像"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "開始",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "",
"edit": ""
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "취소",
"delete": "삭제",
"discard": "",
"close": "",
"confirm": "확인",
"continue": "",
"previous": "이전",
@@ -1630,12 +1757,18 @@
"memory": {
"label": ""
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": ""
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "이미지"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "시작",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
+210 -3
View File
@@ -702,6 +702,132 @@
"create": "",
"edit": ""
},
"error": {
"common": {
"cause": {
"title": ""
}
},
"unknown": {
"title": "",
"description": ""
},
"parse": {
"title": "",
"description": ""
},
"authorization": {
"title": "",
"description": ""
},
"statusCode": {
"title": "",
"description": "",
"otherDescription": "",
"reason": {
"badRequest": "",
"notFound": "",
"tooManyRequests": "",
"internalServerError": "",
"serviceUnavailable": "",
"gatewayTimeout": ""
}
},
"certificate": {
"title": "",
"description": {
"expired": "",
"notYetValid": "",
"untrusted": "",
"hostnameMismatch": ""
},
"alert": {
"permission": {
"title": "",
"message": ""
},
"hostnameMismatch": {
"title": "",
"message": ""
},
"extract": {
"title": "",
"message": ""
}
},
"action": {
"retry": {
"label": ""
},
"trust": {
"label": ""
},
"upload": {
"label": ""
}
},
"hostnameMismatch": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"selfSigned": {
"confirm": {
"title": "",
"message": ""
},
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
},
"details": {
"title": "",
"description": "",
"content": {
"action": "",
"title": ""
}
}
},
"request": {
"title": "",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
},
"timeout": {
"aborted": "",
"timeout": ""
}
}
}
},
"alertNotice": "",
"notification": {
"success": {
@@ -878,6 +1004,7 @@
"cancel": "Atšaukti",
"delete": "",
"discard": "",
"close": "",
"confirm": "",
"continue": "",
"previous": "",
@@ -1630,12 +1757,18 @@
"memory": {
"label": ""
},
"showUptime": {
"label": ""
},
"fileSystem": {
"label": ""
},
"defaultTab": {
"label": ""
},
"visibleClusterSections": {
"label": ""
},
"sectionIndicatorRequirement": {
"label": ""
}
@@ -1705,6 +1838,14 @@
}
}
},
"dockerContainers": {
"name": "",
"description": "",
"option": {},
"error": {
"internalServerError": ""
}
},
"common": {
"location": {
"query": "",
@@ -1818,6 +1959,10 @@
},
"applyFilterToRatio": {
"label": ""
},
"limitPerIntegration": {
"label": "",
"description": ""
}
},
"errors": {
@@ -2964,6 +3109,9 @@
},
"networkController": {
"label": ""
},
"dockerContainers": {
"label": ""
}
}
},
@@ -3028,7 +3176,8 @@
"table": {
"updated": "",
"search": "",
"selected": ""
"selected": "",
"footer": ""
},
"field": {
"name": {
@@ -3046,6 +3195,14 @@
"dead": ""
}
},
"stats": {
"cpu": {
"label": ""
},
"memory": {
"label": ""
}
},
"containerImage": {
"label": "Nuotrauka"
},
@@ -3054,6 +3211,7 @@
}
},
"action": {
"title": "",
"start": {
"label": "Paleisti",
"notification": {
@@ -3496,7 +3654,10 @@
"label": ""
},
"certificates": {
"label": ""
"label": "",
"hostnames": {
"label": ""
}
}
},
"settings": {
@@ -3894,6 +4055,29 @@
}
},
"certificate": {
"field": {
"hostname": {
"label": ""
},
"subject": {
"label": ""
},
"issuer": {
"label": ""
},
"validFrom": {
"label": ""
},
"validTo": {
"label": ""
},
"serialNumber": {
"label": ""
},
"fingerprint": {
"label": ""
}
},
"page": {
"list": {
"title": "",
@@ -3905,7 +4089,16 @@
"title": "",
"description": ""
},
"expires": ""
"expires": "",
"toHostnames": ""
},
"hostnames": {
"title": "",
"description": "",
"noResults": {
"title": ""
},
"toCertificates": ""
}
},
"action": {
@@ -3935,6 +4128,20 @@
"message": ""
}
}
},
"removeHostname": {
"label": "",
"confirm": "",
"notification": {
"success": {
"title": "",
"message": ""
},
"error": {
"title": "",
"message": ""
}
}
}
}
}
Loaded 100 of 140 files, more files were not shown because too many files have changed in this diff. Show more