From 4e89bd1986c9a9fab9e6e034623cbc7be181fab8 Mon Sep 17 00:00:00 2001 From: claude Date: Sat, 1 Aug 2026 03:07:54 +0200 Subject: [PATCH] =?UTF-8?q?F=C3=B6rslag-sidan:=20typ-knappar=20i=20v=C3=A4?= =?UTF-8?q?nsterspalten,=20alla=20fynd=20nyast=20f=C3=B6rst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tre knappar (Artister & album / Låtar / Genrer) ersätter batch-listan; huvudspalten visar alla cachade fynd av vald typ i tidsordning med nyast först, grupperade per körning med datum-avdelare. Nytt API GET /api/suggest/items?type=X (plattar batcher med batch-metadata). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01824ZrvG2mDYYrmwqypLNup --- backend/src/app.js | 5 ++ backend/src/suggest.js | 10 +++ backend/test/suggest.test.js | 12 ++++ frontend/src/pages/SuggestionsPage.vue | 97 +++++++++++++++----------- 4 files changed, 85 insertions(+), 39 deletions(-) diff --git a/backend/src/app.js b/backend/src/app.js index f5773e6..85375f5 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -235,6 +235,11 @@ export function buildApp(config, deps = {}) { } }) + app.get('/api/suggest/items', async (req) => { + const type = SUGGEST_TYPES.includes(req.query.type) ? req.query.type : 'mix' + return suggest.allItems(type) + }) + app.get('/api/suggest/batches', async () => { return suggest.loadBatches().map((b) => ({ id: b.id, diff --git a/backend/src/suggest.js b/backend/src/suggest.js index bdaf07c..f2c67ea 100644 --- a/backend/src/suggest.js +++ b/backend/src/suggest.js @@ -355,6 +355,16 @@ export function suggestEngine({ config, store, lidarr, fetchImpl = fetch }) { return items.slice(0, limit) }, + // alla fynd av en typ, nyast först, med batch-metadata för gruppering + allItems(type = 'mix', limit = 500) { + return loadBatches() + .filter((b) => (b.type ?? 'mix') === type) + .flatMap((b) => + b.items.map((it) => ({ ...it, batchId: b.id, batchCreatedAt: b.createdAt, trigger: b.trigger })), + ) + .slice(0, limit) + }, + lastRun(type = 'mix') { return loadBatches().find((b) => (b.type ?? 'mix') === type)?.createdAt ?? null }, diff --git a/backend/test/suggest.test.js b/backend/test/suggest.test.js index e3f24a4..fb94583 100644 --- a/backend/test/suggest.test.js +++ b/backend/test/suggest.test.js @@ -103,6 +103,18 @@ test('run: batch-id räknas upp och latest tar nyaste först', async () => { assert.equal(engine.loadBatches()[0].id, b2.id) }) +test('allItems: plattar batcher nyast först med batch-metadata', async () => { + const { engine } = setup() + const b1 = await engine.run() + const b2 = await engine.run() + const all = engine.allItems('mix') + assert.equal(all.length, 2) + assert.equal(all[0].batchId, b2.id, 'nyaste batchens fynd först') + assert.equal(all[1].batchId, b1.id) + assert.equal(all[0].batchCreatedAt, b2.createdAt) + assert.equal(engine.allItems('tracks').length, 0) +}) + test('run: markdown-staket runt JSON hanteras', async () => { const { engine } = setup({ geminiResponse: '```json\n[{"type":"artist","name":"Ghost","motivation":"x"}]\n```', diff --git a/frontend/src/pages/SuggestionsPage.vue b/frontend/src/pages/SuggestionsPage.vue index 311c969..d477dbd 100644 --- a/frontend/src/pages/SuggestionsPage.vue +++ b/frontend/src/pages/SuggestionsPage.vue @@ -1,70 +1,85 @@