merge: integrate dev branch, resolve package.json and lockfile conflicts
Co-authored-by: ajnart <49837342+ajnart@users.noreply.github.com>
This commit is contained in:
1 parent
1e438ec3c3
commit
6cbf72462a
117 files changed
+4495
-1648
No files matched your search
@@ -33,6 +33,7 @@ body:
|
||||
options:
|
||||
# The below comment is used to insert a new version with on-release.yml
|
||||
#NEXT_VERSION#
|
||||
- 1.55.0
|
||||
- 1.54.0
|
||||
- 1.53.0
|
||||
- 1.52.0
|
||||
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
- uses: actions/setup-node@v6
|
||||
if: env.SKIP_RELEASE == 'false'
|
||||
with:
|
||||
node-version: 24.13.1
|
||||
node-version: 24.14.0
|
||||
cache: "pnpm"
|
||||
- run: npm i -g pnpm
|
||||
if: env.SKIP_RELEASE == 'false'
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
images: "${{ env.GHCR_REPO }}"
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -167,7 +167,7 @@ jobs:
|
||||
images: "${{ env.GHCR_REPO }}"
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -238,7 +238,7 @@ jobs:
|
||||
permission-contents: write # required to publish the release
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
id: create-pull-request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
add-paths: .github/ISSUE_TEMPLATE/bug_report.yml
|
||||
commit-message: "chore: update bug report template"
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
## [1.55.0](https://github.com/homarr-labs/homarr/compare/v1.54.0...v1.55.0) (2026-03-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add seerr integration ([#5139](https://github.com/homarr-labs/homarr/issues/5139)) ([0e29a2f](https://github.com/homarr-labs/homarr/commit/0e29a2fce172cbfda083b899c01b92bd8b6210b7))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency fast-xml-parser to ^5.4.1 ([#5150](https://github.com/homarr-labs/homarr/issues/5150)) ([eb2f85f](https://github.com/homarr-labs/homarr/commit/eb2f85f6f8c9d7d90c1aeec079225678dfef4dd0))
|
||||
* **deps:** update dependency ioredis to v5.10.0 ([#5169](https://github.com/homarr-labs/homarr/issues/5169)) ([1c06e56](https://github.com/homarr-labs/homarr/commit/1c06e562c33bd9f1387cb05a3dece7beedfe43c2))
|
||||
* **deps:** update dependency ldapts to v8.1.7 ([#5168](https://github.com/homarr-labs/homarr/issues/5168)) ([ec45aac](https://github.com/homarr-labs/homarr/commit/ec45aacc63766c51a99ead6130bade442124e70d))
|
||||
* **deps:** update dependency mysql2 to v3.17.5 ([#5140](https://github.com/homarr-labs/homarr/issues/5140)) ([66ad67e](https://github.com/homarr-labs/homarr/commit/66ad67eced587fd49a470395298477dc09cdd225))
|
||||
* **deps:** update dependency mysql2 to v3.18.0 ([#5141](https://github.com/homarr-labs/homarr/issues/5141)) ([52792af](https://github.com/homarr-labs/homarr/commit/52792af186a6eb3519aafdee5a7c0dd03a86a461))
|
||||
* **deps:** update dependency mysql2 to v3.18.1 ([#5152](https://github.com/homarr-labs/homarr/issues/5152)) ([8bf2a43](https://github.com/homarr-labs/homarr/commit/8bf2a43e065671c7c119ef1da5aa09d284db0ede))
|
||||
* **deps:** update dependency mysql2 to v3.18.2 ([#5164](https://github.com/homarr-labs/homarr/issues/5164)) ([4717a57](https://github.com/homarr-labs/homarr/commit/4717a5724d4a6286c0f2bb92cf1e1fe17903a13a))
|
||||
* **deps:** update dependency pg to ^8.19.0 ([#5153](https://github.com/homarr-labs/homarr/issues/5153)) ([0b0fb1c](https://github.com/homarr-labs/homarr/commit/0b0fb1c5798357d7bc847dfe577b26529be8aa5c))
|
||||
* **deps:** update dependency swagger-ui-react to ^5.32.0 ([#5167](https://github.com/homarr-labs/homarr/issues/5167)) ([ff11599](https://github.com/homarr-labs/homarr/commit/ff1159943c967b6fea44894765c2210c3cdd44cc))
|
||||
* **deps:** update dependency typescript-eslint to ^8.56.1 ([#5142](https://github.com/homarr-labs/homarr/issues/5142)) ([ac3b4e7](https://github.com/homarr-labs/homarr/commit/ac3b4e7de0460cab7723dcc1a5a8e14072a37d25))
|
||||
* **deps:** update trpc monorepo to ^11.11.0 ([#5174](https://github.com/homarr-labs/homarr/issues/5174)) ([bc2a532](https://github.com/homarr-labs/homarr/commit/bc2a532a03d8cb76270f52b766f1a7f46d704096))
|
||||
|
||||
## [1.54.0](https://github.com/homarr-labs/homarr/compare/v1.53.2...v1.54.0) (2026-02-27)
|
||||
|
||||
### Features
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM node:24.13.1-alpine AS base
|
||||
FROM node:24.14.0-alpine AS base
|
||||
|
||||
FROM base AS builder
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
+14
-14
@@ -54,21 +54,21 @@
|
||||
"@homarr/ui": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@homarr/widgets": "workspace:^0.1.0",
|
||||
"@mantine/colors-generator": "^8.3.15",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@mantine/dropzone": "^8.3.15",
|
||||
"@mantine/hooks": "^8.3.15",
|
||||
"@mantine/modals": "^8.3.15",
|
||||
"@mantine/tiptap": "^8.3.15",
|
||||
"@mantine/colors-generator": "^8.3.16",
|
||||
"@mantine/core": "^8.3.16",
|
||||
"@mantine/dropzone": "^8.3.16",
|
||||
"@mantine/hooks": "^8.3.16",
|
||||
"@mantine/modals": "^8.3.16",
|
||||
"@mantine/tiptap": "^8.3.16",
|
||||
"@million/lint": "1.0.14",
|
||||
"@tabler/icons-react": "^3.37.1",
|
||||
"@tabler/icons-react": "^3.40.0",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"@tanstack/react-query-devtools": "^5.91.3",
|
||||
"@tanstack/react-query-next-experimental": "^5.91.0",
|
||||
"@trpc/client": "^11.10.0",
|
||||
"@trpc/next": "^11.10.0",
|
||||
"@trpc/react-query": "^11.10.0",
|
||||
"@trpc/server": "^11.10.0",
|
||||
"@trpc/client": "^11.12.0",
|
||||
"@trpc/next": "^11.12.0",
|
||||
"@trpc/react-query": "^11.12.0",
|
||||
"@trpc/server": "^11.12.0",
|
||||
"@xterm/addon-canvas": "^0.7.0",
|
||||
"@xterm/addon-fit": "0.11.0",
|
||||
"@xterm/xterm": "^6.0.0",
|
||||
@@ -92,7 +92,7 @@
|
||||
"react-simple-code-editor": "^0.14.1",
|
||||
"sass": "^1.97.3",
|
||||
"superjson": "2.2.6",
|
||||
"swagger-ui-react": "^5.31.2",
|
||||
"swagger-ui-react": "^5.32.0",
|
||||
"use-deep-compare-effect": "^1.8.1",
|
||||
"ws": "^8.19.0",
|
||||
"zod": "^4.2.1"
|
||||
@@ -102,7 +102,7 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/chroma-js": "3.1.2",
|
||||
"@types/node": "^24.10.13",
|
||||
"@types/node": "^24.12.0",
|
||||
"@types/prismjs": "^1.26.6",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "19.2.3",
|
||||
@@ -110,7 +110,7 @@
|
||||
"@types/ws": "^8.18.1",
|
||||
"concurrently": "^9.2.1",
|
||||
"esbuild": "^0.27.3",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"node-loader": "^2.1.0",
|
||||
"prettier": "^3.8.1",
|
||||
"tsx": "4.20.4",
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { Button, Card, Center, Grid, Input, Stack, Text } from "@mantine/core";
|
||||
import { Avatar, Button, Card, Center, Grid, Group, Input, Stack, Text, Tooltip } from "@mantine/core";
|
||||
import { IconSearch } from "@tabler/icons-react";
|
||||
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import { getIconUrl, getIntegrationName } from "@homarr/definitions";
|
||||
import type { IntegrationKind, WidgetKind } from "@homarr/definitions";
|
||||
import { createModal } from "@homarr/modals";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import type { TablerIcon } from "@homarr/ui";
|
||||
@@ -21,6 +22,10 @@ export const ItemSelectModal = createModal<void>(({ actions }) => {
|
||||
objectEntries(widgetImports)
|
||||
.map(([kind, value]) => ({
|
||||
kind,
|
||||
supportedIntegrations:
|
||||
"supportedIntegrations" in value.definition
|
||||
? value.definition.supportedIntegrations.filter((integration) => integration !== "mock")
|
||||
: [],
|
||||
icon: value.definition.icon,
|
||||
name: t(`widget.${kind}.name`),
|
||||
description: t(`widget.${kind}.description`),
|
||||
@@ -74,6 +79,7 @@ const WidgetItem = ({
|
||||
}: {
|
||||
item: {
|
||||
kind: WidgetKind;
|
||||
supportedIntegrations: IntegrationKind[];
|
||||
name: string;
|
||||
description: string;
|
||||
icon: TablerIcon;
|
||||
@@ -97,7 +103,8 @@ const WidgetItem = ({
|
||||
{item.description}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Button onClick={onSelect} variant="light" size="xs" mt="auto" radius="md" fullWidth>
|
||||
<SupportedIntegrations mt="auto" integrations={item.supportedIntegrations} />
|
||||
<Button onClick={onSelect} variant="light" size="xs" radius="md" fullWidth>
|
||||
{t(`item.create.addToBoard`)}
|
||||
</Button>
|
||||
</Stack>
|
||||
@@ -105,3 +112,48 @@ const WidgetItem = ({
|
||||
</Grid.Col>
|
||||
);
|
||||
};
|
||||
|
||||
interface SupportedIntegrationsProps {
|
||||
integrations: IntegrationKind[];
|
||||
mt: string;
|
||||
}
|
||||
|
||||
const SupportedIntegrations = ({ integrations, mt }: SupportedIntegrationsProps) => {
|
||||
if (integrations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// When there are 8 or more integrations, we show 6 and a "+X" avatar. Otherwise, we show all integrations.
|
||||
const countToShow = integrations.length >= 8 ? 6 : 7;
|
||||
const moreCount = integrations.length - countToShow;
|
||||
|
||||
return (
|
||||
<Center mt={mt}>
|
||||
<Tooltip.Group openDelay={300} closeDelay={100}>
|
||||
<Group gap={2}>
|
||||
{integrations.slice(0, countToShow).map((integration) => (
|
||||
<Tooltip key={integration} label={getIntegrationName(integration)} withArrow>
|
||||
<Avatar src={getIconUrl(integration)} size="xs" radius="xl" />
|
||||
</Tooltip>
|
||||
))}
|
||||
{moreCount > 0 && (
|
||||
<Tooltip
|
||||
withArrow
|
||||
label={
|
||||
<>
|
||||
{integrations.slice(countToShow).map((integration) => (
|
||||
<div key={integration}>{getIntegrationName(integration)}</div>
|
||||
))}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Avatar radius="xl" size="xs">
|
||||
+{moreCount}
|
||||
</Avatar>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Group>
|
||||
</Tooltip.Group>
|
||||
</Center>
|
||||
);
|
||||
};
|
||||
@@ -39,7 +39,7 @@
|
||||
"@homarr/widgets": "workspace:^0.1.0",
|
||||
"dayjs": "^1.11.19",
|
||||
"dotenv": "^17.3.1",
|
||||
"fastify": "^5.7.4",
|
||||
"fastify": "^5.8.2",
|
||||
"superjson": "2.2.6",
|
||||
"undici": "7.18.2"
|
||||
},
|
||||
@@ -47,10 +47,10 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/node": "^24.10.13",
|
||||
"@types/node": "^24.12.0",
|
||||
"dotenv-cli": "^11.0.0",
|
||||
"esbuild": "^0.27.3",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"prettier": "^3.8.1",
|
||||
"tsx": "4.20.4",
|
||||
"typescript": "^5.9.3"
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/ws": "^8.18.1",
|
||||
"esbuild": "^0.27.3",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"prettier": "^3.8.1",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:24.13.1-trixie AS base
|
||||
FROM node:24.14.0-trixie AS base
|
||||
WORKDIR /app
|
||||
COPY package.json .
|
||||
COPY pnpm-lock.yaml .
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^12.6.2"
|
||||
},
|
||||
"packageManager": "pnpm@10.30.1",
|
||||
"packageManager": "pnpm@10.31.0",
|
||||
"engines": {
|
||||
"node": ">=24.13.1",
|
||||
"pnpm": ">=10.30.1"
|
||||
"node": ">=24.14.0",
|
||||
"pnpm": ">=10.31.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
|
||||
+26
-12
@@ -155,6 +155,13 @@
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/immich" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/immich.svg" alt="Immich" width="90" height="90" />
|
||||
<br/>
|
||||
<p align="center">Immich</p>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/jellyfin" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/jellyfin.svg" alt="Jellyfin" width="90" height="90" />
|
||||
<br/>
|
||||
@@ -195,15 +202,15 @@
|
||||
<br/>
|
||||
<p align="center">NPM</p>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/ntfy" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/ntfy.svg" alt="ntfy" width="90" height="90" />
|
||||
<br/>
|
||||
<p align="center">ntfy</p>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/nzbget" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/nzbget.svg" alt="NZBGet" width="90" height="90" />
|
||||
<br/>
|
||||
@@ -244,15 +251,15 @@
|
||||
<br/>
|
||||
<p align="center">Plex</p>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/prowlarr" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/prowlarr.svg" alt="Prowlarr" width="90" height="90" />
|
||||
<br/>
|
||||
<p align="center">Prowlarr</p>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/proxmox" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/proxmox.svg" alt="Proxmox" width="90" height="90" />
|
||||
<br/>
|
||||
@@ -293,6 +300,13 @@
|
||||
<br/>
|
||||
<p align="center">SABnzbd</p>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/seerr" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/seerr.svg" alt="Seerr" width="90" height="90" />
|
||||
<br/>
|
||||
<p align="center">Seerr</p>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/slskd" target="_blank" rel="noreferrer noopener">
|
||||
@@ -300,8 +314,8 @@
|
||||
<br/>
|
||||
<p align="center">Slskd</p>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/sonarr" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/sonarr.svg" alt="Sonarr" width="90" height="90" />
|
||||
<br/>
|
||||
@@ -335,8 +349,8 @@
|
||||
<br/>
|
||||
<p align="center">Unifi<br/>Controller</p>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
</td></tr>
|
||||
<tr><td align="center">
|
||||
<a href="https://homarr.dev/docs/integrations/unraid" target="_blank" rel="noreferrer noopener">
|
||||
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/unraid.svg" alt="Unraid" width="90" height="90" />
|
||||
<br/>
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("Health checks", () => {
|
||||
// Assert
|
||||
expect(readyResponse.status).toBe(200);
|
||||
expect(liveResponse.status).toBe(200);
|
||||
}, 20_000);
|
||||
}, 60_000);
|
||||
|
||||
test("ready and live should return 200 OK with external redis", async () => {
|
||||
// Arrange
|
||||
@@ -42,5 +42,5 @@ describe("Health checks", () => {
|
||||
liveResponse.status,
|
||||
`Expected live to return OK statusCode=${liveResponse.status} content=${await liveResponse.text()}`,
|
||||
).toBe(200);
|
||||
}, 20_000);
|
||||
}, 60_000);
|
||||
});
|
||||
+1
-1
@@ -12,5 +12,5 @@ describe("Home", () => {
|
||||
|
||||
// Assert
|
||||
expect(homeResponse.status).toBe(200);
|
||||
}, 20_000);
|
||||
}, 60_000);
|
||||
});
|
||||
@@ -18,6 +18,11 @@ export const createHomarrContainer = (
|
||||
.withExposedPorts(7575)
|
||||
.withEnvironment({
|
||||
...options.environment,
|
||||
// We disable external connections due to the following reasons:
|
||||
// - No icons have to be downloaded (11k)
|
||||
// - No analytics data is sent
|
||||
// - It is just faster and makes the tests more reliable (better performance)
|
||||
NO_EXTERNAL_CONNECTION: true.toString(),
|
||||
SECRET_ENCRYPTION_KEY: "0".repeat(64),
|
||||
})
|
||||
.withBindMounts(
|
||||
|
||||
+14
-14
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homarr",
|
||||
"version": "1.54.0",
|
||||
"version": "1.55.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "cross-env CI=true turbo build",
|
||||
@@ -42,29 +42,29 @@
|
||||
"@semantic-release/commit-analyzer": "^13.0.1",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"@semantic-release/github": "^12.0.6",
|
||||
"@semantic-release/npm": "^13.1.4",
|
||||
"@semantic-release/npm": "^13.1.5",
|
||||
"@semantic-release/release-notes-generator": "^14.1.0",
|
||||
"@testcontainers/redis": "^11.12.0",
|
||||
"@turbo/gen": "^2.8.9",
|
||||
"@turbo/gen": "^2.8.14",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"@vitest/ui": "^4.0.18",
|
||||
"conventional-changelog-conventionalcommits": "^9.1.0",
|
||||
"conventional-changelog-conventionalcommits": "^9.3.0",
|
||||
"cross-env": "^10.1.0",
|
||||
"jsdom": "^28.1.0",
|
||||
"json5": "^2.2.3",
|
||||
"prettier": "^3.8.1",
|
||||
"semantic-release": "^25.0.3",
|
||||
"testcontainers": "^11.12.0",
|
||||
"turbo": "^2.8.9",
|
||||
"turbo": "^2.8.14",
|
||||
"typescript": "^5.9.3",
|
||||
"vite-tsconfig-paths": "^6.1.1",
|
||||
"vitest": "^4.0.18"
|
||||
},
|
||||
"packageManager": "pnpm@10.30.1",
|
||||
"packageManager": "pnpm@10.31.0",
|
||||
"engines": {
|
||||
"node": ">=24.13.1",
|
||||
"pnpm": ">=10.30.1"
|
||||
"node": ">=24.14.0",
|
||||
"pnpm": ">=10.31.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
@@ -81,12 +81,12 @@
|
||||
"overrides": {
|
||||
"@babel/helpers@<7.26.10": ">=7.28.6",
|
||||
"@babel/runtime@<7.26.10": ">=7.28.6",
|
||||
"axios@>=1.0.0 <1.8.2": ">=1.13.5",
|
||||
"brace-expansion@>=2.0.0 <=2.0.1": ">=5.0.3",
|
||||
"brace-expansion@>=1.0.0 <=1.1.11": ">=4.0.1",
|
||||
"axios@>=1.0.0 <1.8.2": ">=1.13.6",
|
||||
"brace-expansion@>=2.0.0 <=2.0.1": ">=5.0.4",
|
||||
"brace-expansion@>=1.0.0 <=1.1.11": ">=5.0.4",
|
||||
"esbuild@<=0.24.2": ">=0.27.3",
|
||||
"form-data@>=4.0.0 <4.0.4": ">=4.0.5",
|
||||
"hono@<4.6.5": ">=4.11.9",
|
||||
"hono@<4.6.5": ">=4.12.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",
|
||||
@@ -94,8 +94,8 @@
|
||||
"react-is": "^19.2.4",
|
||||
"rollup@>=4.0.0 <4.22.4": ">=4.59.0",
|
||||
"sha.js@<=2.4.11": ">=2.4.12",
|
||||
"tar-fs@>=3.0.0 <3.0.9": ">=3.1.1",
|
||||
"tar-fs@>=2.0.0 <2.1.3": ">=3.1.1",
|
||||
"tar-fs@>=3.0.0 <3.0.9": ">=3.1.2",
|
||||
"tar-fs@>=2.0.0 <2.1.3": ">=3.1.2",
|
||||
"tmp@<=0.2.3": ">=0.2.5",
|
||||
"vite@>=5.0.0 <=5.4.18": ">=7.3.1"
|
||||
},
|
||||
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,10 @@
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@kubernetes/client-node": "^1.4.0",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"@trpc/client": "^11.10.0",
|
||||
"@trpc/react-query": "^11.10.0",
|
||||
"@trpc/server": "^11.10.0",
|
||||
"@trpc/tanstack-react-query": "^11.10.0",
|
||||
"@trpc/client": "^11.12.0",
|
||||
"@trpc/react-query": "^11.12.0",
|
||||
"@trpc/server": "^11.12.0",
|
||||
"@trpc/tanstack-react-query": "^11.12.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"next": "16.1.6",
|
||||
"react": "19.2.4",
|
||||
@@ -58,7 +58,7 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"prettier": "^3.8.1",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { getIntegrationKindsByCategory } from "@homarr/definitions";
|
||||
import {
|
||||
immichAlbumRequestHandler,
|
||||
immichAlbumsRequestHandler,
|
||||
immichStatsRequestHandler,
|
||||
} from "@homarr/request-handler/immich";
|
||||
|
||||
import type { IntegrationAction } from "../../middlewares/integration";
|
||||
import { createOneIntegrationMiddleware } from "../../middlewares/integration";
|
||||
import { createTRPCRouter, publicProcedure } from "../../trpc";
|
||||
|
||||
const createImmichIntegrationMiddleware = (action: IntegrationAction) =>
|
||||
createOneIntegrationMiddleware(action, ...getIntegrationKindsByCategory("photoService"));
|
||||
|
||||
export const immichRouter = createTRPCRouter({
|
||||
getServerStats: publicProcedure.concat(createImmichIntegrationMiddleware("query")).query(async ({ ctx }) => {
|
||||
const innerHandler = immichStatsRequestHandler.handler(ctx.integration, {});
|
||||
const data = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
|
||||
return data.data;
|
||||
}),
|
||||
|
||||
getAlbum: publicProcedure
|
||||
.concat(createImmichIntegrationMiddleware("query"))
|
||||
.input(
|
||||
z.object({
|
||||
albumId: z.string(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const innerHandler = immichAlbumRequestHandler.handler(ctx.integration, { albumId: input.albumId });
|
||||
const data = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
|
||||
return data.data;
|
||||
}),
|
||||
|
||||
getAlbums: publicProcedure.concat(createImmichIntegrationMiddleware("query")).query(async ({ ctx }) => {
|
||||
const innerHandler = immichAlbumsRequestHandler.handler(ctx.integration, {});
|
||||
const data = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
|
||||
return data.data;
|
||||
}),
|
||||
});
|
||||
@@ -4,6 +4,7 @@ import { createTRPCRouter } from "../../trpc";
|
||||
|
||||
export const widgetRouter = createTRPCRouter({
|
||||
coolify: lazy(() => import("./coolify").then((mod) => mod.coolifyRouter)),
|
||||
immich: lazy(() => import("./immich").then((mod) => mod.immichRouter)),
|
||||
notebook: lazy(() => import("./notebook").then((mod) => mod.notebookRouter)),
|
||||
weather: lazy(() => import("./weather").then((mod) => mod.weatherRouter)),
|
||||
app: lazy(() => import("./app").then((mod) => mod.appRouter)),
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"bcrypt": "^6.0.0",
|
||||
"cookies": "^0.9.1",
|
||||
"ldapts": "8.1.6",
|
||||
"ldapts": "8.1.7",
|
||||
"next": "16.1.6",
|
||||
"next-auth": "5.0.0-beta.30",
|
||||
"react": "19.2.4",
|
||||
@@ -46,7 +46,7 @@
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/bcrypt": "6.0.0",
|
||||
"@types/cookies": "0.9.2",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"prettier": "^3.8.1",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,9 @@
|
||||
"clean": "rm -rf .turbo node_modules",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
"lint": "eslint",
|
||||
"typecheck": "tsc --noEmit"
|
||||
"run": "pnpm with-env node cli.cjs",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"with-env": "dotenv -e .env --"
|
||||
},
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
@@ -35,7 +37,7 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"esbuild": "^0.27.3",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { command, string } from "@drizzle-team/brocli";
|
||||
|
||||
import { db, eq } from "@homarr/db";
|
||||
import { integrations } from "@homarr/db/schema";
|
||||
|
||||
export const integrationsDelete = command({
|
||||
name: "delete",
|
||||
desc: "Delete an integration by id or name",
|
||||
options: {
|
||||
id: string("id").alias("i").desc("ID of the integration"),
|
||||
name: string("name").alias("n").desc("Name of the integration"),
|
||||
},
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
handler: async (options) => {
|
||||
if (!options.id && !options.name) {
|
||||
console.error("Either --id or --name must be provided");
|
||||
return;
|
||||
}
|
||||
|
||||
let entry;
|
||||
if (options.id) {
|
||||
entry = await db.query.integrations.findFirst({
|
||||
where: eq(integrations.id, options.id),
|
||||
});
|
||||
} else if (options.name) {
|
||||
entry = await db.query.integrations.findFirst({
|
||||
where: eq(integrations.name, options.name),
|
||||
});
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
console.error("Integration not found");
|
||||
return;
|
||||
}
|
||||
|
||||
await db.delete(integrations).where(eq(integrations.id, entry.id));
|
||||
console.log(`Integration ${entry.name} (${entry.id}) deleted`);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { command } from "@drizzle-team/brocli";
|
||||
|
||||
import { db } from "@homarr/db";
|
||||
|
||||
export const integrationsList = command({
|
||||
name: "list",
|
||||
desc: "List all integrations (id and name)",
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
handler: async () => {
|
||||
const all = await db.query.integrations.findMany();
|
||||
if (all.length === 0) {
|
||||
console.log("No integrations found");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("ID\t\t\t\tName");
|
||||
for (const i of all) {
|
||||
console.log(`${i.id}\t${i.name}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { command } from "@drizzle-team/brocli";
|
||||
|
||||
import { integrationsDelete } from "./integrations-delete";
|
||||
import { integrationsList } from "./integrations-list";
|
||||
|
||||
export const integrationsRoot = command({
|
||||
name: "integrations",
|
||||
desc: "Group of commands to manage integrations",
|
||||
subcommands: [integrationsList, integrationsDelete],
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { command, string } from "@drizzle-team/brocli";
|
||||
|
||||
import { db, eq } from "@homarr/db";
|
||||
import { users } from "@homarr/db/schema";
|
||||
|
||||
export const usersDelete = command({
|
||||
name: "delete",
|
||||
desc: "Delete a user by id or username",
|
||||
options: {
|
||||
id: string("id").alias("i").desc("ID of the user"),
|
||||
username: string("username").alias("u").desc("Name of the user"),
|
||||
},
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
handler: async (options) => {
|
||||
if (!options.id && !options.username) {
|
||||
console.error("Either --id or --username must be provided");
|
||||
return;
|
||||
}
|
||||
|
||||
let user;
|
||||
if (options.id) {
|
||||
user = await db.query.users.findFirst({
|
||||
where: eq(users.id, options.id),
|
||||
});
|
||||
} else if (options.username) {
|
||||
user = await db.query.users.findFirst({
|
||||
where: eq(users.name, options.username),
|
||||
});
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
console.error("User not found");
|
||||
return;
|
||||
}
|
||||
|
||||
await db.delete(users).where(eq(users.id, user.id));
|
||||
console.log(`User ${user.name ?? user.id} (${user.id}) deleted`);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { command } from "@drizzle-team/brocli";
|
||||
|
||||
import { db } from "@homarr/db";
|
||||
|
||||
export const usersList = command({
|
||||
name: "list",
|
||||
desc: "List all users (id, username, email)",
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
handler: async () => {
|
||||
const allUsers = await db.query.users.findMany();
|
||||
|
||||
if (allUsers.length === 0) {
|
||||
console.log("No users found");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("ID\t\t\t\tUsername\tEmail");
|
||||
for (const user of allUsers) {
|
||||
console.log(`${user.id}\t${user.name ?? ""}\t${user.email ?? ""}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { command, string } from "@drizzle-team/brocli";
|
||||
|
||||
import { hashPasswordAsync } from "@homarr/auth";
|
||||
import { db, eq } from "@homarr/db";
|
||||
import { sessions, users } from "@homarr/db/schema";
|
||||
|
||||
export const usersUpdatePassword = command({
|
||||
name: "update-password",
|
||||
desc: "Update the password for a user (credentials provider only)",
|
||||
options: {
|
||||
id: string("id").alias("i").desc("ID of the user"),
|
||||
username: string("username").alias("u").desc("Name of the user"),
|
||||
password: string("password").alias("p").required().desc("New password"),
|
||||
},
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
handler: async (options) => {
|
||||
if (!process.env.AUTH_PROVIDERS?.toLowerCase().includes("credentials")) {
|
||||
console.error("Credentials provider is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options.id && !options.username) {
|
||||
console.error("Either --id or --username must be provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await db.query.users.findFirst({
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
where: options.id ? eq(users.id, options.id) : eq(users.name, options.username!),
|
||||
});
|
||||
|
||||
if (!user?.salt) {
|
||||
console.error("User not found or has no credentials record");
|
||||
return;
|
||||
}
|
||||
|
||||
await db
|
||||
.update(users)
|
||||
.set({
|
||||
password: await hashPasswordAsync(options.password, user.salt),
|
||||
})
|
||||
.where(eq(users.id, user.id));
|
||||
|
||||
// invalidate existing sessions
|
||||
await db.delete(sessions).where(eq(sessions.userId, user.id));
|
||||
console.log(`All sessions for user ${user.name ?? user.id} have been deleted`);
|
||||
|
||||
console.log("Password updated successfully");
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import { command } from "@drizzle-team/brocli";
|
||||
|
||||
import { usersDelete } from "./users-delete";
|
||||
import { usersList } from "./users-list";
|
||||
import { usersUpdatePassword } from "./users-update-password";
|
||||
|
||||
export const usersRoot = command({
|
||||
name: "users",
|
||||
desc: "Group of commands to manage users",
|
||||
subcommands: [usersList, usersDelete, usersUpdatePassword],
|
||||
});
|
||||
@@ -1,10 +1,12 @@
|
||||
import { run } from "@drizzle-team/brocli";
|
||||
|
||||
import { fixUsernames } from "./commands/fix-usernames";
|
||||
import { integrationsRoot } from "./commands/integrations";
|
||||
import { recreateAdmin } from "./commands/recreate-admin";
|
||||
import { resetPassword } from "./commands/reset-password";
|
||||
import { usersRoot } from "./commands/users";
|
||||
|
||||
const commands = [resetPassword, fixUsernames, recreateAdmin];
|
||||
const commands = [usersRoot, integrationsRoot, resetPassword, fixUsernames, recreateAdmin];
|
||||
|
||||
void run(commands, {
|
||||
name: "homarr-cli",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -41,9 +41,9 @@
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"dns-caching": "^0.2.9",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"ioredis": "5.9.3",
|
||||
"mysql2": "3.17.4",
|
||||
"pg": "^8.18.0",
|
||||
"ioredis": "5.10.0",
|
||||
"mysql2": "3.19.0",
|
||||
"pg": "^8.20.0",
|
||||
"superjson": "2.2.6",
|
||||
"winston": "3.19.0",
|
||||
"zod": "^4.2.1"
|
||||
@@ -53,8 +53,8 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/better-sqlite3": "7.6.13",
|
||||
"@types/pg": "^8.16.0",
|
||||
"eslint": "^9.39.3",
|
||||
"@types/pg": "^8.18.0",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,9 @@
|
||||
"@homarr/core": "workspace:^0.1.0",
|
||||
"@homarr/cron-jobs": "workspace:^0.1.0",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"@trpc/client": "^11.10.0",
|
||||
"@trpc/server": "^11.10.0",
|
||||
"@trpc/tanstack-react-query": "^11.10.0",
|
||||
"@trpc/client": "^11.12.0",
|
||||
"@trpc/server": "^11.12.0",
|
||||
"@trpc/tanstack-react-query": "^11.12.0",
|
||||
"node-cron": "^4.2.1",
|
||||
"react": "19.2.4",
|
||||
"zod": "^4.2.1"
|
||||
@@ -42,7 +42,7 @@
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/node-cron": "^3.0.11",
|
||||
"@types/react": "19.2.14",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/node-cron": "^3.0.11",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@
|
||||
"@homarr/core": "workspace:^0.1.0",
|
||||
"@homarr/definitions": "workspace:^0.1.0",
|
||||
"@homarr/server-settings": "workspace:^0.1.0",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@mantine/core": "^8.3.16",
|
||||
"@paralleldrive/cuid2": "^3.3.0",
|
||||
"@testcontainers/mysql": "^11.12.0",
|
||||
"@testcontainers/postgresql": "^11.12.0",
|
||||
@@ -56,8 +56,8 @@
|
||||
"drizzle-kit": "^0.31.9",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"drizzle-zod": "^0.8.3",
|
||||
"mysql2": "3.17.4",
|
||||
"pg": "^8.18.0",
|
||||
"mysql2": "3.19.0",
|
||||
"pg": "^8.20.0",
|
||||
"superjson": "2.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -65,10 +65,10 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/better-sqlite3": "7.6.13",
|
||||
"@types/pg": "^8.16.0",
|
||||
"@types/pg": "^8.18.0",
|
||||
"dotenv-cli": "^11.0.0",
|
||||
"esbuild": "^0.27.3",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"prettier": "^3.8.1",
|
||||
"tsx": "4.20.4",
|
||||
"typescript": "^5.9.3"
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"@homarr/common": "workspace:^0.1.0",
|
||||
"fast-xml-parser": "^5.3.7",
|
||||
"fast-xml-parser": "^5.4.2",
|
||||
"zod": "^4.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"tsx": "4.20.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
|
||||
@@ -185,6 +185,7 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/radarr"
|
||||
| "/docs/integrations/readarr"
|
||||
| "/docs/integrations/sabnzbd"
|
||||
| "/docs/integrations/seerr"
|
||||
| "/docs/integrations/slskd"
|
||||
| "/docs/integrations/sonarr"
|
||||
| "/docs/integrations/tdarr"
|
||||
|
||||
@@ -143,6 +143,13 @@ export const integrationDefs = {
|
||||
category: ["mediaSearch", "mediaRequest", "search"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/jellyseerr"),
|
||||
},
|
||||
seerr: {
|
||||
name: "Seerr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/seerr.svg",
|
||||
category: ["mediaSearch", "mediaRequest", "search"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/seerr"),
|
||||
},
|
||||
overseerr: {
|
||||
name: "Overseerr",
|
||||
secretKinds: [["apiKey"]],
|
||||
@@ -327,6 +334,14 @@ export const integrationDefs = {
|
||||
// @ts-expect-error - docs page will be created when integration is merged
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/coolify"),
|
||||
},
|
||||
immich: {
|
||||
name: "Immich",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/immich.svg",
|
||||
category: ["photoService"],
|
||||
// @ts-expect-error TS2345
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/immich"),
|
||||
},
|
||||
// This integration only returns mock data, it is used during development (but can also be used in production by directly going to the create page)
|
||||
mock: {
|
||||
name: "Mock",
|
||||
@@ -413,6 +428,7 @@ export const integrationCategories = [
|
||||
"releasesProvider",
|
||||
"notifications",
|
||||
"firewall",
|
||||
"photoService",
|
||||
] as const;
|
||||
|
||||
export type IntegrationCategory = (typeof integrationCategories)[number];
|
||||
@@ -31,5 +31,7 @@ export const widgetKinds = [
|
||||
"systemResources",
|
||||
"coolify",
|
||||
"systemDisks",
|
||||
"immich-serverStats",
|
||||
"immich-albumCarousel",
|
||||
] as const;
|
||||
export type WidgetKind = (typeof widgetKinds)[number];
|
||||
@@ -33,7 +33,7 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/dockerode": "^4.0.1",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
"@homarr/common": "workspace:^0.1.0",
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@mantine/form": "^8.3.15",
|
||||
"@mantine/form": "^8.3.16",
|
||||
"mantine-form-zod-resolver": "^1.3.0",
|
||||
"zod": "^4.2.1"
|
||||
},
|
||||
@@ -34,7 +34,7 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/ui": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@mantine/core": "^8.3.16",
|
||||
"react": "19.2.4",
|
||||
"zod": "^4.2.1"
|
||||
},
|
||||
@@ -38,7 +38,7 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/bcrypt": "6.0.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import { createHmac, hkdfSync } from "node:crypto";
|
||||
|
||||
import { createId } from "@homarr/common";
|
||||
import { env } from "@homarr/common/env";
|
||||
import { decryptSecret, encryptSecret } from "@homarr/common/server";
|
||||
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
@@ -9,29 +10,22 @@ import { createGetSetChannel } from "@homarr/redis";
|
||||
|
||||
const logger = createLogger({ module: "imageProxy" });
|
||||
|
||||
const createHashChannel = (hash: `${string}.${string}`) => createGetSetChannel<string>(`image-proxy:hash:${hash}`);
|
||||
const createHmacChannel = (hmac: `${string}.${string}`) => createGetSetChannel<string>(`image-proxy:hmac:${hmac}`);
|
||||
const createUrlByIdChannel = (id: string) =>
|
||||
createGetSetChannel<{
|
||||
url: `${string}.${string}`;
|
||||
headers: `${string}.${string}`;
|
||||
}>(`image-proxy:url:${id}`);
|
||||
const saltChannel = createGetSetChannel<string>("image-proxy:salt");
|
||||
|
||||
export class ImageProxy {
|
||||
private static salt: string | null = null;
|
||||
private async getOrCreateSaltAsync(): Promise<string> {
|
||||
if (ImageProxy.salt) return ImageProxy.salt;
|
||||
const existingSalt = await saltChannel.getAsync();
|
||||
if (existingSalt) {
|
||||
ImageProxy.salt = existingSalt;
|
||||
return existingSalt;
|
||||
}
|
||||
private static hmacKey: Buffer<ArrayBuffer> | null = null;
|
||||
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
logger.debug("Generated new salt for image proxy", { salt });
|
||||
ImageProxy.salt = salt;
|
||||
await saltChannel.setAsync(salt);
|
||||
return salt;
|
||||
/**
|
||||
* Generate secure key for image-proxy from encryption key
|
||||
*/
|
||||
private static getHmacKey(): Buffer<ArrayBuffer> {
|
||||
this.hmacKey ??= Buffer.from(hkdfSync("sha256", env.SECRET_ENCRYPTION_KEY, "", "image-proxy", 32));
|
||||
return this.hmacKey;
|
||||
}
|
||||
|
||||
public async createImageAsync(url: string, headers?: Record<string, string>): Promise<string> {
|
||||
@@ -106,20 +100,18 @@ export class ImageProxy {
|
||||
}
|
||||
|
||||
private async getExistingIdAsync(url: string, headers: Record<string, string> | undefined): Promise<string | null> {
|
||||
const salt = await this.getOrCreateSaltAsync();
|
||||
const urlHash = await bcrypt.hash(url, salt);
|
||||
const headerHash = await bcrypt.hash(JSON.stringify(headers ?? null), salt);
|
||||
const urlHash = this.hashSecret(url);
|
||||
const headerHash = this.hashSecret(JSON.stringify(headers ?? null));
|
||||
|
||||
const channel = createHashChannel(`${urlHash}.${headerHash}`);
|
||||
const channel = createHmacChannel(`${urlHash}.${headerHash}`);
|
||||
return await channel.getAsync();
|
||||
}
|
||||
|
||||
private async storeImageAsync(id: string, url: string, headers: Record<string, string> | undefined): Promise<void> {
|
||||
const salt = await this.getOrCreateSaltAsync();
|
||||
const urlHash = await bcrypt.hash(url, salt);
|
||||
const headerHash = await bcrypt.hash(JSON.stringify(headers ?? null), salt);
|
||||
const urlHash = this.hashSecret(url);
|
||||
const headerHash = this.hashSecret(JSON.stringify(headers ?? null));
|
||||
|
||||
const hashChannel = createHashChannel(`${urlHash}.${headerHash}`);
|
||||
const hashChannel = createHmacChannel(`${urlHash}.${headerHash}`);
|
||||
const urlHeaderChannel = createUrlByIdChannel(id);
|
||||
await urlHeaderChannel.setAsync({
|
||||
url: encryptSecret(url),
|
||||
@@ -134,6 +126,10 @@ export class ImageProxy {
|
||||
});
|
||||
}
|
||||
|
||||
private hashSecret(value: string): string {
|
||||
return createHmac("sha256", ImageProxy.getHmacKey()).update(value).digest("hex");
|
||||
}
|
||||
|
||||
private redactUrl(url: string): string {
|
||||
const urlObject = new URL(url);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"@homarr/redis": "workspace:^0.1.0",
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@immich/sdk": "^2.5.6",
|
||||
"@jellyfin/sdk": "^0.13.0",
|
||||
"@octokit/auth-app": "^8.2.0",
|
||||
"ical.js": "^2.2.1",
|
||||
@@ -56,7 +57,7 @@
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/node-unifi": "^2.5.1",
|
||||
"@types/xml2js": "^0.4.14",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import { GitlabIntegration } from "../gitlab/gitlab-integration";
|
||||
import { GlancesIntegration } from "../glances/glances-integration";
|
||||
import { HomeAssistantIntegration } from "../homeassistant/homeassistant-integration";
|
||||
import { ICalIntegration } from "../ical/ical-integration";
|
||||
import { ImmichIntegration } from "../immich/immich-integration";
|
||||
import { JellyfinIntegration } from "../jellyfin/jellyfin-integration";
|
||||
import { JellyseerrIntegration } from "../jellyseerr/jellyseerr-integration";
|
||||
import { LinuxServerIOIntegration } from "../linuxserverio/linuxserverio-integration";
|
||||
@@ -39,6 +40,7 @@ import { PlexIntegration } from "../plex/plex-integration";
|
||||
import { ProwlarrIntegration } from "../prowlarr/prowlarr-integration";
|
||||
import { ProxmoxIntegration } from "../proxmox/proxmox-integration";
|
||||
import { QuayIntegration } from "../quay/quay-integration";
|
||||
import { SeerrIntegration } from "../seerr/seerr-integration";
|
||||
import { TrueNasIntegration } from "../truenas/truenas-integration";
|
||||
import { UnifiControllerIntegration } from "../unifi-controller/unifi-controller-integration";
|
||||
import { UnraidIntegration } from "../unraid/unraid-integration";
|
||||
@@ -82,6 +84,7 @@ export const integrationCreators = {
|
||||
slskd: SlskdIntegration,
|
||||
aria2: Aria2Integration,
|
||||
jellyseerr: JellyseerrIntegration,
|
||||
seerr: SeerrIntegration,
|
||||
overseerr: OverseerrIntegration,
|
||||
prowlarr: ProwlarrIntegration,
|
||||
openmediavault: OpenMediaVaultIntegration,
|
||||
@@ -109,6 +112,7 @@ export const integrationCreators = {
|
||||
unraid: UnraidIntegration,
|
||||
coolify: CoolifyIntegration,
|
||||
glances: GlancesIntegration,
|
||||
immich: ImmichIntegration,
|
||||
} satisfies Record<IntegrationKind, IntegrationInstance | [(input: IntegrationInput) => Promise<Integration>]>;
|
||||
|
||||
type IntegrationInstanceOfKind<TKind extends keyof typeof integrationCreators> = {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import { getAlbumInfo, getAllAlbums, getMyUser, getServerStatistics, init, searchUsers } from "@immich/sdk";
|
||||
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
import { ImageProxy } from "@homarr/image-proxy";
|
||||
|
||||
import type { IntegrationInput, IntegrationTestingInput } from "../base/integration";
|
||||
import { Integration } from "../base/integration";
|
||||
import type { TestingResult } from "../base/test-connection/test-connection-service";
|
||||
|
||||
export interface ImmichServerStats {
|
||||
userCount: number;
|
||||
photoCount: number;
|
||||
videoCount: number;
|
||||
totalLibraryUsageInBytes: number;
|
||||
}
|
||||
|
||||
export interface ImmichAlbum {
|
||||
id: string;
|
||||
albumName: string;
|
||||
assets: ImmichAsset[];
|
||||
}
|
||||
|
||||
export interface ImmichAsset {
|
||||
id: string;
|
||||
deviceAssetId: string;
|
||||
originalPath: string;
|
||||
thumbhash: string | null;
|
||||
fileModifiedAt: string;
|
||||
fileCreatedAt: string;
|
||||
updatedAt: string;
|
||||
type: "IMAGE" | "VIDEO" | "AUDIO" | "OTHER";
|
||||
publicLink: string;
|
||||
}
|
||||
|
||||
const logger = createLogger({ module: "immich-integration" });
|
||||
|
||||
export class ImmichIntegration extends Integration {
|
||||
constructor(integration: IntegrationInput) {
|
||||
super(integration);
|
||||
}
|
||||
|
||||
public async getServerStatsAsync(): Promise<ImmichServerStats> {
|
||||
this.initClient();
|
||||
const [statistics, users] = await Promise.all([getServerStatistics(), searchUsers()]);
|
||||
return {
|
||||
photoCount: statistics.photos,
|
||||
userCount: users.length,
|
||||
totalLibraryUsageInBytes: statistics.usage,
|
||||
videoCount: statistics.videos,
|
||||
};
|
||||
}
|
||||
|
||||
public async getAlbumAsync(albumId: string): Promise<ImmichAlbum> {
|
||||
this.initClient();
|
||||
const album = await getAlbumInfo({ id: albumId });
|
||||
const imageProxy = new ImageProxy();
|
||||
return {
|
||||
albumName: album.albumName,
|
||||
assets: await Promise.all(
|
||||
album.assets.map(async (asset) => {
|
||||
const publicLink = await imageProxy.createImageAsync(
|
||||
this.url(`/api/assets/${asset.id}/original`).toString(),
|
||||
{
|
||||
"x-api-key": this.getSecretValue("apiKey"),
|
||||
},
|
||||
);
|
||||
return {
|
||||
id: asset.id,
|
||||
type: asset.type,
|
||||
deviceAssetId: asset.deviceAssetId,
|
||||
thumbhash: asset.thumbhash,
|
||||
fileCreatedAt: asset.fileCreatedAt,
|
||||
fileModifiedAt: asset.fileModifiedAt,
|
||||
originalPath: asset.originalPath,
|
||||
updatedAt: asset.updatedAt,
|
||||
publicLink,
|
||||
};
|
||||
}),
|
||||
),
|
||||
id: album.id,
|
||||
};
|
||||
}
|
||||
|
||||
public async getAlbumsAsync(): Promise<
|
||||
{
|
||||
id: string;
|
||||
albumName: string;
|
||||
assetCount: number;
|
||||
}[]
|
||||
> {
|
||||
this.initClient();
|
||||
const albums = await getAllAlbums({});
|
||||
return albums.map((album) => ({ id: album.id, albumName: album.albumName, assetCount: album.assetCount }));
|
||||
}
|
||||
|
||||
protected async testingAsync(_: IntegrationTestingInput): Promise<TestingResult> {
|
||||
this.initClient();
|
||||
const user = await getMyUser();
|
||||
logger.debug(`Logged in as ${user.name} (${user.id})`);
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the credentials and prepares the client for calls.
|
||||
* Must be called before any other functions.
|
||||
* @private
|
||||
*/
|
||||
private initClient() {
|
||||
init({ baseUrl: this.url("/api").toString(), apiKey: this.getSecretValue("apiKey") });
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ export { NTFYIntegration } from "./ntfy/ntfy-integration";
|
||||
export { OpenMediaVaultIntegration } from "./openmediavault/openmediavault-integration";
|
||||
export { GlancesIntegration } from "./glances/glances-integration";
|
||||
export { OverseerrIntegration } from "./overseerr/overseerr-integration";
|
||||
export { SeerrIntegration } from "./seerr/seerr-integration";
|
||||
export { PiHoleIntegrationV5 } from "./pi-hole/v5/pi-hole-integration-v5";
|
||||
export { PiHoleIntegrationV6 } from "./pi-hole/v6/pi-hole-integration-v6";
|
||||
export { PlexIntegration } from "./plex/plex-integration";
|
||||
@@ -28,6 +29,7 @@ export { UnraidIntegration } from "./unraid/unraid-integration";
|
||||
export { OPNsenseIntegration } from "./opnsense/opnsense-integration";
|
||||
export { ICalIntegration } from "./ical/ical-integration";
|
||||
export { CoolifyIntegration } from "./coolify/coolify-integration";
|
||||
export { ImmichIntegration } from "./immich/immich-integration";
|
||||
|
||||
// Types
|
||||
export type { IntegrationInput } from "./base/integration";
|
||||
@@ -53,6 +55,7 @@ export type {
|
||||
} from "./interfaces/media-transcoding/media-transcoding-types";
|
||||
export type { ReleasesRepository, ReleaseResponse } from "./interfaces/releases-providers/releases-providers-types";
|
||||
export type { Notification } from "./interfaces/notifications/notification-types";
|
||||
export type { ImmichServerStats, ImmichAlbum, ImmichAsset } from "./immich/immich-integration";
|
||||
|
||||
// Schemas
|
||||
export { downloadClientItemSchema } from "./interfaces/downloads/download-client-items";
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import { OverseerrIntegration } from "../overseerr/overseerr-integration";
|
||||
|
||||
// Seerr is a fork of Overseerr, the API is compatible and no additional logic is required.
|
||||
export class SeerrIntegration extends OverseerrIntegration {}
|
||||
@@ -33,8 +33,8 @@
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/ui": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@tabler/icons-react": "^3.37.1",
|
||||
"@mantine/core": "^8.3.16",
|
||||
"@tabler/icons-react": "^3.40.0",
|
||||
"dayjs": "^1.11.19",
|
||||
"next": "16.1.6",
|
||||
"react": "19.2.4",
|
||||
@@ -45,7 +45,7 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -24,15 +24,15 @@
|
||||
"dependencies": {
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/ui": "workspace:^0.1.0",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@mantine/hooks": "^8.3.15",
|
||||
"@mantine/core": "^8.3.16",
|
||||
"@mantine/hooks": "^8.3.16",
|
||||
"react": "19.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -24,14 +24,14 @@
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"@homarr/ui": "workspace:^0.1.0",
|
||||
"@mantine/notifications": "^8.3.15",
|
||||
"@tabler/icons-react": "^3.37.1"
|
||||
"@mantine/notifications": "^8.3.16",
|
||||
"@tabler/icons-react": "^3.40.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,8 @@
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/ui": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@mantine/hooks": "^8.3.15",
|
||||
"@mantine/core": "^8.3.16",
|
||||
"@mantine/hooks": "^8.3.16",
|
||||
"adm-zip": "0.5.16",
|
||||
"next": "16.1.6",
|
||||
"react": "19.2.4",
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -26,14 +26,14 @@
|
||||
"@homarr/core": "workspace:^",
|
||||
"@homarr/db": "workspace:^",
|
||||
"@homarr/definitions": "workspace:^",
|
||||
"ioredis": "5.9.3",
|
||||
"ioredis": "5.10.0",
|
||||
"superjson": "2.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import type { IntegrationKindByCategory } from "@homarr/definitions";
|
||||
import { createIntegrationAsync } from "@homarr/integrations";
|
||||
import type { ImmichAlbum, ImmichServerStats } from "@homarr/integrations";
|
||||
|
||||
import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler";
|
||||
|
||||
export const immichStatsRequestHandler = createCachedIntegrationRequestHandler<
|
||||
ImmichServerStats,
|
||||
IntegrationKindByCategory<"photoService">,
|
||||
Record<string, never>
|
||||
>({
|
||||
async requestAsync(integration) {
|
||||
const integrationInstance = await createIntegrationAsync(integration);
|
||||
return await integrationInstance.getServerStatsAsync();
|
||||
},
|
||||
cacheDuration: dayjs.duration(15, "minute"),
|
||||
queryKey: "immich-server-stats",
|
||||
});
|
||||
|
||||
export const immichAlbumsRequestHandler = createCachedIntegrationRequestHandler<
|
||||
{
|
||||
id: string;
|
||||
albumName: string;
|
||||
assetCount: number;
|
||||
}[],
|
||||
IntegrationKindByCategory<"photoService">,
|
||||
Record<string, never>
|
||||
>({
|
||||
async requestAsync(integration) {
|
||||
const integrationInstance = await createIntegrationAsync(integration);
|
||||
return await integrationInstance.getAlbumsAsync();
|
||||
},
|
||||
cacheDuration: dayjs.duration(15, "minute"),
|
||||
queryKey: "immich-albums",
|
||||
});
|
||||
|
||||
export const immichAlbumRequestHandler = createCachedIntegrationRequestHandler<
|
||||
ImmichAlbum,
|
||||
IntegrationKindByCategory<"photoService">,
|
||||
{ albumId: string }
|
||||
>({
|
||||
async requestAsync(integration, input) {
|
||||
const integrationInstance = await createIntegrationAsync(integration);
|
||||
return await integrationInstance.getAlbumAsync(input.albumId);
|
||||
},
|
||||
cacheDuration: dayjs.duration(15, "minute"),
|
||||
queryKey: "immich-album",
|
||||
});
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
"dependencies": {
|
||||
"@homarr/db": "workspace:^0.1.0",
|
||||
"@homarr/server-settings": "workspace:^0.1.0",
|
||||
"@mantine/dates": "^8.3.15",
|
||||
"@mantine/dates": "^8.3.16",
|
||||
"next": "16.1.6",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
@@ -34,7 +34,7 @@
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,10 @@
|
||||
"@homarr/settings": "workspace:^0.1.0",
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/ui": "workspace:^0.1.0",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@mantine/hooks": "^8.3.15",
|
||||
"@mantine/spotlight": "^8.3.15",
|
||||
"@tabler/icons-react": "^3.37.1",
|
||||
"@mantine/core": "^8.3.16",
|
||||
"@mantine/hooks": "^8.3.16",
|
||||
"@mantine/spotlight": "^8.3.16",
|
||||
"@tabler/icons-react": "^3.40.0",
|
||||
"jotai": "^2.18.0",
|
||||
"next": "16.1.6",
|
||||
"react": "19.2.4",
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -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.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "下载客户端",
|
||||
"description": "允许您查看和管理来自Torrent 和 Usenet 客户端的下载。",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "crwdns3880:0crwdne3880:0",
|
||||
"description": "crwdns3882:0crwdne3882:0",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "crwdns3884:0crwdne3884:0",
|
||||
"description": "crwdns3886:0crwdne3886:0"
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "crwdns3888:0crwdne3888:0",
|
||||
"description": "crwdns3890:0crwdne3890:0"
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "crwdns3892:0crwdne3892:0",
|
||||
"description": "crwdns3894:0crwdne3894:0"
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "crwdns3896:0crwdne3896:0",
|
||||
"description": "crwdns3898:0crwdne3898:0"
|
||||
}
|
||||
},
|
||||
"users": "crwdns3900:0crwdne3900:0",
|
||||
"photos": "crwdns3902:0crwdne3902:0",
|
||||
"videos": "crwdns3904:0crwdne3904:0",
|
||||
"storage": "crwdns3906:0crwdne3906:0"
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "crwdns3908:0crwdne3908:0",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "crwdns3910:0crwdne3910:0",
|
||||
"description": "crwdns3912:0crwdne3912:0"
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "crwdns3914:0crwdne3914:0",
|
||||
"description": "crwdns3916:0crwdne3916:0"
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "crwdns3918:0crwdne3918:0",
|
||||
"description": "crwdns3920:0crwdne3920:0"
|
||||
}
|
||||
},
|
||||
"description": "crwdns3922:0crwdne3922:0",
|
||||
"noAlbumSelected": "crwdns3924:0crwdne3924:0",
|
||||
"noPhotos": "crwdns3926:0crwdne3926:0"
|
||||
},
|
||||
"downloads": {
|
||||
"name": "crwdns1170:0crwdne1170:0",
|
||||
"description": "crwdns1172:0crwdne1172:0",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Download Klient",
|
||||
"description": "Giver dig mulighed for at se og administrere dine downloads fra både Torrent og Usenet klienter.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "Ermöglicht es Ihnen, Ihre Downloads sowohl von Torrent- als auch von Usenet-Clients anzusehen und zu verwalten.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Download Client",
|
||||
"description": "Ermöglicht es Ihnen, Ihre Downloads sowohl von Torrent- als auch von Usenet-Clients anzusehen und zu verwalten.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -1366,46 +1366,46 @@
|
||||
"label": "Vertical"
|
||||
},
|
||||
"grid": {
|
||||
"label": ""
|
||||
"label": "Grid"
|
||||
},
|
||||
"gridHorizontal": {
|
||||
"label": ""
|
||||
"label": "Grid horizontal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"hideTitle": {
|
||||
"label": ""
|
||||
"label": "Hide title"
|
||||
},
|
||||
"hideIcon": {
|
||||
"label": ""
|
||||
"label": "Hide icons"
|
||||
},
|
||||
"hideHostname": {
|
||||
"label": ""
|
||||
"label": "Hide hostnames"
|
||||
},
|
||||
"openNewTab": {
|
||||
"label": ""
|
||||
"label": "Open in new tab"
|
||||
},
|
||||
"items": {
|
||||
"label": "",
|
||||
"add": ""
|
||||
"label": "Bookmarks",
|
||||
"add": "Add bookmark"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dnsHoleSummary": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"name": "DNS Hole Summary",
|
||||
"description": "Displays the summary of your DNS Hole",
|
||||
"option": {
|
||||
"layout": {
|
||||
"label": "",
|
||||
"label": "Layout",
|
||||
"option": {
|
||||
"row": {
|
||||
"label": ""
|
||||
"label": "Horizontal"
|
||||
},
|
||||
"column": {
|
||||
"label": ""
|
||||
"label": "Vertical"
|
||||
},
|
||||
"grid": {
|
||||
"label": ""
|
||||
"label": "Grid"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1414,19 +1414,19 @@
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"internalServerError": "",
|
||||
"integrationsDisconnected": ""
|
||||
"internalServerError": "Failed to fetch DNS Hole Summary",
|
||||
"integrationsDisconnected": "No data available, all integrations disconnected"
|
||||
},
|
||||
"data": {
|
||||
"adsBlockedToday": "",
|
||||
"adsBlockedTodayPercentage": "",
|
||||
"dnsQueriesToday": "",
|
||||
"domainsBeingBlocked": ""
|
||||
"adsBlockedToday": "Blocked today",
|
||||
"adsBlockedTodayPercentage": "Blocked today",
|
||||
"dnsQueriesToday": "Queries today",
|
||||
"domainsBeingBlocked": "Domains on blocklist"
|
||||
},
|
||||
"domainsTooltip": ""
|
||||
"domainsTooltip": "Due to multiple integrations Homarr can't calculate the exact number of domains being blocked"
|
||||
},
|
||||
"dnsHoleControls": {
|
||||
"name": "",
|
||||
"name": "DNS Hole Controls",
|
||||
"description": "Control PiHole or AdGuard from your dashboard",
|
||||
"option": {
|
||||
"layout": {
|
||||
@@ -1469,224 +1469,224 @@
|
||||
"description": "Displays the current date and time.",
|
||||
"option": {
|
||||
"customTitleToggle": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
"label": "Custom Title/City display",
|
||||
"description": "Show off a custom title or the name of the city/country on top of the clock."
|
||||
},
|
||||
"customTitle": {
|
||||
"label": ""
|
||||
"label": "Title"
|
||||
},
|
||||
"is24HourFormat": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
"label": "24-hour format",
|
||||
"description": "Use 24-hour format instead of 12-hour format"
|
||||
},
|
||||
"showSeconds": {
|
||||
"label": ""
|
||||
"label": "Display seconds"
|
||||
},
|
||||
"useCustomTimezone": {
|
||||
"label": " "
|
||||
},
|
||||
"timezone": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
"label": "Time zone",
|
||||
"description": "Choose the time zone following the IANA standard"
|
||||
},
|
||||
"showDate": {
|
||||
"label": ""
|
||||
"label": "Show the date"
|
||||
},
|
||||
"dateFormat": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
"label": "Date Format",
|
||||
"description": "How the date should look like"
|
||||
},
|
||||
"customTimeFormat": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
"label": "Custom time format",
|
||||
"description": "Use ISO 8601 to format time (this will override other options)"
|
||||
},
|
||||
"customDateFormat": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
"label": "Custom date format",
|
||||
"description": "Use ISO 8601 to format date (this will override other options)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraftServerStatus": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"name": "Minecraft Server Status",
|
||||
"description": "Displays the status of a Minecraft server",
|
||||
"option": {
|
||||
"title": {
|
||||
"label": ""
|
||||
"label": "Title"
|
||||
},
|
||||
"domain": {
|
||||
"label": ""
|
||||
"label": "Server address"
|
||||
},
|
||||
"isBedrockServer": {
|
||||
"label": ""
|
||||
"label": "Bedrock server"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"online": "",
|
||||
"offline": ""
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
}
|
||||
},
|
||||
"notebook": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"name": "Notebook",
|
||||
"description": "A simple notebook widget that supports markdown",
|
||||
"option": {
|
||||
"showToolbar": {
|
||||
"label": ""
|
||||
"label": "Show the toolbar to help you write markdown"
|
||||
},
|
||||
"allowReadOnlyCheck": {
|
||||
"label": ""
|
||||
"label": "Allow check in read only mode"
|
||||
},
|
||||
"content": {
|
||||
"label": ""
|
||||
"label": "The content of the notebook"
|
||||
}
|
||||
},
|
||||
"controls": {
|
||||
"bold": "",
|
||||
"italic": "",
|
||||
"strikethrough": "",
|
||||
"underline": "",
|
||||
"bold": "Bold",
|
||||
"italic": "Italic",
|
||||
"strikethrough": "Strikethrough",
|
||||
"underline": "Underline",
|
||||
"colorText": "Colour text",
|
||||
"colorHighlight": "Coloured highlight text",
|
||||
"code": "",
|
||||
"clear": "",
|
||||
"heading": "",
|
||||
"align": "",
|
||||
"blockquote": "",
|
||||
"horizontalLine": "",
|
||||
"bulletList": "",
|
||||
"orderedList": "",
|
||||
"checkList": "",
|
||||
"increaseIndent": "",
|
||||
"decreaseIndent": "",
|
||||
"link": "",
|
||||
"unlink": "",
|
||||
"image": "",
|
||||
"addTable": "",
|
||||
"deleteTable": "",
|
||||
"code": "Code",
|
||||
"clear": "Clear formatting",
|
||||
"heading": "Heading {level}",
|
||||
"align": "Align text: {position}",
|
||||
"blockquote": "Blockquote",
|
||||
"horizontalLine": "Horizontal line",
|
||||
"bulletList": "Bullet list",
|
||||
"orderedList": "Ordered list",
|
||||
"checkList": "Check list",
|
||||
"increaseIndent": "Increase Indent",
|
||||
"decreaseIndent": "Decrease Indent",
|
||||
"link": "Link",
|
||||
"unlink": "Remove link",
|
||||
"image": "Embed Image",
|
||||
"addTable": "Add table",
|
||||
"deleteTable": "Delete Table",
|
||||
"colorCell": "Colour cell",
|
||||
"mergeCell": "",
|
||||
"addColumnLeft": "",
|
||||
"addColumnRight": "",
|
||||
"deleteColumn": "",
|
||||
"addRowTop": "",
|
||||
"addRowBelow": "",
|
||||
"deleteRow": ""
|
||||
"mergeCell": "Toggle cell merging",
|
||||
"addColumnLeft": "Add column before",
|
||||
"addColumnRight": "Add column after",
|
||||
"deleteColumn": "Delete column",
|
||||
"addRowTop": "Add row before",
|
||||
"addRowBelow": "Add row after",
|
||||
"deleteRow": "Delete row"
|
||||
},
|
||||
"align": {
|
||||
"left": "",
|
||||
"center": "",
|
||||
"right": ""
|
||||
"left": "Left",
|
||||
"center": "Centre",
|
||||
"right": "Right"
|
||||
},
|
||||
"popover": {
|
||||
"clearColor": "Clear colour",
|
||||
"source": "",
|
||||
"widthPlaceholder": "",
|
||||
"columns": "",
|
||||
"rows": "",
|
||||
"width": "",
|
||||
"height": ""
|
||||
"source": "Source",
|
||||
"widthPlaceholder": "Value in % or pixels",
|
||||
"columns": "Columns",
|
||||
"rows": "Rows",
|
||||
"width": "Width",
|
||||
"height": "Height"
|
||||
},
|
||||
"placeholder": "",
|
||||
"placeholder": "Start writing your notes",
|
||||
"dismiss": {
|
||||
"title": "",
|
||||
"message": "",
|
||||
"title": "Dismiss changes?",
|
||||
"message": "You have unsaved changes in your notebook. Are you sure you want to discard them?",
|
||||
"action": {
|
||||
"discard": "",
|
||||
"keepEditing": ""
|
||||
"discard": "Discard changes",
|
||||
"keepEditing": "Keep editing"
|
||||
}
|
||||
}
|
||||
},
|
||||
"iframe": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"name": "iFrame",
|
||||
"description": "Embed any content from the Internet. Some websites may restrict access.",
|
||||
"option": {
|
||||
"embedUrl": {
|
||||
"label": ""
|
||||
"label": "Embed URL"
|
||||
},
|
||||
"allowFullScreen": {
|
||||
"label": ""
|
||||
"label": "Allow full screen"
|
||||
},
|
||||
"allowTransparency": {
|
||||
"label": ""
|
||||
"label": "Allow transparency"
|
||||
},
|
||||
"allowScrolling": {
|
||||
"label": ""
|
||||
"label": "Allow scrolling"
|
||||
},
|
||||
"allowPayment": {
|
||||
"label": ""
|
||||
"label": "Allow payment"
|
||||
},
|
||||
"allowAutoPlay": {
|
||||
"label": ""
|
||||
"label": "Allow auto play"
|
||||
},
|
||||
"allowMicrophone": {
|
||||
"label": ""
|
||||
"label": "Allow microphone"
|
||||
},
|
||||
"allowCamera": {
|
||||
"label": ""
|
||||
"label": "Allow camera"
|
||||
},
|
||||
"allowGeolocation": {
|
||||
"label": ""
|
||||
"label": "Allow geolocation"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"noUrl": "",
|
||||
"unsupportedProtocol": "",
|
||||
"noBrowerSupport": ""
|
||||
"noUrl": "No iFrame URL provided",
|
||||
"unsupportedProtocol": "The URL provided is using an unsupported protocol. Please use one of ({supportedProtocols})",
|
||||
"noBrowerSupport": "Your Browser does not support iframes. Please update your browser."
|
||||
}
|
||||
},
|
||||
"smartHome-entityState": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"name": "Entity State",
|
||||
"description": "Display the state of an entity and toggle it optionally",
|
||||
"option": {
|
||||
"entityId": {
|
||||
"label": ""
|
||||
"label": "Entity ID"
|
||||
},
|
||||
"displayName": {
|
||||
"label": ""
|
||||
"label": "Display-name"
|
||||
},
|
||||
"entityUnit": {
|
||||
"label": ""
|
||||
"label": "Entity Unit"
|
||||
},
|
||||
"clickable": {
|
||||
"label": ""
|
||||
"label": "Clickable"
|
||||
}
|
||||
}
|
||||
},
|
||||
"smartHome-executeAutomation": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"name": "Execute Automation",
|
||||
"description": "Trigger an automation with one click",
|
||||
"option": {
|
||||
"displayName": {
|
||||
"label": ""
|
||||
"label": "Display name"
|
||||
},
|
||||
"automationId": {
|
||||
"label": ""
|
||||
"label": "Automation ID"
|
||||
}
|
||||
},
|
||||
"spotlightAction": {
|
||||
"run": ""
|
||||
"run": "Run {name}"
|
||||
}
|
||||
},
|
||||
"stockPrice": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"name": "Stock Price",
|
||||
"description": "Displays the current stock price of a company",
|
||||
"option": {
|
||||
"stock": {
|
||||
"label": ""
|
||||
"label": "Stock symbol"
|
||||
},
|
||||
"timeRange": {
|
||||
"label": "",
|
||||
"label": "Time Range",
|
||||
"option": {
|
||||
"1d": {
|
||||
"label": ""
|
||||
"label": "1 Day"
|
||||
},
|
||||
"5d": {
|
||||
"label": ""
|
||||
"label": "5 Day"
|
||||
},
|
||||
"1mo": {
|
||||
"label": ""
|
||||
"label": "1 Month"
|
||||
},
|
||||
"3mo": {
|
||||
"label": ""
|
||||
"label": "3 Months"
|
||||
},
|
||||
"6mo": {
|
||||
"label": ""
|
||||
@@ -1816,9 +1816,9 @@
|
||||
"fog": "",
|
||||
"drizzle": "",
|
||||
"freezingDrizzle": "",
|
||||
"rain": "",
|
||||
"freezingRain": "",
|
||||
"snowFall": "",
|
||||
"rain": "Rain",
|
||||
"freezingRain": "Freezing rain",
|
||||
"snowFall": "Snow fall",
|
||||
"snowGrains": "",
|
||||
"rainShowers": "",
|
||||
"snowShowers": "",
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
@@ -4311,7 +4357,7 @@
|
||||
}
|
||||
},
|
||||
"local": {
|
||||
"title": ""
|
||||
"title": "Local results"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4364,50 +4410,50 @@
|
||||
"label": "Global settings"
|
||||
},
|
||||
"about": {
|
||||
"label": ""
|
||||
"label": "About"
|
||||
},
|
||||
"homeBoard": {
|
||||
"label": ""
|
||||
"label": "Home board"
|
||||
},
|
||||
"preferences": {
|
||||
"label": ""
|
||||
"label": "Your preferences"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"userGroup": {
|
||||
"help": "",
|
||||
"help": "Search for users or groups",
|
||||
"group": {
|
||||
"user": {
|
||||
"title": "",
|
||||
"title": "Users",
|
||||
"children": {
|
||||
"action": {
|
||||
"detail": {
|
||||
"label": ""
|
||||
"label": "Show user details"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": ""
|
||||
"title": "Select an action for the user"
|
||||
}
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"title": "",
|
||||
"title": "Groups",
|
||||
"children": {
|
||||
"action": {
|
||||
"detail": {
|
||||
"label": ""
|
||||
"label": "Show group details"
|
||||
},
|
||||
"manageMember": {
|
||||
"label": ""
|
||||
"label": "Manage members"
|
||||
},
|
||||
"managePermission": {
|
||||
"label": ""
|
||||
"label": "Manage permissions"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": ""
|
||||
"title": "Select an action for the group"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4415,32 +4461,32 @@
|
||||
}
|
||||
},
|
||||
"engine": {
|
||||
"search": "",
|
||||
"search": "Find a search engine",
|
||||
"field": {
|
||||
"name": {
|
||||
"label": ""
|
||||
"label": "Name"
|
||||
},
|
||||
"short": {
|
||||
"label": ""
|
||||
"label": "Short"
|
||||
},
|
||||
"urlTemplate": {
|
||||
"label": ""
|
||||
"label": "URL search template"
|
||||
},
|
||||
"description": {
|
||||
"label": ""
|
||||
"label": "Description"
|
||||
}
|
||||
},
|
||||
"page": {
|
||||
"list": {
|
||||
"title": "",
|
||||
"title": "Search engines",
|
||||
"noResults": {
|
||||
"title": "",
|
||||
"action": ""
|
||||
"title": "There are no search engines yet",
|
||||
"action": "Create your first search engine"
|
||||
},
|
||||
"interactive": ""
|
||||
"interactive": "Interactive, uses an integration"
|
||||
},
|
||||
"create": {
|
||||
"title": "",
|
||||
"title": "New search engine",
|
||||
"notification": {
|
||||
"success": {
|
||||
"title": "Search engine created",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "Immich Server Stats",
|
||||
"description": "Information about your Immich instance",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "Show users",
|
||||
"description": "Show count of users on your instance"
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "Show photos",
|
||||
"description": "Show count of photos on your instance"
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "Show videos",
|
||||
"description": "Show count of videos on your instance"
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "Show storage",
|
||||
"description": "Show the total amount of storage used"
|
||||
}
|
||||
},
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Used Storage"
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "Immich Album",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "Album ID",
|
||||
"description": "This is a unique ID which refers to your Immich album. You can find this id by opening an album and copying the unique string from the URL, for example 'a21aca09-9f05-47dc-b1a1-7b53c547226e'"
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "Interval in seconds",
|
||||
"description": "Rotate between pictures in the album every X seconds. Must be at least 1. Must be below 3600."
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "Show photo info",
|
||||
"description": "Display date of the picture and the current index at the bottom of the slideshow"
|
||||
}
|
||||
},
|
||||
"description": "Slideshow of pictures in your Immich album",
|
||||
"noAlbumSelected": "No album selected, edit widget and choose an album",
|
||||
"noPhotos": "No photos in this album"
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Download Client",
|
||||
"description": "Allows you to view and manage your Downloads from both Torrent and Usenet clients.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Cliente de descarga",
|
||||
"description": "Te permite ver y gestionar tus descargas tanto desde los clientes de Torrent como desde Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Client de téléchargement",
|
||||
"description": "Vous permet de visualiser et de gérer vos téléchargements à partir de clients Torrent et Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "הורדת לקוח",
|
||||
"description": "מאפשר לך להציג ולנהל את ההורדות שלך הן מלקוחות Torrent והן מלקוחות Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "Statistiche Server Immich",
|
||||
"description": "Informazioni sulla tua istanza Immich",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "Mostra utenti",
|
||||
"description": "Mostra il conteggio degli utenti sulla tua istanza"
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "Mostra foto",
|
||||
"description": "Mostra il conteggio delle foto sulla tua istanza"
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "Mostra video",
|
||||
"description": "Mostra il conteggio dei video sulla tua istanza"
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "Mostra spazio di archiviazione",
|
||||
"description": "Visualizza la quantità totale di memoria utilizzata"
|
||||
}
|
||||
},
|
||||
"users": "Utenti",
|
||||
"photos": "Foto",
|
||||
"videos": "Video",
|
||||
"storage": "Spazio utilizzato"
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "Album Immich",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "ID Album",
|
||||
"description": "Si tratta di un ID univoco che si riferisce al tuo album Immich. Puoi trovare questo id aprendo un album e copiando la stringa univoca dall'URL, ad esempio 'a21aca09-9f05-47dc-b1a1-7b53c547226e'"
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "Intervallo in secondi",
|
||||
"description": "Ruota le immagini nell'album ogni X secondi. Deve essere almeno 1. Deve essere inferiore a 3600."
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "Mostra informazioni foto",
|
||||
"description": "Visualizza la data dell'immagine e l'indice corrente nella parte inferiore della presentazione"
|
||||
}
|
||||
},
|
||||
"description": "Presentazione delle immagini nel tuo album Immich",
|
||||
"noAlbumSelected": "Nessun album selezionato, modifica il widget e scegli un album",
|
||||
"noPhotos": "Nessuna foto in questo album"
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Scarica Client",
|
||||
"description": "Ti consente di visualizzare e gestire i tuoi download dai client Torrent e Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "クライアントをダウンロード",
|
||||
"description": "Torrent クライアントと Usenet クライアントの両方から、ダウンロードを表示および管理できます。",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Client downloaden",
|
||||
"description": "Geeft je de mogelijkheid om downloads van torrent- en usenet-clients te bekijken en beheren.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "Immich-serverstatistikk",
|
||||
"description": "Informasjon om din Immich-instans",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "Vis brukere",
|
||||
"description": "Vis antall brukere på din instans"
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "Vis bilder",
|
||||
"description": "Vis antall bilder på din instans"
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "Vis videoer",
|
||||
"description": "Vis antall videoer på din instans"
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "Vis lagring",
|
||||
"description": "Vis total mengde lagringsplass brukt"
|
||||
}
|
||||
},
|
||||
"users": "Brukere",
|
||||
"photos": "Bilder",
|
||||
"videos": "Videoer",
|
||||
"storage": "Brukt lagringsplass"
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "Immich Album",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "Album ID",
|
||||
"description": "Dette er en unik ID som refererer til ditt Immich-album. Du kan finne denne ID-en ved å åpne et album og kopiere den unike strengen fra URL-en, for eksempel 'a21aca09-9f05-47dc-b1a1-7b53c547226e'"
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "Intervall i sekunder",
|
||||
"description": "Roter mellom bilder i albumet hvert X. sekund. Må være minst 1. Må være under 3600."
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "Vis bildeinformasjon",
|
||||
"description": "Vis datoen for bildet og gjeldende indeks nederst i lysbildeserien"
|
||||
}
|
||||
},
|
||||
"description": "Lysbildefremvisning av bilder i ditt Immich-album",
|
||||
"noAlbumSelected": "Ingen album valgt, rediger widgeten og velg et album",
|
||||
"noPhotos": "Ingen bilder i dette albumet"
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Nedlastings-klient",
|
||||
"description": "Lar deg se og behandle nedlastinger fra både Torrent og Usenet klienter.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Klient pobierania",
|
||||
"description": "Pozwala na oglądanie i zarządzanie pobieraniem zarówno przez klientów Torrent, jak i Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Cliente de Download",
|
||||
"description": "Permite visualizar e gerenciar seus Downloads de clientes Torrent e Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "Статистика сервера Immich",
|
||||
"description": "Информация о вашем экземпляре Immich",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "Показать пользователей",
|
||||
"description": "Показать количество пользователей на вашем экземпляре"
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "Показать фото",
|
||||
"description": "Показать количество фотографий на вашем экземпляре"
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "Показать видео",
|
||||
"description": "Показать количество видео на вашем экземпляре"
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "Показать хранилище",
|
||||
"description": "Показать общий объём используемого хранилища"
|
||||
}
|
||||
},
|
||||
"users": "Пользователи",
|
||||
"photos": "Фото",
|
||||
"videos": "Видео",
|
||||
"storage": "Занято"
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "Альбом Immich",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "ID альбома",
|
||||
"description": "Уникальный идентификатор вашего альбома Immich. Его можно найти, открыв альбом и скопировав уникальную строку из URL, например 'a21aca09-9f05-47dc-b1a1-7b53c547226e'"
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "Интервал в секундах",
|
||||
"description": "Переключать фотографии в альбоме каждые X секунд. Минимум 1. Максимум 3600."
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "Показать информацию о фото",
|
||||
"description": "Отображать дату снимка и текущий номер в нижней части слайд-шоу"
|
||||
}
|
||||
},
|
||||
"description": "Слайд-шоу фотографий из вашего альбома Immich",
|
||||
"noAlbumSelected": "Альбом не выбран — отредактируйте виджет и выберите альбом",
|
||||
"noPhotos": "В этом альбоме нет фотографий"
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Загрузки",
|
||||
"description": "Позволяет просматривать и управлять загрузками как из торрент-клиентов, так и из Usenet-клиентов.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Download klient",
|
||||
"description": "Umožňuje vám zobraziť a spravovať stiahnuté súbory z klientov Torrent aj Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
@@ -649,14 +649,14 @@
|
||||
"app": {
|
||||
"option": {
|
||||
"existing": {
|
||||
"title": "",
|
||||
"label": ""
|
||||
"title": "Mevcut",
|
||||
"label": "Mevcut uygulamayı seçin"
|
||||
},
|
||||
"new": {
|
||||
"title": "",
|
||||
"title": "Yeni",
|
||||
"url": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
"label": "Uygulama url si",
|
||||
"description": "Kontrol panelinden erişildiğinde uygulamanın açılacağı URL"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,8 +676,8 @@
|
||||
},
|
||||
"app": {
|
||||
"action": {
|
||||
"add": "",
|
||||
"remove": "",
|
||||
"add": "Bir uygulamayı bağla",
|
||||
"remove": "Bağlantıyı kaldır",
|
||||
"select": ""
|
||||
}
|
||||
}
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "İndirme İstemcisi",
|
||||
"description": "Hem Torrent hem de Usenet istemcilerinden indirdiklerinizi görüntülemenizi ve yönetmenizi sağlar.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "Завантаження",
|
||||
"description": "Дозволяє переглядати та керувати завантаженнями від клієнтів Torrent та Usenet.",
|
||||
|
||||
@@ -2091,6 +2091,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"immich-serverStats": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
"option": {
|
||||
"showUsers": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showVideos": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showStorage": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"users": "",
|
||||
"photos": "",
|
||||
"videos": "",
|
||||
"storage": ""
|
||||
},
|
||||
"immich-albumCarousel": {
|
||||
"name": "",
|
||||
"option": {
|
||||
"albumId": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"rotationIntervalSeconds": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
},
|
||||
"showPhotoInfo": {
|
||||
"label": "",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"noAlbumSelected": "",
|
||||
"noPhotos": ""
|
||||
},
|
||||
"downloads": {
|
||||
"name": "",
|
||||
"description": "",
|
||||
|
||||
Loaded 100 of 117 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user