diff --git a/CHANGELOG.md b/CHANGELOG.md index 46bd1b0..6749c44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +# v0.8.01-beta — "Nog 106 tonen" onder een leeg scherm + +De app store toonde geen enkele kaart, met daaronder een knop die beloofde dat +er nog 106 apps wachtten. Twee bronnen die uit elkaar konden lopen: het raster +liep over de **repolijst**, de teller over de **opgehaalde apps**. Waren die +twee het oneens, dan stond er een getal onder een leeg scherm — zonder dat er +ergens een foutmelding te zien was. + +- Teller en raster komen nu uit dezelfde lijst. De knop kan niets meer beloven + wat er niet staat. +- Een lege store zegt nu wát er aan de hand is: geen repository toegevoegd, of + geen apps die aan het filter voldoen. Eerder bleef het scherm gewoon leeg. +- `GET /api/repos` gaf een 500 op een repo zonder `id`. Eén rare regel in de + configuratie maakte daarmee de hele store leeg; zulke regels worden nu + overgeslagen. + # v0.8.00-beta — Een kapotte cache herstelt zichzelf `fatal: shallow file has changed since we read it` liet een repo achter die zich diff --git a/VERSION b/VERSION index 752fcfd..56d8572 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.00-beta +0.8.01-beta diff --git a/server-up/app.py b/server-up/app.py index 8b40b95..65529c9 100644 --- a/server-up/app.py +++ b/server-up/app.py @@ -1228,7 +1228,14 @@ _BAD_URL_MSG = ("Ongeldige repo-URL. Toegestaan zijn http(s)://, ssh:// en " def api_repos(): # Nooit het token zelf teruggeven — alleen of er één ingesteld is. repos = cfg.redact(cfg.load()).get("APP_REPOS", []) - result = [{**r, "cloned": git.cache_dir(r["id"]).exists()} for r in repos] + # Een repo zonder id gaf hier een KeyError, dus een 500, dus een lege + # repolijst in de interface — en daarmee een app store zonder enkele kaart. + # Eén rare regel in de configuratie hoort de rest niet mee te nemen. + result = [] + for r in repos: + if not isinstance(r, dict) or not r.get("id"): + continue + result.append({**r, "cloned": git.cache_dir(r["id"]).exists()}) return jsonify(result) diff --git a/server-up/templates/index.html b/server-up/templates/index.html index b630170..23c7cdc 100644 --- a/server-up/templates/index.html +++ b/server-up/templates/index.html @@ -683,6 +683,15 @@ tailwind.config = { +
+ +

Nog geen repository toegevoegd

+
+
+ +

Geen apps gevonden

