Compare commits

..
Author SHA1 Message Date
Manuel fe9228010c experiment: build as bin 2025-11-19 21:30:18 +01:00
139 changed files with 2263 additions and 2839 deletions

No files matched your search

-3
View File
@@ -33,9 +33,6 @@ body:
options:
# The below comment is used to insert a new version with on-release.yml
#NEXT_VERSION#
- 1.45.1
- 1.45.0
- 1.44.0
- 1.43.1
- 1.43.0
- 1.42.1
@@ -1,43 +0,0 @@
name: Extract Build Artifact
description: Extracts artifacts from an existing Docker image to be used for from source installation
inputs:
digest:
description: Digest of Docker image to use
required: true
architecture:
description: Name of architecture, will be used to create directories (e.g. amd64, arm64)
required: true
release-tag:
description: Tag of the release to which the artifact will be attached
required: true
repository:
description: Repository to which the release belongs, e.g. owner/repo
required: true
token:
description: GitHub token with permissions to upload release assets
required: true
runs:
using: "composite"
steps:
- name: Start docker container for ${{ inputs.architecture }}
run: |
docker run --name homarr \
-e "SECRET_ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000" \
--detach --rm ${{ inputs.digest }}
shell: bash
- name: Extract build from ${{ inputs.architecture }} container
run: |
docker exec homarr cp /etc/nginx/templates/nginx.conf /app && \
docker exec homarr tar -czf extraction.tar.gz -C /app . && \
mkdir -p ${{ runner.temp }}/extraction/${{ inputs.architecture }} && \
docker cp homarr:/app/extraction.tar.gz ${{ runner.temp }}/extraction/${{ inputs.architecture }}/build-${{ inputs.architecture }}.tar.gz
shell: bash
- name: Stop ${{ inputs.architecture }} container
if: always()
run: docker container remove --force --volumes homarr
shell: bash
- name: Add build archive to release
env:
GH_TOKEN: ${{ inputs.token }}
run: gh release upload --repo ${{ inputs.repository }} ${{ inputs.release-tag }} ${{ runner.temp }}/extraction/${{ inputs.architecture }}/build-${{ inputs.architecture }}.tar.gz --clobber
shell: bash
-15
View File
@@ -15,21 +15,6 @@
matchUpdateTypes: ["minor", "patch", "pin", "digest"],
automerge: true,
},
{
// disallow automerge for onlyBuiltDependencies
matchPackageNames: [
"@tree-sitter-grammars/tree-sitter-yaml",
"bcrypt",
"better-sqlite3",
"cpu-features",
"esbuild",
"sharp",
"ssh2",
"tree-sitter",
"tree-sitter-json",
],
automerge: false,
},
],
updateInternalDeps: true,
rangeStrategy: "bump",
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
if: github.actor_id == 158783068 || github.actor_id == 190541745 || github.actor_id == 210161987 # Id of renovate bot and crowdin bot see https://api.github.com/users/homarr-renovate%5Bbot%5D and https://api.github.com/users/homarr-crowdin%5Bbot%5D and https://api.github.com/users/homarr-update-contributors%5Bbot%5D
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Obtain token
id: obtainToken
uses: actions/create-github-app-token@v2
+6 -8
View File
@@ -1,6 +1,4 @@
name: "[Quality] Code Analysis"
permissions:
contents: read
on:
pull_request:
@@ -24,7 +22,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- name: Setup
uses: ./tooling/github/setup
@@ -39,7 +37,7 @@ jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- name: Setup
uses: ./tooling/github/setup
@@ -50,7 +48,7 @@ jobs:
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- name: Setup
uses: ./tooling/github/setup
@@ -61,7 +59,7 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- name: Setup
uses: ./tooling/github/setup
@@ -79,7 +77,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- name: Setup
uses: ./tooling/github/setup
- name: Build docker image
@@ -102,7 +100,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- name: Setup
uses: ./tooling/github/setup
- name: Copy env
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Obtain token
id: obtainToken
+1 -3
View File
@@ -1,6 +1,4 @@
name: "[Crowdin] Upload translations"
permissions:
contents: read
on:
workflow_dispatch:
@@ -17,7 +15,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Upload Crowdin translations
uses: crowdin/github-action@v2
+6 -40
View File
@@ -37,7 +37,7 @@ jobs:
outputs:
version: ${{ steps.read-semver.outputs.version || steps.version-fallback.outputs.version }}
git_ref: ${{ steps.read-git-ref.outputs.ref || github.ref }}
skipped: ${{ env.SKIP_RELEASE }}
steps:
- run: echo "Skipping release for workflow_dispatch event"
if: env.SKIP_RELEASE == 'true'
@@ -55,7 +55,7 @@ jobs:
app-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
permission-contents: write # required to commit package.json & changelog changes, merge them to dev and publish the release
- uses: actions/checkout@v6
- uses: actions/checkout@v5
if: env.SKIP_RELEASE == 'false'
with:
persist-credentials: false
@@ -115,7 +115,7 @@ jobs:
outputs:
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
with:
ref: ${{ needs.release.outputs.git_ref }}
@@ -146,6 +146,7 @@ jobs:
outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true
env:
SKIP_ENV_VALIDATION: true
build-arm64:
name: Build docker image for arm64
needs: release
@@ -153,7 +154,7 @@ jobs:
outputs:
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
with:
ref: ${{ needs.release.outputs.git_ref }}
@@ -184,38 +185,10 @@ jobs:
outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true
env:
SKIP_ENV_VALIDATION: true
extract-asset-amd64:
name: Extract amd64 asset from docker image
needs: [release, build-amd64]
runs-on: ubuntu-latest
steps:
- name: Extract amd64
if: needs.release.outputs.skipped == 'false'
uses: homarr-labs/homarr/.github/actions/extract-build-artifact@dev
with:
digest: "${{ env.GHCR_REPO }}@${{ needs.build-amd64.outputs.digest }}"
architecture: amd64
release-tag: ${{ needs.release.outputs.version }}
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
extract-asset-arm64:
name: Extract arm64 asset from docker image
needs: [release, build-arm64]
runs-on: ubuntu-24.04-arm
steps:
- name: Extract arm64
if: needs.release.outputs.skipped == 'false'
uses: homarr-labs/homarr/.github/actions/extract-build-artifact@dev
with:
digest: "${{ env.GHCR_REPO }}@${{ needs.build-arm64.outputs.digest }}"
architecture: arm64
release-tag: ${{ needs.release.outputs.version }}
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
publish:
name: Complete deployment and notify
needs: [release, build-amd64, build-arm64, extract-asset-amd64, extract-asset-arm64]
needs: [release, build-amd64, build-arm64]
runs-on: ubuntu-latest
env:
NEXT_VERSION: ${{ needs.release.outputs.version }}
@@ -249,13 +222,6 @@ jobs:
${{ env.GHCR_REPO }}@${{ needs.build-amd64.outputs.digest }} \
${{ env.GHCR_REPO }}@${{ needs.build-arm64.outputs.digest }}
- name: Publish release
if: needs.release.outputs.skipped == 'false'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release edit --repo ${{ github.repository }} ${{ needs.release.outputs.version }} --draft=false
- name: Discord notification
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
@@ -27,7 +27,7 @@ jobs:
with:
args: "Automatic release has been triggered: [run ${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Get Next Version
@@ -12,7 +12,7 @@ jobs:
renovate-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: |
npx --yes --package renovate -- \
renovate-config-validator --strict .github/renovate.json5
+1 -1
View File
@@ -49,7 +49,7 @@ jobs:
permission-contents: write # required to commit to branch
permission-pull-requests: write # required to create pr & enable automerge
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v5
with:
token: ${{ steps.obtainToken.outputs.token }}
- name: Setup
+1 -3
View File
@@ -9,8 +9,6 @@ env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
CROWDIN_TOKEN: "${{ secrets.CROWDIN_UPDATE_CONTRIBUTORS_TOKEN }}"
permissions:
contents: read
jobs:
update-contributors:
runs-on: ubuntu-latest
@@ -28,7 +26,7 @@ jobs:
permission-pull-requests: write # required to create pr & enable automerge
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v5
env:
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
@@ -27,7 +27,7 @@ jobs:
permission-contents: write # required to commit to branch
permission-pull-requests: write # required to create pr & enable automerge
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v5
env:
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
- name: Setup
-1
View File
@@ -3,4 +3,3 @@
# @link https://docs.expo.dev/guides/monorepos/#common-issues
node-linker=hoisted
strict-peer-dependencies=false
engine-strict=true
-1
View File
@@ -44,7 +44,6 @@
{
"successComment": false,
"failComment": false,
"draftRelease": true,
"releaseBodyTemplate": "<%= _.truncate(nextRelease.notes, { 'length': 124000, 'omission': '' }) %>"
}
]
-105
View File
@@ -1,108 +1,3 @@
## [1.46.0](https://github.com/homarr-labs/homarr/compare/v1.45.3...v1.46.0) (2025-12-12)
### Features
* **docker:** add widget options to sort containers ([#4636](https://github.com/homarr-labs/homarr/issues/4636)) ([dd24925](https://github.com/homarr-labs/homarr/commit/dd24925d906dc13d73c52a47fdd07bec89798789))
### Bug Fixes
* add autocomplete and id attributes for password manager compatibility ([#4602](https://github.com/homarr-labs/homarr/issues/4602)) ([681aee0](https://github.com/homarr-labs/homarr/commit/681aee05f07a6e09371ed089d2b9ef361494c416))
* **deps:** update dependency @tanstack/react-query to ^5.90.12 ([#4615](https://github.com/homarr-labs/homarr/issues/4615)) ([efc0384](https://github.com/homarr-labs/homarr/commit/efc0384b372fadafb65f61f715f08edd2a8f8573))
* **deps:** update dependency better-sqlite3 to ^12.5.0 ([#4569](https://github.com/homarr-labs/homarr/issues/4569)) ([a20248d](https://github.com/homarr-labs/homarr/commit/a20248d0b689ab1ca475f606edfca458897ce442))
* **deps:** update dependency drizzle-kit to ^0.31.8 ([#4618](https://github.com/homarr-labs/homarr/issues/4618)) ([5cbab28](https://github.com/homarr-labs/homarr/commit/5cbab28099d41b8ade6cc8a42e69c4191310296c))
* **deps:** update dependency drizzle-orm to ^0.45.0 ([#4619](https://github.com/homarr-labs/homarr/issues/4619)) ([cab5d19](https://github.com/homarr-labs/homarr/commit/cab5d19141a38fbb977f4ef6e9c2ddbfdfea6aff))
* **deps:** update dependency ldapts to v8.0.12 ([#4613](https://github.com/homarr-labs/homarr/issues/4613)) ([4689ec9](https://github.com/homarr-labs/homarr/commit/4689ec9933e5286c0d19c66989023b5b3376ffb1))
* **deps:** update dependency ldapts to v8.0.13 ([#4626](https://github.com/homarr-labs/homarr/issues/4626)) ([8a14a6c](https://github.com/homarr-labs/homarr/commit/8a14a6cb456a6f16975372f64451e3b54ebfd88d))
* **deps:** update dependency ldapts to v8.0.14 ([#4627](https://github.com/homarr-labs/homarr/issues/4627)) ([e37325f](https://github.com/homarr-labs/homarr/commit/e37325f5e0314b13d031fba1bff591b881baf8d1))
* **deps:** update dependency winston to v3.19.0 ([#4632](https://github.com/homarr-labs/homarr/issues/4632)) ([3b1c564](https://github.com/homarr-labs/homarr/commit/3b1c564a5abbf1d1fca6ecab46e173c8f6938130))
* **deps:** update next monorepo to v16.0.10 [security] ([#4634](https://github.com/homarr-labs/homarr/issues/4634)) ([2b2c0e7](https://github.com/homarr-labs/homarr/commit/2b2c0e7e3a813525bd977276df6e5594bc283055))
* **deps:** update react monorepo to v19.2.1 ([#4608](https://github.com/homarr-labs/homarr/issues/4608)) ([f6d16fe](https://github.com/homarr-labs/homarr/commit/f6d16fe44bf239fb85a4ee3e9ae6491131315dce))
* **deps:** update tiptap monorepo to v3 (major) ([#3612](https://github.com/homarr-labs/homarr/issues/3612)) ([d111eee](https://github.com/homarr-labs/homarr/commit/d111eee0e0a41e55de87049f3cb0a9154ae82ea1))
* **deps:** update turbo monorepo to ^2.6.2 ([#4612](https://github.com/homarr-labs/homarr/issues/4612)) ([7de45e6](https://github.com/homarr-labs/homarr/commit/7de45e6fe50ccf4333959f924889463a22316984))
* **deps:** update turbo monorepo to ^2.6.3 ([#4622](https://github.com/homarr-labs/homarr/issues/4622)) ([85689ca](https://github.com/homarr-labs/homarr/commit/85689caf6c25b80cb4ce04a0baf2980a1a4deece))
* format issues ([1dd9694](https://github.com/homarr-labs/homarr/commit/1dd9694719ec4dcefe3c8d221015ba9aecede78c))
* improve run script ([#4609](https://github.com/homarr-labs/homarr/issues/4609)) ([d084dfb](https://github.com/homarr-labs/homarr/commit/d084dfb4705fca68bb9f9465ec9564050d0b04b2))
* **plex:** test connection not fully checking connection ([#4617](https://github.com/homarr-labs/homarr/issues/4617)) ([6a90839](https://github.com/homarr-labs/homarr/commit/6a908397cd8a6189123b91ea9d68f683af2bed05))
* **transmission:** total download incorrect for cross seeded torrents ([#3211](https://github.com/homarr-labs/homarr/issues/3211)) ([0b4ca93](https://github.com/homarr-labs/homarr/commit/0b4ca93aa13e9838b481daed5703640d30a52ffc))
## [1.45.3](https://github.com/homarr-labs/homarr/compare/v1.45.2...v1.45.3) (2025-12-08)
### Bug Fixes
* **deps:** update dependency glob to v13 ([#4584](https://github.com/homarr-labs/homarr/issues/4584)) ([020cbd7](https://github.com/homarr-labs/homarr/commit/020cbd72d387c9f50f4eddcbc2685829cf7787de))
* **deps:** update dependency jotai to ^2.15.2 ([#4597](https://github.com/homarr-labs/homarr/issues/4597)) ([ed638d4](https://github.com/homarr-labs/homarr/commit/ed638d47679594eab3cc19a12473722644ebf694))
* **deps:** update dependency next-intl to v4.5.7 ([#4598](https://github.com/homarr-labs/homarr/issues/4598)) ([6b28aa8](https://github.com/homarr-labs/homarr/commit/6b28aa86d0bad29e4806592079a7f5d2e22b5ade))
* **deps:** update dependency next-intl to v4.5.8 ([#4606](https://github.com/homarr-labs/homarr/issues/4606)) ([4f92e52](https://github.com/homarr-labs/homarr/commit/4f92e5265a40c636f303406e728e88cc056da23c))
* **deps:** update dependency prettier to ^3.7.4 ([#4582](https://github.com/homarr-labs/homarr/issues/4582)) ([5480982](https://github.com/homarr-labs/homarr/commit/54809823e9edeacc245b560747b622aba683b3bf))
* **deps:** update dependency typescript-eslint to ^8.48.1 ([#4438](https://github.com/homarr-labs/homarr/issues/4438)) ([d88c602](https://github.com/homarr-labs/homarr/commit/d88c6027fe3accf7a6872ada8aa2724d30bf691c))
## [1.45.2](https://github.com/homarr-labs/homarr/compare/v1.45.1...v1.45.2) (2025-12-05)
### Bug Fixes
* add ipv6 support for internal nginx proxy ([2c48b18](https://github.com/homarr-labs/homarr/commit/2c48b18968a74cb7150c246ebb2505d07764f109))
* disable react-compiler due to issue with mantine-react-table data updates ([#4593](https://github.com/homarr-labs/homarr/issues/4593)) ([10572ca](https://github.com/homarr-labs/homarr/commit/10572ca962081961fb63b3ad9f164c610edf35e4))
## [1.45.1](https://github.com/homarr-labs/homarr/compare/v1.45.0...v1.45.1) (2025-12-03)
### Bug Fixes
* **deps:** update dependency chroma-js to ^3.1.4 ([#4570](https://github.com/homarr-labs/homarr/issues/4570)) ([d6fc46d](https://github.com/homarr-labs/homarr/commit/d6fc46df3b5e2dd79ff6f9a3dd3a3e2050a0eeef))
* **deps:** update dependency chroma-js to ^3.2.0 ([#4585](https://github.com/homarr-labs/homarr/issues/4585)) ([b2c46d3](https://github.com/homarr-labs/homarr/commit/b2c46d33d6cc769e89e208fd29d3a1d143cf74c7))
* **deps:** update dependency isomorphic-dompurify to ^2.33.0 ([#4581](https://github.com/homarr-labs/homarr/issues/4581)) ([ca01a31](https://github.com/homarr-labs/homarr/commit/ca01a31fe5cbce53eb0e6bd1a943320c092161ef))
* **deps:** update dependency next-intl to v4.5.6 ([#4571](https://github.com/homarr-labs/homarr/issues/4571)) ([3062dda](https://github.com/homarr-labs/homarr/commit/3062ddafbe0bc1dbac9259af4036f0fa32d85237))
* **deps:** update dependency sass to ^1.94.2 ([#4572](https://github.com/homarr-labs/homarr/issues/4572)) ([7a8c50f](https://github.com/homarr-labs/homarr/commit/7a8c50fa4c5224dd74af3c17f56e2e5b8d6a4f43))
* **deps:** update dependency superjson to v2.2.6 ([#4573](https://github.com/homarr-labs/homarr/issues/4573)) ([deb5e9d](https://github.com/homarr-labs/homarr/commit/deb5e9d96092069e296ba473eaad58367b516f85))
* **deps:** update dependency swagger-ui-react to ^5.30.3 ([#4574](https://github.com/homarr-labs/homarr/issues/4574)) ([d2c1dc3](https://github.com/homarr-labs/homarr/commit/d2c1dc3cc1dd72fc9fc8ae9613467fa0b0b8d75a))
* **deps:** update dependency zod to ^4.1.13 ([#4575](https://github.com/homarr-labs/homarr/issues/4575)) ([879a77f](https://github.com/homarr-labs/homarr/commit/879a77ff2a81b0d0a17d1487eaf6d8539a955301))
* **deps:** update mantine monorepo to ^8.3.9 ([#4576](https://github.com/homarr-labs/homarr/issues/4576)) ([d5d59dd](https://github.com/homarr-labs/homarr/commit/d5d59dd2561f0be2f4f4c689f33c6a9a7840a21c))
* **deps:** update nextjs monorepo to v16.0.5 ([#4577](https://github.com/homarr-labs/homarr/issues/4577)) ([16f12d9](https://github.com/homarr-labs/homarr/commit/16f12d98e6cdae50fe2989db0911cb1350fcb93b))
* **deps:** update tanstack-query monorepo ([#4578](https://github.com/homarr-labs/homarr/issues/4578)) ([59bcbc8](https://github.com/homarr-labs/homarr/commit/59bcbc8b4de4a0a8cee8adf6336c7c10477c766a))
* **deps:** update testcontainers-node monorepo to ^11.9.0 ([#4583](https://github.com/homarr-labs/homarr/issues/4583)) ([10bdd74](https://github.com/homarr-labs/homarr/commit/10bdd74b2b287cb08ec0926147ac0e7fcfd492bb))
* **deps:** update trpc monorepo to ^11.7.2 ([#4579](https://github.com/homarr-labs/homarr/issues/4579)) ([3453482](https://github.com/homarr-labs/homarr/commit/3453482ed43644025c39dee8e20549e1beb86be0))
* **security:** rce vulnerability in nextjs ([b40deba](https://github.com/homarr-labs/homarr/commit/b40deba9ff1a3d629b6027565378d9f3ad2f1980))
## [1.45.0](https://github.com/homarr-labs/homarr/compare/v1.44.0...v1.45.0) (2025-11-28)
### Features
* **docker:** hide containers with label homarr.hide ([#4506](https://github.com/homarr-labs/homarr/issues/4506)) ([60ab98a](https://github.com/homarr-labs/homarr/commit/60ab98ae36abe712c825f7828394d3e3e98c888a))
### Bug Fixes
* Add fallback when no icon in Minecraft Server widget ([#4544](https://github.com/homarr-labs/homarr/issues/4544)) ([#4545](https://github.com/homarr-labs/homarr/issues/4545)) ([99949fe](https://github.com/homarr-labs/homarr/commit/99949fe095ac5a3616c8e9c1964d7eb253c9f826))
* **deps:** update dependency @tanstack/react-query to ^5.90.10 ([#4523](https://github.com/homarr-labs/homarr/issues/4523)) ([e87170a](https://github.com/homarr-labs/homarr/commit/e87170ae6e56cdbeef52e943353060329c39bdc9))
* **deps:** update dependency glob to ^11.1.0 ([#4529](https://github.com/homarr-labs/homarr/issues/4529)) ([24c9854](https://github.com/homarr-labs/homarr/commit/24c985424ecc795eb96b56881a9b00c0c37386c1))
* **deps:** update dependency glob to v12 ([#4530](https://github.com/homarr-labs/homarr/issues/4530)) ([18a6bfd](https://github.com/homarr-labs/homarr/commit/18a6bfd69d86de8c58dbfe6dc8b8fab78b2b5ee6))
* **deps:** update dependency next-intl to v4.5.4 ([#4540](https://github.com/homarr-labs/homarr/issues/4540)) ([77a86ea](https://github.com/homarr-labs/homarr/commit/77a86ead41c0d098987561249203667ac4d88177))
* **deps:** update dependency next-intl to v4.5.5 ([#4542](https://github.com/homarr-labs/homarr/issues/4542)) ([2bc6964](https://github.com/homarr-labs/homarr/commit/2bc6964f7efb5203f626d2f07b847dffd53191f0))
* **deps:** update dependency sass to ^1.94.1 ([#4531](https://github.com/homarr-labs/homarr/issues/4531)) ([292e36f](https://github.com/homarr-labs/homarr/commit/292e36fec5acff9b1d143f19e18ea170c87fa0d0))
* **deps:** update dependency zod-validation-error to v5 ([#4437](https://github.com/homarr-labs/homarr/issues/4437)) ([9a3feb4](https://github.com/homarr-labs/homarr/commit/9a3feb404c0c284b4f33fce12d87a469741a6ebd))
* **security:** restrict modification of entrypoint script ([#4555](https://github.com/homarr-labs/homarr/issues/4555)) ([524e1a4](https://github.com/homarr-labs/homarr/commit/524e1a485be56dbebf8f71d4546bc65672737f30))
## [1.44.0](https://github.com/homarr-labs/homarr/compare/v1.43.3...v1.44.0) (2025-11-21)
### Features
* **pi-hole:** support no-auth ([#4480](https://github.com/homarr-labs/homarr/issues/4480)) ([c89e35e](https://github.com/homarr-labs/homarr/commit/c89e35e13c794bbdf98748c00644b86f7f5dbe68))
### Bug Fixes
* **deps:** update dependency @tanstack/react-query to ^5.90.8 ([#4494](https://github.com/homarr-labs/homarr/issues/4494)) ([a5b6203](https://github.com/homarr-labs/homarr/commit/a5b6203be6ac3c2308614f10ef6a17590917e2c9))
* **deps:** update dependency @tanstack/react-query to ^5.90.9 ([#4508](https://github.com/homarr-labs/homarr/issues/4508)) ([b3db5d5](https://github.com/homarr-labs/homarr/commit/b3db5d5f7bc2d146f0b2c230a52e7bd4efad3bcb))
* **deps:** update dependency @tanstack/react-query-next-experimental to ^5.91.0 ([#4505](https://github.com/homarr-labs/homarr/issues/4505)) ([8ea6cff](https://github.com/homarr-labs/homarr/commit/8ea6cffb537ca54a413c583ab8b8fd24a52185be))
* **deps:** update dependency drizzle-kit to ^0.31.7 ([#4507](https://github.com/homarr-labs/homarr/issues/4507)) ([b4f9fb8](https://github.com/homarr-labs/homarr/commit/b4f9fb8b46a8f74e2d7896dfe98e80618cfbcde4))
* **deps:** update dependency fast-xml-parser to ^5.3.2 ([#4510](https://github.com/homarr-labs/homarr/issues/4510)) ([5e57a49](https://github.com/homarr-labs/homarr/commit/5e57a4906bcedc53d220e983827293f4a699c425))
* **deps:** update dependency next-intl to v4.5.1 ([#4484](https://github.com/homarr-labs/homarr/issues/4484)) ([06942ec](https://github.com/homarr-labs/homarr/commit/06942ecbcd245f5540f2960f437ca2955a5ed0c3))
* **deps:** update dependency next-intl to v4.5.3 ([#4503](https://github.com/homarr-labs/homarr/issues/4503)) ([0642773](https://github.com/homarr-labs/homarr/commit/064277373cacd3309d8da3779d5451d195da7f81))
* **deps:** update dependency sass to ^1.94.0 ([#4482](https://github.com/homarr-labs/homarr/issues/4482)) ([19ecede](https://github.com/homarr-labs/homarr/commit/19ecedea4370924d47545ca8d9d46a0b7c016cc9))
* **deps:** update mantine monorepo to ^8.3.8 ([#4516](https://github.com/homarr-labs/homarr/issues/4516)) ([ded4e72](https://github.com/homarr-labs/homarr/commit/ded4e72e5407b0076495a06111f3b04445f27276))
* **deps:** update nextjs monorepo to v16.0.3 ([#4504](https://github.com/homarr-labs/homarr/issues/4504)) ([7d0c1a1](https://github.com/homarr-labs/homarr/commit/7d0c1a14fdf1731ff44e3d00793cf4cd1c3e9b1f))
* **deps:** update testcontainers-node monorepo to ^11.8.1 ([#4486](https://github.com/homarr-labs/homarr/issues/4486)) ([64657d8](https://github.com/homarr-labs/homarr/commit/64657d831cbe28a59708b280b07889b9f0232743))
* **deps:** update turbo monorepo to ^2.6.1 ([#4483](https://github.com/homarr-labs/homarr/issues/4483)) ([cd124d6](https://github.com/homarr-labs/homarr/commit/cd124d6e8392eef5df0092481ec3cc26599f2902))
* **iframe:** allow clicking links within ([#4521](https://github.com/homarr-labs/homarr/issues/4521)) ([5a418d7](https://github.com/homarr-labs/homarr/commit/5a418d73bdb07cf3d3270983b6881f2de8d58ad7))
* **media-requests:** incorrect availability mapping ([#4520](https://github.com/homarr-labs/homarr/issues/4520)) ([d9cc35b](https://github.com/homarr-labs/homarr/commit/d9cc35b9859a14f44c4e4b13c6518287f8d18e54))
## [1.43.3](https://github.com/homarr-labs/homarr/compare/v1.43.2...v1.43.3) (2025-11-14)
### Bug Fixes
+2 -2
View File
@@ -1,4 +1,4 @@
FROM node:24.11.1-alpine AS base
FROM node:24.11.0-alpine AS base
FROM base AS builder
RUN apk add --no-cache libc6-compat
@@ -55,7 +55,7 @@ COPY --from=builder /app/apps/nextjs/.next/standalone ./
COPY --from=builder /app/apps/nextjs/.next/static ./apps/nextjs/.next/static
COPY --from=builder /app/apps/nextjs/public ./apps/nextjs/public
COPY scripts/run.sh ./run.sh
COPY --chmod=755 scripts/entrypoint.sh ./entrypoint.sh
COPY --chmod=777 scripts/entrypoint.sh ./entrypoint.sh
COPY packages/redis/redis.conf /app/redis.conf
COPY nginx.conf /etc/nginx/templates/nginx.conf
+1 -2
View File
@@ -20,8 +20,7 @@ const withNextIntl = createNextIntlPlugin({
const nextConfig: NextConfig = {
output: "standalone",
reactStrictMode: true,
// react compiler breaks mantine-react-table, so disabled for now
//reactCompiler: true,
reactCompiler: true,
/** We already do typechecking as separate tasks in CI */
typescript: { ignoreBuildErrors: true },
/**
+25 -25
View File
@@ -50,46 +50,46 @@
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@homarr/widgets": "workspace:^0.1.0",
"@mantine/colors-generator": "^8.3.9",
"@mantine/core": "^8.3.9",
"@mantine/dropzone": "^8.3.9",
"@mantine/hooks": "^8.3.9",
"@mantine/modals": "^8.3.9",
"@mantine/tiptap": "^8.3.9",
"@mantine/colors-generator": "^8.3.7",
"@mantine/core": "^8.3.7",
"@mantine/dropzone": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"@mantine/modals": "^8.3.7",
"@mantine/tiptap": "^8.3.7",
"@million/lint": "1.0.14",
"@tabler/icons-react": "^3.35.0",
"@tanstack/react-query": "^5.90.12",
"@tanstack/react-query-devtools": "^5.91.1",
"@tanstack/react-query": "^5.90.9",
"@tanstack/react-query-devtools": "^5.90.2",
"@tanstack/react-query-next-experimental": "^5.91.0",
"@trpc/client": "^11.7.2",
"@trpc/next": "^11.7.2",
"@trpc/react-query": "^11.7.2",
"@trpc/server": "^11.7.2",
"@trpc/client": "^11.7.1",
"@trpc/next": "^11.7.1",
"@trpc/react-query": "^11.7.1",
"@trpc/server": "^11.7.1",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "0.10.0",
"@xterm/xterm": "^5.5.0",
"babel-plugin-react-compiler": "^1.0.0",
"chroma-js": "^3.2.0",
"chroma-js": "^3.1.2",
"clsx": "^2.1.1",
"dayjs": "^1.11.19",
"dotenv": "^17.2.3",
"flag-icons": "^7.5.0",
"glob": "^13.0.0",
"isomorphic-dompurify": "^2.33.0",
"jotai": "^2.15.2",
"glob": "^11.0.3",
"isomorphic-dompurify": "^2.32.0",
"jotai": "^2.15.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.0.10",
"next": "16.0.3",
"postcss-preset-mantine": "^1.18.0",
"prismjs": "^1.30.0",
"react": "19.2.1",
"react-dom": "19.2.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-error-boundary": "^6.0.0",
"react-simple-code-editor": "^0.14.1",
"sass": "^1.94.2",
"superjson": "2.2.6",
"swagger-ui-react": "^5.30.3",
"sass": "^1.94.0",
"superjson": "2.2.5",
"swagger-ui-react": "^5.30.2",
"use-deep-compare-effect": "^1.8.1",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -98,13 +98,13 @@
"@types/chroma-js": "3.1.2",
"@types/node": "^24.10.1",
"@types/prismjs": "^1.26.5",
"@types/react": "19.2.7",
"@types/react": "19.2.4",
"@types/react-dom": "19.2.3",
"@types/swagger-ui-react": "^5.18.0",
"concurrently": "^9.2.1",
"eslint": "^9.39.1",
"node-loader": "^2.1.0",
"prettier": "^3.7.4",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
}
}
@@ -64,23 +64,16 @@ export const RegistrationForm = ({ invite }: RegistrationFormProps) => {
<Stack gap="xl">
<form onSubmit={form.onSubmit(handleSubmit)}>
<Stack gap="lg">
<TextInput
label={t("field.username.label")}
id="username"
autoComplete="username"
{...form.getInputProps("username")}
/>
<TextInput label={t("field.username.label")} autoComplete="off" {...form.getInputProps("username")} />
<CustomPasswordInput
withPasswordRequirements
label={t("field.password.label")}
id="password"
autoComplete="new-password"
{...form.getInputProps("password")}
/>
<PasswordInput
label={t("field.passwordConfirm.label")}
id="password-confirm"
autoComplete="new-password"
{...form.getInputProps("confirmPassword")}
/>
@@ -116,18 +116,8 @@ export const LoginForm = ({ providers, oidcClientName, isOidcAutoLoginEnabled, c
<>
<form onSubmit={form.onSubmit((credentials) => void signInAsync(credentials.provider, credentials))}>
<Stack gap="lg">
<TextInput
label={t("field.username.label")}
id="username"
autoComplete="username"
{...form.getInputProps("name")}
/>
<PasswordInput
label={t("field.password.label")}
id="password"
autoComplete="current-password"
{...form.getInputProps("password")}
/>
<TextInput label={t("field.username.label")} {...form.getInputProps("name")} />
<PasswordInput label={t("field.password.label")} {...form.getInputProps("password")} />
{providers.includes("credentials") && (
<Stack gap="sm">
@@ -12,11 +12,7 @@ import { groupCreateSchema } from "@homarr/validation/group";
export const InitGroup = () => {
const t = useI18n();
const { mutateAsync } = clientApi.group.createInitialExternalGroup.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/init");
},
});
const { mutateAsync } = clientApi.group.createInitialExternalGroup.useMutation();
const form = useZodForm(groupCreateSchema, {
initialValues: {
name: "",
@@ -25,6 +21,9 @@ export const InitGroup = () => {
const handleSubmitAsync = async (values: z.infer<typeof groupCreateSchema>) => {
await mutateAsync(values, {
async onSuccess() {
await revalidatePathActionAsync("/init");
},
onError(error) {
if (error.data?.code === "CONFLICT") {
form.setErrors({ name: t("common.zod.errors.custom.groupNameTaken") });
@@ -17,11 +17,7 @@ import { settingsInitSchema } from "@homarr/validation/settings";
export const InitSettings = () => {
const tSection = useScopedI18n("management.page.settings.section");
const t = useI18n();
const { mutateAsync } = clientApi.serverSettings.initSettings.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/init");
},
});
const { mutateAsync } = clientApi.serverSettings.initSettings.useMutation();
const form = useZodForm(settingsInitSchema, { initialValues: defaultServerSettings });
form.watch("analytics.enableGeneral", ({ value }) => {
@@ -35,7 +31,11 @@ export const InitSettings = () => {
});
const handleSubmitAsync = async (values: z.infer<typeof settingsInitSchema>) => {
await mutateAsync(values);
await mutateAsync(values, {
async onSuccess() {
await revalidatePathActionAsync("/init");
},
});
};
return (
@@ -26,19 +26,19 @@ export const InitUserForm = () => {
const handleSubmitAsync = async (values: FormType) => {
await mutateAsync(values, {
onSuccess() {
async onSuccess() {
showSuccessNotification({
title: tUser("notification.success.title"),
message: tUser("notification.success.message"),
});
void signIn("credentials", {
await signIn("credentials", {
name: values.username,
password: values.password,
redirect: false,
}).then(async () => {
await revalidatePathActionAsync("/init");
});
await revalidatePathActionAsync("/init");
},
onError: (error) => {
showErrorNotification({
@@ -84,6 +84,9 @@ export const BoardCardMenuDropdown = ({ board }: BoardCardMenuDropdownProps) =>
id: board.id,
name: board.name,
},
onSuccess: async () => {
await revalidatePathActionAsync("/manage/boards");
},
});
}, [board.id, board.name, openDuplicateModal]);
@@ -86,11 +86,7 @@ export const NewIntegrationForm = ({ searchParams }: NewIntegrationFormProps) =>
},
});
const { mutateAsync: createIntegrationAsync, isPending } = clientApi.integration.create.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/manage/integrations");
},
});
const { mutateAsync: createIntegrationAsync, isPending } = clientApi.integration.create.useMutation();
const [error, setError] = useState<null | AnyMappedTestConnectionError>(null);
const handleSubmitAsync = async ({ appId, appHref, hasApp, ...values }: FormType) => {
@@ -120,7 +116,7 @@ export const NewIntegrationForm = ({ searchParams }: NewIntegrationFormProps) =>
app,
},
{
onSuccess(data) {
async onSuccess(data) {
// We do it this way as we are unable to send a typesafe error through onError
if (data?.error) {
setError(data.error);
@@ -136,7 +132,7 @@ export const NewIntegrationForm = ({ searchParams }: NewIntegrationFormProps) =>
message: t("integration.page.create.notification.success.message"),
});
router.push("/manage/integrations");
await revalidatePathActionAsync("/manage/integrations").then(() => router.push("/manage/integrations"));
},
onError: () => {
showErrorNotification({
@@ -15,11 +15,7 @@ interface RemoveCertificateProps {
export const RemoveCertificate = ({ fileName }: RemoveCertificateProps) => {
const { openConfirmModal } = useConfirmModal();
const { mutateAsync } = clientApi.certificates.removeCertificate.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/manage/tools/certificates");
},
});
const { mutateAsync } = clientApi.certificates.removeCertificate.useMutation();
const t = useI18n();
const handleClick = () => {
@@ -31,11 +27,12 @@ export const RemoveCertificate = ({ fileName }: RemoveCertificateProps) => {
await mutateAsync(
{ fileName },
{
onSuccess() {
async onSuccess() {
showSuccessNotification({
title: t("certificate.action.remove.notification.success.title"),
message: t("certificate.action.remove.notification.success.message"),
});
await revalidatePathActionAsync("/manage/tools/certificates");
},
onError() {
showErrorNotification({
@@ -15,11 +15,7 @@ interface RemoveHostnameActionIconProps {
}
export const RemoveHostnameActionIcon = (input: RemoveHostnameActionIconProps) => {
const { mutateAsync } = clientApi.certificates.removeTrustedHostname.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/manage/tools/certificates/hostnames");
},
});
const { mutateAsync } = clientApi.certificates.removeTrustedHostname.useMutation();
const { openConfirmModal } = useConfirmModal();
const t = useI18n();
@@ -30,7 +26,8 @@ export const RemoveHostnameActionIcon = (input: RemoveHostnameActionIconProps) =
// eslint-disable-next-line no-restricted-syntax
async onConfirm() {
await mutateAsync(input, {
onSuccess() {
async onSuccess() {
await revalidatePathActionAsync("/manage/tools/certificates/hostnames");
showSuccessNotification({
title: t("certificate.action.removeHostname.notification.success.title"),
message: t("certificate.action.removeHostname.notification.success.message"),
@@ -206,16 +206,15 @@ const ContainerActionBarButton = (props: ContainerActionBarButtonProps) => {
const t = useScopedI18n("docker.action");
const utils = clientApi.useUtils();
const { mutateAsync, isPending } = clientApi.docker[`${props.action}All`].useMutation({
async onSettled() {
await utils.docker.getContainers.invalidate();
},
});
const { mutateAsync, isPending } = clientApi.docker[`${props.action}All`].useMutation();
const handleClickAsync = async () => {
await mutateAsync(
{ ids: props.selectedIds },
{
async onSettled() {
await utils.docker.getContainers.invalidate();
},
onSuccess() {
showSuccessNotification({
title: t(`${props.action}.notification.success.title`),
@@ -18,12 +18,7 @@ interface UserProfileAvatarForm {
}
export const UserProfileAvatarForm = ({ user }: UserProfileAvatarForm) => {
const { mutate } = clientApi.user.setProfileImage.useMutation({
async onSuccess() {
// Revalidate all as the avatar is used in multiple places
await revalidatePathActionAsync("/");
},
});
const { mutate } = clientApi.user.setProfileImage.useMutation();
const [opened, { toggle }] = useDisclosure(false);
const { openConfirmModal } = useConfirmModal();
const t = useI18n();
@@ -43,7 +38,9 @@ export const UserProfileAvatarForm = ({ user }: UserProfileAvatarForm) => {
image: base64Url,
},
{
onSuccess() {
async onSuccess() {
// Revalidate all as the avatar is used in multiple places
await revalidatePathActionAsync("/");
showSuccessNotification({
message: tManageAvatar("changeImage.notification.success.message"),
});
@@ -77,7 +74,9 @@ export const UserProfileAvatarForm = ({ user }: UserProfileAvatarForm) => {
image: null,
},
{
onSuccess() {
async onSuccess() {
// Revalidate all as the avatar is used in multiple places
await revalidatePathActionAsync("/");
showSuccessNotification({
message: tManageAvatar("removeImage.notification.success.message"),
});
@@ -25,11 +25,7 @@ export const TransferGroupOwnership = ({ group }: TransferGroupOwnershipProps) =
const [innerOwnerId, setInnerOwnerId] = useState(group.ownerId);
const { openModal } = useModalAction(UserSelectModal);
const { openConfirmModal } = useConfirmModal();
const { mutateAsync } = clientApi.group.transferOwnership.useMutation({
async onSuccess() {
await revalidatePathActionAsync(`/manage/users/groups/${group.id}`);
},
});
const { mutateAsync } = clientApi.group.transferOwnership.useMutation();
const handleTransfer = useCallback(() => {
openModal(
@@ -51,7 +47,7 @@ export const TransferGroupOwnership = ({ group }: TransferGroupOwnershipProps) =
userId: id,
},
{
onSuccess() {
async onSuccess() {
setInnerOwnerId(id);
showSuccessNotification({
title: tRoot("common.notification.transfer.success"),
@@ -60,6 +56,7 @@ export const TransferGroupOwnership = ({ group }: TransferGroupOwnershipProps) =
user: name,
}),
});
await revalidatePathActionAsync(`/manage/users/groups/${group.id}`);
},
onError() {
showErrorNotification({
@@ -56,19 +56,16 @@ export const GroupsTable = ({ groups, initialGroupIds, hasFilter }: GroupsTableP
() => initialGroupIds.some((groupId, index) => groupIds.indexOf(groupId) !== index),
[groupIds, initialGroupIds],
);
const { mutateAsync, isPending } = clientApi.group.savePositions.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/manage/users/groups");
},
});
const { mutateAsync, isPending } = clientApi.group.savePositions.useMutation();
const handleSavePositionsAsync = async () => {
await mutateAsync(
{ positions: groupIds },
{
onSuccess() {
async onSuccess() {
showSuccessNotification({
message: t("group.action.changePosition.notification.success.message"),
});
await revalidatePathActionAsync("/manage/users/groups");
},
onError() {
showSuccessNotification({
+3 -3
View File
@@ -40,7 +40,7 @@
"dayjs": "^1.11.19",
"dotenv": "^17.2.3",
"fastify": "^5.6.2",
"superjson": "2.2.6",
"superjson": "2.2.5",
"undici": "7.16.0"
},
"devDependencies": {
@@ -49,9 +49,9 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^24.10.1",
"dotenv-cli": "^11.0.0",
"esbuild": "^0.27.1",
"esbuild": "^0.27.0",
"eslint": "^9.39.1",
"prettier": "^3.7.4",
"prettier": "^3.6.2",
"tsx": "4.20.4",
"typescript": "^5.9.3"
}
+2 -2
View File
@@ -34,9 +34,9 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.18.1",
"esbuild": "^0.27.1",
"esbuild": "^0.27.0",
"eslint": "^9.39.1",
"prettier": "^3.7.4",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
}
}
+1 -2
View File
@@ -5,7 +5,6 @@ events {
http {
server {
listen 7575;
listen [::]:7575;
# Route websockets traffic to port 3001
location /websockets {
@@ -26,4 +25,4 @@ http {
client_max_body_size 32M;
}
}
}
}
+25 -20
View File
@@ -1,6 +1,6 @@
{
"name": "homarr",
"version": "1.46.0",
"version": "1.43.3",
"private": true,
"scripts": {
"build": "cross-env CI=true turbo build",
@@ -40,29 +40,27 @@
"@semantic-release/commit-analyzer": "^13.0.1",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^12.0.2",
"@semantic-release/npm": "^13.1.2",
"@semantic-release/npm": "^13.1.1",
"@semantic-release/release-notes-generator": "^14.1.0",
"@testcontainers/redis": "^11.9.0",
"@turbo/gen": "^2.6.3",
"@testcontainers/redis": "^11.8.1",
"@turbo/gen": "^2.6.1",
"@vitejs/plugin-react": "^5.1.1",
"@vitest/coverage-v8": "^4.0.15",
"@vitest/ui": "^4.0.15",
"@vitest/coverage-v8": "^4.0.8",
"@vitest/ui": "^4.0.8",
"conventional-changelog-conventionalcommits": "^9.1.0",
"cross-env": "^10.1.0",
"jsdom": "^27.2.0",
"json5": "^2.2.3",
"prettier": "^3.7.4",
"prettier": "^3.6.2",
"semantic-release": "^25.0.2",
"testcontainers": "^11.9.0",
"turbo": "^2.6.3",
"testcontainers": "^11.8.1",
"turbo": "^2.6.1",
"typescript": "^5.9.3",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^4.0.15"
"vitest": "^4.0.8"
},
"packageManager": "pnpm@10.24.0",
"packageManager": "pnpm@10.22.0",
"engines": {
"node": ">=24.11.1",
"pnpm": ">=10.24.0"
"node": ">=24.11.1"
},
"pnpm": {
"onlyBuiltDependencies": [
@@ -82,20 +80,20 @@
"axios@>=1.0.0 <1.8.2": ">=1.13.2",
"brace-expansion@>=2.0.0 <=2.0.1": ">=4.0.1",
"brace-expansion@>=1.0.0 <=1.1.11": ">=4.0.1",
"esbuild@<=0.24.2": ">=0.27.1",
"form-data@>=4.0.0 <4.0.4": ">=4.0.5",
"hono@<4.6.5": ">=4.10.7",
"esbuild@<=0.24.2": ">=0.27.0",
"form-data@>=4.0.0 <4.0.4": ">=4.0.4",
"hono@<4.6.5": ">=4.10.5",
"linkifyjs@<4.3.2": ">=4.3.2",
"nanoid@>=4.0.0 <5.0.9": ">=5.1.6",
"prismjs@<1.30.0": ">=1.30.0",
"proxmox-api>undici": "7.16.0",
"react-is": "^19.2.1",
"rollup@>=4.0.0 <4.22.4": ">=4.53.3",
"react-is": "^19.2.0",
"rollup@>=4.0.0 <4.22.4": ">=4.53.2",
"sha.js@<=2.4.11": ">=2.4.12",
"tar-fs@>=3.0.0 <3.0.9": ">=3.1.1",
"tar-fs@>=2.0.0 <2.1.3": ">=3.1.1",
"tmp@<=0.2.3": ">=0.2.5",
"vite@>=5.0.0 <=5.4.18": ">=7.2.6"
"vite@>=5.0.0 <=5.4.18": ">=7.2.2"
},
"patchedDependencies": {
"@types/node-unifi": "patches/@types__node-unifi.patch",
@@ -107,5 +105,12 @@
"core-js-pure",
"protobufjs"
]
},
"bin": "apps/tasks/tasks.cjs",
"pkg": {
"scripts": ["apps/tasks/tasks.cjs", "apps/websocket/wssServer.cjs", "apps/nextjs/server.js"],
"assets": ["apps/nextjs/public/**/*"],
"targets": ["latest-linux-x64"],
"outputPath": "dist-pkg"
}
}
+1 -1
View File
@@ -26,7 +26,7 @@
"@homarr/log": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@umami/node": "^0.4.0",
"superjson": "2.2.6"
"superjson": "2.2.5"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+11 -11
View File
@@ -43,25 +43,25 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@kubernetes/client-node": "^1.4.0",
"@tanstack/react-query": "^5.90.12",
"@trpc/client": "^11.7.2",
"@trpc/react-query": "^11.7.2",
"@trpc/server": "^11.7.2",
"@trpc/tanstack-react-query": "^11.7.2",
"@tanstack/react-query": "^5.90.9",
"@trpc/client": "^11.7.1",
"@trpc/react-query": "^11.7.1",
"@trpc/server": "^11.7.1",
"@trpc/tanstack-react-query": "^11.7.1",
"lodash.clonedeep": "^4.5.0",
"next": "16.0.10",
"react": "19.2.1",
"react-dom": "19.2.1",
"superjson": "2.2.6",
"next": "16.0.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"superjson": "2.2.5",
"trpc-to-openapi": "^3.1.0",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.39.1",
"prettier": "^3.7.4",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
}
}
@@ -3,7 +3,6 @@ import { z } from "zod/v4";
import { getIntegrationKindsByCategory } from "@homarr/definitions";
import { createIntegrationAsync } from "@homarr/integrations";
import { mediaRequestStatusConfiguration } from "@homarr/integrations/types";
import type { MediaRequest } from "@homarr/integrations/types";
import { mediaRequestListRequestHandler } from "@homarr/request-handler/media-request-list";
import { mediaRequestStatsRequestHandler } from "@homarr/request-handler/media-request-stats";
@@ -36,10 +35,7 @@ export const mediaRequestsRouter = createTRPCRouter({
return dataB.createdAt.getTime() - dataA.createdAt.getTime();
}
return (
mediaRequestStatusConfiguration[dataA.status].position -
mediaRequestStatusConfiguration[dataB.status].position
);
return dataA.status - dataB.status;
});
}),
subscribeToLatestRequests: publicProcedure
+6 -6
View File
@@ -34,12 +34,12 @@
"@homarr/validation": "workspace:^0.1.0",
"bcrypt": "^6.0.0",
"cookies": "^0.9.1",
"ldapts": "8.0.14",
"next": "16.0.10",
"ldapts": "8.0.9",
"next": "16.0.3",
"next-auth": "5.0.0-beta.30",
"react": "19.2.1",
"react-dom": "19.2.1",
"zod": "^4.1.13"
"react": "19.2.0",
"react-dom": "19.2.0",
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -48,7 +48,7 @@
"@types/bcrypt": "6.0.0",
"@types/cookies": "0.9.2",
"eslint": "^9.39.1",
"prettier": "^3.7.4",
"prettier": "^3.6.2",
"typescript": "^5.9.3"
}
}
@@ -6,14 +6,14 @@ import type { Database, InferInsertModel } from "@homarr/db";
import { and, eq } from "@homarr/db";
import { users } from "@homarr/db/schema";
import { logger } from "@homarr/log";
import type { ldapSignInSchema } from "@homarr/validation/user";
import type { userSignInSchema } from "@homarr/validation/user";
import { env } from "../../../env";
import { LdapClient } from "../ldap-client";
export const authorizeWithLdapCredentialsAsync = async (
db: Database,
credentials: z.infer<typeof ldapSignInSchema>,
credentials: z.infer<typeof userSignInSchema>,
) => {
logger.info(`user ${credentials.name} is trying to log in using LDAP. Connecting to LDAP server...`);
const client = new LdapClient();
@@ -38,14 +38,7 @@ export const authorizeWithLdapCredentialsAsync = async (
attributes: [env.AUTH_LDAP_USERNAME_ATTRIBUTE, env.AUTH_LDAP_USER_MAIL_ATTRIBUTE],
},
})
.then((entries) => {
if (entries.length > 1) {
logger.warn(`Multiple LDAP users found for ${credentials.name}, expected only one.`);
throw new CredentialsSignin();
}
return entries.at(0);
});
.then((entries) => entries.at(0));
if (!ldapUser) {
logger.warn(`User ${credentials.name} not found in LDAP`);
@@ -1,7 +1,7 @@
import type Credentials from "@auth/core/providers/credentials";
import type { Database } from "@homarr/db";
import { ldapSignInSchema, userSignInSchema } from "@homarr/validation/user";
import { userSignInSchema } from "@homarr/validation/user";
import { authorizeWithBasicCredentialsAsync } from "./authorization/basic-authorization";
import { authorizeWithLdapCredentialsAsync } from "./authorization/ldap-authorization";
@@ -28,7 +28,7 @@ export const createLdapConfiguration = (db: Database) =>
name: "Ldap",
// eslint-disable-next-line no-restricted-syntax
async authorize(credentials) {
const data = await ldapSignInSchema.parseAsync(credentials);
const data = await userSignInSchema.parseAsync(credentials);
return await authorizeWithLdapCredentialsAsync(db, data).catch(() => null);
},
}) satisfies CredentialsConfiguration;
+2 -2
View File
@@ -25,8 +25,8 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/api": "workspace:^0.1.0",
"react": "19.2.1",
"react-dom": "19.2.1"
"react": "19.2.0",
"react-dom": "19.2.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -34,7 +34,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"esbuild": "^0.27.1",
"esbuild": "^0.27.0",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
+5 -5
View File
@@ -32,13 +32,13 @@
"@paralleldrive/cuid2": "^3.1.0",
"dayjs": "^1.11.19",
"dns-caching": "^0.2.7",
"next": "16.0.10",
"next": "16.0.3",
"octokit": "^5.0.5",
"react": "19.2.1",
"react-dom": "19.2.1",
"react": "19.2.0",
"react-dom": "19.2.0",
"undici": "7.16.0",
"zod": "^4.1.13",
"zod-validation-error": "^5.0.0"
"zod": "^4.1.12",
"zod-validation-error": "^4.0.2"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -26,7 +26,7 @@
"dependencies": {
"@t3-oss/env-nextjs": "^0.13.8",
"ioredis": "5.8.2",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+7 -7
View File
@@ -29,20 +29,20 @@
"@homarr/core": "workspace:^0.1.0",
"@homarr/cron-jobs": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@tanstack/react-query": "^5.90.12",
"@trpc/client": "^11.7.2",
"@trpc/server": "^11.7.2",
"@trpc/tanstack-react-query": "^11.7.2",
"@tanstack/react-query": "^5.90.9",
"@trpc/client": "^11.7.1",
"@trpc/server": "^11.7.1",
"@trpc/tanstack-react-query": "^11.7.1",
"node-cron": "^4.2.1",
"react": "19.2.1",
"zod": "^4.1.13"
"react": "19.2.0",
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node-cron": "^3.0.11",
"@types/react": "19.2.7",
"@types/react": "19.2.4",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
+9 -9
View File
@@ -49,18 +49,18 @@
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.3.9",
"@mantine/core": "^8.3.7",
"@paralleldrive/cuid2": "^3.1.0",
"@testcontainers/mysql": "^11.9.0",
"@testcontainers/postgresql": "^11.9.0",
"better-sqlite3": "^12.5.0",
"@testcontainers/mysql": "^11.8.1",
"@testcontainers/postgresql": "^11.8.1",
"better-sqlite3": "^12.4.1",
"dotenv": "^17.2.3",
"drizzle-kit": "^0.31.8",
"drizzle-orm": "^0.45.0",
"drizzle-kit": "^0.31.7",
"drizzle-orm": "^0.44.7",
"drizzle-zod": "^0.8.3",
"mysql2": "3.15.3",
"pg": "^8.16.3",
"superjson": "2.2.6"
"superjson": "2.2.5"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -69,9 +69,9 @@
"@types/better-sqlite3": "7.6.13",
"@types/pg": "^8.15.6",
"dotenv-cli": "^11.0.0",
"esbuild": "^0.27.1",
"esbuild": "^0.27.0",
"eslint": "^9.39.1",
"prettier": "^3.7.4",
"prettier": "^3.6.2",
"tsx": "4.20.4",
"typescript": "^5.9.3"
}
+1 -1
View File
@@ -25,7 +25,7 @@
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"fast-xml-parser": "^5.3.2",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -144,7 +144,6 @@ export type HomarrDocumentationPath =
| "/docs/getting-started/installation/proxmox"
| "/docs/getting-started/installation/qnap"
| "/docs/getting-started/installation/railway"
| "/docs/getting-started/installation/runtipi"
| "/docs/getting-started/installation/saltbox"
| "/docs/getting-started/installation/source"
| "/docs/getting-started/installation/synology"
+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",
"@types/dockerode": "^3.3.47",
"@types/dockerode": "^3.3.45",
"eslint": "^9.39.1",
"typescript": "^5.9.3"
}
-1
View File
@@ -8,4 +8,3 @@ export type { Docker };
export const containerStates = ["created", "running", "paused", "restarting", "exited", "removing", "dead"] as const;
export type ContainerState = (typeof containerStates)[number];
export * from "./labels";
-4
View File
@@ -1,4 +0,0 @@
export const dockerLabels = {
// Label to hide a container from Homarrs docker integration
hide: "homarr.hide",
} as const;
+2 -2
View File
@@ -26,9 +26,9 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/form": "^8.3.9",
"@mantine/form": "^8.3.7",
"mantine-form-zod-resolver": "^1.3.0",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+2 -4
View File
@@ -1,9 +1,7 @@
import type { ChangeEvent, FocusEvent } from "react";
export interface InputPropsFor<T, TOnChangeArg, TComponent extends HTMLElement = HTMLInputElement> extends BasePropsFor<
TOnChangeArg,
TComponent
> {
export interface InputPropsFor<T, TOnChangeArg, TComponent extends HTMLElement = HTMLInputElement>
extends BasePropsFor<TOnChangeArg, TComponent> {
value?: T;
defaultValue?: T;
}
+3 -3
View File
@@ -30,9 +30,9 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.9",
"react": "19.2.1",
"zod": "^4.1.13"
"@mantine/core": "^8.3.7",
"react": "19.2.0",
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -16,19 +16,7 @@ interface UploadMediaProps {
export const UploadMedia = ({ children, onSettled, onSuccess, multiple = false }: UploadMediaProps) => {
const t = useI18n();
const { mutateAsync, isPending } = clientApi.media.uploadMedia.useMutation({
async onSuccess(mediaIds) {
await onSuccess?.(
mediaIds.map((id) => ({
id,
url: `/api/user-medias/${id}`,
})),
);
},
async onSettled() {
await onSettled?.();
},
});
const { mutateAsync, isPending } = clientApi.media.uploadMedia.useMutation();
const handleFileUploadAsync = async (files: File[] | File | null) => {
if (!files || (Array.isArray(files) && files.length === 0)) return;
@@ -36,16 +24,25 @@ export const UploadMedia = ({ children, onSettled, onSuccess, multiple = false }
const formData = new FormData();
filesArray.forEach((file) => formData.append("files", file));
await mutateAsync(formData, {
onSuccess() {
async onSuccess(mediaIds) {
showSuccessNotification({
message: t("media.action.upload.notification.success.message"),
});
await onSuccess?.(
mediaIds.map((id) => ({
id,
url: `/api/user-medias/${id}`,
})),
);
},
onError() {
showErrorNotification({
message: t("media.action.upload.notification.error.message"),
});
},
async onSettled() {
await onSettled?.();
},
});
};
+1 -1
View File
@@ -49,7 +49,7 @@
"tsdav": "^2.1.6",
"undici": "7.16.0",
"xml2js": "^0.6.2",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -46,7 +46,6 @@ export class TransmissionIntegration extends Integration implements IDownloadCli
name: torrent.name,
size: torrent.totalSize,
sent: torrent.uploadedEver,
received: torrent.downloadedEver,
downSpeed: torrent.percentDone !== 1 ? torrent.rateDownload : undefined,
upSpeed: torrent.rateUpload,
time:
+1 -1
View File
@@ -38,7 +38,7 @@ export type {
FirewallMemorySummary,
} from "./interfaces/firewall-summary/firewall-summary-types";
export type { SystemHealthMonitoring } from "./interfaces/health-monitoring/health-monitoring-types";
export { UpstreamMediaRequestStatus } from "./interfaces/media-requests/media-request-types";
export { MediaRequestStatus } from "./interfaces/media-requests/media-request-types";
export type { MediaRequestList, MediaRequestStats } from "./interfaces/media-requests/media-request-types";
export type { StreamSession } from "./interfaces/media-server/media-server-types";
export type {
@@ -26,8 +26,6 @@ export const downloadClientItemSchema = z.object({
size: z.number(),
/** Total uploaded in Bytes, only required for Torrent items */
sent: z.number().optional(),
/** Total downloaded in Bytes, only required for Torrent items */
received: z.number().optional(),
/** Download speed in Bytes/s, only required if not complete
* (Says 0 only if it should be downloading but isn't) */
downSpeed: z.number().optional(),
@@ -1,5 +1,3 @@
import { objectKeys } from "@homarr/common";
interface SerieSeason {
id: number;
seasonNumber: number;
@@ -36,64 +34,6 @@ export interface MediaRequest {
requestedBy?: Omit<RequestUser, "requestCount">;
}
export const mediaAvailabilityConfiguration = {
available: {
color: "green",
},
partiallyAvailable: {
color: "yellow",
},
processing: {
color: "blue",
},
requested: {
color: "violet",
},
pending: {
color: "violet",
},
unknown: {
color: "orange",
},
deleted: {
color: "red",
},
blacklisted: {
color: "gray",
},
} satisfies Record<string, { color: string }>;
export const mediaAvailabilities = objectKeys(mediaAvailabilityConfiguration);
export type MediaAvailability = (typeof mediaAvailabilities)[number];
export const mediaRequestStatusConfiguration = {
pending: {
color: "blue",
position: 1,
},
approved: {
color: "green",
position: 2,
},
declined: {
color: "red",
position: 3,
},
failed: {
color: "red",
position: 4,
},
completed: {
color: "green",
position: 5,
},
} satisfies Record<string, { color: string; position: number }>;
export const mediaRequestStatuses = objectKeys(mediaRequestStatusConfiguration);
export type MediaRequestStatus = (typeof mediaRequestStatuses)[number];
export interface MediaRequestList {
integration: {
id: string;
@@ -126,7 +66,7 @@ export interface MediaRequestStats {
}
// https://github.com/fallenbagel/jellyseerr/blob/0fd03f38480f853e7015ad9229ed98160e37602e/server/constants/media.ts#L1
export enum UpstreamMediaRequestStatus {
export enum MediaRequestStatus {
PendingApproval = 1,
Approved = 2,
Declined = 3,
@@ -135,12 +75,12 @@ export enum UpstreamMediaRequestStatus {
}
// https://github.com/fallenbagel/jellyseerr/blob/0fd03f38480f853e7015ad9229ed98160e37602e/server/constants/media.ts#L14
export enum UpstreamMediaAvailability {
export enum MediaAvailability {
Unknown = 1,
Pending = 2,
Processing = 3,
PartiallyAvailable = 4,
Available = 5,
JellyseerrBlacklistedOrOverseerrDeleted = 6,
JellyseerrDeleted = 7,
Blacklisted = 6,
Deleted = 7,
}
@@ -1,12 +1,3 @@
import type { MediaAvailability } from "../interfaces/media-requests/media-request-types";
import { UpstreamMediaAvailability } from "../interfaces/media-requests/media-request-types";
import { OverseerrIntegration } from "../overseerr/overseerr-integration";
export class JellyseerrIntegration extends OverseerrIntegration {
protected override mapAvailability(availability: UpstreamMediaAvailability, inProgress: boolean): MediaAvailability {
// Availability statuses are not exactly the same between Jellyseerr and Overseerr (Jellyseerr has "blacklisted" additionally (deleted is the same value in overseerr))
if (availability === UpstreamMediaAvailability.JellyseerrBlacklistedOrOverseerrDeleted) return "blacklisted";
if (availability === UpstreamMediaAvailability.JellyseerrDeleted) return "deleted";
return super.mapAvailability(availability, inProgress);
}
}
export class JellyseerrIntegration extends OverseerrIntegration {}
@@ -1,13 +1,8 @@
import { objectEntries } from "@homarr/common";
import type { IMediaRequestIntegration } from "../../interfaces/media-requests/media-request-integration";
import type {
MediaAvailability,
MediaInformation,
MediaRequest,
MediaRequestStatus,
RequestStats,
RequestUser,
} from "../../types";
import { mediaAvailabilities, mediaRequestStatuses } from "../../types";
import type { MediaInformation, MediaRequest, RequestStats, RequestUser } from "../../types";
import { MediaAvailability, MediaRequestStatus } from "../../types";
export class MediaRequestMockService implements IMediaRequestIntegration {
public async getSeriesInformationAsync(mediaType: "movie" | "tv", id: number): Promise<MediaInformation> {
@@ -91,10 +86,12 @@ export class MediaRequestMockService implements IMediaRequestIntegration {
}
private static randomAvailability(): MediaAvailability {
return mediaAvailabilities.at(Math.floor(Math.random() * mediaAvailabilities.length)) ?? "unknown";
const values = objectEntries(MediaAvailability).filter(([key]) => typeof key === "number");
return values[Math.floor(Math.random() * values.length)]?.[1] ?? MediaAvailability.Available;
}
private static randomStatus(): MediaRequestStatus {
return mediaRequestStatuses.at(Math.floor(Math.random() * mediaRequestStatuses.length)) ?? "pending";
const values = objectEntries(MediaRequestStatus).filter(([key]) => typeof key === "number");
return values[Math.floor(Math.random() * values.length)]?.[1] ?? MediaRequestStatus.PendingApproval;
}
}
@@ -9,17 +9,8 @@ import type { ISearchableIntegration } from "../base/searchable-integration";
import { TestConnectionError } from "../base/test-connection/test-connection-error";
import type { TestingResult } from "../base/test-connection/test-connection-service";
import type { IMediaRequestIntegration } from "../interfaces/media-requests/media-request-integration";
import type {
MediaAvailability,
MediaRequest,
MediaRequestStatus,
RequestStats,
RequestUser,
} from "../interfaces/media-requests/media-request-types";
import {
UpstreamMediaAvailability,
UpstreamMediaRequestStatus,
} from "../interfaces/media-requests/media-request-types";
import type { MediaRequest, RequestStats, RequestUser } from "../interfaces/media-requests/media-request-types";
import { MediaAvailability, MediaRequestStatus } from "../interfaces/media-requests/media-request-types";
interface OverseerrSearchResult {
id: number;
@@ -137,7 +128,7 @@ export class OverseerrIntegration
if (pendingResults.length > 0 && allResults.length > 0) {
requests = pendingResults.concat(
allResults.filter(({ status }) => status !== UpstreamMediaRequestStatus.PendingApproval),
allResults.filter(({ status }) => status !== MediaRequestStatus.PendingApproval),
);
} else if (pendingResults.length > 0) requests = pendingResults;
else if (allResults.length > 0) requests = allResults;
@@ -146,15 +137,11 @@ export class OverseerrIntegration
return await Promise.all(
requests.map(async (request): Promise<MediaRequest> => {
const information = await this.getItemInformationAsync(request.media.tmdbId, request.type);
// See https://github.com/seerr-team/seerr/blob/af083a3cd5c3e3d5d7917fdf4fdd67fe3f39c46b/src/components/StatusBadge/index.tsx#L40
const inProgress = (request.media.downloadStatus ?? []).length >= 1;
return {
id: request.id,
name: information.name,
status: this.mapRequestStatus(request.status),
availability: this.mapAvailability(request.media.status, inProgress),
status: request.status,
availability: request.media.status,
backdropImageUrl: `https://image.tmdb.org/t/p/original/${information.backdropPath}`,
posterImagePath: `https://image.tmdb.org/t/p/w600_and_h900_bestv2/${information.posterPath}`,
href: this.externalUrl(`/${request.type}/${request.media.tmdbId}`).toString(),
@@ -174,42 +161,6 @@ export class OverseerrIntegration
);
}
protected mapRequestStatus(status: UpstreamMediaRequestStatus): MediaRequestStatus {
switch (status) {
case UpstreamMediaRequestStatus.PendingApproval:
return "pending";
case UpstreamMediaRequestStatus.Approved:
return "approved";
case UpstreamMediaRequestStatus.Declined:
return "declined";
case UpstreamMediaRequestStatus.Failed:
return "failed";
case UpstreamMediaRequestStatus.Completed:
return "completed";
default:
return "failed";
}
}
// See https://github.com/seerr-team/seerr/blob/af083a3cd5c3e3d5d7917fdf4fdd67fe3f39c46b/src/components/StatusBadge/index.tsx#L153-L387
protected mapAvailability(availability: UpstreamMediaAvailability, inProgress: boolean): MediaAvailability {
switch (availability) {
case UpstreamMediaAvailability.Available:
return inProgress ? "processing" : "available";
case UpstreamMediaAvailability.PartiallyAvailable:
return inProgress ? "processing" : "partiallyAvailable";
case UpstreamMediaAvailability.Processing:
return inProgress ? "processing" : "requested";
case UpstreamMediaAvailability.Pending:
return "pending";
case UpstreamMediaAvailability.JellyseerrBlacklistedOrOverseerrDeleted:
return "deleted";
case UpstreamMediaAvailability.Unknown:
default:
return inProgress ? "processing" : "unknown";
}
}
public async getStatsAsync(): Promise<RequestStats> {
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/v1/request/count"), {
headers: {
@@ -388,12 +339,11 @@ const getRequestsSchema = z.object({
.array(
z.object({
id: z.number(),
status: z.enum(UpstreamMediaRequestStatus),
status: z.nativeEnum(MediaRequestStatus),
createdAt: z.string().transform((value) => new Date(value)),
media: z.object({
status: z.enum(UpstreamMediaAvailability),
status: z.nativeEnum(MediaAvailability),
tmdbId: z.number(),
downloadStatus: z.array(z.unknown()).optional(),
}),
type: z.enum(["movie", "tv"]),
requestedBy: z
@@ -169,15 +169,17 @@ export class PlexIntegration extends Integration implements IMediaServerIntegrat
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
const token = super.getSecretValue("apiKey");
const response = await input.fetchAsync(super.url("/prefs"), {
const response = await input.fetchAsync(this.url("/"), {
headers: {
"X-Plex-Token": token,
Accept: "application/json",
},
});
if (!response.ok) return TestConnectionError.StatusResult(response);
const result = await response.text();
await PlexIntegration.parseXmlAsync<PlexResponse>(result);
return { success: true };
}
+3 -3
View File
@@ -25,9 +25,9 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/core": "workspace:^0.1.0",
"superjson": "2.2.6",
"winston": "3.19.0",
"zod": "^4.1.13"
"superjson": "2.2.5",
"winston": "3.18.3",
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+5 -5
View File
@@ -33,13 +33,13 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.9",
"@mantine/core": "^8.3.7",
"@tabler/icons-react": "^3.35.0",
"dayjs": "^1.11.19",
"next": "16.0.10",
"react": "19.2.1",
"react-dom": "19.2.1",
"zod": "^4.1.13"
"next": "16.0.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
@@ -2,6 +2,7 @@ import type { z } from "zod/v4";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import type { MaybePromise } from "@homarr/common/types";
import { AppForm } from "@homarr/forms-collection";
import { createModal } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
@@ -9,7 +10,7 @@ import { useI18n, useScopedI18n } from "@homarr/translation/client";
import type { appManageSchema } from "@homarr/validation/app";
interface QuickAddAppModalProps {
onClose: (createdApp: Omit<RouterOutputs["app"]["create"], "appId">) => void;
onClose: (createdApp: Omit<RouterOutputs["app"]["create"], "appId">) => MaybePromise<void>;
}
export const QuickAddAppModal = createModal<QuickAddAppModalProps>(({ actions, innerProps }) => {
@@ -27,13 +28,13 @@ export const QuickAddAppModal = createModal<QuickAddAppModalProps>(({ actions, i
const handleSubmit = (values: z.infer<typeof appManageSchema>) => {
mutate(values, {
onSuccess(app) {
async onSuccess(app) {
showSuccessNotification({
title: tScoped("success.title"),
message: tScoped("success.message"),
});
innerProps.onClose(app);
await innerProps.onClose(app);
actions.closeModal();
},
});
@@ -1,7 +1,7 @@
import { Button, Group, Stack, Text, TextInput } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import type { MaybePromise } from "@homarr/common/types";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
@@ -15,6 +15,7 @@ interface InnerProps {
id: string;
name: string;
};
onSuccess: () => MaybePromise<void>;
}
export const DuplicateBoardModal = createModal<InnerProps>(({ actions, innerProps }) => {
@@ -26,11 +27,7 @@ export const DuplicateBoardModal = createModal<InnerProps>(({ actions, innerProp
},
});
const boardNameStatus = useBoardNameStatus(form.values.name);
const { mutateAsync, isPending } = clientApi.board.duplicateBoard.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/manage/boards");
},
});
const { mutateAsync, isPending } = clientApi.board.duplicateBoard.useMutation();
return (
<form
@@ -43,12 +40,13 @@ export const DuplicateBoardModal = createModal<InnerProps>(({ actions, innerProp
id: innerProps.board.id,
},
{
onSuccess() {
async onSuccess() {
actions.closeModal();
showSuccessNotification({
title: t("board.action.duplicate.notification.success.title"),
message: t("board.action.duplicate.notification.success.message"),
});
await innerProps.onSuccess();
},
onError() {
showErrorNotification({
@@ -65,11 +65,7 @@ export const ImportBoardModal = createModal(({ actions }) => {
},
);
const { mutateAsync, isPending } = clientApi.board.importOldmarrConfig.useMutation({
async onSuccess() {
await revalidatePathActionAsync("/manage/boards");
},
});
const { mutateAsync, isPending } = clientApi.board.importOldmarrConfig.useMutation();
const boardNameStatus = useBoardNameStatus(form.values.configuration.name);
const handleSubmitAsync = async (values: { file: File; configuration: OldmarrImportConfiguration }) => {
@@ -78,8 +74,9 @@ export const ImportBoardModal = createModal(({ actions }) => {
formData.set("configuration", JSON.stringify(values.configuration));
await mutateAsync(formData, {
onSuccess() {
async onSuccess() {
actions.closeModal();
await revalidatePathActionAsync("/manage/boards");
showSuccessNotification({
title: tOldImport("notification.success.title"),
message: tOldImport("notification.success.message"),
@@ -27,11 +27,7 @@ export const AddCertificateModal = createModal<InnerProps>(({ actions, innerProp
},
},
);
const { mutateAsync } = clientApi.certificates.addCertificate.useMutation({
async onSuccess() {
await innerProps.onSuccess?.();
},
});
const { mutateAsync } = clientApi.certificates.addCertificate.useMutation();
return (
<form
@@ -39,11 +35,12 @@ export const AddCertificateModal = createModal<InnerProps>(({ actions, innerProp
const formData = new FormData();
formData.set("file", values.file);
await mutateAsync(formData, {
onSuccess() {
async onSuccess() {
showSuccessNotification({
title: t("certificate.action.create.notification.success.title"),
message: t("certificate.action.create.notification.success.message"),
});
await innerProps.onSuccess?.();
actions.closeModal();
},
onError() {
+3 -3
View File
@@ -24,9 +24,9 @@
"dependencies": {
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.9",
"@mantine/hooks": "^8.3.9",
"react": "19.2.1"
"@mantine/core": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"react": "19.2.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -24,7 +24,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/ui": "workspace:^0.1.0",
"@mantine/notifications": "^8.3.9",
"@mantine/notifications": "^8.3.7",
"@tabler/icons-react": "^3.35.0"
},
"devDependencies": {
+7 -7
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.3.9",
"@mantine/hooks": "^8.3.9",
"@mantine/core": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"adm-zip": "0.5.16",
"next": "16.0.10",
"react": "19.2.1",
"react-dom": "19.2.1",
"superjson": "2.2.6",
"zod": "^4.1.13",
"next": "16.0.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"superjson": "2.2.5",
"zod": "^4.1.12",
"zod-form-data": "^3.0.1"
},
"devDependencies": {
@@ -29,10 +29,10 @@ export const ImportTokenModal = createModal<InnerProps>(({ actions, innerProps }
mutate(
{ checksum: innerProps.checksum, token: values.token },
{
onSuccess(isValid) {
async onSuccess(isValid) {
if (isValid) {
actions.closeModal();
void innerProps.onSuccessAsync(values.token);
await innerProps.onSuccessAsync(values.token);
} else {
showErrorNotification({
title: tTokenModal("notification.error.title"),
+1 -1
View File
@@ -23,7 +23,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -28,7 +28,7 @@
"@homarr/definitions": "workspace:^",
"@homarr/log": "workspace:^",
"ioredis": "5.8.2",
"superjson": "2.2.6"
"superjson": "2.2.5"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+2 -3
View File
@@ -26,15 +26,14 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/docker": "workspace:^0.1.0",
"@homarr/integrations": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0",
"@homarr/redis": "workspace:^0.1.0",
"dayjs": "^1.11.19",
"octokit": "^5.0.5",
"superjson": "2.2.6",
"superjson": "2.2.5",
"undici": "7.16.0",
"zod": "^4.1.13"
"zod": "^4.1.12"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+7 -5
View File
@@ -3,9 +3,9 @@ import type { ContainerInfo, ContainerStats } from "dockerode";
import { db, like, or } from "@homarr/db";
import { icons } from "@homarr/db/schema";
import type { ContainerState } from "@homarr/docker";
import { dockerLabels, DockerSingleton } from "@homarr/docker";
import type { ContainerState } from "../../docker/src";
import { DockerSingleton } from "../../docker/src";
import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler";
export const dockerContainersRequestHandler = createCachedWidgetRequestHandler({
@@ -27,11 +27,13 @@ async function getContainersWithStatsAsync() {
const containers = await Promise.all(
dockerInstances.map(async ({ instance, host }) => {
const instanceContainers = await instance.listContainers({ all: true });
return instanceContainers
.filter((container) => dockerLabels.hide in container.Labels === false)
.map((container) => ({ ...container, instance: host }));
return instanceContainers.map((container) => ({
...container,
instance: host,
}));
}),
).then((res) => res.flat());
const likeQueries = containers.map((container) => like(icons.name, `%${extractImage(container)}%`));
const dbIcons =
+4 -4
View File
@@ -26,10 +26,10 @@
"@homarr/api": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/dates": "^8.3.9",
"next": "16.0.10",
"react": "19.2.1",
"react-dom": "19.2.1"
"@mantine/dates": "^8.3.7",
"next": "16.0.3",
"react": "19.2.0",
"react-dom": "19.2.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+7 -7
View File
@@ -33,14 +33,14 @@
"@homarr/settings": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.9",
"@mantine/hooks": "^8.3.9",
"@mantine/spotlight": "^8.3.9",
"@mantine/core": "^8.3.7",
"@mantine/hooks": "^8.3.7",
"@mantine/spotlight": "^8.3.7",
"@tabler/icons-react": "^3.35.0",
"jotai": "^2.15.2",
"next": "16.0.10",
"react": "19.2.1",
"react-dom": "19.2.1",
"jotai": "^2.15.1",
"next": "16.0.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"use-deep-compare-effect": "^1.8.1"
},
"devDependencies": {
+4 -4
View File
@@ -32,10 +32,10 @@
"dayjs": "^1.11.19",
"deepmerge": "4.3.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.0.10",
"next-intl": "4.5.8",
"react": "19.2.1",
"react-dom": "19.2.1"
"next": "16.0.3",
"next-intl": "4.5.3",
"react": "19.2.0",
"react-dom": "19.2.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "",
"pending": "",
"processing": "",
"requested": "",
"partiallyAvailable": "",
"available": "",
"blacklisted": "",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "未知",
"pending": "等待处理",
"processing": "处理中",
"requested": "",
"partiallyAvailable": "部分",
"available": "可用",
"blacklisted": "已列入黑名单",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "crwdns1314:0crwdne1314:0",
"pending": "crwdns1316:0crwdne1316:0",
"processing": "crwdns1318:0crwdne1318:0",
"requested": "crwdns3806:0crwdne3806:0",
"partiallyAvailable": "crwdns1320:0crwdne1320:0",
"available": "crwdns1322:0crwdne1322:0",
"blacklisted": "crwdns3468:0crwdne3468:0",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Neznámý",
"pending": "",
"processing": "",
"requested": "",
"partiallyAvailable": "Částečně dostupné",
"available": "K dispozici",
"blacklisted": "",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Ukendt",
"pending": "Afventende",
"processing": "Behandler",
"requested": "Anmodet",
"partiallyAvailable": "Delvis",
"available": "Tilgængelig",
"blacklisted": "Blacklistet",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Unbekannt",
"pending": "Ausstehend",
"processing": "In Bearbeitung",
"requested": "",
"partiallyAvailable": "Teilweise",
"available": "Verfügbar",
"blacklisted": "",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Unbekannt",
"pending": "Ausstehend",
"processing": "In Bearbeitung",
"requested": "",
"partiallyAvailable": "Teilweise",
"available": "Verfügbar",
"blacklisted": "Gesperrt",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Άγνωστο",
"pending": "",
"processing": "",
"requested": "",
"partiallyAvailable": "Μερικώς",
"available": "Διαθέσιμο",
"blacklisted": "",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "",
"pending": "",
"processing": "",
"requested": "",
"partiallyAvailable": "",
"available": "",
"blacklisted": "",
+1 -18
View File
@@ -1939,23 +1939,7 @@
"dockerContainers": {
"name": "Docker stats",
"description": "Stats of your containers (This widget can only be added with administrator privileges)",
"option": {
"enableRowSorting": {
"label": "Enable items sorting"
},
"defaultSort": {
"label": "Column used for sorting by default",
"option": {
"name": "Name",
"state": "State",
"cpuUsage": "CPU usage",
"memoryUsage": "Memory usage"
}
},
"descendingDefaultSort": {
"label": "Invert sorting"
}
},
"option": {},
"error": {
"internalServerError": "Failed to fetch containers stats"
}
@@ -2248,7 +2232,6 @@
"unknown": "Unknown",
"pending": "Pending",
"processing": "Processing",
"requested": "Requested",
"partiallyAvailable": "Partial",
"available": "Available",
"blacklisted": "Blacklisted",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Desconocido",
"pending": "Pendiente",
"processing": "Procesando",
"requested": "Solicitado",
"partiallyAvailable": "Parcial",
"available": "Disponible",
"blacklisted": "Lista negra",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "",
"pending": "",
"processing": "",
"requested": "",
"partiallyAvailable": "",
"available": "",
"blacklisted": "",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Inconnu",
"pending": "En attente",
"processing": "Traitement en cours",
"requested": "",
"partiallyAvailable": "Partiel",
"available": "Disponible",
"blacklisted": "Sur la liste noire",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "לא ידוע",
"pending": "בהמתנה",
"processing": "מעבד",
"requested": "",
"partiallyAvailable": "חלקי",
"available": "זמין",
"blacklisted": "ברשימה השחורה",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Nepoznato",
"pending": "",
"processing": "",
"requested": "",
"partiallyAvailable": "",
"available": "",
"blacklisted": "",
-1
View File
@@ -2232,7 +2232,6 @@
"unknown": "Ismeretlen",
"pending": "",
"processing": "Feldolgozás",
"requested": "",
"partiallyAvailable": "Részleges",
"available": "Elérhető",
"blacklisted": "",
+64 -65
View File
@@ -730,7 +730,7 @@
"error": {
"common": {
"cause": {
"title": "Causa con più dettagli"
"title": ""
}
},
"unknown": {
@@ -738,7 +738,7 @@
"description": "Si è verificato un errore sconosciuto, apri la causa sottostante per vedere maggiori dettagli"
},
"parse": {
"title": "Errore di analisi",
"title": "",
"description": "La risposta non può essere analizzata. Si prega di verificare che l'URL stia puntando all'URL di base del servizio."
},
"authorization": {
@@ -959,8 +959,8 @@
"newLabel": "Nuovo ID token"
},
"realm": {
"label": "Dominio",
"newLabel": "Nuovo dominio"
"label": "",
"newLabel": ""
},
"personalAccessToken": {
"label": "Token d'Accesso Personale",
@@ -1053,7 +1053,7 @@
"backToOverview": "Torna alla panoramica",
"change": "Cambia",
"create": "Crea",
"createAnother": "Crea e ricomincia",
"createAnother": "",
"edit": "Modifica",
"import": "Importa",
"insert": "Inserisci",
@@ -1389,8 +1389,8 @@
}
},
"dnsHoleSummary": {
"name": "Riepilogo del filtraggio DNS",
"description": "Mostra il riepilogo del tuo filtro DNS",
"name": "",
"description": "",
"option": {
"layout": {
"label": "Layout",
@@ -1411,7 +1411,7 @@
}
},
"error": {
"internalServerError": "Impossibile recuperare il riepilogo del filtro DNS",
"internalServerError": "",
"integrationsDisconnected": "Nessun dato disponibile, tutte le integrazioni disconnesse"
},
"data": {
@@ -1423,7 +1423,7 @@
"domainsTooltip": "A causa di più integrazioni, Homarr non può calcolare il numero esatto di domini bloccati"
},
"dnsHoleControls": {
"name": "Controlli del filtro DNS",
"name": "",
"description": "Controlla PiHole o AdGuard dalla tua dashboard",
"option": {
"layout": {
@@ -1445,7 +1445,7 @@
}
},
"error": {
"internalServerError": "Impossibile controllare il DNS Hole"
"internalServerError": ""
},
"controls": {
"enableAll": "Abilita tutto",
@@ -1514,7 +1514,7 @@
"label": "Indirizzo del server"
},
"isBedrockServer": {
"label": "Server Bedrock"
"label": ""
}
},
"status": {
@@ -1625,7 +1625,7 @@
}
},
"error": {
"noUrl": "Nessun URL iFrame fornito",
"noUrl": "",
"unsupportedProtocol": "L'URL fornito sta usando un protocollo non supportato. Si prega di utilizzare uno di ({supportedProtocols})",
"noBrowerSupport": "Il tuo browser non supporta iframes. Aggiorna il tuo browser."
}
@@ -1664,7 +1664,7 @@
}
},
"stockPrice": {
"name": "Prezzo delle azioni",
"name": "",
"description": "Visualizza il prezzo attuale delle azioni di una società",
"option": {
"stock": {
@@ -1835,7 +1835,7 @@
"title": "Index manager",
"testAll": "Prova tutto",
"error": {
"internalServerError": "Impossibile recuperare lo stato degli indicizzatori"
"internalServerError": ""
}
},
"healthMonitoring": {
@@ -2020,7 +2020,7 @@
"name": "Nome",
"id": "Id",
"metadata": {
"title": "Statistiche per nerd",
"title": "",
"video": {
"title": "Video",
"resolution": "Risoluzione"
@@ -2034,7 +2034,7 @@
"title": "Transcodifica",
"container": "Container",
"resolution": "Risoluzione",
"target": "Codec di destinazione"
"target": ""
}
}
}
@@ -2098,7 +2098,7 @@
"detailsTitle": "Categorie (Informazioni aggiuntive)"
},
"downSpeed": {
"columnTitle": "Giù",
"columnTitle": "",
"detailsTitle": "Velocità Di Download"
},
"index": {
@@ -2112,22 +2112,22 @@
"columnTitle": "Integrazione"
},
"name": {
"columnTitle": "Nome del job"
"columnTitle": ""
},
"progress": {
"columnTitle": "Avanzamento",
"detailsTitle": "Avanzamento del download"
"detailsTitle": ""
},
"ratio": {
"columnTitle": "Rapporto",
"detailsTitle": "Rapporto torrent (ricevuti/inviati)"
},
"received": {
"columnTitle": "Totale fuori servizio",
"columnTitle": "",
"detailsTitle": "Totale scaricati"
},
"sent": {
"columnTitle": "Totale operativo",
"columnTitle": "",
"detailsTitle": "Totale Caricati"
},
"size": {
@@ -2136,7 +2136,7 @@
},
"state": {
"columnTitle": "Stato",
"detailsTitle": "Stato job"
"detailsTitle": ""
},
"time": {
"columnTitle": "Ora di fine",
@@ -2158,7 +2158,7 @@
"completed": "Completato",
"failed": "Non riuscito",
"processing": "In lavorazione",
"leeching": "Leeching",
"leeching": "",
"stalled": "In stallo",
"unknown": "Sconosciuto",
"seeding": "Seeding"
@@ -2205,7 +2205,7 @@
"label": "Mostra suggerimento descrizione"
},
"showType": {
"label": "Mostra il badge del tipo di media"
"label": ""
},
"showSource": {
"label": "Mostra sorgente integrazione"
@@ -2216,7 +2216,7 @@
}
},
"mediaRequests-requestList": {
"name": "Elenco Richieste Media",
"name": "",
"description": "Visualizza un elenco di tutte le richieste media dalla tua istanza Overseerr o Jellyseerr",
"option": {
"linksTargetNewTab": {
@@ -2232,10 +2232,9 @@
"unknown": "Sconosciuto",
"pending": "In sospeso",
"processing": "In lavorazione",
"requested": "Richiesto",
"partiallyAvailable": "Parziale",
"available": "Disponibile",
"blacklisted": "In blacklist",
"blacklisted": "",
"deleted": "Eliminato"
},
"status": {
@@ -2248,7 +2247,7 @@
"toBeDetermined": "TBD"
},
"mediaRequests-requestStats": {
"name": "Statistiche Richiesta Media",
"name": "",
"description": "Statistiche sulle richieste dei media",
"option": {},
"titles": {
@@ -2339,7 +2338,7 @@
"label": "Abilita RTL"
},
"textLinesClamp": {
"label": "Limita le righe della descrizione"
"label": ""
},
"maximumAmountPosts": {
"label": "Limite di post"
@@ -2354,11 +2353,11 @@
"description": "Visualizza un elenco della versione corrente dei repository dati con la versione regex specificata.",
"option": {
"newReleaseWithin": {
"label": "Nuova versione entro",
"label": "",
"description": "Esempio di utilizzo: 1w (1 settimana), 10M (10 mesi). Tipi di unità accettati h (ore), d (giorni), w (settimane), M (mesi), y (anni). Lasciare vuoto per non evidenziare le nuove versioni."
},
"staleReleaseWithin": {
"label": "Rilascio obsoleto entro",
"label": "",
"description": "Esempio di utilizzo: 1w (1 settimana), 10M (10 mesi). Tipi di unità accettati h (ore), d (giorni), w (settimane), M (mesi), y (anni). Lasciare vuoto per non evidenziare le release obsolete."
},
"showOnlyHighlighted": {
@@ -2703,7 +2702,7 @@
"label": "Titolo della pagina"
},
"metaTitle": {
"label": "Meta title"
"label": ""
},
"logoImageUrl": {
"label": "URL immagine del logo"
@@ -2949,7 +2948,7 @@
"label": "Numero di colonne"
},
"breakpoint": {
"label": "Breakpoint",
"label": "",
"description": "Il layout verrà utilizzato su tutti gli schermi più grandi di questo breakpoint fino al breakpoint più grande successivo."
}
}
@@ -3323,7 +3322,7 @@
"label": "Analytics"
},
"smartHomeEntityState": {
"label": "Stato dell'entità Smart Home"
"label": ""
},
"ping": {
"label": "Ping"
@@ -3338,10 +3337,10 @@
"label": "Scaricamenti"
},
"mediaRequestStats": {
"label": "Statistiche richieste media"
"label": ""
},
"mediaRequestList": {
"label": "Elenco richieste media"
"label": ""
},
"rssFeeds": {
"label": "Feeds RSS"
@@ -3350,10 +3349,10 @@
"label": "Gestione Indicizzatori"
},
"healthMonitoring": {
"label": "Monitoraggio integrità del sistema"
"label": ""
},
"dnsHole": {
"label": "Dati di filtraggio DNS"
"label": ""
},
"updateChecker": {
"label": "Controllo aggiornamenti"
@@ -3436,10 +3435,10 @@
},
"trigger": {
"success": {
"message": "Attività attivata con successo"
"message": ""
},
"error": {
"message": "Impossibile attivare l'attività"
"message": ""
}
},
"enable": {
@@ -3454,7 +3453,7 @@
},
"toggle": {
"error": {
"message": "Impossibile attivare lo stato dell'attività"
"message": ""
}
}
},
@@ -3518,12 +3517,12 @@
"action": "Azione"
},
"action": {
"toggleBoardEdit": "Attiva la modalità di modifica della board",
"toggleColorScheme": "Attiva tema chiaro/scuro",
"saveNotebook": "Salva notebook (solo nel widget notebook)",
"toggleBoardEdit": "",
"toggleColorScheme": "",
"saveNotebook": "",
"openSpotlight": "Apri ricerca"
},
"note": "Suggerimento: 'Mod' si riferisce sia al tasto Ctrl che al tasto ⌘ su macOS"
"note": ""
}
}
}
@@ -3535,7 +3534,7 @@
"updated": "Aggiornato {when}",
"search": "Cerca {count} container",
"selected": "{selectCount} di {totalCount} containers selezionati",
"footer": "Totale container {count}"
"footer": ""
},
"field": {
"name": {
@@ -3673,11 +3672,11 @@
"resources": {
"title": "Risorse",
"nodes": "Nodi",
"namespaces": "Spazi dei nomi",
"namespaces": "",
"ingresses": "Ingressi",
"services": "Servizi",
"pods": "Pods",
"configmaps": "ConfigMaps",
"configmaps": "",
"secrets": "Secrets",
"volumes": "Volumi"
}
@@ -3722,7 +3721,7 @@
}
},
"namespaces": {
"label": "Spazi dei nomi",
"label": "",
"field": {
"name": {
"label": "Nome"
@@ -3731,7 +3730,7 @@
"label": "Stato",
"option": {
"active": "Attivo",
"terminating": "Terminare"
"terminating": ""
}
},
"creationTimestamp": {
@@ -3739,7 +3738,7 @@
}
},
"table": {
"search": "Cerca {count} spazi dei nomi"
"search": ""
}
},
"ingresses": {
@@ -3762,7 +3761,7 @@
}
},
"table": {
"search": "Cerca {count} ingresses"
"search": ""
}
},
"services": {
@@ -3772,7 +3771,7 @@
"label": "Nome"
},
"namespace": {
"label": "Spazio del nome"
"label": ""
},
"type": {
"label": "Tipo"
@@ -3801,7 +3800,7 @@
"label": "Nome"
},
"namespace": {
"label": "Spazio del nome"
"label": ""
},
"image": {
"label": "Immagine"
@@ -3827,7 +3826,7 @@
"label": "Nome"
},
"namespace": {
"label": "spazio del nome"
"label": ""
},
"type": {
"label": "tipo"
@@ -3837,24 +3836,24 @@
}
},
"table": {
"search": "Cerca {count} segreti"
"search": ""
}
},
"configmaps": {
"label": "ConfigMaps",
"label": "",
"field": {
"name": {
"label": "Nome"
},
"namespace": {
"label": "namespace"
"label": ""
},
"creationTimestamp": {
"label": "Creato"
}
},
"table": {
"search": "Cerca {count} ConfigMaps"
"search": ""
}
},
"volumes": {
@@ -3864,7 +3863,7 @@
"label": "Nome"
},
"namespace": {
"label": "Namespace"
"label": ""
},
"accessModes": {
"label": "Modalità Di Accesso"
@@ -3873,7 +3872,7 @@
"label": "Spazio di archiviazione"
},
"storageClassName": {
"label": "Nome Classe Archivio"
"label": ""
},
"volumeMode": {
"label": "Modalità Volume"
@@ -3889,7 +3888,7 @@
}
},
"table": {
"search": "Cerca {count} volumi"
"search": ""
}
},
"error": {
@@ -3990,7 +3989,7 @@
"label": "Nodi"
},
"namespaces": {
"label": "Namespaces"
"label": ""
},
"ingresses": {
"label": "Ingressi"
@@ -4002,7 +4001,7 @@
"label": "pods"
},
"configmaps": {
"label": "ConfigMaps"
"label": ""
},
"secrets": {
"label": "Secrets"
@@ -4093,7 +4092,7 @@
"option": {
"colorScheme": {
"light": "Passa al tema chiaro",
"dark": "Passa al tema scuro"
"dark": "Passa alla modalità scura"
},
"language": {
"label": "Cambia lingua",
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff. Show more