diff --git a/CHANGELOG.md b/CHANGELOG.md index 99502ed..4f06830 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,43 @@ +# v0.6.10-beta — ARR-stack met een schakelaar per onderdeel + +De ARR-stack installeerde altijd dezelfde zeven containers. Nu kies je per +onderdeel wat je wilt, uit twintig: + +**Media beheren** — Sonarr (series), Radarr (films), Lidarr (muziek), Readarr +(boeken), Whisparr + +**Indexers en ondersteuning** — Prowlarr, Jackett, FlareSolverr, Bazarr +(ondertitels) + +**Downloaden** — qBittorrent, SABnzbd, NZBGet, en Gluetun om al het +downloadverkeer door een VPN te leiden + +**Verzoeken en aanvullingen** — Jellyseerr, Recyclarr (TRaSH-profielen), +Unpackerr, Tdarr (hercoderen), Autobrr, Maintainerr, Huntarr + +Standaard staan Sonarr, Radarr, Prowlarr, Bazarr, qBittorrent en Jellyseerr aan; +de rest zet je zelf bij. + +## Gluetun schakelt de downloadclients om + +Zet je Gluetun aan, dan verhuizen qBittorrent, SABnzbd en NZBGet naar diens +netwerknamespace en verliezen ze hun eigen poortmapping — precies zoals het +hoort, want anders lekt hun verkeer om de VPN heen. Hun webinterfaces bereik je +dan via de poorten van de Gluetun-container. + +Daarbij zat een val: qBittorrent en SABnzbd luisteren allebei standaard op 8080, +en achter één VPN-container botsen ze. qBittorrent draait nu intern op 8090. + +## Groepsschakelaars werkten niet + +Een groepsschakelaar in template.json was zelf geen variabele en kreeg dus nooit +een startwaarde. Elk schakelbaar onderdeel stond daardoor standaard uit — een +stack met schakelaars zou leeg binnenkomen. Ze worden nu als veld meegegeven met +een instelbare standaardstand, en de interface toont ze alleen als schakelaar in +de kop van de groep. + +--- + # v0.6.00-beta — 29 apps erbij, en een bug die zes bestaande apps onstartbaar maakte ## 🐛 Named volumes verdwenen uit het compose-bestand diff --git a/VERSION b/VERSION index 465f593..56cbdd8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.00-beta +0.6.10-beta diff --git a/apps/arr-stack/files/compose.yaml b/apps/arr-stack/files/compose.yaml index 049f146..04a0cd1 100644 --- a/apps/arr-stack/files/compose.yaml +++ b/apps/arr-stack/files/compose.yaml @@ -1,19 +1,13 @@ +# ARR-stack — kies per onderdeel of je het wilt. +# +# Aandachtspunten: +# * Zet de download- en mediamap op hetzelfde bestandssysteem, anders kopieert +# elke voltooide download in plaats van te verplaatsen (traag, dubbele opslag). +# * Draai je met Gluetun, dan zitten de downloadclients in het netwerk van die +# container en bereik je hun webinterface via de Gluetun-poorten. services: - << service_name >>-radarr: - image: lscr.io/linuxserver/radarr:latest - container_name: << service_name >>-radarr - environment: - - PUID=<< puid >> - - PGID=<< pgid >> - - TZ=<< timezone >> - volumes: - - << data_dir >>/<< service_name >>/radarr:/config - - << media_dir >>/films:/movies - - << downloads_dir >>:/downloads - ports: - - "<< port_radarr >>:7878" - restart: unless-stopped +<%- if enable_sonarr %> << service_name >>-sonarr: image: lscr.io/linuxserver/sonarr:latest container_name: << service_name >>-sonarr @@ -28,7 +22,26 @@ services: ports: - "<< port_sonarr >>:8989" restart: unless-stopped +<%- endif %> +<%- if enable_radarr %> + << service_name >>-radarr: + image: lscr.io/linuxserver/radarr:latest + container_name: << service_name >>-radarr + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/radarr:/config + - << media_dir >>/films:/movies + - << downloads_dir >>:/downloads + ports: + - "<< port_radarr >>:7878" + restart: unless-stopped +<%- endif %> + +<%- if enable_lidarr %> << service_name >>-lidarr: image: lscr.io/linuxserver/lidarr:latest container_name: << service_name >>-lidarr @@ -43,7 +56,9 @@ services: ports: - "<< port_lidarr >>:8686" restart: unless-stopped +<%- endif %> +<%- if enable_readarr %> << service_name >>-readarr: image: lscr.io/linuxserver/readarr:develop container_name: << service_name >>-readarr @@ -58,7 +73,26 @@ services: ports: - "<< port_readarr >>:8787" restart: unless-stopped +<%- endif %> +<%- if enable_whisparr %> + << service_name >>-whisparr: + image: ghcr.io/hotio/whisparr:latest + container_name: << service_name >>-whisparr + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/whisparr:/config + - << media_dir >>/volwassen:/adult + - << downloads_dir >>:/downloads + ports: + - "<< port_whisparr >>:6969" + restart: unless-stopped +<%- endif %> + +<%- if enable_prowlarr %> << service_name >>-prowlarr: image: lscr.io/linuxserver/prowlarr:latest container_name: << service_name >>-prowlarr @@ -71,7 +105,24 @@ services: ports: - "<< port_prowlarr >>:9696" restart: unless-stopped +<%- endif %> +<%- if enable_jackett %> + << service_name >>-jackett: + image: lscr.io/linuxserver/jackett:latest + container_name: << service_name >>-jackett + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/jackett:/config + ports: + - "<< port_jackett >>:9117" + restart: unless-stopped +<%- endif %> + +<%- if enable_bazarr %> << service_name >>-bazarr: image: lscr.io/linuxserver/bazarr:latest container_name: << service_name >>-bazarr @@ -86,14 +137,226 @@ services: ports: - "<< port_bazarr >>:6767" restart: unless-stopped +<%- endif %> +<%- if enable_flaresolverr %> + << service_name >>-flaresolverr: + image: ghcr.io/flaresolverr/flaresolverr:latest + container_name: << service_name >>-flaresolverr + environment: + - TZ=<< timezone >> + - LOG_LEVEL=info + ports: + - "<< port_flaresolverr >>:8191" + restart: unless-stopped +<%- endif %> + +<%- if enable_gluetun %> + << service_name >>-gluetun: + image: qmcgaw/gluetun:latest + container_name: << service_name >>-gluetun + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + environment: + - TZ=<< timezone >> + - VPN_SERVICE_PROVIDER=<< vpn_provider >> + - VPN_TYPE=<< vpn_type >> + - WIREGUARD_PRIVATE_KEY=<< wireguard_private_key >> + - WIREGUARD_ADDRESSES=<< wireguard_addresses >> + - OPENVPN_USER=<< openvpn_user >> + - OPENVPN_PASSWORD=<< openvpn_password >> + ports: + # De downloadclients delen dit netwerk, dus hun poorten staan hier. +<%- if enable_qbittorrent %> + - "<< port_qbittorrent >>:8090" + - "<< port_qbittorrent_tcp >>:6881" + - "<< port_qbittorrent_tcp >>:6881/udp" +<%- endif %> +<%- if enable_sabnzbd %> + - "<< port_sabnzbd >>:8080" +<%- endif %> +<%- if enable_nzbget %> + - "<< port_nzbget >>:6789" +<%- endif %> + volumes: + - << data_dir >>/<< service_name >>/gluetun:/gluetun + restart: unless-stopped +<%- endif %> + +<%- if enable_qbittorrent %> + << service_name >>-qbittorrent: + image: lscr.io/linuxserver/qbittorrent:latest + container_name: << service_name >>-qbittorrent + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + - WEBUI_PORT=8090 + volumes: + - << data_dir >>/<< service_name >>/qbittorrent:/config + - << downloads_dir >>:/downloads +<%- if enable_gluetun %> + network_mode: "service:<< service_name >>-gluetun" + depends_on: + - << service_name >>-gluetun +<%- endif %> +<%- if not enable_gluetun %> + ports: + - "<< port_qbittorrent >>:8090" + - "<< port_qbittorrent_tcp >>:6881" + - "<< port_qbittorrent_tcp >>:6881/udp" +<%- endif %> + restart: unless-stopped +<%- endif %> + +<%- if enable_sabnzbd %> + << service_name >>-sabnzbd: + image: lscr.io/linuxserver/sabnzbd:latest + container_name: << service_name >>-sabnzbd + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/sabnzbd:/config + - << downloads_dir >>:/downloads +<%- if enable_gluetun %> + network_mode: "service:<< service_name >>-gluetun" + depends_on: + - << service_name >>-gluetun +<%- endif %> +<%- if not enable_gluetun %> + ports: + - "<< port_sabnzbd >>:8080" +<%- endif %> + restart: unless-stopped +<%- endif %> + +<%- if enable_nzbget %> + << service_name >>-nzbget: + image: lscr.io/linuxserver/nzbget:latest + container_name: << service_name >>-nzbget + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/nzbget:/config + - << downloads_dir >>:/downloads +<%- if enable_gluetun %> + network_mode: "service:<< service_name >>-gluetun" + depends_on: + - << service_name >>-gluetun +<%- endif %> +<%- if not enable_gluetun %> + ports: + - "<< port_nzbget >>:6789" +<%- endif %> + restart: unless-stopped +<%- endif %> + +<%- if enable_jellyseerr %> << service_name >>-jellyseerr: image: fallenbagel/jellyseerr:latest container_name: << service_name >>-jellyseerr environment: - TZ=<< timezone >> + - LOG_LEVEL=info volumes: - << data_dir >>/<< service_name >>/jellyseerr:/app/config ports: - "<< port_jellyseerr >>:5055" restart: unless-stopped +<%- endif %> + +<%- if enable_recyclarr %> + << service_name >>-recyclarr: + image: ghcr.io/recyclarr/recyclarr:latest + container_name: << service_name >>-recyclarr + user: << puid >>:<< pgid >> + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/recyclarr:/config + restart: unless-stopped +<%- endif %> + +<%- if enable_unpackerr %> + << service_name >>-unpackerr: + image: ghcr.io/unpackerr/unpackerr:latest + container_name: << service_name >>-unpackerr + user: << puid >>:<< pgid >> + environment: + - TZ=<< timezone >> + - UN_SONARR_0_URL=http://<< service_name >>-sonarr:8989 + - UN_RADARR_0_URL=http://<< service_name >>-radarr:7878 + volumes: + - << data_dir >>/<< service_name >>/unpackerr:/config + - << downloads_dir >>:/downloads + restart: unless-stopped +<%- endif %> + +<%- if enable_tdarr %> + << service_name >>-tdarr: + image: ghcr.io/haveagitgat/tdarr:latest + container_name: << service_name >>-tdarr + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + - serverIP=0.0.0.0 + - serverPort=8266 + - webUIPort=8265 + - internalNode=true + volumes: + - << data_dir >>/<< service_name >>/tdarr/server:/app/server + - << data_dir >>/<< service_name >>/tdarr/configs:/app/configs + - << media_dir >>:/media + - << downloads_dir >>/tdarr-cache:/temp + ports: + - "<< port_tdarr >>:8265" + - "<< port_tdarr_server >>:8266" + restart: unless-stopped +<%- endif %> + +<%- if enable_autobrr %> + << service_name >>-autobrr: + image: ghcr.io/autobrr/autobrr:latest + container_name: << service_name >>-autobrr + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/autobrr:/config + ports: + - "<< port_autobrr >>:7474" + restart: unless-stopped +<%- endif %> + +<%- if enable_maintainerr %> + << service_name >>-maintainerr: + image: ghcr.io/jorenn92/maintainerr:latest + container_name: << service_name >>-maintainerr + user: << puid >>:<< pgid >> + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/maintainerr:/opt/data + ports: + - "<< port_maintainerr >>:6246" + restart: unless-stopped +<%- endif %> + +<%- if enable_huntarr %> + << service_name >>-huntarr: + image: ghcr.io/plexguide/huntarr:latest + container_name: << service_name >>-huntarr + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/huntarr:/config + ports: + - "<< port_huntarr >>:9705" + restart: unless-stopped +<%- endif %> diff --git a/apps/arr-stack/template.json b/apps/arr-stack/template.json index 0af6830..4c7045a 100644 --- a/apps/arr-stack/template.json +++ b/apps/arr-stack/template.json @@ -2,10 +2,21 @@ "kind": "compose", "metadata": { "name": "ARR-stack", - "description": "Complete media-automatiseringsstack: Radarr (films), Sonarr (series), Lidarr (muziek), Readarr (boeken), Prowlarr (indexers), Bazarr (ondertitels) en Jellyseerr (verzoeken).", - "tags": ["media", "automatisering", "radarr", "sonarr", "prowlarr", "bazarr", "jellyseerr"], - "icon": {"provider": "selfhst", "id": "radarr"}, - "version": {"name": "latest"} + "description": "Media-automatisering met een schakelaar per onderdeel: Sonarr, Radarr, Lidarr, Readarr, Whisparr, Prowlarr, Jackett, Bazarr, FlareSolverr, qBittorrent, SABnzbd, NZBGet, Gluetun (VPN), Jellyseerr, Recyclarr, Unpackerr, Tdarr, Autobrr, Maintainerr en Huntarr.", + "tags": [ + "media", + "automatisering", + "films", + "series", + "downloaden" + ], + "icon": { + "provider": "selfhst", + "id": "sonarr" + }, + "version": { + "name": "latest" + } }, "variables": [ { @@ -14,34 +25,33 @@ { "name": "service_name", "type": "str", - "title": "Servicenaam (prefix)", + "title": "Naam van de stack", "default": "arr", "required": true, - "description": "Prefix voor alle containers in de stack, bijv. 'arr' geeft arr-radarr, arr-sonarr, etc." + "description": "Wordt het voorvoegsel van elke container, bv. arr-sonarr" }, { "name": "data_dir", "type": "str", - "title": "Config directory", + "title": "Configuratiemap", "default": "/opt/serverup/appdata", - "required": true, - "description": "Basismap voor configuratiebestanden van alle ARR-apps" + "required": true }, { "name": "media_dir", "type": "str", - "title": "Media directory", + "title": "Mediamap", "default": "/mnt/media", "required": true, - "description": "Map voor films, series en muziek. Moet ook zichtbaar zijn voor de download-client." + "description": "Hier komen films/, series/, muziek/ en boeken/ onder te staan" }, { "name": "downloads_dir", "type": "str", - "title": "Downloads directory", + "title": "Downloadmap", "default": "/mnt/downloads", "required": true, - "description": "Map waar de download-client bestanden neerzet (qBittorrent of SABnzbd). Moet overeenkomen met het pad in de download-client." + "description": "Zet deze op hetzelfde bestandssysteem als de mediamap, anders kopieert elke download in plaats van te verplaatsen" }, { "name": "timezone", @@ -49,84 +59,365 @@ "title": "Tijdzone", "default": "Europe/Amsterdam", "required": true - } - ] - }, - { - "title": "Gebruiker", - "items": [ + }, { "name": "puid", "type": "int", - "title": "PUID", + "title": "Gebruikers-ID (PUID)", "default": 1000, "required": true, - "description": "User ID van de systeemgebruiker (id -u)" + "description": "`id -u` op je host; bepaalt de eigenaar van bestanden" }, { "name": "pgid", "type": "int", - "title": "PGID", + "title": "Groeps-ID (PGID)", "default": 1000, - "required": true, - "description": "Group ID van de systeemgebruiker (id -g)" + "required": true } ] }, { - "title": "Poorten", + "title": "Sonarr — series", + "items": [ + { + "name": "port_sonarr", + "type": "int", + "title": "Poort", + "default": 8989, + "required": true + } + ], + "toggle": "enable_sonarr", + "toggle_default": true, + "description": "Zoekt, downloadt en hernoemt series" + }, + { + "title": "Radarr — films", "items": [ { "name": "port_radarr", "type": "int", - "title": "Radarr poort", + "title": "Poort", "default": 7878, "required": true - }, - { - "name": "port_sonarr", - "type": "int", - "title": "Sonarr poort", - "default": 8989, - "required": true - }, + } + ], + "toggle": "enable_radarr", + "toggle_default": true, + "description": "Zoekt, downloadt en hernoemt films" + }, + { + "title": "Lidarr — muziek", + "items": [ { "name": "port_lidarr", "type": "int", - "title": "Lidarr poort", + "title": "Poort", "default": 8686, "required": true - }, + } + ], + "toggle": "enable_lidarr", + "toggle_default": false + }, + { + "title": "Readarr — boeken", + "items": [ { "name": "port_readarr", "type": "int", - "title": "Readarr poort", + "title": "Poort", "default": 8787, "required": true - }, + } + ], + "toggle": "enable_readarr", + "toggle_default": false, + "description": "Let op: de ontwikkeling van Readarr is stilgelegd; het draait nog wel" + }, + { + "title": "Whisparr — volwassenen", + "items": [ + { + "name": "port_whisparr", + "type": "int", + "title": "Poort", + "default": 6969, + "required": true + } + ], + "toggle": "enable_whisparr", + "toggle_default": false + }, + { + "title": "Prowlarr — indexerbeheer", + "items": [ { "name": "port_prowlarr", "type": "int", - "title": "Prowlarr poort", + "title": "Poort", "default": 9696, "required": true - }, + } + ], + "toggle": "enable_prowlarr", + "toggle_default": true, + "description": "Beheert je indexers centraal en duwt ze naar de andere *arr-apps" + }, + { + "title": "Jackett — indexerproxy", + "items": [ + { + "name": "port_jackett", + "type": "int", + "title": "Poort", + "default": 9117, + "required": true + } + ], + "toggle": "enable_jackett", + "toggle_default": false, + "description": "Ouder alternatief voor Prowlarr; meestal heb je er maar één nodig" + }, + { + "title": "FlareSolverr — Cloudflare omzeilen", + "items": [ + { + "name": "port_flaresolverr", + "type": "int", + "title": "Poort", + "default": 8191, + "required": true + } + ], + "toggle": "enable_flaresolverr", + "toggle_default": false, + "description": "Nodig voor indexers die achter een Cloudflare-controle zitten" + }, + { + "title": "Bazarr — ondertitels", + "items": [ { "name": "port_bazarr", "type": "int", - "title": "Bazarr poort", + "title": "Poort", "default": 6767, "required": true + } + ], + "toggle": "enable_bazarr", + "toggle_default": true + }, + { + "title": "qBittorrent — torrents", + "items": [ + { + "name": "port_qbittorrent", + "type": "int", + "title": "Webinterface", + "default": 8097, + "required": true }, + { + "name": "port_qbittorrent_tcp", + "type": "int", + "title": "Inkomende poort", + "default": 6881, + "required": true + } + ], + "toggle": "enable_qbittorrent", + "toggle_default": true, + "description": "Torrentclient met webinterface" + }, + { + "title": "SABnzbd — usenet", + "items": [ + { + "name": "port_sabnzbd", + "type": "int", + "title": "Poort", + "default": 8098, + "required": true + } + ], + "toggle": "enable_sabnzbd", + "toggle_default": false + }, + { + "title": "NZBGet — usenet (lichter)", + "items": [ + { + "name": "port_nzbget", + "type": "int", + "title": "Poort", + "default": 6789, + "required": true + } + ], + "toggle": "enable_nzbget", + "toggle_default": false, + "description": "Zuiniger alternatief voor SABnzbd" + }, + { + "title": "Gluetun — VPN voor de downloadclient", + "items": [ + { + "name": "vpn_provider", + "type": "str", + "title": "VPN-aanbieder", + "default": "mullvad", + "required": true, + "description": "Bijvoorbeeld mullvad, nordvpn, protonvpn of surfshark" + }, + { + "name": "vpn_type", + "type": "enum", + "title": "Protocol", + "default": "wireguard", + "required": true, + "config": { + "options": [ + "wireguard", + "openvpn" + ] + } + }, + { + "name": "wireguard_private_key", + "type": "str", + "title": "WireGuard privésleutel", + "default": "", + "required": false, + "config": { + "placeholder": "alleen bij wireguard" + } + }, + { + "name": "wireguard_addresses", + "type": "str", + "title": "WireGuard adressen", + "default": "", + "required": false, + "config": { + "placeholder": "10.64.0.2/32" + } + }, + { + "name": "openvpn_user", + "type": "str", + "title": "OpenVPN gebruiker", + "default": "", + "required": false + }, + { + "name": "openvpn_password", + "type": "str", + "title": "OpenVPN wachtwoord", + "default": "", + "required": false + } + ], + "toggle": "enable_gluetun", + "toggle_default": false, + "description": "Leidt al je downloadverkeer door een VPN. De downloadclients delen dan het netwerk van deze container, dus hun poorten komen hier te liggen." + }, + { + "title": "Jellyseerr — verzoeken", + "items": [ { "name": "port_jellyseerr", "type": "int", - "title": "Jellyseerr poort", + "title": "Poort", "default": 5055, - "required": true, - "description": "Webinterface voor gebruikers om films en series aan te vragen" + "required": true } - ] + ], + "toggle": "enable_jellyseerr", + "toggle_default": true, + "description": "Laat huisgenoten films en series aanvragen" + }, + { + "title": "Recyclarr — TRaSH-instellingen", + "items": [], + "toggle": "enable_recyclarr", + "toggle_default": false, + "description": "Synchroniseert kwaliteitsprofielen uit de TRaSH-gidsen naar Sonarr en Radarr" + }, + { + "title": "Unpackerr — archieven uitpakken", + "items": [], + "toggle": "enable_unpackerr", + "toggle_default": false, + "description": "Pakt gedownloade rar-archieven automatisch uit" + }, + { + "title": "Tdarr — hercoderen", + "items": [ + { + "name": "port_tdarr", + "type": "int", + "title": "Webinterface", + "default": 8265, + "required": true + }, + { + "name": "port_tdarr_server", + "type": "int", + "title": "Serverpoort", + "default": 8266, + "required": true + } + ], + "toggle": "enable_tdarr", + "toggle_default": false, + "description": "Zet je bibliotheek om naar een zuiniger formaat" + }, + { + "title": "Autobrr — automatisch grijpen", + "items": [ + { + "name": "port_autobrr", + "type": "int", + "title": "Poort", + "default": 7474, + "required": true + } + ], + "toggle": "enable_autobrr", + "toggle_default": false, + "description": "Reageert direct op aankondigingen in plaats van periodiek te zoeken" + }, + { + "title": "Maintainerr — opruimen", + "items": [ + { + "name": "port_maintainerr", + "type": "int", + "title": "Poort", + "default": 6246, + "required": true + } + ], + "toggle": "enable_maintainerr", + "toggle_default": false, + "description": "Ruimt media op volgens regels die je zelf instelt" + }, + { + "title": "Huntarr — gaten opvullen", + "items": [ + { + "name": "port_huntarr", + "type": "int", + "title": "Poort", + "default": 9705, + "required": true + } + ], + "toggle": "enable_huntarr", + "toggle_default": false, + "description": "Zoekt gericht naar ontbrekende en te verbeteren afleveringen" } ] } diff --git a/server-up/core/boilerplates.py b/server-up/core/boilerplates.py index d5ce5ae..aed4d45 100644 --- a/server-up/core/boilerplates.py +++ b/server-up/core/boilerplates.py @@ -81,6 +81,19 @@ def fields(d: Path) -> list[dict]: for grp in t.get("variables", []) or []: gname = grp.get("title") or grp.get("name", "") toggle = grp.get("toggle") + if toggle: + # De groepsschakelaar is zelf geen item in template.json, waardoor + # hij nergens een startwaarde kreeg en dus altijd uit stond. Als + # synthetisch veld krijgt hij die wel; de UI toont hem als schakelaar + # in de kop en slaat hem over in de lijst eronder. + out.append({ + "name": toggle, "type": "bool", + "title": gname, "group": gname, "group_toggle": toggle, + "default": bool(grp.get("toggle_default", True)), + "required": False, "options": [], "needs": [], + "placeholder": "", "description": grp.get("description", ""), + "is_group_toggle": True, + }) for item in grp.get("items", []) or []: cfg = item.get("config") or {} out.append({ diff --git a/server-up/templates/index.html b/server-up/templates/index.html index 18e8e6f..c2f90ab 100644 --- a/server-up/templates/index.html +++ b/server-up/templates/index.html @@ -1156,7 +1156,9 @@ tailwind.config = {