+
+
@@ -2927,7 +2936,7 @@ function app() { }, // Hoeveel er nog wachten achter de knop, over alle repo's heen. get storeVerborgen() { - return Math.max(0, this.storeResultaat - Object.keys(this.storeStacks || {}) + return Math.max(0, this.storeResultaat - this.storeRepoIds .reduce((n, id) => n + this.zichtbareStore(id).length, 0)); }, // Alle labels uit alle repo's met hun aantal, op frequentie gesorteerd @@ -2967,9 +2976,15 @@ function app() { return (this.storeCat ? 1 : 0) + (this.storeTag ? 1 : 0); }, // Hoeveel apps er over blijven met de huidige keuze, over alle repo's heen. + // Tellen over dezelfde lijst die ook de kaarten oplevert. Eerder telde dit + // over `storeStacks` terwijl het raster over `repos` liep: liepen die twee + // uit elkaar, dan beloofde de knop "Nog 106 tonen" apps die nergens op het + // scherm stonden, zonder dat er ergens iets van een fout te zien was. + get storeRepoIds() { + return (this.repos || []).map(r => r.id).filter(Boolean); + }, get storeResultaat() { - return Object.keys(this.storeStacks || {}) - .reduce((n, id) => n + this.filteredStore(id).length, 0); + return this.storeRepoIds.reduce((n, id) => n + this.filteredStore(id).length, 0); }, // Wat er op een telefoon onder de meer-knop komt te staan. Met namen // erbij: twaalf icoontjes zonder tekst zeggen niets. diff --git a/server-up/translations/en.json b/server-up/translations/en.json index 2006eab..0dd93b3 100644 --- a/server-up/translations/en.json +++ b/server-up/translations/en.json @@ -49,7 +49,7 @@ "docker": "Docker", "no_stacks": "No apps found", "no_images": "No images found", - "no_repos": "No repositories", + "no_repos": "No repository added yet — add one to see apps.", "add_repo": "Add repository", "repo_name": "Name", "repo_url": "Git URL", @@ -465,5 +465,6 @@ "move_data_confirm": "Move {n} folder(s)? Apps are stopped, data is copied and verified, and only then is the old cleared out.", "manual_started": "Started manually", "manual_hint": "These apps run on this host but were not created by Server Up — started manually, or from before you began using Server Up. You can start, stop and view their logs here.", - "containers_n": "{n} containers" + "containers_n": "{n} containers", + "no_apps_found": "No apps found" } diff --git a/server-up/translations/nl.json b/server-up/translations/nl.json index 616f678..5c707d2 100644 --- a/server-up/translations/nl.json +++ b/server-up/translations/nl.json @@ -49,7 +49,7 @@ "docker": "Docker", "no_stacks": "Geen apps gevonden", "no_images": "Geen images gevonden", - "no_repos": "Geen repositories", + "no_repos": "Nog geen repository toegevoegd — voeg er een toe om apps te zien.", "add_repo": "Repository toevoegen", "repo_name": "Naam", "repo_url": "Git URL", @@ -465,5 +465,6 @@ "move_data_confirm": "{n} map(pen) verplaatsen? De apps worden gestopt, de data wordt gekopieerd en gecontroleerd, en pas daarna wordt het oude opgeruimd.", "manual_started": "Handmatig gestart", "manual_hint": "Deze apps draaien op deze host maar zijn niet door Server Up aangemaakt — handmatig gestart, of van vóór je Server Up ging gebruiken. Je kunt ze hier starten, stoppen en hun logs bekijken.", - "containers_n": "{n} containers" + "containers_n": "{n} containers", + "no_apps_found": "Geen apps gevonden" } diff --git a/tests/js/menu.test.js b/tests/js/menu.test.js index d3a3727..8eac5d1 100644 --- a/tests/js/menu.test.js +++ b/tests/js/menu.test.js @@ -163,6 +163,8 @@ check('doorklikken opent de stackspagina', c.page === 'stacks'); // ── Filtermenu van de app store ───────────────────────────────────────────── // De labelrij was afgekapt op veertien, waardoor je de rest niet kon kiezen. Het // menu zoekt nu in de volledige lijst. +// De teller volgt de repolijst, want die bepaalt ook welke kaarten er komen. +c.repos = [{id:'r', name:'Proefrepo'}]; c.storeStacks = { r: [ {dir:'sonarr', name:'Sonarr', categories:['media'], tags:['media','series']}, {dir:'radarr', name:'Radarr', categories:['media'], tags:['media','films']}, @@ -395,6 +397,33 @@ check('balk staat halverwege', c.job.progress.pct === 50); await c.verplaatsPaden(); check('afbreken bij de bevestiging start niets', verstuurd === null); + // ── De store telt wat hij ook laat zien ─────────────────────────────────── + // Het raster liep over `repos`, de teller over `storeStacks`. Liepen die twee + // uit elkaar, dan stond er "Nog 106 tonen" onder een leeg scherm — zonder dat + // er ergens een fout te zien was. + const nepApps = n => Array.from({length: n}, + (_, i) => ({dir: 'a' + i, name: 'App' + i, categories: [], tags: []})); + const kaarten = () => c.repos.reduce((n, r) => n + c.zichtbareStore(r.id).length, 0); + + c._storeCache = {sleutel: null, lijsten: {}}; + c.storeQuery = ''; c.storeCat = ''; c.storeTag = ''; c.storeLimiet = 60; + c.repos = [{id: 'server-up', name: 'Server Up'}]; + c.storeStacks = {'server-up': nepApps(106)}; + check('de eerste zestig staan in beeld', kaarten() === 60); + check('en de rest wacht achter de knop', c.storeVerborgen === 46); + c.meerTonen(); + c._storeCache = {sleutel: null, lijsten: {}}; + check('meer tonen laat de rest zien', kaarten() === 106); + check('en de knop verdwijnt', c.storeVerborgen === 0); + + // Zonder repo's is er niets te tonen — en dus ook niets te beloven. + c._storeCache = {sleutel: null, lijsten: {}}; + c.storeLimiet = 60; + c.repos = []; + check('geen repo\'s: geen kaarten', kaarten() === 0); + check('en geen knop die apps belooft', c.storeVerborgen === 0); + check('de teller is ook nul', c.storeResultaat === 0); + c.rpc = poortRpc; // ── Eén lijst voor beheerde en handmatig gestarte apps ────────────────────