Compare commits

...

95 Commits

Author SHA1 Message Date
Ben Phelps
ea6a668a84 add version information 2022-09-24 01:18:37 +03:00
Ben Phelps
08615fe9f6 Update docker-publish.yml 2022-09-24 00:17:23 +03:00
SuperDOS
f8ef5ddf5a Translated using Weblate (Swedish)
Currently translated at 93.0% (107 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/
2022-09-23 13:44:01 +02:00
XNRavenZen
595d81dd2f Translated using Weblate (Chinese (Simplified))
Currently translated at 94.7% (109 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2022-09-23 13:44:01 +02:00
nicedc
00c654953d Translated using Weblate (Chinese (Simplified))
Currently translated at 94.7% (109 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2022-09-23 13:44:01 +02:00
Bruno Rossetto
bf2f3a7d17 Translated using Weblate (Portuguese)
Currently translated at 100.0% (115 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/
2022-09-23 13:44:01 +02:00
Nonoss117
612f0fde2d Translated using Weblate (French)
Currently translated at 100.0% (115 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2022-09-23 13:44:00 +02:00
Ángel Fernández Sánchez
a701e031a7 Translated using Weblate (Spanish)
Currently translated at 100.0% (115 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2022-09-23 13:44:00 +02:00
Juan Manuel Bennàssar Carretero
d51854e663 Translated using Weblate (Spanish)
Currently translated at 100.0% (115 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2022-09-23 13:44:00 +02:00
Moritz Neumann
cb9a18fd40 Translated using Weblate (German)
Currently translated at 100.0% (115 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2022-09-23 13:44:00 +02:00
Ben Phelps
ed28d69d76 Merge pull request #251 from JazzFisch/patch-nextjs-logging
Patch console object to instead use homepage's logger for logging
2022-09-23 11:51:15 +03:00
Jason Fischer
5667cedafc Merge branch 'main' into patch-nextjs-logging 2022-09-21 23:38:53 -07:00
Jason Fischer
42fe535df7 Patch console object to instead use winston for logging
- Allow setting labels via new createLogger method
- Make logger initialization more robust
2022-09-21 23:37:17 -07:00
Ben Phelps
0e1e2bde22 Update FUNDING.yml 2022-09-22 03:01:00 +03:00
Ben Phelps
1a5e2f3cda Update FUNDING.yml 2022-09-22 03:00:39 +03:00
Ben Phelps
32cb113014 Create FUNDING.yml 2022-09-22 02:57:58 +03:00
Ben Phelps
559af0cd56 Update README.md 2022-09-21 22:53:19 +03:00
Ben Phelps
0e5477eecf experiment with lazily loaded widgets 2022-09-21 22:26:58 +03:00
Jason Fischer
ab631fa26e Merge pull request #246 from JazzFisch/fix-log-folder
Write homepage.log into config folder
2022-09-21 08:46:21 -07:00
Jason Fischer
5776544c20 Write homepage.log into config folder
This will make it easier for people to find their log file(s)
2022-09-21 08:32:37 -07:00
Ben Phelps
666e2a42cf fix context state race 2022-09-21 17:39:46 +03:00
Ben Phelps
2fc1dda122 add tailwind-scollbars 2022-09-21 16:11:48 +03:00
Juan Manuel Bennàssar Carretero
0115b594d6 Translated using Weblate (Catalan)
Currently translated at 100.0% (115 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2022-09-21 11:32:07 +02:00
Juan Manuel Bennàssar Carretero
c5828978b2 Translated using Weblate (Spanish)
Currently translated at 100.0% (115 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2022-09-21 11:32:07 +02:00
Ben Phelps
3ff756e057 update readme 2022-09-21 10:09:24 +03:00
Anonymous
1c405ff4ec Translated using Weblate (Hebrew)
Currently translated at 87.8% (101 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/
2022-09-21 08:06:43 +02:00
Anonymous
5d1041d564 Translated using Weblate (Hungarian)
Currently translated at 93.9% (108 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/
2022-09-21 08:06:42 +02:00
Anonymous
9e8942398c Translated using Weblate (Croatian)
Currently translated at 7.8% (9 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hr/
2022-09-21 08:06:42 +02:00
Anonymous
a5b7c8439d Translated using Weblate (Swedish)
Currently translated at 83.4% (96 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/
2022-09-21 08:06:42 +02:00
Anonymous
9131a8f118 Translated using Weblate (Polish)
Currently translated at 85.2% (98 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/
2022-09-21 08:06:42 +02:00
Anonymous
8687fe6b26 Translated using Weblate (Catalan)
Currently translated at 93.9% (108 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2022-09-21 08:06:41 +02:00
Anonymous
1d38fd8dea Translated using Weblate (Chinese (Traditional))
Currently translated at 7.8% (9 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hant/
2022-09-21 08:06:41 +02:00
Anonymous
4186bbb3c3 Translated using Weblate (Dutch)
Currently translated at 54.7% (63 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2022-09-21 08:06:41 +02:00
Anonymous
897c71f36e Translated using Weblate (Vietnamese)
Currently translated at 38.2% (44 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/vi/
2022-09-21 08:06:41 +02:00
Anonymous
f9ce9b7716 Translated using Weblate (Norwegian Bokmål)
Currently translated at 68.6% (79 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nb_NO/
2022-09-21 08:06:40 +02:00
Anonymous
ec230ba249 Translated using Weblate (Italian)
Currently translated at 66.9% (77 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2022-09-21 08:06:40 +02:00
Anonymous
6bfa49689e Translated using Weblate (Chinese (Simplified))
Currently translated at 93.9% (108 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2022-09-21 08:06:39 +02:00
Anonymous
177acf86d7 Translated using Weblate (Russian)
Currently translated at 20.0% (23 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/
2022-09-21 08:06:39 +02:00
Anonymous
c89ed904cc Translated using Weblate (Portuguese)
Currently translated at 76.5% (88 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/
2022-09-21 08:06:39 +02:00
Anonymous
6add7c3d82 Translated using Weblate (French)
Currently translated at 96.5% (111 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2022-09-21 08:06:39 +02:00
Anonymous
c562035776 Translated using Weblate (Spanish)
Currently translated at 93.9% (108 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2022-09-21 08:06:38 +02:00
Anonymous
4757e25fdc Translated using Weblate (German)
Currently translated at 90.4% (104 of 115 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2022-09-21 08:06:38 +02:00
Nonoss117
077bc356b8 Translated using Weblate (French)
Currently translated at 100.0% (111 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2022-09-21 08:06:30 +02:00
Ben Phelps
1dff880a93 Merge pull request #230 from DevPGSV/feature/widget_strelaysrv
Add Syncthing Relay Server widget
2022-09-21 09:06:26 +03:00
Ben Phelps
122b987fa3 Merge branch 'main' into feature/widget_strelaysrv 2022-09-21 09:05:42 +03:00
Ben Phelps
c024c4f01c Merge pull request #241 from JazzFisch/add-logger
Add Winston for log handling
2022-09-21 09:03:52 +03:00
Ben Phelps
a677fbefbf add global settings context
will be useful going forward, and simplify widget props being passed around all over the place
2022-09-21 09:00:57 +03:00
Ben Phelps
244a76de0b fix bookmark styling 2022-09-21 08:58:24 +03:00
Ben Phelps
20ac15b18c allow setting a global link target 2022-09-21 08:40:19 +03:00
Anonymous
75244cc40e Translated using Weblate (Hebrew)
Currently translated at 90.9% (101 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/
2022-09-21 07:39:32 +02:00
Anonymous
3e731298a5 Translated using Weblate (Hungarian)
Currently translated at 97.2% (108 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/
2022-09-21 07:39:32 +02:00
Anonymous
ed0bf027fc Translated using Weblate (Croatian)
Currently translated at 8.1% (9 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hr/
2022-09-21 07:39:31 +02:00
Anonymous
7a10131768 Translated using Weblate (Swedish)
Currently translated at 86.4% (96 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/
2022-09-21 07:39:31 +02:00
Anonymous
19522b8712 Translated using Weblate (Polish)
Currently translated at 88.2% (98 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/
2022-09-21 07:39:31 +02:00
Anonymous
af79061a45 Translated using Weblate (Catalan)
Currently translated at 97.2% (108 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2022-09-21 07:39:31 +02:00
Anonymous
d56d9f7a50 Translated using Weblate (Chinese (Traditional))
Currently translated at 8.1% (9 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hant/
2022-09-21 07:39:30 +02:00
Anonymous
45a1a9ed5a Translated using Weblate (Dutch)
Currently translated at 56.7% (63 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2022-09-21 07:39:30 +02:00
Anonymous
50954cf3d4 Translated using Weblate (Vietnamese)
Currently translated at 39.6% (44 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/vi/
2022-09-21 07:39:30 +02:00
Anonymous
6beefbf39a Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.1% (79 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nb_NO/
2022-09-21 07:39:30 +02:00
Anonymous
8f21d1ae31 Translated using Weblate (Italian)
Currently translated at 69.3% (77 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2022-09-21 07:39:29 +02:00
Anonymous
e4825531c4 Translated using Weblate (Chinese (Simplified))
Currently translated at 97.2% (108 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2022-09-21 07:39:29 +02:00
Anonymous
6174f53f37 Translated using Weblate (Russian)
Currently translated at 20.7% (23 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/
2022-09-21 07:39:29 +02:00
Anonymous
42baa4b188 Translated using Weblate (Portuguese)
Currently translated at 79.2% (88 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/
2022-09-21 07:39:28 +02:00
Anonymous
52eaddae37 Translated using Weblate (French)
Currently translated at 97.2% (108 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2022-09-21 07:39:28 +02:00
Anonymous
f43ce0db44 Translated using Weblate (Spanish)
Currently translated at 97.2% (108 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2022-09-21 07:39:28 +02:00
Anonymous
b46cb0a1f7 Translated using Weblate (German)
Currently translated at 93.6% (104 of 111 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2022-09-21 07:39:28 +02:00
Juan Manuel Bennàssar Carretero
e4e5ad7eba Translated using Weblate (Catalan)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2022-09-21 07:39:20 +02:00
Ben Phelps
0e6ea57023 Merge pull request #229 from DevPGSV/feature/widget_mastodon
Add Mastodon widget
2022-09-21 08:39:16 +03:00
Jason Fischer
280bb5fc81 Add Winston for log handling
- write log data to 'homepage.log'
2022-09-20 20:16:04 -07:00
Pablo Garcia de los Salmones Valencia
077d21eb7e Updated stat literals to single words 2022-09-21 02:15:25 +02:00
Pablo Garcia de los Salmones Valencia
f281d86e8a Fixed missing text 2022-09-20 05:29:24 +02:00
Pablo Garcia de los Salmones Valencia
f7000a280e Add Syncthing Relay Server widget 2022-09-20 04:42:04 +02:00
Pablo Garcia de los Salmones Valencia
586ded6b3f Add Mastodon widget 2022-09-20 03:41:10 +02:00
3vilson
539e0f005a Translated using Weblate (German)
Currently translated at 96.2% (104 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2022-09-19 19:16:41 +02:00
Ben Phelps
330575bab3 fix links 2022-09-18 18:49:50 +03:00
Ben Phelps
30ec4aed28 Translated using Weblate (Dutch)
Currently translated at 58.3% (63 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2022-09-18 16:53:21 +02:00
Ben Phelps
ee456fd8e5 Translated using Weblate (Italian)
Currently translated at 71.2% (77 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2022-09-18 16:53:21 +02:00
Ben Phelps
ed25c8a84b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2022-09-18 16:53:21 +02:00
Ben Phelps
b0a45fe09c Translated using Weblate (Russian)
Currently translated at 21.2% (23 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/
2022-09-18 16:53:20 +02:00
Nonoss117
50f0f46ad9 Translated using Weblate (French)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2022-09-18 16:53:20 +02:00
Ben Phelps
bd61d459ad Translated using Weblate (Spanish)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2022-09-18 16:53:20 +02:00
Ben Phelps
4f73c60d37 Translated using Weblate (German)
Currently translated at 62.0% (67 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2022-09-18 16:53:20 +02:00
Ben Phelps
7c536f0cb0 update attribution sorting 2022-09-18 17:05:31 +03:00
Ben Phelps
d5a489198a update readme 2022-09-18 17:00:40 +03:00
Ben Phelps
17f54da524 yaml validation 2022-09-18 16:41:01 +03:00
ShlomiPorush
b5065673ab Translated using Weblate (Hebrew)
Currently translated at 93.5% (101 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/
2022-09-18 15:13:10 +02:00
Pacux
610b0f63e0 Translated using Weblate (Catalan)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2022-09-18 15:13:09 +02:00
yahoo~~
73317bda67 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2022-09-18 15:13:09 +02:00
Nonoss117
f690f3acba Translated using Weblate (French)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2022-09-18 15:13:09 +02:00
Anonymous
eea9f1f6cb Translated using Weblate (Hebrew)
Currently translated at 100.0% (0 of 0 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/
2022-09-18 08:37:27 +02:00
Daniel Varga
d9089e8d1c Translated using Weblate (Hungarian)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/
2022-09-18 08:37:26 +02:00
Nonoss117
bed5acc9d5 Translated using Weblate (French)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2022-09-18 08:37:25 +02:00
Ángel Fernández Sánchez
f46feff445 Translated using Weblate (Spanish)
Currently translated at 100.0% (108 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2022-09-18 08:37:25 +02:00
Daniel Varga
d46a98c7d5 Translated using Weblate (German)
Currently translated at 62.0% (67 of 108 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2022-09-18 08:37:25 +02:00
ShlomiPorush
05af60df4f Added translation using Weblate (Hebrew) 2022-09-18 08:37:17 +02:00
49 changed files with 1247 additions and 362 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
github: benphelps
ko_fi: benphelps
custom: ["https://paypal.me/phelpsben"]

View File

@@ -94,6 +94,10 @@ jobs:
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
build-args: |
BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
# https://github.com/docker/setup-qemu-action#about # https://github.com/docker/setup-qemu-action#about
# platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6 # platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6

4
.gitignore vendored
View File

@@ -19,6 +19,10 @@
.DS_Store .DS_Store
*.pem *.pem
# log files
error.log
homepage.log
# debug # debug
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*

View File

@@ -22,6 +22,10 @@ RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm i
FROM node:current-alpine AS builder FROM node:current-alpine AS builder
WORKDIR /app WORKDIR /app
ARG BUILDTIME
ARG VERSION
ARG REVISION
COPY --link --from=deps /app/node_modules ./node_modules/ COPY --link --from=deps /app/node_modules ./node_modules/
COPY . . COPY . .
@@ -29,7 +33,7 @@ RUN <<EOF
set -xe set -xe
yarn next telemetry disable yarn next telemetry disable
mkdir config && echo '-' > config/settings.yaml mkdir config && echo '-' > config/settings.yaml
npm run build NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
EOF EOF
# Production image, copy all the files and run next # Production image, copy all the files and run next

View File

@@ -1,7 +1,15 @@
![Homepage Preview](/images/preview.png) ![Homepage Preview](/images/preview.png)
[![Docker](https://github.com/benphelps/homepage/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/benphelps/homepage/actions/workflows/docker-publish.yml) <p align="center">
[![Weblate](https://hosted.weblate.org/widgets/homepage/-/homepage/svg-badge.svg)](https://hosted.weblate.org/engage/homepage/) <a href="https://discord.gg/k4ruYNrudu"><img src="https://img.shields.io/badge/Discord - Chat-blue?logo=discord&logoColor=white" /></a>
<a href="https://paypal.me/phelpsben" title="Donate"><img src="https://img.shields.io/badge/PayPal - Donate-blue?logo=paypal&logoColor=white" alt="Linkedin - phelpsben"></a>
</p>
<p align="center">
<a href="https://github.com/benphelps/homepage/actions/workflows/docker-publish.yml"><img src="https://github.com/benphelps/homepage/actions/workflows/docker-publish.yml/badge.svg" alt="Docker"></a>
<a href="https://hosted.weblate.org/engage/homepage/"><img src="https://hosted.weblate.org/widgets/homepage/-/homepage/svg-badge.svg" alt="Weblate"></a>
</p>
## Features ## Features
@@ -9,7 +17,7 @@
- Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6 - Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6
- Supports all Raspberry Pi's, most SBCs & Apple Silicon - Supports all Raspberry Pi's, most SBCs & Apple Silicon
- Full i18n support with automatic language detection - Full i18n support with automatic language detection
- Translations for Chinese, Dutch, French, German, Norwegian Bokmål, Polish, Portuguese, Russian, Spanish and Swedish - Translations for Chinese, Dutch, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Russian, Spanish and Swedish
- Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/) - Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/)
- Service & Web Bookmarks - Service & Web Bookmarks
- Docker Integration - Docker Integration
@@ -18,9 +26,9 @@
- Service Integration - Service Integration
- Sonarr, Radarr, Readarr, Prowlarr, Bazarr, Lidarr, Emby, Jellyfin, Tautulli (Plex) - Sonarr, Radarr, Readarr, Prowlarr, Bazarr, Lidarr, Emby, Jellyfin, Tautulli (Plex)
- Ombi, Overseerr, Jellyseerr, Jackett, NZBGet, SABnzbd, ruTorrent, Transmission, qBittorrent - Ombi, Overseerr, Jellyseerr, Jackett, NZBGet, SABnzbd, ruTorrent, Transmission, qBittorrent
- Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify - Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server
- Information Providers - Information Providers
- Coin Market Cap - Coin Market Cap, Mastodon
- Information & Utility Widgets - Information & Utility Widgets
- System Stats (Disk, CPU, Memory) - System Stats (Disk, CPU, Memory)
- Weather via WeatherAPI.com or OpenWeatherMap - Weather via WeatherAPI.com or OpenWeatherMap
@@ -120,10 +128,13 @@ Huge thanks to the all the contributors who have helped make this project what i
- [aidenpwnz](https://github.com/benphelps/homepage/commits?author=aidenpwnz) - Nginx Proxy Manager, Search Bar Widget - [aidenpwnz](https://github.com/benphelps/homepage/commits?author=aidenpwnz) - Nginx Proxy Manager, Search Bar Widget
- [AlexFullmoon](https://github.com/benphelps/homepage/commits?author=AlexFullmoon) - OpenWeatherMap Widget - [AlexFullmoon](https://github.com/benphelps/homepage/commits?author=AlexFullmoon) - OpenWeatherMap Widget
- [AmadeusGraves](https://github.com/benphelps/homepage/commits?author=AmadeusGraves) - Spanish Translation - [AmadeusGraves](https://github.com/benphelps/homepage/commits?author=AmadeusGraves) - Spanish Translation
- [andrii-kryvoviaz](https://github.com/benphelps/homepage/commits?author=andrii-kryvoviaz) - Background opacity option
- [boerniee](https://github.com/benphelps/homepage/commits?author=boerniee) - German Translation - [boerniee](https://github.com/benphelps/homepage/commits?author=boerniee) - German Translation
- [comradekingu](https://github.com/benphelps/homepage/commits?author=comradekingu) - Norwegian Bokmål Translation - [comradekingu](https://github.com/benphelps/homepage/commits?author=comradekingu) - Norwegian Bokmål Translation
- Daniel Varga - German & Hungarian Translation
- [deffcolony](https://github.com/benphelps/homepage/commits?author=deffcolony) - Dutch Translation - [deffcolony](https://github.com/benphelps/homepage/commits?author=deffcolony) - Dutch Translation
- [desolaris](https://github.com/benphelps/homepage/commits?author=desolaris) - Russian Translation - [desolaris](https://github.com/benphelps/homepage/commits?author=desolaris) - Russian Translation
- [DevPGSV](https://github.com/benphelps/homepage/commits?author=DevPGSV) - Syncthing Relay Server & Mastodon widgets
- [ilusi0n](https://github.com/benphelps/homepage/commits?author=ilusi0n) - Jellyseerr Integration - [ilusi0n](https://github.com/benphelps/homepage/commits?author=ilusi0n) - Jellyseerr Integration
- [ItsJustMeChris](https://github.com/benphelps/homepage/commits?author=ItsJustMeChris) - Coin Market Cap Widget - [ItsJustMeChris](https://github.com/benphelps/homepage/commits?author=ItsJustMeChris) - Coin Market Cap Widget
- [jackblk](https://github.com/benphelps/homepage/commits?author=jackblk) - Vietnamese Translation - [jackblk](https://github.com/benphelps/homepage/commits?author=jackblk) - Vietnamese Translation
@@ -136,6 +147,6 @@ Huge thanks to the all the contributors who have helped make this project what i
- [psychodracon](https://github.com/benphelps/homepage/commits?author=psychodracon) - Polish Translation - [psychodracon](https://github.com/benphelps/homepage/commits?author=psychodracon) - Polish Translation
- [quod](https://github.com/benphelps/homepage/commits?author=quod) - Fixed Typos - [quod](https://github.com/benphelps/homepage/commits?author=quod) - Fixed Typos
- [schklom](https://github.com/benphelps/homepage/commits?author=schklom) - ARM64, ARMv7 and ARMv6 - [schklom](https://github.com/benphelps/homepage/commits?author=schklom) - ARM64, ARMv7 and ARMv6
- [ShlomiPorush](https://github.com/benphelps/homepage/commits?author=ShlomiPorush) - Hebrew Translation
- [SuperDOS](https://github.com/benphelps/homepage/commits?author=SuperDOS) - Swedish Translation - [SuperDOS](https://github.com/benphelps/homepage/commits?author=SuperDOS) - Swedish Translation
- [xicopitz](https://github.com/benphelps/homepage/commits?author=xicopitz) - Gotify & Prowlarr Integration - [xicopitz](https://github.com/benphelps/homepage/commits?author=xicopitz) - Gotify & Prowlarr Integration
- [andrii-kryvoviaz](https://github.com/benphelps/homepage/commits?author=andrii-kryvoviaz) - Background opacity option

View File

@@ -13,6 +13,7 @@
"@headlessui/react": "^1.7.0", "@headlessui/react": "^1.7.0",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"compare-versions": "^5.0.1",
"dockerode": "^3.3.4", "dockerode": "^3.3.4",
"follow-redirects": "^1.15.2", "follow-redirects": "^1.15.2",
"i18next": "^21.9.1", "i18next": "^21.9.1",
@@ -32,7 +33,9 @@
"rutorrent-promise": "^2.0.0", "rutorrent-promise": "^2.0.0",
"shvl": "^3.0.0", "shvl": "^3.0.0",
"swr": "^1.3.0", "swr": "^1.3.0",
"tough-cookie": "^4.1.2" "tailwind-scrollbar": "^2.0.1",
"tough-cookie": "^4.1.2",
"winston": "^3.8.2"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.9", "autoprefixer": "^10.4.9",

158
pnpm-lock.yaml generated
View File

@@ -5,6 +5,7 @@ specifiers:
'@tailwindcss/forms': ^0.5.3 '@tailwindcss/forms': ^0.5.3
autoprefixer: ^10.4.9 autoprefixer: ^10.4.9
classnames: ^2.3.1 classnames: ^2.3.1
compare-versions: ^5.0.1
dockerode: ^3.3.4 dockerode: ^3.3.4
eslint: ^8.23.1 eslint: ^8.23.1
eslint-config-airbnb: ^19.0.4 eslint-config-airbnb: ^19.0.4
@@ -35,14 +36,17 @@ specifiers:
rutorrent-promise: ^2.0.0 rutorrent-promise: ^2.0.0
shvl: ^3.0.0 shvl: ^3.0.0
swr: ^1.3.0 swr: ^1.3.0
tailwind-scrollbar: ^2.0.1
tailwindcss: ^3.1.8 tailwindcss: ^3.1.8
tough-cookie: ^4.1.2 tough-cookie: ^4.1.2
typescript: ^4.8.3 typescript: ^4.8.3
winston: ^3.8.2
dependencies: dependencies:
'@headlessui/react': 1.7.0_biqbaboplfbrettd7655fr4n2y '@headlessui/react': 1.7.0_biqbaboplfbrettd7655fr4n2y
'@tailwindcss/forms': 0.5.3_tailwindcss@3.1.8 '@tailwindcss/forms': 0.5.3_tailwindcss@3.1.8
classnames: 2.3.1 classnames: 2.3.1
compare-versions: 5.0.1
dockerode: 3.3.4 dockerode: 3.3.4
follow-redirects: 1.15.2 follow-redirects: 1.15.2
i18next: 21.9.1 i18next: 21.9.1
@@ -62,7 +66,9 @@ dependencies:
rutorrent-promise: 2.0.0 rutorrent-promise: 2.0.0
shvl: 3.0.0 shvl: 3.0.0
swr: 1.3.0_react@18.2.0 swr: 1.3.0_react@18.2.0
tailwind-scrollbar: 2.0.1_tailwindcss@3.1.8
tough-cookie: 4.1.2 tough-cookie: 4.1.2
winston: 3.8.2
devDependencies: devDependencies:
autoprefixer: 10.4.9_postcss@8.4.16 autoprefixer: 10.4.9_postcss@8.4.16
@@ -100,6 +106,19 @@ packages:
resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
dev: false dev: false
/@colors/colors/1.5.0:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
dev: false
/@dabh/diagnostics/2.0.3:
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
dependencies:
colorspace: 1.1.4
enabled: 2.0.0
kuler: 2.0.0
dev: false
/@eslint/eslintrc/1.3.2: /@eslint/eslintrc/1.3.2:
resolution: {integrity: sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==} resolution: {integrity: sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -500,6 +519,10 @@ packages:
resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==}
dev: true dev: true
/async/3.2.4:
resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==}
dev: false
/asynckit/0.4.0: /asynckit/0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
dev: false dev: false
@@ -646,6 +669,12 @@ packages:
resolution: {integrity: sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==} resolution: {integrity: sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==}
dev: false dev: false
/color-convert/1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
color-name: 1.1.3
dev: false
/color-convert/2.0.1: /color-convert/2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'} engines: {node: '>=7.0.0'}
@@ -653,9 +682,34 @@ packages:
color-name: 1.1.4 color-name: 1.1.4
dev: true dev: true
/color-name/1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: false
/color-name/1.1.4: /color-name/1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
/color-string/1.9.1:
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
dependencies:
color-name: 1.1.4
simple-swizzle: 0.2.2
dev: false
/color/3.2.1:
resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==}
dependencies:
color-convert: 1.9.3
color-string: 1.9.1
dev: false
/colorspace/1.1.4:
resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==}
dependencies:
color: 3.2.1
text-hex: 1.0.0
dev: false
/combined-stream/1.0.8: /combined-stream/1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@@ -663,6 +717,10 @@ packages:
delayed-stream: 1.0.0 delayed-stream: 1.0.0
dev: false dev: false
/compare-versions/5.0.1:
resolution: {integrity: sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ==}
dev: false
/concat-map/0.0.1: /concat-map/0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: true dev: true
@@ -837,6 +895,10 @@ packages:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
dev: true dev: true
/enabled/2.0.0:
resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==}
dev: false
/end-of-stream/1.4.4: /end-of-stream/1.4.4:
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
dependencies: dependencies:
@@ -1323,6 +1385,10 @@ packages:
dependencies: dependencies:
reusify: 1.0.4 reusify: 1.0.4
/fecha/4.2.3:
resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==}
dev: false
/file-entry-cache/6.0.1: /file-entry-cache/6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0} engines: {node: ^10.12.0 || >=12.0.0}
@@ -1356,6 +1422,10 @@ packages:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: true dev: true
/fn.name/1.1.0:
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
dev: false
/follow-redirects/1.15.2: /follow-redirects/1.15.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'} engines: {node: '>=4.0'}
@@ -1602,6 +1672,10 @@ packages:
side-channel: 1.0.4 side-channel: 1.0.4
dev: true dev: true
/is-arrayish/0.3.2:
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
dev: false
/is-bigint/1.0.4: /is-bigint/1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
dependencies: dependencies:
@@ -1679,6 +1753,11 @@ packages:
call-bind: 1.0.2 call-bind: 1.0.2
dev: true dev: true
/is-stream/2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
dev: false
/is-string/1.0.7: /is-string/1.0.7:
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -1743,6 +1822,10 @@ packages:
object.assign: 4.1.4 object.assign: 4.1.4
dev: true dev: true
/kuler/2.0.0:
resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
dev: false
/language-subtag-registry/0.3.22: /language-subtag-registry/0.3.22:
resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
dev: true dev: true
@@ -1776,6 +1859,16 @@ packages:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
dev: true dev: true
/logform/2.4.2:
resolution: {integrity: sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==}
dependencies:
'@colors/colors': 1.5.0
fecha: 4.2.3
ms: 2.1.3
safe-stable-stringify: 2.4.0
triple-beam: 1.3.0
dev: false
/loose-envify/1.4.0: /loose-envify/1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true hasBin: true
@@ -1843,7 +1936,6 @@ packages:
/ms/2.1.3: /ms/2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
dev: true
/nan/2.16.0: /nan/2.16.0:
resolution: {integrity: sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==} resolution: {integrity: sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==}
@@ -2000,6 +2092,12 @@ packages:
dependencies: dependencies:
wrappy: 1.0.2 wrappy: 1.0.2
/one-time/1.0.0:
resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==}
dependencies:
fn.name: 1.1.0
dev: false
/optionator/0.9.1: /optionator/0.9.1:
resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@@ -2347,6 +2445,11 @@ packages:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: false dev: false
/safe-stable-stringify/2.4.0:
resolution: {integrity: sha512-eehKHKpab6E741ud7ZIMcXhKcP6TSIezPkNZhy5U8xC6+VvrRdUA2tMgxGxaGl4cz7c2Ew5+mg5+wNB16KQqrA==}
engines: {node: '>=10'}
dev: false
/safer-buffer/2.1.2: /safer-buffer/2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
dev: false dev: false
@@ -2398,6 +2501,12 @@ packages:
object-inspect: 1.12.2 object-inspect: 1.12.2
dev: true dev: true
/simple-swizzle/0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
dependencies:
is-arrayish: 0.3.2
dev: false
/slash/3.0.0: /slash/3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -2423,6 +2532,10 @@ packages:
nan: 2.16.0 nan: 2.16.0
dev: false dev: false
/stack-trace/0.0.10:
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
dev: false
/statuses/2.0.1: /statuses/2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@@ -2515,6 +2628,15 @@ packages:
react: 18.2.0 react: 18.2.0
dev: false dev: false
/tailwind-scrollbar/2.0.1_tailwindcss@3.1.8:
resolution: {integrity: sha512-OcR7qHBbux4k+k6bWqnEQFYFooLK/F4dhkBz6nvswIoaA9ancZ5h20e0tyV7ifSWLDCUBtpG+1NHRA8HMRH/wg==}
engines: {node: '>=12.13.0'}
peerDependencies:
tailwindcss: 3.x
dependencies:
tailwindcss: 3.1.8_postcss@8.4.16
dev: false
/tailwindcss/3.1.8_postcss@8.4.16: /tailwindcss/3.1.8_postcss@8.4.16:
resolution: {integrity: sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==} resolution: {integrity: sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==}
engines: {node: '>=12.13.0'} engines: {node: '>=12.13.0'}
@@ -2567,6 +2689,10 @@ packages:
readable-stream: 3.6.0 readable-stream: 3.6.0
dev: false dev: false
/text-hex/1.0.0:
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
dev: false
/text-table/0.2.0: /text-table/0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: true dev: true
@@ -2596,6 +2722,10 @@ packages:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
dev: false dev: false
/triple-beam/1.3.0:
resolution: {integrity: sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==}
dev: false
/tsconfig-paths/3.14.1: /tsconfig-paths/3.14.1:
resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==}
dependencies: dependencies:
@@ -2733,6 +2863,32 @@ packages:
isexe: 2.0.0 isexe: 2.0.0
dev: true dev: true
/winston-transport/4.5.0:
resolution: {integrity: sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==}
engines: {node: '>= 6.4.0'}
dependencies:
logform: 2.4.2
readable-stream: 3.6.0
triple-beam: 1.3.0
dev: false
/winston/3.8.2:
resolution: {integrity: sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==}
engines: {node: '>= 12.0.0'}
dependencies:
'@colors/colors': 1.5.0
'@dabh/diagnostics': 2.0.3
async: 3.2.4
is-stream: 2.0.1
logform: 2.4.2
one-time: 1.0.0
readable-stream: 3.6.0
safe-stable-stringify: 2.4.0
stack-trace: 0.0.10
triple-beam: 1.3.0
winston-transport: 4.5.0
dev: false
/word-wrap/1.2.3: /word-wrap/1.2.3:
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}

View File

@@ -97,7 +97,7 @@
"pihole": { "pihole": {
"queries": "Consultes", "queries": "Consultes",
"blocked": "Bloquejat", "blocked": "Bloquejat",
"gravity": "Gravetat" "gravity": "Gravity"
}, },
"portainer": { "portainer": {
"running": "Executant", "running": "Executant",
@@ -147,15 +147,26 @@
"albums": "Àlbums" "albums": "Àlbums"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "Consultes",
"blocked": "Blocked", "blocked": "Bloquejat",
"filtered": "Filtered", "filtered": "Filtrat",
"latency": "Latency" "latency": "Latència"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "Descàrrega",
"upload": "Upload", "upload": "Càrrega",
"leech": "Leech", "leech": "Companys",
"seed": "Seed" "seed": "Llavors"
},
"mastodon": {
"user_count": "Usuaris",
"status_count": "Publicacions",
"domain_count": "Dominis"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connexions",
"dataRelayed": "Transmès",
"transferRate": "Velocitat"
} }
} }

View File

@@ -11,7 +11,7 @@
"total": "Gesamt", "total": "Gesamt",
"free": "Frei", "free": "Frei",
"used": "Gebraucht", "used": "Gebraucht",
"load": "Load" "load": "Belastung"
}, },
"docker": { "docker": {
"rx": "Rx", "rx": "Rx",
@@ -24,13 +24,13 @@
"playing": "Spielen", "playing": "Spielen",
"transcoding": "Transcodierung", "transcoding": "Transcodierung",
"bitrate": "Bitrate", "bitrate": "Bitrate",
"no_active": "No Active Streams" "no_active": "Keine aktive Streams"
}, },
"tautulli": { "tautulli": {
"playing": "Spielen", "playing": "Spielen",
"transcoding": "Transcodierung", "transcoding": "Transcodierung",
"bitrate": "Bitrate", "bitrate": "Bitrate",
"no_active": "No Active Streams" "no_active": "Keine aktiven streamen"
}, },
"rutorrent": { "rutorrent": {
"active": "Aktiv", "active": "Aktiv",
@@ -48,9 +48,9 @@
"movies": "Filme" "movies": "Filme"
}, },
"readarr": { "readarr": {
"wanted": "Wanted", "wanted": "Gesucht",
"queued": "Queued", "queued": "In Warteschlange",
"books": "Books" "books": "Bücher"
}, },
"ombi": { "ombi": {
"pending": "Ausstehend", "pending": "Ausstehend",
@@ -79,8 +79,8 @@
}, },
"traefik": { "traefik": {
"routers": "Router", "routers": "Router",
"services": "Services", "services": "Dienste",
"middleware": "Middleware" "middleware": "Zwischenanwendung"
}, },
"npm": { "npm": {
"enabled": "Aktiviert", "enabled": "Aktiviert",
@@ -94,68 +94,79 @@
"wait": "Bitte warten" "wait": "Bitte warten"
}, },
"overseerr": { "overseerr": {
"pending": "Pending", "pending": "Ausstehend",
"approved": "Approved", "approved": "Genehmigt",
"available": "Available" "available": "Verfügbar"
}, },
"sabnzbd": { "sabnzbd": {
"rate": "Rate", "rate": "Geschwindigkeit",
"queue": "Queue", "queue": "Warteschlange",
"timeleft": "Time Left" "timeleft": "Verbleibende Zeit"
}, },
"nzbget": { "nzbget": {
"rate": "Rate", "rate": "Geschwindigkeit",
"remaining": "Remaining", "remaining": "Verbleibend",
"downloaded": "Downloaded" "downloaded": "Heruntergeladen"
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "Configure one or more crypto currencies to track", "configure": "Konfiguriere eine oder mehrere Kryptowährungen zur Verfolgung",
"1hour": "1 Hour", "1hour": "1 Stunde",
"1day": "1 Day", "1day": "1 Tag",
"7days": "7 Days", "7days": "7 Tage",
"30days": "30 Days" "30days": "30 Tage"
}, },
"gotify": { "gotify": {
"apps": "Applications", "apps": "Programme",
"clients": "Clients", "clients": "Benutzer",
"messages": "Messages" "messages": "Nachrichten"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "Indexer",
"numberOfGrabs": "Grabs", "numberOfGrabs": "Abrufungen",
"numberOfQueries": "Queries", "numberOfQueries": "Anfragen",
"numberOfFailGrabs": "Fail Grabs", "numberOfFailGrabs": "Fehlgeschlagene Abrufungen",
"numberOfFailQueries": "Fail Queries" "numberOfFailQueries": "Fehlgeschlagene Anfragen"
}, },
"transmission": { "transmission": {
"download": "Download", "download": "Herunterladen",
"upload": "Upload", "upload": "Hochladen",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"jackett": { "jackett": {
"configured": "Configured", "configured": "Konfiguriert",
"errored": "Errored" "errored": "Fehlerhaft"
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "Missing Episodes", "missingEpisodes": "Fehlende Episoden",
"missingMovies": "Missing Movies" "missingMovies": "Fehlende Filme"
}, },
"lidarr": { "lidarr": {
"wanted": "Wanted", "wanted": "Gesucht",
"queued": "Queued", "queued": "In Warteschlange",
"albums": "Albums" "albums": "Alben"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "Anfragen",
"blocked": "Blocked", "blocked": "Blockiert",
"filtered": "Filtered", "filtered": "Gefiltert",
"latency": "Latency" "latency": "Latenz"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "Herunterladen",
"upload": "Upload", "upload": "Hochladen",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Nutzer",
"status_count": "Beiträge",
"domain_count": "Domänen"
},
"strelaysrv": {
"numActiveSessions": "Sitzungen",
"numConnections": "Verbindungen",
"dataRelayed": "Weitergeleitet",
"transferRate": "Bewerten"
} }
} }

View File

@@ -168,5 +168,16 @@
"jackett": { "jackett": {
"configured": "Configured", "configured": "Configured",
"errored": "Errored" "errored": "Errored"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
} }
} }

View File

@@ -35,7 +35,7 @@
"rutorrent": { "rutorrent": {
"active": "Activo", "active": "Activo",
"upload": "Subida", "upload": "Subida",
"download": "Descarga" "download": "Bajada"
}, },
"sonarr": { "sonarr": {
"wanted": "Más deseado", "wanted": "Más deseado",
@@ -69,7 +69,7 @@
}, },
"speedtest": { "speedtest": {
"upload": "Subida", "upload": "Subida",
"download": "Descarga", "download": "Bajada",
"ping": "Ping" "ping": "Ping"
}, },
"portainer": { "portainer": {
@@ -89,7 +89,7 @@
}, },
"weather": { "weather": {
"current": "Ubicación actual", "current": "Ubicación actual",
"allow": "Haga clic para permitir", "allow": "Clic para permitir",
"updating": "Actualizando", "updating": "Actualizando",
"wait": "Espere, por favor" "wait": "Espere, por favor"
}, },
@@ -128,7 +128,7 @@
"numberOfFailQueries": "Consultas fallidas" "numberOfFailQueries": "Consultas fallidas"
}, },
"transmission": { "transmission": {
"download": "Descarga", "download": "Bajada",
"upload": "Subida", "upload": "Subida",
"leech": "Compañeros", "leech": "Compañeros",
"seed": "Semillas" "seed": "Semillas"
@@ -153,9 +153,20 @@
"latency": "Latencia" "latency": "Latencia"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "Bajada",
"upload": "Upload", "upload": "Subida",
"leech": "Leech", "leech": "Compañeros",
"seed": "Seed" "seed": "Semillas"
},
"mastodon": {
"user_count": "Usuarios",
"status_count": "Publicaciones",
"domain_count": "Dominios"
},
"strelaysrv": {
"numActiveSessions": "Sesiones",
"numConnections": "Conexiones",
"dataRelayed": "Retransmitido",
"transferRate": "Velocidad"
} }
} }

View File

@@ -34,22 +34,22 @@
}, },
"rutorrent": { "rutorrent": {
"active": "Actif", "active": "Actif",
"upload": "Téléverser", "upload": "Envoi",
"download": "Télécharger" "download": "Réception"
}, },
"sonarr": { "sonarr": {
"wanted": "Demandé", "wanted": "Demande",
"queued": "En queue", "queued": "En attente",
"series": "Séries" "series": "Séries"
}, },
"radarr": { "radarr": {
"wanted": "Demandé", "wanted": "Demande",
"queued": "En queue", "queued": "En attente",
"movies": "Films" "movies": "Films"
}, },
"readarr": { "readarr": {
"wanted": "Demandé", "wanted": "Demande",
"queued": "En Queue", "queued": "Attente",
"books": "Livres" "books": "Livres"
}, },
"ombi": { "ombi": {
@@ -68,8 +68,8 @@
"gravity": "Listes dom. bloqués" "gravity": "Listes dom. bloqués"
}, },
"speedtest": { "speedtest": {
"upload": "Téléversement", "upload": "Envoi",
"download": "Téléchargement", "download": "Récep.",
"ping": "Ping" "ping": "Ping"
}, },
"portainer": { "portainer": {
@@ -132,11 +132,11 @@
"messages": "Msg" "messages": "Msg"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexeurs", "enableIndexers": "Indexeur",
"numberOfGrabs": "Capture", "numberOfGrabs": "Capture",
"numberOfQueries": "Demandes", "numberOfQueries": "Demande",
"numberOfFailGrabs": "Capture échouée", "numberOfFailGrabs": "Capt. échouée",
"numberOfFailQueries": "Demande échouée" "numberOfFailQueries": "Dem. échouée"
}, },
"transmission": { "transmission": {
"download": "Réception", "download": "Réception",
@@ -164,9 +164,20 @@
"latency": "Latence" "latency": "Latence"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "Récep.",
"upload": "Upload", "upload": "Envoi",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Utilisateurs",
"status_count": "Messages",
"domain_count": "Domaines"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Cnx",
"dataRelayed": "Relayé",
"transferRate": "Débit"
} }
} }

View File

@@ -0,0 +1,172 @@
{
"widget": {
"missing_type": "סוג ווידג'ט חסר: {{type}}",
"api_error": "שגיאת API",
"status": "סטטוס"
},
"weather": {
"current": "מיקום נוכחי",
"allow": "יש ללחוץ כדי לאשר",
"updating": "מעדכן",
"wait": "המתן בבקשה"
},
"search": {
"placeholder": "חיפוש…"
},
"resources": {
"total": "סה\"כ",
"free": "פנוי",
"used": "בשימוש",
"load": "עומס"
},
"docker": {
"rx": "RX",
"tx": "TX",
"mem": "זיכרון",
"cpu": "מעבד",
"offline": "כבוי"
},
"emby": {
"playing": "מנגן",
"transcoding": "מקודד",
"bitrate": "סיביות",
"no_active": "אין הזרמות פעילות"
},
"tautulli": {
"playing": "מנגן",
"transcoding": "מקודד",
"bitrate": "סיביות",
"no_active": "אין הזרמות פעילות"
},
"nzbget": {
"rate": "יחס",
"remaining": "נותר",
"downloaded": "הורד"
},
"sabnzbd": {
"rate": "יחס",
"queue": "תור",
"timeleft": "זמן שנותר"
},
"rutorrent": {
"active": "פעיל",
"upload": "העלאה",
"download": "הורדה"
},
"transmission": {
"download": "הורדה",
"upload": "העלאה",
"leech": "בהורדה",
"seed": "בשיתוף"
},
"qbittorrent": {
"download": "הורדה",
"upload": "העלאה",
"leech": "בהורדה",
"seed": "בשיתוף"
},
"sonarr": {
"wanted": "מבוקש",
"queued": "בתור",
"series": "סדרות"
},
"radarr": {
"wanted": "מבוקש",
"queued": "בתור",
"movies": "סרטים"
},
"lidarr": {
"wanted": "מבוקש",
"queued": "בתור",
"albums": "אלבומים"
},
"readarr": {
"wanted": "מבוקש",
"queued": "בתור",
"books": "ספרים"
},
"bazarr": {
"missingEpisodes": "פרקים חסרים",
"missingMovies": "סרטים חסרים"
},
"ombi": {
"pending": "ממתין",
"approved": "מאושר",
"available": "זמין"
},
"jellyseerr": {
"pending": "ממתין",
"approved": "מאושר",
"available": "זמין"
},
"overseerr": {
"pending": "ממתין",
"approved": "מאושר",
"available": "זמין"
},
"pihole": {
"queries": "שאילתות",
"blocked": "נחסם",
"gravity": "Gravity"
},
"adguard": {
"queries": "שאילתות",
"blocked": "נחסם",
"filtered": "מסונן",
"latency": "השהיה"
},
"speedtest": {
"upload": "העלאה",
"download": "הורדה",
"ping": "פינג"
},
"portainer": {
"running": "פעיל",
"stopped": "נעצר",
"total": "סה\"כ"
},
"traefik": {
"routers": "ניתובים",
"services": "שירותים",
"middleware": "מתווך"
},
"npm": {
"enabled": "מופעל",
"disabled": "מבוטל",
"total": "סה\"כ"
},
"coinmarketcap": {
"configure": "קבע את התצורה של מטבע קריפטו אחד או יותר למעקב",
"1hour": "שעה אחת",
"1day": "יום 1",
"7days": "7 יום",
"30days": "30 יום"
},
"gotify": {
"apps": "אפליקציות",
"clients": "לקוחות",
"messages": "הודעות"
},
"prowlarr": {
"enableIndexers": "אינדקסים",
"numberOfGrabs": "Grabs",
"numberOfQueries": "שאילתות",
"numberOfFailGrabs": "Fail Grabs",
"numberOfFailQueries": "Fail Queries"
},
"jackett": {
"configured": "מוגדר",
"errored": "שגיאה"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
}
}

View File

@@ -157,5 +157,16 @@
"upload": "Upload", "upload": "Upload",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -1,9 +1,9 @@
{ {
"resources": { "resources": {
"total": "Total", "total": "Összes",
"free": "Free", "free": "Szabad",
"used": "Used", "used": "Használt",
"load": "Load" "load": "Terhelés"
}, },
"docker": { "docker": {
"rx": "RX", "rx": "RX",
@@ -13,149 +13,160 @@
"offline": "Offline" "offline": "Offline"
}, },
"lidarr": { "lidarr": {
"albums": "Albums", "albums": "Albumok",
"wanted": "Wanted", "wanted": "Keresett",
"queued": "Queued" "queued": "Sorban áll"
}, },
"readarr": { "readarr": {
"wanted": "Wanted", "wanted": "Keresett",
"queued": "Queued", "queued": "Sorban áll",
"books": "Books" "books": "Könyvek"
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "Missing Episodes", "missingEpisodes": "Hiányzó epizódok",
"missingMovies": "Missing Movies" "missingMovies": "Hiányzó filmek"
}, },
"widget": { "widget": {
"missing_type": "Missing Widget Type: {{type}}", "missing_type": "Hiányzó Widget Típus: {{type}}",
"api_error": "API Error", "api_error": "API Hiba",
"status": "Status" "status": "Státusz"
}, },
"weather": { "weather": {
"current": "Current Location", "current": "Aktuális hely",
"allow": "Click to allow", "allow": "Kattints az engedélyezéshez",
"updating": "Updating", "updating": "Frissítés",
"wait": "Please wait" "wait": "Kérlek várj"
}, },
"search": { "search": {
"placeholder": "Search…" "placeholder": "Keresés…"
}, },
"emby": { "emby": {
"playing": "Playing", "playing": "Lejátszás",
"transcoding": "Transcoding", "transcoding": "Átkódolás",
"bitrate": "Bitrate", "bitrate": "Bitráta",
"no_active": "No Active Streams" "no_active": "Nincs aktív lejátszás"
}, },
"tautulli": { "tautulli": {
"playing": "Playing", "playing": "Lejátszás folyamatban",
"transcoding": "Transcoding", "transcoding": "Átkódolás",
"bitrate": "Bitrate", "bitrate": "Bitráta",
"no_active": "No Active Streams" "no_active": "Nincs aktív lejátszás"
}, },
"nzbget": { "nzbget": {
"rate": "Rate", "rate": "Ráta",
"remaining": "Remaining", "remaining": "Hátralévő",
"downloaded": "Downloaded" "downloaded": "Letöltött"
}, },
"sabnzbd": { "sabnzbd": {
"rate": "Rate", "rate": "Ráta",
"queue": "Queue", "queue": "Sor",
"timeleft": "Time Left" "timeleft": "Hátralévő idő"
}, },
"rutorrent": { "rutorrent": {
"active": "Active", "active": "Aktív",
"upload": "Upload", "upload": "Feltöltés",
"download": "Download" "download": "Letöltés"
}, },
"transmission": { "transmission": {
"leech": "Leech", "leech": "Leechelés",
"seed": "Seed", "seed": "Seedelés",
"download": "Download", "download": "Letöltés",
"upload": "Upload" "upload": "Feltöltés"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "Letöltés",
"upload": "Upload", "upload": "Feltöltés",
"leech": "Leech", "leech": "Leechelés",
"seed": "Seed" "seed": "Seedelés"
}, },
"sonarr": { "sonarr": {
"wanted": "Wanted", "wanted": "Keresett",
"queued": "Queued", "queued": "Sorban áll",
"series": "Series" "series": "Sorozat"
}, },
"radarr": { "radarr": {
"wanted": "Wanted", "wanted": "Keresett",
"queued": "Queued", "queued": "Sorban áll",
"movies": "Movies" "movies": "Filmek"
}, },
"ombi": { "ombi": {
"pending": "Pending", "pending": "Függőben",
"approved": "Approved", "approved": "Engedélyezett",
"available": "Available" "available": "Elérhető"
}, },
"jellyseerr": { "jellyseerr": {
"pending": "Pending", "pending": "Függőben",
"approved": "Approved", "approved": "Engedélyezett",
"available": "Available" "available": "Elérhető"
}, },
"overseerr": { "overseerr": {
"pending": "Pending", "pending": "Függőben",
"approved": "Approved", "approved": "Engedélyezett",
"available": "Available" "available": "Elérhető"
}, },
"pihole": { "pihole": {
"queries": "Queries", "queries": "Lekérdezések",
"blocked": "Blocked", "blocked": "Blokkolt",
"gravity": "Gravity" "gravity": "Gravitáció"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "Lekérdezések",
"blocked": "Blocked", "blocked": "Blokkolt",
"filtered": "Filtered", "filtered": "Szűrt",
"latency": "Latency" "latency": "Késleltetés"
}, },
"speedtest": { "speedtest": {
"upload": "Upload", "upload": "Feltöltés",
"download": "Download", "download": "Letöltés",
"ping": "Ping" "ping": "Ping"
}, },
"portainer": { "portainer": {
"running": "Running", "running": "Futó",
"stopped": "Stopped", "stopped": "Megállított",
"total": "Total" "total": "Összes"
}, },
"traefik": { "traefik": {
"routers": "Routers", "routers": "Routerek",
"services": "Services", "services": "Folyamatok",
"middleware": "Middleware" "middleware": "Közvetítő"
}, },
"npm": { "npm": {
"enabled": "Enabled", "enabled": "Bekapcsolva",
"disabled": "Disabled", "disabled": "Kikapcsolva",
"total": "Total" "total": "Összes"
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "Configure one or more crypto currencies to track", "configure": "Állíts be egy vagy több Cryptovalutát a követéshez",
"1hour": "1 Hour", "1hour": "1 Óra",
"1day": "1 Day", "1day": "1 Nap",
"7days": "7 Days", "7days": "7 Nap",
"30days": "30 Days" "30days": "30 Nap"
}, },
"gotify": { "gotify": {
"apps": "Applications", "apps": "Applikációk",
"clients": "Clients", "clients": "Kliensek",
"messages": "Messages" "messages": "Üzenetek"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "Indexerek",
"numberOfGrabs": "Grabs", "numberOfGrabs": "Fogott",
"numberOfFailGrabs": "Fail Grabs", "numberOfFailGrabs": "Hibás fogások",
"numberOfQueries": "Queries", "numberOfQueries": "Lekérdezések",
"numberOfFailQueries": "Fail Queries" "numberOfFailQueries": "Hibás lekérdezések"
}, },
"jackett": { "jackett": {
"configured": "Configured", "configured": "Beállított",
"errored": "Errored" "errored": "Hibás"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -99,14 +99,14 @@
"available": "Disponibili" "available": "Disponibili"
}, },
"sabnzbd": { "sabnzbd": {
"rate": "Rate", "rate": "Rapporto",
"queue": "Queue", "queue": "Coda",
"timeleft": "Time Left" "timeleft": "Tempo Rimanente"
}, },
"nzbget": { "nzbget": {
"rate": "Rate", "rate": "Rapporto",
"remaining": "Remaining", "remaining": "Rimanente",
"downloaded": "Downloaded" "downloaded": "Scaricato"
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "Configure one or more crypto currencies to track", "configure": "Configure one or more crypto currencies to track",
@@ -116,9 +116,9 @@
"30days": "30 Days" "30days": "30 Days"
}, },
"gotify": { "gotify": {
"apps": "Applications", "apps": "Applicazioni",
"clients": "Clients", "clients": "Clients",
"messages": "Messages" "messages": "Messaggi"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "Indexers",
@@ -157,5 +157,16 @@
"leech": "Leech", "leech": "Leech",
"upload": "Upload", "upload": "Upload",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -157,5 +157,16 @@
"upload": "Upload", "upload": "Upload",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -40,7 +40,7 @@
"playing": "Afspelen", "playing": "Afspelen",
"transcoding": "Transcodering", "transcoding": "Transcodering",
"bitrate": "Bitsnelheid", "bitrate": "Bitsnelheid",
"no_active": "No Active Streams" "no_active": "Geen Actieve Steams"
}, },
"tautulli": { "tautulli": {
"playing": "Afspelen", "playing": "Afspelen",
@@ -157,5 +157,16 @@
"upload": "Upload", "upload": "Upload",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -157,5 +157,16 @@
"upload": "Upload", "upload": "Upload",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -11,7 +11,7 @@
"total": "Total", "total": "Total",
"free": "Livre", "free": "Livre",
"used": "Usado", "used": "Usado",
"load": "Load" "load": "Carregar"
}, },
"docker": { "docker": {
"rx": "Rx", "rx": "Rx",
@@ -23,7 +23,7 @@
"emby": { "emby": {
"playing": "A reproduzir", "playing": "A reproduzir",
"transcoding": "Transcodificação", "transcoding": "Transcodificação",
"bitrate": "Bitrate", "bitrate": "Taxa de bits",
"no_active": "Sem streams ativas" "no_active": "Sem streams ativas"
}, },
"tautulli": { "tautulli": {
@@ -34,8 +34,8 @@
}, },
"rutorrent": { "rutorrent": {
"active": "Ativo", "active": "Ativo",
"upload": "Envio", "upload": "Enviando",
"download": "ReceçãoDownload" "download": "Baixando"
}, },
"sonarr": { "sonarr": {
"wanted": "Desejada", "wanted": "Desejada",
@@ -48,7 +48,7 @@
"movies": "Filmes" "movies": "Filmes"
}, },
"readarr": { "readarr": {
"wanted": "Wanted", "wanted": "Desejados",
"queued": "Em fila", "queued": "Em fila",
"books": "Livros" "books": "Livros"
}, },
@@ -65,7 +65,7 @@
"pihole": { "pihole": {
"queries": "Consultas", "queries": "Consultas",
"blocked": "Bloqueado", "blocked": "Bloqueado",
"gravity": "Gravity" "gravity": "Gravidade"
}, },
"speedtest": { "speedtest": {
"upload": "Envio", "upload": "Envio",
@@ -78,7 +78,7 @@
"total": "Total" "total": "Total"
}, },
"traefik": { "traefik": {
"routers": "Routers", "routers": "Roteadores",
"services": "Serviços", "services": "Serviços",
"middleware": "Middleware" "middleware": "Middleware"
}, },
@@ -110,21 +110,21 @@
"available": "Disponível" "available": "Disponível"
}, },
"sabnzbd": { "sabnzbd": {
"rate": "Rate", "rate": "Taxa",
"queue": "Fila", "queue": "Fila",
"timeleft": "Tempo restante" "timeleft": "Tempo restante"
}, },
"nzbget": { "nzbget": {
"rate": "Rate", "rate": "Taxa",
"remaining": "Restante", "remaining": "Restante",
"downloaded": "Downloaded" "downloaded": "Baixado"
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "Configurar uma ou mais moedas", "configure": "Configurar uma ou mais moedas",
"1hour": "1 Hour", "1hour": "1 Hora",
"1day": "1 Day", "1day": "1 Dia",
"7days": "7 Days", "7days": "7 Dias",
"30days": "30 Days" "30days": "30 Dias"
}, },
"gotify": { "gotify": {
"apps": "Aplicações", "apps": "Aplicações",
@@ -132,41 +132,52 @@
"messages": "Mensagens" "messages": "Mensagens"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "Indexadores",
"numberOfGrabs": "Grabs", "numberOfGrabs": "Agarrados",
"numberOfQueries": "Queries", "numberOfQueries": "Consultas",
"numberOfFailGrabs": "Falhados", "numberOfFailGrabs": "Falhados",
"numberOfFailQueries": "Pesquisas falhadas" "numberOfFailQueries": "Pesquisas falhadas"
}, },
"transmission": { "transmission": {
"download": "Download", "download": "Baixando",
"upload": "Envio", "upload": "Enviando",
"leech": "Leech", "leech": "Sanguessugas",
"seed": "Seed" "seed": "Semeadores"
}, },
"jackett": { "jackett": {
"configured": "Configured", "configured": "Configurado",
"errored": "Errored" "errored": "Errado"
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "Missing Episodes", "missingEpisodes": "Episódios Faltantes",
"missingMovies": "Missing Movies" "missingMovies": "Filmes Faltantes"
}, },
"lidarr": { "lidarr": {
"queued": "Queued", "queued": "Enfileirado",
"wanted": "Wanted", "wanted": "Desejado",
"albums": "Albums" "albums": "Álbuns"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "Consultas",
"blocked": "Blocked", "blocked": "Bloqueado",
"filtered": "Filtered", "filtered": "Filtrado",
"latency": "Latency" "latency": "Latência"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "Baixando",
"upload": "Upload", "upload": "Enviando",
"leech": "Leech", "leech": "Sanguessugas",
"seed": "Seed" "seed": "Semeadores"
},
"mastodon": {
"user_count": "Usuários",
"status_count": "Postagens",
"domain_count": "Domínios"
},
"strelaysrv": {
"numActiveSessions": "Sessões",
"numConnections": "Conexões",
"dataRelayed": "Retransmitido",
"transferRate": "Taxa"
} }
} }

View File

@@ -113,7 +113,7 @@
"1hour": "1 Hour", "1hour": "1 Hour",
"1day": "1 Day", "1day": "1 Day",
"7days": "7 Days", "7days": "7 Days",
"30days": "30 Days" "30days": "30 Дней"
}, },
"gotify": { "gotify": {
"apps": "Applications", "apps": "Applications",
@@ -157,5 +157,16 @@
"upload": "Upload", "upload": "Upload",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate",
"numActiveSessions": "Sessions"
} }
} }

View File

@@ -138,24 +138,35 @@
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexerare", "enableIndexers": "Indexerare",
"numberOfGrabs": "Hämtningar", "numberOfGrabs": "Hämtningar",
"numberOfQueries": "Queries", "numberOfQueries": "Hämtningar",
"numberOfFailGrabs": "Misslyckade hämtningar", "numberOfFailGrabs": "Misslyckade hämtningar",
"numberOfFailQueries": "Fail Queries" "numberOfFailQueries": "Misslyckade hämtningar"
}, },
"jackett": { "jackett": {
"configured": "Konfigurerade", "configured": "Konfigurerade",
"errored": "Felaktiga" "errored": "Felaktiga"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "Förfrågningar",
"blocked": "Blocked", "blocked": "Blockerad",
"filtered": "Filtered", "filtered": "Filtrerad",
"latency": "Latency" "latency": "Svarstid"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "Nedladdning",
"upload": "Upload", "upload": "Uppladdning",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Användare",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessioner",
"numConnections": "Anslutningar",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -157,5 +157,16 @@
"upload": "Upload", "upload": "Upload",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -21,13 +21,13 @@
"offline": "离线" "offline": "离线"
}, },
"emby": { "emby": {
"playing": "正在播放", "playing": "播放",
"transcoding": "转码", "transcoding": "转码",
"bitrate": "比特率", "bitrate": "比特率",
"no_active": "暂无播放" "no_active": "暂无播放"
}, },
"tautulli": { "tautulli": {
"playing": "正在播放", "playing": "播放",
"transcoding": "转码", "transcoding": "转码",
"bitrate": "比特率", "bitrate": "比特率",
"no_active": "暂无播放" "no_active": "暂无播放"
@@ -38,12 +38,12 @@
"download": "下载" "download": "下载"
}, },
"sonarr": { "sonarr": {
"wanted": "通缉", "wanted": "想看",
"queued": "排队", "queued": "排队",
"series": "系列" "series": "系列"
}, },
"radarr": { "radarr": {
"wanted": "订阅", "wanted": "想看",
"queued": "队列", "queued": "队列",
"movies": "电影" "movies": "电影"
}, },
@@ -74,7 +74,7 @@
}, },
"portainer": { "portainer": {
"running": "运行中", "running": "运行中",
"stopped": "停止", "stopped": "停止",
"total": "总计" "total": "总计"
}, },
"traefik": { "traefik": {
@@ -91,7 +91,7 @@
"current": "当前定位", "current": "当前定位",
"allow": "点击并允许", "allow": "点击并允许",
"updating": "更新中", "updating": "更新中",
"wait": "请等待" "wait": "请稍后"
}, },
"overseerr": { "overseerr": {
"pending": "待办", "pending": "待办",
@@ -110,10 +110,10 @@
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "配置一个或多个需要追踪的加密", "configure": "配置一个或多个需要追踪的加密",
"1hour": "1 Hour", "1hour": "1小时",
"1day": "1 Day", "1day": "1",
"7days": "7 Days", "7days": "7",
"30days": "30 Days" "30days": "30"
}, },
"gotify": { "gotify": {
"apps": "应用", "apps": "应用",
@@ -121,41 +121,52 @@
"messages": "信息" "messages": "信息"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "索引器",
"numberOfGrabs": "Grabs", "numberOfGrabs": "抓取",
"numberOfQueries": "Queries", "numberOfQueries": "查询",
"numberOfFailGrabs": "Fail Grabs", "numberOfFailGrabs": "抓取失败",
"numberOfFailQueries": "Fail Queries" "numberOfFailQueries": "查询失败"
}, },
"transmission": { "transmission": {
"download": "下载", "download": "下载",
"upload": "上传", "upload": "上传",
"leech": "Leech", "leech": "下载中",
"seed": "做种" "seed": "做种"
}, },
"jackett": { "jackett": {
"configured": "Configured", "configured": "已配置",
"errored": "Errored" "errored": "出错了"
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "Missing Episodes", "missingEpisodes": "缺少的剧集",
"missingMovies": "Missing Movies" "missingMovies": "缺少的电影"
}, },
"lidarr": { "lidarr": {
"wanted": "Wanted", "wanted": "订阅",
"queued": "Queued", "queued": "队列",
"albums": "Albums" "albums": "相册"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "查询",
"blocked": "Blocked", "blocked": "阻止",
"filtered": "Filtered", "filtered": "过滤",
"latency": "Latency" "latency": "延迟"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "下载",
"upload": "Upload", "upload": "上传",
"leech": "Leech", "leech": "下载中",
"seed": "Seed" "seed": "做种"
},
"mastodon": {
"user_count": "用户",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"dataRelayed": "Relayed",
"numConnections": "Connections",
"transferRate": "Rate"
} }
} }

View File

@@ -157,5 +157,16 @@
"upload": "Upload", "upload": "Upload",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
} }
} }

View File

@@ -2,13 +2,8 @@ import List from "components/bookmarks/list";
export default function BookmarksGroup({ group }) { export default function BookmarksGroup({ group }) {
return ( return (
<div <div key={group.name} className="basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4 flex-1 p-1">
key={group.name} <h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
className="basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4 flex-1 p-1"
>
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">
{group.name}
</h2>
<List bookmarks={group.bookmarks} /> <List bookmarks={group.bookmarks} />
</div> </div>
); );

View File

@@ -1,12 +1,18 @@
import { useContext } from "react";
import { SettingsContext } from "utils/settings-context";
export default function Item({ bookmark }) { export default function Item({ bookmark }) {
const { hostname } = new URL(bookmark.href); const { hostname } = new URL(bookmark.href);
const { settings } = useContext(SettingsContext);
return ( return (
<li key={bookmark.name}> <li key={bookmark.name}>
<button <a
type="button" href={bookmark.href}
onClick={() => window.open(bookmark.href, "_blank").focus()} title={bookmark.name}
className="w-full text-left mb-3 cursor-pointer rounded-md font-medium text-theme-700 hover:text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-black/10 dark:shadow-black/20 bg-white/50 hover:bg-theme-300/10 dark:bg-white/10 dark:hover:bg-white/20" target={settings.target ?? "_blank"}
className="block w-full text-left mb-3 cursor-pointer rounded-md font-medium text-theme-700 hover:text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-black/10 dark:shadow-black/20 bg-white/50 hover:bg-theme-300/10 dark:bg-white/10 dark:hover:bg-white/20"
> >
<div className="flex"> <div className="flex">
<div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md"> <div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md">
@@ -17,7 +23,7 @@ export default function Item({ bookmark }) {
<div className="px-2 py-2 truncate text-theme-500 dark:text-theme-400 opacity-50 text-xs">{hostname}</div> <div className="px-2 py-2 truncate text-theme-500 dark:text-theme-400 opacity-50 text-xs">{hostname}</div>
</div> </div>
</div> </div>
</button> </a>
</li> </li>
); );
} }

View File

@@ -1,10 +1,13 @@
import Image from "next/future/image"; import Image from "next/future/image";
import { useContext } from "react";
import { Disclosure } from "@headlessui/react"; import { Disclosure } from "@headlessui/react";
import Status from "./status"; import Status from "./status";
import Widget from "./widget"; import Widget from "./widget";
import Docker from "./widgets/service/docker"; import Docker from "./widgets/service/docker";
import { SettingsContext } from "utils/settings-context";
function resolveIcon(icon) { function resolveIcon(icon) {
if (icon.startsWith("http")) { if (icon.startsWith("http")) {
return `/api/proxy?url=${encodeURIComponent(icon)}`; return `/api/proxy?url=${encodeURIComponent(icon)}`;
@@ -22,13 +25,8 @@ function resolveIcon(icon) {
} }
export default function Item({ service }) { export default function Item({ service }) {
const handleOnClick = () => {
if (service.href && service.href !== "#") {
window.open(service.href, "_blank").focus();
}
};
const hasLink = service.href && service.href !== "#"; const hasLink = service.href && service.href !== "#";
const { settings } = useContext(SettingsContext);
return ( return (
<li key={service.name}> <li key={service.name}>
@@ -41,13 +39,14 @@ export default function Item({ service }) {
<div className="flex select-none"> <div className="flex select-none">
{service.icon && {service.icon &&
(hasLink ? ( (hasLink ? (
<button <a
type="button" href={service.href}
onClick={handleOnClick} target={settings.target ?? "_blank"}
rel="noreferrer"
className="flex-shrink-0 flex items-center justify-center w-12 " className="flex-shrink-0 flex items-center justify-center w-12 "
> >
<Image src={resolveIcon(service.icon)} width={32} height={32} alt="logo" /> <Image src={resolveIcon(service.icon)} width={32} height={32} alt="logo" />
</button> </a>
) : ( ) : (
<div className="flex-shrink-0 flex items-center justify-center w-12 "> <div className="flex-shrink-0 flex items-center justify-center w-12 ">
<Image src={resolveIcon(service.icon)} width={32} height={32} alt="logo" /> <Image src={resolveIcon(service.icon)} width={32} height={32} alt="logo" />
@@ -55,16 +54,17 @@ export default function Item({ service }) {
))} ))}
{hasLink ? ( {hasLink ? (
<button <a
type="button" href={service.href}
onClick={handleOnClick} target={settings.target ?? "_blank"}
rel="noreferrer"
className="flex-1 flex items-center justify-between rounded-r-md " className="flex-1 flex items-center justify-between rounded-r-md "
> >
<div className="flex-1 px-2 py-2 text-sm text-left"> <div className="flex-1 px-2 py-2 text-sm text-left">
{service.name} {service.name}
<p className="text-theme-500 dark:text-theme-400 text-xs font-extralight">{service.description}</p> <p className="text-theme-500 dark:text-theme-400 text-xs font-extralight">{service.description}</p>
</div> </div>
</button> </a>
) : ( ) : (
<div className="flex-1 flex items-center justify-between rounded-r-md "> <div className="flex-1 flex items-center justify-between rounded-r-md ">
<div className="flex-1 px-2 py-2 text-sm text-left"> <div className="flex-1 px-2 py-2 text-sm text-left">

View File

@@ -1,32 +1,35 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import dynamic from "next/dynamic";
import Sonarr from "./widgets/service/sonarr"; const Sonarr = dynamic(() => import("./widgets/service/sonarr"));
import Radarr from "./widgets/service/radarr"; const Radarr = dynamic(() => import("./widgets/service/radarr"));
import Lidarr from "./widgets/service/lidarr"; const Lidarr = dynamic(() => import("./widgets/service/lidarr"));
import Readarr from "./widgets/service/readarr"; const Readarr = dynamic(() => import("./widgets/service/readarr"));
import Bazarr from "./widgets/service/bazarr"; const Bazarr = dynamic(() => import("./widgets/service/bazarr"));
import Ombi from "./widgets/service/ombi"; const Ombi = dynamic(() => import("./widgets/service/ombi"));
import Portainer from "./widgets/service/portainer"; const Portainer = dynamic(() => import("./widgets/service/portainer"));
import Emby from "./widgets/service/emby"; const Emby = dynamic(() => import("./widgets/service/emby"));
import Nzbget from "./widgets/service/nzbget"; const Nzbget = dynamic(() => import("./widgets/service/nzbget"));
import SABnzbd from "./widgets/service/sabnzbd"; const SABnzbd = dynamic(() => import("./widgets/service/sabnzbd"));
import Transmission from "./widgets/service/transmission"; const Transmission = dynamic(() => import("./widgets/service/transmission"));
import QBittorrent from "./widgets/service/qbittorrent"; const QBittorrent = dynamic(() => import("./widgets/service/qbittorrent"));
import Docker from "./widgets/service/docker"; const Docker = dynamic(() => import("./widgets/service/docker"));
import Pihole from "./widgets/service/pihole"; const Pihole = dynamic(() => import("./widgets/service/pihole"));
import Rutorrent from "./widgets/service/rutorrent"; const Rutorrent = dynamic(() => import("./widgets/service/rutorrent"));
import Jellyfin from "./widgets/service/jellyfin"; const Jellyfin = dynamic(() => import("./widgets/service/jellyfin"));
import Speedtest from "./widgets/service/speedtest"; const Speedtest = dynamic(() => import("./widgets/service/speedtest"));
import Traefik from "./widgets/service/traefik"; const Traefik = dynamic(() => import("./widgets/service/traefik"));
import Jellyseerr from "./widgets/service/jellyseerr"; const Jellyseerr = dynamic(() => import("./widgets/service/jellyseerr"));
import Overseerr from "./widgets/service/overseerr"; const Overseerr = dynamic(() => import("./widgets/service/overseerr"));
import Npm from "./widgets/service/npm"; const Npm = dynamic(() => import("./widgets/service/npm"));
import Tautulli from "./widgets/service/tautulli"; const Tautulli = dynamic(() => import("./widgets/service/tautulli"));
import CoinMarketCap from "./widgets/service/coinmarketcap"; const CoinMarketCap = dynamic(() => import("./widgets/service/coinmarketcap"));
import Gotify from "./widgets/service/gotify"; const Gotify = dynamic(() => import("./widgets/service/gotify"));
import Prowlarr from "./widgets/service/prowlarr"; const Prowlarr = dynamic(() => import("./widgets/service/prowlarr"));
import Jackett from "./widgets/service/jackett"; const Jackett = dynamic(() => import("./widgets/service/jackett"));
import AdGuard from "./widgets/service/adguard"; const AdGuard = dynamic(() => import("./widgets/service/adguard"));
const StRelaySrv = dynamic(() => import("./widgets/service/strelaysrv"));
const Mastodon = dynamic(() => import("./widgets/service/mastodon"));
const widgetMappings = { const widgetMappings = {
docker: Docker, docker: Docker,
@@ -56,6 +59,8 @@ const widgetMappings = {
prowlarr: Prowlarr, prowlarr: Prowlarr,
jackett: Jackett, jackett: Jackett,
adguard: AdGuard, adguard: AdGuard,
strelaysrv: StRelaySrv,
mastodon: Mastodon,
}; };
export default function Widget({ service }) { export default function Widget({ service }) {

View File

@@ -0,0 +1,37 @@
import useSWR from "swr";
import { useTranslation } from "react-i18next";
import Widget from "../widget";
import Block from "../block";
import { formatApiUrl } from "utils/api-helpers";
export default function Mastodon({ service }) {
const { t } = useTranslation();
const config = service.widget;
const { data: statsData, error: statsError } = useSWR(formatApiUrl(config, `instance`));
if (statsError) {
return <Widget error={t("widget.api_error")} />;
}
if (!statsData) {
return (
<Widget>
<Block label={t("mastodon.user_count")} />
<Block label={t("mastodon.status_count")} />
<Block label={t("mastodon.domain_count")} />
</Widget>
);
}
return (
<Widget>
<Block label={t("mastodon.user_count")} value={t("common.number", { value: statsData.stats.user_count })} />
<Block label={t("mastodon.status_count")} value={t("common.number", { value: statsData.stats.status_count })} />
<Block label={t("mastodon.domain_count")} value={t("common.number", { value: statsData.stats.domain_count })} />
</Widget>
);
}

View File

@@ -0,0 +1,38 @@
import useSWR from "swr";
import { useTranslation } from "react-i18next";
import Widget from "../widget";
import Block from "../block";
import { formatApiUrl } from "utils/api-helpers";
export default function StRelaySrv({ service }) {
const { t } = useTranslation();
const config = service.widget;
const { data: statsData, error: statsError } = useSWR(formatApiUrl(config, `status`));
if (statsError) {
return <Widget error={t("widget.api_error")} />;
}
if (!statsData) {
return (
<Widget>
<Block label={t("strelaysrv.numActiveSessions")} />
<Block label={t("strelaysrv.numConnections")} />
<Block label={t("strelaysrv.bytesProxied")} />
</Widget>
);
}
return (
<Widget>
<Block label={t("strelaysrv.numActiveSessions")} value={t("common.number", { value: statsData.numActiveSessions })} />
<Block label={t("strelaysrv.numConnections")} value={t("common.number", { value: statsData.numConnections })} />
<Block label={t("strelaysrv.dataRelayed")} value={t("common.bytes", { value: statsData.bytesProxied })} />
<Block label={t("strelaysrv.transferRate")} value={t("common.bitrate",{ value: statsData.kbps10s1m5m15m30m60m[5] })} />
</Widget>
);
}

View File

@@ -0,0 +1,47 @@
import { useTranslation } from "react-i18next";
import useSWR from "swr";
import { compareVersions } from "compare-versions";
import { MdNewReleases } from "react-icons/md";
export default function Version() {
const { t, i18n } = useTranslation();
const buildTime = process.env.NEXT_PUBLIC_BUILDTIME ?? new Date().toISOString();
const revision = process.env.NEXT_PUBLIC_REVISION ?? "dev";
const version = process.env.NEXT_PUBLIC_VERSION ?? "dev";
const { data: releaseData } = useSWR("https://api.github.com/repos/benphelps/homepage/releases");
// use Intl.DateTimeFormat to format the date
const formatDate = (date) => {
const options = {
year: "numeric",
month: "short",
day: "numeric",
};
return new Intl.DateTimeFormat(i18n.language, options).format(new Date(date));
};
const latestRelease = releaseData?.[0];
return (
<div className="flex flex-row items-center">
<span className="text-xs text-theme-500 opacity-50">
{version} ({revision.substring(0, 7)}, {formatDate(buildTime)})
</span>
{version === "main" || version === "dev"
? null
: releaseData &&
compareVersions(latestRelease.tag_name, version) > 0 && (
<a
href={latestRelease.html_url}
target="_blank"
rel="noopener noreferrer"
className="ml-2 text-xs text-theme-500 opacity-50 flex flex-row items-center"
>
<MdNewReleases className="mr-1" /> {t("Update Available")}
</a>
)}
</div>
);
}

View File

@@ -8,6 +8,7 @@ import "styles/theme.css";
import "utils/i18n"; import "utils/i18n";
import { ColorProvider } from "utils/color-context"; import { ColorProvider } from "utils/color-context";
import { ThemeProvider } from "utils/theme-context"; import { ThemeProvider } from "utils/theme-context";
import { SettingsProvider } from "utils/settings-context";
function MyApp({ Component, pageProps }) { function MyApp({ Component, pageProps }) {
return ( return (
@@ -18,7 +19,9 @@ function MyApp({ Component, pageProps }) {
> >
<ColorProvider> <ColorProvider>
<ThemeProvider> <ThemeProvider>
<Component {...pageProps} /> <SettingsProvider>
<Component {...pageProps} />
</SettingsProvider>
</ThemeProvider> </ThemeProvider>
</ColorProvider> </ColorProvider>
</SWRConfig> </SWRConfig>

View File

@@ -1,3 +1,4 @@
import createLogger from "utils/logger";
import genericProxyHandler from "utils/proxies/generic"; import genericProxyHandler from "utils/proxies/generic";
import credentialedProxyHandler from "utils/proxies/credentialed"; import credentialedProxyHandler from "utils/proxies/credentialed";
import rutorrentProxyHandler from "utils/proxies/rutorrent"; import rutorrentProxyHandler from "utils/proxies/rutorrent";
@@ -6,6 +7,8 @@ import npmProxyHandler from "utils/proxies/npm";
import transmissionProxyHandler from "utils/proxies/transmission"; import transmissionProxyHandler from "utils/proxies/transmission";
import qbittorrentProxyHandler from "utils/proxies/qbittorrent"; import qbittorrentProxyHandler from "utils/proxies/qbittorrent";
const logger = createLogger('servicesProxy');
function asJson(data) { function asJson(data) {
if (data?.length > 0) { if (data?.length > 0) {
const json = JSON.parse(data.toString()); const json = JSON.parse(data.toString());
@@ -81,6 +84,8 @@ const serviceProxyHandlers = {
sabnzbd: genericProxyHandler, sabnzbd: genericProxyHandler,
jackett: genericProxyHandler, jackett: genericProxyHandler,
adguard: genericProxyHandler, adguard: genericProxyHandler,
strelaysrv: genericProxyHandler,
mastodon: genericProxyHandler,
// uses X-API-Key (or similar) header auth // uses X-API-Key (or similar) header auth
gotify: credentialedProxyHandler, gotify: credentialedProxyHandler,
portainer: credentialedProxyHandler, portainer: credentialedProxyHandler,
@@ -98,20 +103,27 @@ const serviceProxyHandlers = {
}; };
export default async function handler(req, res) { export default async function handler(req, res) {
const { type } = req.query; try {
const { type } = req.query;
const serviceProxyHandler = serviceProxyHandlers[type]; const serviceProxyHandler = serviceProxyHandlers[type];
if (serviceProxyHandler) { if (serviceProxyHandler) {
if (serviceProxyHandler instanceof Function) { if (serviceProxyHandler instanceof Function) {
return serviceProxyHandler(req, res); return serviceProxyHandler(req, res);
}
const { proxy, maps } = serviceProxyHandler;
if (proxy) {
return proxy(req, res, maps);
}
} }
const { proxy, maps } = serviceProxyHandler; logger.debug("Unknown proxy service type: %s", type);
if (proxy) { return res.status(403).json({ error: "Unkown proxy service type" });
return proxy(req, res, maps); }
} catch (ex) {
logger.error(ex);
return res.status(500).send({ error: "Unexpected error" });
} }
return res.status(403).json({ error: "Unkown proxy service type" });
} }

View File

@@ -0,0 +1,9 @@
import checkAndCopyConfig from "utils/config";
const configs = ["docker.yaml", "settings.yaml", "services.yaml", "bookmarks.yaml"];
export default async function handler(req, res) {
const errors = configs.map((config) => checkAndCopyConfig(config)).filter((status) => status !== true);
res.send(errors);
}

View File

@@ -14,7 +14,7 @@ export default async function handler(req, res) {
} }
if (!apiKey && provider) { if (!apiKey && provider) {
const settings = await getSettings(); const settings = getSettings();
apiKey = settings?.providers?.openweathermap; apiKey = settings?.providers?.openweathermap;
} }

View File

@@ -14,7 +14,7 @@ export default async function handler(req, res) {
} }
if (!apiKey && provider) { if (!apiKey && provider) {
const settings = await getSettings(); const settings = getSettings();
apiKey = settings?.providers?.weatherapi; apiKey = settings?.providers?.weatherapi;
} }

View File

@@ -4,14 +4,17 @@ import Head from "next/head";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useEffect, useContext } from "react"; import { useEffect, useContext } from "react";
import { BiError } from "react-icons/bi";
import ServicesGroup from "components/services/group"; import ServicesGroup from "components/services/group";
import BookmarksGroup from "components/bookmarks/group"; import BookmarksGroup from "components/bookmarks/group";
import Widget from "components/widget"; import Widget from "components/widget";
import Revalidate from "components/revalidate"; import Revalidate from "components/revalidate";
import createLogger from "utils/logger";
import { getSettings } from "utils/config"; import { getSettings } from "utils/config";
import { ColorContext } from "utils/color-context"; import { ColorContext } from "utils/color-context";
import { ThemeContext } from "utils/theme-context"; import { ThemeContext } from "utils/theme-context";
import { SettingsContext } from "utils/settings-context";
const ThemeToggle = dynamic(() => import("components/theme-toggle"), { const ThemeToggle = dynamic(() => import("components/theme-toggle"), {
ssr: false, ssr: false,
@@ -21,29 +24,81 @@ const ColorToggle = dynamic(() => import("components/color-toggle"), {
ssr: false, ssr: false,
}); });
const Version = dynamic(() => import("components/version"), {
ssr: false,
});
const rightAlignedWidgets = ["weatherapi", "openweathermap", "weather", "search", "datetime"]; const rightAlignedWidgets = ["weatherapi", "openweathermap", "weather", "search", "datetime"];
export async function getStaticProps() { export function getStaticProps() {
const settings = await getSettings(); let logger;
try {
logger = createLogger("index");
const { providers, ...settings } = getSettings();
return { return {
props: { props: {
settings, initialSettings: settings,
}, },
}; };
} catch (e) {
if (logger) {
logger.error(e);
}
return {
props: {
initialSettings: {},
},
};
}
} }
export default function Home({ settings }) { export default function Index({ initialSettings }) {
const { data: errorsData } = useSWR("/api/validate");
if (errorsData && errorsData.length > 0) {
return (
<div className="w-full container m-auto justify-center p-10">
<div className="flex flex-col">
{errorsData.map((error, i) => (
<div
className="basis-1/2 bg-theme-500 dark:bg-theme-600 text-theme-600 dark:text-theme-300 m-2 rounded-md font-mono shadow-md border-4 border-transparent"
key={i}
>
<div className="bg-amber-200 text-amber-800 dark:text-amber-200 dark:bg-amber-800 p-2 rounded-md font-bold">
<BiError className="float-right w-6 h-6" />
{error.config}
</div>
<div className="p-2 text-theme-100 dark:text-theme-200">
<pre className="opacity-50 font-bold pb-2">{error.reason}</pre>
<pre className="text-sm">{error.mark.snippet}</pre>
</div>
</div>
))}
</div>
</div>
);
}
return <Home initialSettings={initialSettings} />;
}
function Home({ initialSettings }) {
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const { theme, setTheme } = useContext(ThemeContext); const { theme, setTheme } = useContext(ThemeContext);
const { color, setColor } = useContext(ColorContext); const { color, setColor } = useContext(ColorContext);
const { settings, setSettings } = useContext(SettingsContext);
useEffect(() => {
setSettings(initialSettings);
}, [initialSettings, setSettings]);
const { data: services } = useSWR("/api/services"); const { data: services } = useSWR("/api/services");
const { data: bookmarks } = useSWR("/api/bookmarks"); const { data: bookmarks } = useSWR("/api/bookmarks");
const { data: widgets } = useSWR("/api/widgets"); const { data: widgets } = useSWR("/api/widgets");
const wrappedStyle = {}; const wrappedStyle = {};
if (settings.background) { if (settings && settings.background) {
wrappedStyle.backgroundImage = `url(${settings.background})`; wrappedStyle.backgroundImage = `url(${settings.background})`;
wrappedStyle.backgroundSize = "cover"; wrappedStyle.backgroundSize = "cover";
wrappedStyle.opacity = settings.backgroundOpacity ?? 1; wrappedStyle.opacity = settings.backgroundOpacity ?? 1;
@@ -108,11 +163,15 @@ export default function Home({ settings }) {
</div> </div>
)} )}
<div className="rounded-full flex p-8 w-full justify-end"> <div className="flex p-8 pb-0 w-full justify-end">
{!settings?.color && <ColorToggle />} {!settings?.color && <ColorToggle />}
<Revalidate /> <Revalidate />
{!settings?.theme && <ThemeToggle />} {!settings?.theme && <ThemeToggle />}
</div> </div>
<div className="flex p-8 pt-4 w-full justify-end">
<Version />
</div>
</div> </div>
</> </>
); );

View File

@@ -1,3 +1,4 @@
---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://github.com/benphelps/homepage/wiki/Bookmarks # https://github.com/benphelps/homepage/wiki/Bookmarks

View File

@@ -1,9 +1,10 @@
---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://github.com/benphelps/homepage/wiki/Docker-Integration # https://github.com/benphelps/homepage/wiki/Docker-Integration
my-docker: # my-docker:
host: 127.0.0.1 # host: 127.0.0.1
port: 2375 # port: 2375
other-docker: # my-docker:
socket: /var/run/docker.sock # socket: /var/run/docker.sock

View File

@@ -1,3 +1,4 @@
---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://github.com/benphelps/homepage/wiki/Services # https://github.com/benphelps/homepage/wiki/Services

View File

@@ -1,3 +1,4 @@
---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://github.com/benphelps/homepage/wiki/Settings # https://github.com/benphelps/homepage/wiki/Settings

View File

@@ -1,3 +1,4 @@
---
# For configuration options and examples, please see: # For configuration options and examples, please see:
# https://github.com/benphelps/homepage/wiki/Information-Widgets # https://github.com/benphelps/homepage/wiki/Information-Widgets

View File

@@ -24,6 +24,8 @@ const formats = {
prowlarr: `{url}/api/v1/{endpoint}`, prowlarr: `{url}/api/v1/{endpoint}`,
jackett: `{url}/api/v2.0/{endpoint}?apikey={key}&configured=true`, jackett: `{url}/api/v2.0/{endpoint}?apikey={key}&configured=true`,
adguard: `{url}/control/{endpoint}`, adguard: `{url}/control/{endpoint}`,
strelaysrv: `{url}/{endpoint}`,
mastodon: `{url}/api/v1/{endpoint}`,
}; };
export function formatApiCall(api, args) { export function formatApiCall(api, args) {

View File

@@ -1,6 +1,6 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import { join } from "path"; import { join } from "path";
import { existsSync, copyFile, promises as fs } from "fs"; import { existsSync, copyFile, readFileSync } from "fs";
import yaml from "js-yaml"; import yaml from "js-yaml";
@@ -15,13 +15,22 @@ export default function checkAndCopyConfig(config) {
} }
console.info("%s was copied to the config folder", config); console.info("%s was copied to the config folder", config);
}); });
return true;
}
try {
yaml.load(readFileSync(configYaml, "utf8"));
return true;
} catch (e) {
return { ...e, config };
} }
} }
export async function getSettings() { export function getSettings() {
checkAndCopyConfig("settings.yaml"); checkAndCopyConfig("settings.yaml");
const settingsYaml = join(process.cwd(), "config", "settings.yaml"); const settingsYaml = join(process.cwd(), "config", "settings.yaml");
const fileContents = await fs.readFile(settingsYaml, "utf8"); const fileContents = readFileSync(settingsYaml, "utf8");
return yaml.load(fileContents); return yaml.load(fileContents);
} }

88
src/utils/logger.js Normal file
View File

@@ -0,0 +1,88 @@
/* eslint-disable no-console */
import { join } from "path";
import { format as utilFormat } from "node:util"
import winston from "winston";
let winstonLogger;
function init() {
const configPath = join(process.cwd(), "config");
function combineMessageAndSplat() {
return {
// eslint-disable-next-line no-unused-vars
transform: (info, opts) => {
// combine message and args if any
// eslint-disable-next-line no-param-reassign
info.message = utilFormat(info.message, ...info[Symbol.for('splat')] || []);
return info;
}
}
}
function messageFormatter(logInfo) {
if (logInfo.label) {
if (logInfo.stack) {
return `[${logInfo.timestamp}] ${logInfo.level}: <${logInfo.label}> ${logInfo.stack}`;
}
return `[${logInfo.timestamp}] ${logInfo.level}: <${logInfo.label}> ${logInfo.message}`;
}
if (logInfo.stack) {
return `[${logInfo.timestamp}] ${logInfo.level}: ${logInfo.stack}`;
}
return `[${logInfo.timestamp}] ${logInfo.level}: ${logInfo.message}`;
};
winstonLogger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.errors({ stack: true}),
combineMessageAndSplat(),
winston.format.timestamp(),
winston.format.colorize(),
winston.format.printf(messageFormatter)
),
handleExceptions: true,
handleRejections: true
}),
new winston.transports.File({
format: winston.format.combine(
winston.format.errors({ stack: true}),
combineMessageAndSplat(),
winston.format.timestamp(),
winston.format.printf(messageFormatter)
),
filename: `${configPath}/logs/homepage.log`,
handleExceptions: true,
handleRejections: true
}),
]
});
// patch the console log mechanism to use our logger
const consoleMethods = ['log', 'debug', 'info', 'warn', 'error']
consoleMethods.forEach(method => {
// workaround for https://github.com/winstonjs/winston/issues/1591
switch (method) {
case 'log':
console[method] = winstonLogger.info.bind(winstonLogger);
break;
default:
console[method] = winstonLogger[method].bind(winstonLogger);
break;
}
})
}
export default function createLogger(label) {
if (!winstonLogger) {
init();
}
return winstonLogger.child({ label });
}

View File

@@ -1,6 +1,9 @@
import getServiceWidget from "utils/service-helpers"; import getServiceWidget from "utils/service-helpers";
import { formatApiCall } from "utils/api-helpers"; import { formatApiCall } from "utils/api-helpers";
import { httpProxy } from "utils/http"; import { httpProxy } from "utils/http";
import createLogger from "utils/logger";
const logger = createLogger('genericProxyHandler');
export default async function genericProxyHandler(req, res, maps) { export default async function genericProxyHandler(req, res, maps) {
const { group, service, endpoint } = req.query; const { group, service, endpoint } = req.query;
@@ -24,7 +27,7 @@ export default async function genericProxyHandler(req, res, maps) {
}); });
let resultData = data; let resultData = data;
if (maps?.[endpoint]) { if ((status === 200) && (maps?.[endpoint])) {
resultData = maps[endpoint](data); resultData = maps[endpoint](data);
} }
@@ -34,9 +37,14 @@ export default async function genericProxyHandler(req, res, maps) {
return res.status(status).end(); return res.status(status).end();
} }
if (status >= 400) {
logger.debug("HTTP Error %d calling %s//%s%s...", status, url.protocol, url.hostname, url.pathname);
}
return res.status(status).send(resultData); return res.status(status).send(resultData);
} }
} }
logger.debug("Invalid or missing proxy service type '%s' in group '%s'", service, group);
return res.status(400).json({ error: "Invalid proxy service type" }); return res.status(400).json({ error: "Invalid proxy service type" });
} }

View File

@@ -0,0 +1,15 @@
import { createContext, useState, useMemo } from "react";
export const SettingsContext = createContext();
export function SettingsProvider({ initialSettings, children }) {
const [settings, setSettings] = useState({});
if (initialSettings) {
setSettings(initialSettings);
}
const value = useMemo(() => ({ settings, setSettings }), [settings]);
return <SettingsContext.Provider value={value}>{children}</SettingsContext.Provider>;
}

View File

@@ -1,4 +1,7 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
const tailwindForms = require("@tailwindcss/forms");
const tailwindScrollbars = require("tailwind-scrollbar");
module.exports = { module.exports = {
darkMode: "class", darkMode: "class",
content: ["./src/pages/**/*.{js,ts,jsx,tsx}", "./src/components/**/*.{js,ts,jsx,tsx}"], content: ["./src/pages/**/*.{js,ts,jsx,tsx}", "./src/components/**/*.{js,ts,jsx,tsx}"],
@@ -6,19 +9,19 @@ module.exports = {
extend: { extend: {
colors: { colors: {
theme: { theme: {
["50"]: "rgb(var(--color-50) / <alpha-value>)", 50: "rgb(var(--color-50) / <alpha-value>)",
["100"]: "rgb(var(--color-100) / <alpha-value>)", 100: "rgb(var(--color-100) / <alpha-value>)",
["200"]: "rgb(var(--color-200) / <alpha-value>)", 200: "rgb(var(--color-200) / <alpha-value>)",
["300"]: "rgb(var(--color-300) / <alpha-value>)", 300: "rgb(var(--color-300) / <alpha-value>)",
["400"]: "rgb(var(--color-400) / <alpha-value>)", 400: "rgb(var(--color-400) / <alpha-value>)",
["500"]: "rgb(var(--color-500) / <alpha-value>)", 500: "rgb(var(--color-500) / <alpha-value>)",
["600"]: "rgb(var(--color-600) / <alpha-value>)", 600: "rgb(var(--color-600) / <alpha-value>)",
["700"]: "rgb(var(--color-700) / <alpha-value>)", 700: "rgb(var(--color-700) / <alpha-value>)",
["800"]: "rgb(var(--color-800) / <alpha-value>)", 800: "rgb(var(--color-800) / <alpha-value>)",
["900"]: "rgb(var(--color-900) / <alpha-value>)", 900: "rgb(var(--color-900) / <alpha-value>)",
}, },
}, },
}, },
}, },
plugins: [require("@tailwindcss/forms")], plugins: [tailwindForms, tailwindScrollbars],
}; };