mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-06 21:57:48 +01:00
Compare commits
14 Commits
a4a8e70d25
...
v1.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4028194830 | ||
|
|
4c04a7a45f | ||
|
|
ce344a9db5 | ||
|
|
8e90ece498 | ||
|
|
151ad552ca | ||
|
|
251cb65e12 | ||
|
|
8ebd0d0b2e | ||
|
|
c20f71738b | ||
|
|
78b73e8166 | ||
|
|
547ef0c4c5 | ||
|
|
11d148fff0 | ||
|
|
eb61d69626 | ||
|
|
876304cda5 | ||
|
|
5fe5a3869e |
6
.github/workflows/docker-publish.yml
vendored
6
.github/workflows/docker-publish.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/docs-publish.yml
vendored
6
.github/workflows/docs-publish.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
- name: Install python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Check files
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
- pre-commit
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
run: |
|
||||
git config user.name github-actions[bot]
|
||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: echo "cache_id=${{github.sha}}" >> $GITHUB_ENV
|
||||
|
||||
8
.github/workflows/repo-maintenance.yml
vendored
8
.github/workflows/repo-maintenance.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
name: 'Stale'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
days-before-stale: 7
|
||||
days-before-close: 14
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
name: 'Close Answered Discussions'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
- uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
function sleep(ms) {
|
||||
@@ -113,7 +113,7 @@ jobs:
|
||||
name: 'Close Outdated Discussions'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
- uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
function sleep(ms) {
|
||||
@@ -204,7 +204,7 @@ jobs:
|
||||
name: 'Close Unsupported Feature Requests'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
- uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
function sleep(ms) {
|
||||
|
||||
@@ -441,6 +441,7 @@ There are a few optional settings for the Quick Launch feature:
|
||||
- `showSearchSuggestions`: show search suggestions for the internet search. If this is not specified then the setting will be inherited from the search widget. If it is not specified there either, it will default to false. For custom providers the `suggestionUrl` needs to be set in order for this to work.
|
||||
- `provider`: search engine provider. If none is specified it will try to use the provider set for the Search Widget, if neither are present then internet search will be disabled.
|
||||
- `hideVisitURL`: disable detecting and offering an option to open URLs. This is false by default, enabling the feature.
|
||||
- `mobileButtonPosition`: enables and sets the position of the mobile quicklaunch button. Options are `top-left`, `top-right`, `bottom-left`, `bottom-right`. This is empty by default, disabling the feature.
|
||||
|
||||
```yaml
|
||||
quicklaunch:
|
||||
|
||||
@@ -28,7 +28,7 @@ These companies help the Homepage project by providing services, tools, and reso
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 16px;">
|
||||
<a href="https://crowdin.com/project/homepage"><img src="https://support.crowdin.com/assets/logos/core-logo/png/crowdin-core-logo-cWhite.png" alt="Crowdin" style="max-width: 100%; height: 64px; display: block;" /></a>
|
||||
<a href="https://crowdin.com/project/gethomepage"><img src="https://support.crowdin.com/assets/logos/core-logo/png/crowdin-core-logo-cWhite.png" alt="Crowdin" style="max-width: 100%; height: 64px; display: block;" /></a>
|
||||
<p>
|
||||
Crowdin provides the translation platform for the project. Making it easy to translate the project into multiple languages.
|
||||
</p>
|
||||
|
||||
@@ -32,7 +32,7 @@ More detail on configuring service widgets can be found in the [Service Widgets
|
||||
|
||||
## Info Widgets
|
||||
|
||||
Info widgets are used to display information in the header, often about your system or environment. Info widgets are defined your `widgets.yaml` file. Here's an example:
|
||||
Info widgets are used to display information in the header, often about your system or environment. Info widgets are defined in your `widgets.yaml` file. Here's an example:
|
||||
|
||||
```yaml
|
||||
- openmeteo:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homepage",
|
||||
"version": "1.4.6",
|
||||
"version": "1.5.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
"pending": "Afwagtend",
|
||||
"approved": "Goedgekeur",
|
||||
"available": "Beskikbaar",
|
||||
"issues": "Open Issues"
|
||||
"issues": "Oop Kwessies"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "Afwagtend",
|
||||
@@ -1074,45 +1074,45 @@
|
||||
"containers": "Houers"
|
||||
},
|
||||
"filebrowser": {
|
||||
"available": "Available",
|
||||
"used": "Used",
|
||||
"total": "Total"
|
||||
"available": "Beskikbaar",
|
||||
"used": "Gebruik",
|
||||
"total": "Totaal"
|
||||
},
|
||||
"wallos": {
|
||||
"activeSubscriptions": "Subscriptions",
|
||||
"thisMonthlyCost": "This Month",
|
||||
"nextMonthlyCost": "Next Month",
|
||||
"previousMonthlyCost": "Prev. Month",
|
||||
"nextRenewingSubscription": "Next Payment"
|
||||
"activeSubscriptions": "Intekeninge",
|
||||
"thisMonthlyCost": "Hierdie Maand",
|
||||
"nextMonthlyCost": "Volgende Maand",
|
||||
"previousMonthlyCost": "Vorige Maand",
|
||||
"nextRenewingSubscription": "Volgende paaiement"
|
||||
},
|
||||
"unraid": {
|
||||
"STARTED": "Started",
|
||||
"STOPPED": "Stopped",
|
||||
"NEW_ARRAY": "New Array",
|
||||
"RECON_DISK": "Reconstructing Disk",
|
||||
"DISABLE_DISK": "Disk Disabled",
|
||||
"SWAP_DSBL": "Swap Disable",
|
||||
"INVALID_EXPANSION": "Invalid Expansion",
|
||||
"PARITY_NOT_BIGGEST": "Parity Not Biggest",
|
||||
"TOO_MANY_MISSING_DISKS": "Too Many Missing Disks",
|
||||
"NEW_DISK_TOO_SMALL": "New Disk Too Small",
|
||||
"NO_DATA_DISKS": "No Data Disks",
|
||||
"notifications": "Notifications",
|
||||
"STARTED": "Begin",
|
||||
"STOPPED": "Gestop",
|
||||
"NEW_ARRAY": "Nuwe Skikking",
|
||||
"RECON_DISK": "Rekonstruksie van Skyf",
|
||||
"DISABLE_DISK": "Skyf Gedeaktiveer",
|
||||
"SWAP_DSBL": "Ruil Gedeaktiveer",
|
||||
"INVALID_EXPANSION": "Ongeldige Uitbreiding",
|
||||
"PARITY_NOT_BIGGEST": "Pariteit nie die grootste nie",
|
||||
"TOO_MANY_MISSING_DISKS": "Te Veel Ontbrekende Skywe",
|
||||
"NEW_DISK_TOO_SMALL": "Nuwe Skyf te Klein",
|
||||
"NO_DATA_DISKS": "Geen Data Skywe",
|
||||
"notifications": "Kennisgewings",
|
||||
"status": "Status",
|
||||
"cpu": "CPU",
|
||||
"memoryUsed": "Memory Used",
|
||||
"memoryAvailable": "Memory Available",
|
||||
"arrayUsed": "Array Used",
|
||||
"arrayFree": "Array Free",
|
||||
"poolUsed": "{{pool}} Used",
|
||||
"poolFree": "{{pool}} Free"
|
||||
"cpu": "SVE",
|
||||
"memoryUsed": "Geheue Gebruik",
|
||||
"memoryAvailable": "Geheue Beskikbaar",
|
||||
"arrayUsed": "Skikking Gebruik",
|
||||
"arrayFree": "Skikking Vry",
|
||||
"poolUsed": "{{pool}} Gebruik",
|
||||
"poolFree": "{{pool}} Vry"
|
||||
},
|
||||
"backrest": {
|
||||
"num_plans": "Plans",
|
||||
"num_success_30": "Successes",
|
||||
"num_failure_30": "Failures",
|
||||
"num_success_latest": "Succeeding",
|
||||
"num_failure_latest": "Failing",
|
||||
"bytes_added_30": "Bytes Added"
|
||||
"num_plans": "Planne",
|
||||
"num_success_30": "Suksesse",
|
||||
"num_failure_30": "Mislukkings",
|
||||
"num_success_latest": "Slaag",
|
||||
"num_failure_latest": "Mislukking",
|
||||
"bytes_added_30": "Grepe bygevoeg"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,9 +630,9 @@
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU-Last",
|
||||
"memory": "Aktiver RAM",
|
||||
"wanUpload": "WAN-Upload",
|
||||
"wanDownload": "WAN-Download"
|
||||
"memory": "RAM aktiv",
|
||||
"wanUpload": "WAN Up",
|
||||
"wanDownload": "WAN Down"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Druckerstatus",
|
||||
@@ -786,7 +786,7 @@
|
||||
"downloadCount": "Warteschlange",
|
||||
"downloadBytesRemaining": "Verbleibend",
|
||||
"downloadTotalBytes": "Größe",
|
||||
"downloadSpeed": "Geschwindigkeit"
|
||||
"downloadSpeed": "Datenrate"
|
||||
},
|
||||
"kavita": {
|
||||
"seriesCount": "Serien",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -241,16 +241,16 @@
|
||||
"sonarr": {
|
||||
"wanted": "Poszukiwane",
|
||||
"queued": "W kolejce",
|
||||
"series": "Series",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"series": "Seriale",
|
||||
"queue": "Kolejka",
|
||||
"unknown": "Nieznany"
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Wanted",
|
||||
"wanted": "Poszukiwane",
|
||||
"missing": "Brakujące",
|
||||
"queued": "Queued",
|
||||
"movies": "Movies",
|
||||
"queue": "Queue",
|
||||
"queued": "W kolejce",
|
||||
"movies": "Filmy",
|
||||
"queue": "Kolejka",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"lidarr": {
|
||||
@@ -273,16 +273,16 @@
|
||||
"available": "Dostępne"
|
||||
},
|
||||
"jellyseerr": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available",
|
||||
"pending": "Oczekujące",
|
||||
"approved": "Zaakceptowane",
|
||||
"available": "Dostępne",
|
||||
"issues": "Open Issues"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "Pending",
|
||||
"pending": "Oczekujące",
|
||||
"processing": "Przetwarzane",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
"approved": "Zaakceptowane",
|
||||
"available": "Dostępne"
|
||||
},
|
||||
"netalertx": {
|
||||
"total": "Total",
|
||||
@@ -297,8 +297,8 @@
|
||||
"gravity": "Grawitacja"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"queries": "Zapytania",
|
||||
"blocked": "Zablokowane",
|
||||
"filtered": "Przefiltrowane",
|
||||
"latency": "Opóźnienia"
|
||||
},
|
||||
@@ -313,7 +313,7 @@
|
||||
"total": "Total"
|
||||
},
|
||||
"suwayomi": {
|
||||
"download": "Downloaded",
|
||||
"download": "Pobrano",
|
||||
"nondownload": "Niepobrane",
|
||||
"read": "Read",
|
||||
"unread": "Unread",
|
||||
@@ -367,7 +367,7 @@
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"nothing_streaming": "Brak aktywnych strumieni",
|
||||
"please_wait": "Proszę czekać"
|
||||
},
|
||||
"npm": {
|
||||
@@ -426,26 +426,26 @@
|
||||
"unread": "Unread"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Users",
|
||||
"users": "Użytkownicy",
|
||||
"loginsLast24H": "Logowania (24h)",
|
||||
"failedLoginsLast24H": "Nieudane logowania (24h)"
|
||||
},
|
||||
"proxmox": {
|
||||
"mem": "MEM",
|
||||
"mem": "RAM",
|
||||
"cpu": "Procesor",
|
||||
"lxc": "Kontenery LXC",
|
||||
"vms": "Maszyn wirtualnych"
|
||||
},
|
||||
"glances": {
|
||||
"cpu": "Procesor",
|
||||
"load": "Load",
|
||||
"load": "Obciążenie",
|
||||
"wait": "Proszę czekać",
|
||||
"temp": "TEMP",
|
||||
"temp": "TEMP.",
|
||||
"_temp": "Temperatura",
|
||||
"warn": "Ostrzeżenie",
|
||||
"uptime": "UP",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"free": "Wolne",
|
||||
"used": "Used",
|
||||
"days": "d",
|
||||
"hours": "h",
|
||||
@@ -471,57 +471,57 @@
|
||||
"1-day": "Głównie słoneczny",
|
||||
"1-night": "Głównie bezchmurny",
|
||||
"2-day": "Częściowo pochmurnie",
|
||||
"2-night": "Partly Cloudy",
|
||||
"2-night": "Częściowo pochmurnie",
|
||||
"3-day": "Pochmurnie",
|
||||
"3-night": "Cloudy",
|
||||
"3-night": "Pochmurnie",
|
||||
"45-day": "Mgliście",
|
||||
"45-night": "Foggy",
|
||||
"48-day": "Foggy",
|
||||
"48-night": "Foggy",
|
||||
"45-night": "Mgliście",
|
||||
"48-day": "Mgliście",
|
||||
"48-night": "Mgliście",
|
||||
"51-day": "Lekka mżawka",
|
||||
"51-night": "Light Drizzle",
|
||||
"51-night": "Lekka mżawka",
|
||||
"53-day": "Mżawka",
|
||||
"53-night": "Drizzle",
|
||||
"53-night": "Mżawka",
|
||||
"55-day": "Gęsta mżawka",
|
||||
"55-night": "Heavy Drizzle",
|
||||
"55-night": "Gęsta mżawka",
|
||||
"56-day": "Lekko chłodna mżawka",
|
||||
"56-night": "Light Freezing Drizzle",
|
||||
"56-night": "Lekko chłodna mżawka",
|
||||
"57-day": "Chłodna mżawka",
|
||||
"57-night": "Freezing Drizzle",
|
||||
"57-night": "Chłodna mżawka",
|
||||
"61-day": "Lekki deszcz",
|
||||
"61-night": "Light Rain",
|
||||
"61-night": "Lekki deszcz",
|
||||
"63-day": "Deszcz",
|
||||
"63-night": "Rain",
|
||||
"63-night": "Deszcz",
|
||||
"65-day": "Ciężki deszcz",
|
||||
"65-night": "Heavy Rain",
|
||||
"65-night": "Ciężki deszcz",
|
||||
"66-day": "Mroźny deszcz",
|
||||
"66-night": "Freezing Rain",
|
||||
"67-day": "Freezing Rain",
|
||||
"67-night": "Freezing Rain",
|
||||
"66-night": "Mroźny deszcz",
|
||||
"67-day": "Mroźny deszcz",
|
||||
"67-night": "Mroźny deszcz",
|
||||
"71-day": "Lekki śnieg",
|
||||
"71-night": "Light Snow",
|
||||
"71-night": "Lekki śnieg",
|
||||
"73-day": "Śnieg",
|
||||
"73-night": "Snow",
|
||||
"73-night": "Śnieg",
|
||||
"75-day": "Ciężki śnieg",
|
||||
"75-night": "Heavy Snow",
|
||||
"75-night": "Ciężki śnieg",
|
||||
"77-day": "Ziarnisty śnieg",
|
||||
"77-night": "Snow Grains",
|
||||
"77-night": "Ziarnisty śnieg",
|
||||
"80-day": "Lekkie opady",
|
||||
"80-night": "Light Showers",
|
||||
"80-night": "Lekkie opady",
|
||||
"81-day": "Opady",
|
||||
"81-night": "Showers",
|
||||
"81-night": "Opady",
|
||||
"82-day": "Ciężkie opady",
|
||||
"82-night": "Heavy Showers",
|
||||
"82-night": "Ciężkie opady",
|
||||
"85-day": "Opady śniegu",
|
||||
"85-night": "Snow Showers",
|
||||
"86-day": "Snow Showers",
|
||||
"86-night": "Snow Showers",
|
||||
"85-night": "Opady śniegu",
|
||||
"86-day": "Opady śniegu",
|
||||
"86-night": "Opady śniegu",
|
||||
"95-day": "Burze z piorunami",
|
||||
"95-night": "Thunderstorm",
|
||||
"95-night": "Burze z piorunami",
|
||||
"96-day": "Burza z gradobiciem",
|
||||
"96-night": "Thunderstorm With Hail",
|
||||
"99-day": "Thunderstorm With Hail",
|
||||
"99-night": "Thunderstorm With Hail"
|
||||
"96-night": "Burza z gradobiciem",
|
||||
"99-day": "Burza z gradobiciem",
|
||||
"99-night": "Burza z gradobiciem"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"wlan_users": "Usuários de WLAN",
|
||||
"up": "UP",
|
||||
"down": "Desligado",
|
||||
"wait": "Please wait",
|
||||
"wait": "Por favor, aguarde",
|
||||
"empty_data": "Status do Subsistema desconhecido"
|
||||
},
|
||||
"docker": {
|
||||
@@ -83,7 +83,7 @@
|
||||
"partial": "Parcial"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Error",
|
||||
"error": "Erro",
|
||||
"ping": "Tempo de resposta",
|
||||
"down": "Inativo",
|
||||
"up": "Ativo",
|
||||
@@ -91,11 +91,11 @@
|
||||
},
|
||||
"siteMonitor": {
|
||||
"http_status": "Estado HTTP",
|
||||
"error": "Error",
|
||||
"error": "Erro",
|
||||
"response": "Resposta",
|
||||
"down": "Down",
|
||||
"up": "Up",
|
||||
"not_available": "Not Available"
|
||||
"down": "Inativo",
|
||||
"up": "Ativo",
|
||||
"not_available": "Não Disponível"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "A reproduzir",
|
||||
@@ -112,7 +112,7 @@
|
||||
"offline_alt": "Offline",
|
||||
"online": "Disponível",
|
||||
"total": "Total",
|
||||
"unknown": "Unknown"
|
||||
"unknown": "Desconhecido"
|
||||
},
|
||||
"evcc": {
|
||||
"pv_power": "Produção",
|
||||
@@ -141,11 +141,11 @@
|
||||
"connectionStatusDisconnecting": "Desconectando",
|
||||
"connectionStatusDisconnected": "Desconectado",
|
||||
"connectionStatusConnected": "Conectado",
|
||||
"uptime": "Uptime",
|
||||
"uptime": "Tempo ativo",
|
||||
"maxDown": "Tempo de inatividade máximo",
|
||||
"maxUp": "Máx. Acima",
|
||||
"down": "Down",
|
||||
"up": "Up",
|
||||
"down": "Inativo",
|
||||
"up": "Ativo",
|
||||
"received": "Recebido",
|
||||
"sent": "Enviado",
|
||||
"externalIPAddress": "IP Externo",
|
||||
@@ -168,10 +168,10 @@
|
||||
"passes": "Passes"
|
||||
},
|
||||
"tautulli": {
|
||||
"playing": "Playing",
|
||||
"transcoding": "Transcoding",
|
||||
"bitrate": "Bitrate",
|
||||
"no_active": "No Active Streams",
|
||||
"playing": "Tocando",
|
||||
"transcoding": "Transcodificando",
|
||||
"bitrate": "Taxa de bits",
|
||||
"no_active": "Sem Streams Ativos",
|
||||
"plex_connection_error": "Verifique a conexão do Plex"
|
||||
},
|
||||
"omada": {
|
||||
@@ -189,28 +189,28 @@
|
||||
"plex": {
|
||||
"streams": "Streams Ativas",
|
||||
"albums": "Álbuns",
|
||||
"movies": "Movies",
|
||||
"movies": "Filmes",
|
||||
"tv": "Series de TV"
|
||||
},
|
||||
"sabnzbd": {
|
||||
"rate": "Rate",
|
||||
"rate": "Taxa",
|
||||
"queue": "Fila",
|
||||
"timeleft": "Tempo restante"
|
||||
},
|
||||
"rutorrent": {
|
||||
"active": "Ativo",
|
||||
"upload": "Upload",
|
||||
"download": "Download"
|
||||
"upload": "Carregar",
|
||||
"download": "Descarregar"
|
||||
},
|
||||
"transmission": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "Descarregar",
|
||||
"upload": "Carregar",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"qbittorrent": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "Descarregar",
|
||||
"upload": "Carregar",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
@@ -223,8 +223,8 @@
|
||||
"invalid": "Inválido"
|
||||
},
|
||||
"deluge": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "Descarregar",
|
||||
"upload": "Carregar",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
@@ -233,25 +233,25 @@
|
||||
"cachemissbytes": "Bytes de Falha de Cache"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "Descarregar",
|
||||
"upload": "Carregar",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"sonarr": {
|
||||
"wanted": "Desejada",
|
||||
"queued": "Em fila",
|
||||
"series": "Series",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"series": "Séries",
|
||||
"queue": "Fila",
|
||||
"unknown": "Desconhecido"
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Wanted",
|
||||
"missing": "Faltando",
|
||||
"queued": "Queued",
|
||||
"movies": "Movies",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queued": "Em fila",
|
||||
"movies": "Filmes",
|
||||
"queue": "Fila",
|
||||
"unknown": "Desconhecido"
|
||||
},
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
"pending": "На чекању",
|
||||
"approved": "Одобрено",
|
||||
"available": "Доступно",
|
||||
"issues": "Open Issues"
|
||||
"issues": "Отворених питања"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "На чекању",
|
||||
@@ -1108,11 +1108,11 @@
|
||||
"poolFree": "{{pool}} слободно"
|
||||
},
|
||||
"backrest": {
|
||||
"num_plans": "Plans",
|
||||
"num_success_30": "Successes",
|
||||
"num_failure_30": "Failures",
|
||||
"num_success_latest": "Succeeding",
|
||||
"num_failure_latest": "Failing",
|
||||
"bytes_added_30": "Bytes Added"
|
||||
"num_plans": "Планови",
|
||||
"num_success_30": "Успешно",
|
||||
"num_failure_30": "Неуспешно",
|
||||
"num_success_latest": "Успевајући",
|
||||
"num_failure_latest": "Неуспешно",
|
||||
"bytes_added_30": "Додати бајтови"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"nothing_streaming": "",
|
||||
"please_wait": "请等待"
|
||||
},
|
||||
"npm": {
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
Babel==2.12.1
|
||||
backrefs==5.9
|
||||
cairocffi==1.7.1
|
||||
CairoSVG==2.7.1
|
||||
certifi==2023.7.22
|
||||
cffi==1.17.1
|
||||
cfgv==3.4.0
|
||||
charset-normalizer==3.2.0
|
||||
click==8.1.7
|
||||
colorama==0.4.6
|
||||
cssselect2==0.7.0
|
||||
defusedxml==0.7.1
|
||||
distlib==0.3.9
|
||||
filelock==3.17.0
|
||||
ghp-import==2.1.0
|
||||
identify==2.6.7
|
||||
idna==3.4
|
||||
Jinja2==3.1.2
|
||||
Markdown==3.4.4
|
||||
MarkupSafe==2.1.3
|
||||
mergedeep==1.3.4
|
||||
mkdocs==1.6
|
||||
mkdocs-material==9.5.26
|
||||
mkdocs==1.6.0
|
||||
mkdocs-get-deps==0.2.0
|
||||
mkdocs-material==9.6.18
|
||||
mkdocs-material-extensions==1.3.1
|
||||
mkdocs-redirects==1.2.1
|
||||
nodeenv==1.9.1
|
||||
packaging==23.1
|
||||
paginate==0.5.6
|
||||
pathspec==0.11.2
|
||||
pillow==10.4.0
|
||||
platformdirs==3.10.0
|
||||
pre-commit==3.5.0
|
||||
pycparser==2.22
|
||||
Pygments==2.16.1
|
||||
pymdown-extensions==10.3
|
||||
python-dateutil==2.8.2
|
||||
@@ -24,8 +40,8 @@ pyyaml_env_tag==0.1
|
||||
regex==2023.8.8
|
||||
requests==2.31.0
|
||||
six==1.16.0
|
||||
tinycss2==1.4.0
|
||||
urllib3==2.0.5
|
||||
virtualenv==20.29.2
|
||||
watchdog==3.0.0
|
||||
pre-commit==3.5.0
|
||||
mkdocs-material[imaging]==9.5.26
|
||||
mkdocs-redirects==1.2.1
|
||||
webencodings==0.5.1
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import classNames from "classnames";
|
||||
import { useTranslation } from "next-i18next";
|
||||
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
||||
import { FiSearch } from "react-icons/fi";
|
||||
import useSWR from "swr";
|
||||
import { SettingsContext } from "utils/contexts/settings";
|
||||
|
||||
import ResolvedIcon from "./resolvedicon";
|
||||
import { getStoredProvider, searchProviders } from "./widgets/search/search";
|
||||
|
||||
export default function QuickLaunch({ servicesAndBookmarks, searchString, setSearchString, isOpen, close }) {
|
||||
const MOBILE_BUTTON_POSITIONS = {
|
||||
"top-left": "top-4 left-4",
|
||||
"top-right": "top-4 right-4",
|
||||
"bottom-left": "bottom-4 left-4",
|
||||
"bottom-right": "bottom-4 right-4",
|
||||
};
|
||||
|
||||
export default function QuickLaunch({ servicesAndBookmarks, searchString, setSearchString, isOpen, setSearching }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { settings } = useContext(SettingsContext);
|
||||
@@ -49,6 +57,10 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
|
||||
);
|
||||
}
|
||||
|
||||
let mobileButtonPosition = settings.quicklaunch?.mobileButtonPosition
|
||||
? MOBILE_BUTTON_POSITIONS[settings.quicklaunch.mobileButtonPosition]
|
||||
: null;
|
||||
|
||||
function openCurrentItem(newWindow) {
|
||||
const result = results[currentItemIndex];
|
||||
window.open(
|
||||
@@ -59,13 +71,13 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
|
||||
}
|
||||
|
||||
const closeAndReset = useCallback(() => {
|
||||
close(false);
|
||||
setSearching(false);
|
||||
setTimeout(() => {
|
||||
setSearchString("");
|
||||
setCurrentItemIndex(null);
|
||||
setSearchSuggestions([]);
|
||||
}, 200); // delay a little for animations
|
||||
}, [close, setSearchString, setCurrentItemIndex, setSearchSuggestions]);
|
||||
}, [setSearching, setSearchString, setCurrentItemIndex, setSearchSuggestions]);
|
||||
|
||||
function handleSearchChange(event) {
|
||||
const rawSearchString = event.target.value;
|
||||
@@ -245,86 +257,98 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"relative z-40 ease-in-out duration-300 transition-opacity",
|
||||
hidden && !isOpen && "hidden",
|
||||
!hidden && isOpen && "opacity-100",
|
||||
!isOpen && "opacity-0",
|
||||
)}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<div className="fixed inset-0 bg-gray-500 opacity-50" />
|
||||
<div className="fixed inset-0 z-20 overflow-y-auto">
|
||||
<div className="flex min-h-full min-w-full items-start justify-center text-center">
|
||||
<dialog className="mt-[10%] mx-auto min-w-[90%] max-w-[90%] md:min-w-[40%] md:max-w-[40%] rounded-md p-0 block font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-50 dark:bg-theme-800">
|
||||
<input
|
||||
placeholder="Search"
|
||||
className={classNames(
|
||||
results.length > 0 && "rounded-t-md",
|
||||
results.length === 0 && "rounded-md",
|
||||
"w-full p-4 m-0 border-0 border-b border-slate-700 focus:border-slate-700 focus:outline-0 focus:ring-0 text-sm md:text-xl text-theme-700 dark:text-theme-200 bg-theme-60 dark:bg-theme-800",
|
||||
)}
|
||||
type="text"
|
||||
autoCorrect="false"
|
||||
ref={searchField}
|
||||
value={searchString}
|
||||
onChange={handleSearchChange}
|
||||
onKeyDown={handleSearchKeyDown}
|
||||
/>
|
||||
{results.length > 0 && (
|
||||
<ul className="max-h-[60vh] overflow-y-auto m-2">
|
||||
{results.map((r, i) => (
|
||||
<li key={[r.name, r.container, r.app, r.href].filter((s) => s).join("-")}>
|
||||
<button
|
||||
type="button"
|
||||
data-index={i}
|
||||
onMouseEnter={handleItemHover}
|
||||
onClick={handleItemClick}
|
||||
onKeyDown={handleItemKeyDown}
|
||||
className={classNames(
|
||||
"flex flex-row w-full items-center justify-between rounded-md text-sm md:text-xl py-2 px-4 cursor-pointer text-theme-700 dark:text-theme-200",
|
||||
i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50",
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-row items-center mr-4 pointer-events-none">
|
||||
{(r.icon || r.abbr) && (
|
||||
<div className="w-5 text-xs mr-4">
|
||||
{r.icon && <ResolvedIcon icon={r.icon} />}
|
||||
{r.abbr && r.abbr}
|
||||
</div>
|
||||
<>
|
||||
<div
|
||||
className={classNames(
|
||||
"relative z-40 ease-in-out duration-300 transition-opacity",
|
||||
hidden && !isOpen && "hidden",
|
||||
!hidden && isOpen && "opacity-100",
|
||||
!isOpen && "opacity-0",
|
||||
)}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<div className="fixed inset-0 bg-gray-500 opacity-50" />
|
||||
<div className="fixed inset-0 z-20 overflow-y-auto">
|
||||
<div className="flex min-h-full min-w-full items-start justify-center text-center">
|
||||
<dialog className="mt-[10%] mx-auto min-w-[90%] max-w-[90%] md:min-w-[40%] md:max-w-[40%] rounded-md p-0 block font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-50 dark:bg-theme-800">
|
||||
<input
|
||||
placeholder="Search"
|
||||
className={classNames(
|
||||
results.length > 0 && "rounded-t-md",
|
||||
results.length === 0 && "rounded-md",
|
||||
"w-full p-4 m-0 border-0 border-b border-slate-700 focus:border-slate-700 focus:outline-0 focus:ring-0 text-sm md:text-xl text-theme-700 dark:text-theme-200 bg-theme-60 dark:bg-theme-800",
|
||||
)}
|
||||
type="text"
|
||||
autoCorrect="false"
|
||||
ref={searchField}
|
||||
value={searchString}
|
||||
onChange={handleSearchChange}
|
||||
onKeyDown={handleSearchKeyDown}
|
||||
/>
|
||||
{results.length > 0 && (
|
||||
<ul className="max-h-[60vh] overflow-y-auto m-2">
|
||||
{results.map((r, i) => (
|
||||
<li key={[r.name, r.container, r.app, r.href].filter((s) => s).join("-")}>
|
||||
<button
|
||||
type="button"
|
||||
data-index={i}
|
||||
onMouseEnter={handleItemHover}
|
||||
onClick={handleItemClick}
|
||||
onKeyDown={handleItemKeyDown}
|
||||
className={classNames(
|
||||
"flex flex-row w-full items-center justify-between rounded-md text-sm md:text-xl py-2 px-4 cursor-pointer text-theme-700 dark:text-theme-200",
|
||||
i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50",
|
||||
)}
|
||||
<div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none">
|
||||
{r.type !== "searchSuggestion" && <span className="mr-4">{r.name}</span>}
|
||||
{r.type === "searchSuggestion" && (
|
||||
<div className="flex-nowrap">
|
||||
<span className="whitespace-pre">
|
||||
{r.name.indexOf(searchString) === 0 ? searchString : ""}
|
||||
</span>
|
||||
<span className="whitespace-pre opacity-50">
|
||||
{r.name.indexOf(searchString) === 0 ? r.name.substring(searchString.length) : r.name}
|
||||
</span>
|
||||
>
|
||||
<div className="flex flex-row items-center mr-4 pointer-events-none">
|
||||
{(r.icon || r.abbr) && (
|
||||
<div className="w-5 text-xs mr-4">
|
||||
{r.icon && <ResolvedIcon icon={r.icon} />}
|
||||
{r.abbr && r.abbr}
|
||||
</div>
|
||||
)}
|
||||
{r.description && (
|
||||
<span className="text-xs text-theme-600 text-light">
|
||||
{searchDescriptions && r.priority < 2 ? highlightText(r.description) : r.description}
|
||||
</span>
|
||||
)}
|
||||
<div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none">
|
||||
{r.type !== "searchSuggestion" && <span className="mr-4">{r.name}</span>}
|
||||
{r.type === "searchSuggestion" && (
|
||||
<div className="flex-nowrap">
|
||||
<span className="whitespace-pre">
|
||||
{r.name.indexOf(searchString) === 0 ? searchString : ""}
|
||||
</span>
|
||||
<span className="whitespace-pre opacity-50">
|
||||
{r.name.indexOf(searchString) === 0 ? r.name.substring(searchString.length) : r.name}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{r.description && (
|
||||
<span className="text-xs text-theme-600 text-light">
|
||||
{searchDescriptions && r.priority < 2 ? highlightText(r.description) : r.description}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-theme-600 font-bold pointer-events-none">
|
||||
{t(`quicklaunch.${r.type ? r.type.toLowerCase() : "bookmark"}`)}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</dialog>
|
||||
<div className="text-xs text-theme-600 font-bold pointer-events-none">
|
||||
{t(`quicklaunch.${r.type ? r.type.toLowerCase() : "bookmark"}`)}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</dialog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{mobileButtonPosition && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={setSearching.bind(this, !isOpen)}
|
||||
className={`fixed ${mobileButtonPosition} z-40 p-2 rounded-full sm:hidden text-theme-700 dark:text-theme-200 bg-theme-50 dark:bg-theme-800 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 transition-opacity duration-100`}
|
||||
style={{ opacity: isOpen ? 0 : 1 }}
|
||||
>
|
||||
<FiSearch className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ function Home({ initialSettings }) {
|
||||
searchString={searchString}
|
||||
setSearchString={setSearchString}
|
||||
isOpen={searching}
|
||||
close={setSearching}
|
||||
setSearching={setSearching}
|
||||
/>
|
||||
<div
|
||||
id="information-widgets"
|
||||
@@ -499,6 +499,7 @@ function Home({ initialSettings }) {
|
||||
|
||||
export default function Wrapper({ initialSettings, fallback }) {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { color } = useContext(ColorContext);
|
||||
let backgroundImage = "";
|
||||
let opacity = initialSettings?.backgroundOpacity ?? 0;
|
||||
let backgroundBlur = false;
|
||||
@@ -527,14 +528,22 @@ export default function Wrapper({ initialSettings, fallback }) {
|
||||
html.classList.toggle("dark", theme === "dark");
|
||||
html.classList.add(theme === "dark" ? "scheme-dark" : "scheme-light");
|
||||
|
||||
html.classList.remove(...Array.from(html.classList).filter((cls) => cls.startsWith("theme-")));
|
||||
html.classList.add(`theme-${initialSettings.color || "slate"}`);
|
||||
const desiredThemeClass = `theme-${color || initialSettings.color || "slate"}`;
|
||||
const themeClassesToRemove = Array.from(html.classList).filter(
|
||||
(cls) => cls.startsWith("theme-") && cls !== desiredThemeClass,
|
||||
);
|
||||
if (themeClassesToRemove.length) {
|
||||
html.classList.remove(...themeClassesToRemove);
|
||||
}
|
||||
if (!html.classList.contains(desiredThemeClass)) {
|
||||
html.classList.add(desiredThemeClass);
|
||||
}
|
||||
|
||||
// Remove any previously applied inline styles
|
||||
body.style.backgroundImage = "";
|
||||
body.style.backgroundColor = "";
|
||||
body.style.backgroundAttachment = "";
|
||||
}, [backgroundImage, opacity, theme, initialSettings.color]);
|
||||
}, [backgroundImage, opacity, theme, color, initialSettings.color]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -8,6 +8,10 @@ import widgets from "widgets/widgets";
|
||||
|
||||
const logger = createLogger("credentialedProxyHandler");
|
||||
|
||||
function basicAuthHeader(widget) {
|
||||
return `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
}
|
||||
|
||||
export default async function credentialedProxyHandler(req, res, map) {
|
||||
const { group, service, endpoint, index } = req.query;
|
||||
|
||||
@@ -61,7 +65,7 @@ export default async function credentialedProxyHandler(req, res, map) {
|
||||
if (widget.key) {
|
||||
headers.Authorization = `Bearer ${widget.key}`;
|
||||
} else {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
headers.Authorization = basicAuthHeader(widget);
|
||||
}
|
||||
} else if (widget.type === "proxmox") {
|
||||
headers.Authorization = `PVEAPIToken=${widget.username}=${widget.password}`;
|
||||
@@ -78,31 +82,31 @@ export default async function credentialedProxyHandler(req, res, map) {
|
||||
if (widget.key) {
|
||||
headers["NC-Token"] = `${widget.key}`;
|
||||
} else {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
headers.Authorization = basicAuthHeader(widget);
|
||||
}
|
||||
} else if (widget.type === "paperlessngx") {
|
||||
if (widget.key) {
|
||||
headers.Authorization = `Token ${widget.key}`;
|
||||
} else {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
headers.Authorization = basicAuthHeader(widget);
|
||||
}
|
||||
} else if (widget.type === "azuredevops") {
|
||||
headers.Authorization = `Basic ${Buffer.from(`$:${widget.key}`).toString("base64")}`;
|
||||
} else if (widget.type === "glances") {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
headers.Authorization = basicAuthHeader(widget);
|
||||
} else if (widget.type === "plantit") {
|
||||
headers.Key = `${widget.key}`;
|
||||
} else if (widget.type === "myspeed") {
|
||||
headers.Password = `${widget.password}`;
|
||||
} else if (widget.type === "esphome") {
|
||||
if (widget.username && widget.password) {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
headers.Authorization = basicAuthHeader(widget);
|
||||
} else if (widget.key) {
|
||||
headers.Cookie = `authenticated=${widget.key}`;
|
||||
}
|
||||
} else if (widget.type === "wgeasy") {
|
||||
if (widget.username && widget.password) {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
headers.Authorization = basicAuthHeader(widget);
|
||||
} else {
|
||||
headers.Authorization = widget.password;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user