From c8a94e1ea74c786f52d06a83fb1afd803f613ce6 Mon Sep 17 00:00:00 2001 From: Pepe Ziberi Date: Wed, 20 May 2026 23:06:25 +0200 Subject: [PATCH] hotfix(1.4.2): admin empty + legacy symbol migration --- CHANGELOG.md | 6 +++ package.json | 2 +- prisma/migrate.js | 56 +++++++++++++++++++++++++ src/components/admin/symbol-manager.tsx | 6 ++- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae0d7bd..c8355cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ Alle nennenswerten Änderungen an diesem Projekt werden in dieser Datei dokumentiert. Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/). +## [1.4.2] – 2026-05-20 — Hotfix: Admin leer & Legacy-Symbole + +### Behoben +- **Admin Symbol-Manager**: Liest jetzt korrekt `categories` statt `groups` aus der API-Response von `/api/tenant/symbols?grouped=true`. +- **Datenmigration (Step 18)**: Neue Migration in `prisma/migrate.js` migriert bestehende `tenantSymbols` automatisch: setzt fehlende `name`, `svgPath`, `categoryId` (Default-Kategorie „Meine Symbole“) und `migratedFromIconId`. Behebt „Leichen“ mit broken images. + ## [1.4.1] – 2026-05-20 — Hotfix: Production 500 & Null-Crash ### Behoben diff --git a/package.json b/package.json index 2176845..a26607f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lageplan", - "version": "1.4.1", + "version": "1.4.2", "description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation", "private": true, "scripts": { diff --git a/prisma/migrate.js b/prisma/migrate.js index 04958cc..832d626 100644 --- a/prisma/migrate.js +++ b/prisma/migrate.js @@ -344,6 +344,62 @@ async function migrate() { console.log(' Unique constraint drop skipped:', e.message) } + // ─── Step 18: Migrate legacy tenantSymbols (name, svgPath, categoryId, migratedFromIconId) ─── + console.log(' [18] Migrating legacy tenantSymbols data...') + try { + const tenantsWithSymbols = await prisma.$queryRawUnsafe(` + SELECT "tenantId", COUNT(id) as cnt FROM tenant_symbols GROUP BY "tenantId" + `) + let catsCreated = 0 + let symsMigrated = 0 + for (const row of tenantsWithSymbols) { + const tenantId = row.tenantId + // Create default category if none exists for this tenant + let defaultCat = await prisma.$queryRawUnsafe(` + SELECT id FROM tenant_categories WHERE "tenantId" = '${tenantId}' AND name = 'Meine Symbole' LIMIT 1 + `) + if (!defaultCat || !defaultCat.length) { + const newCatId = crypto.randomUUID() + await prisma.$executeRawUnsafe(` + INSERT INTO tenant_categories (id, "tenantId", name, "sortOrder", "createdAt", "updatedAt") + VALUES ('${newCatId}', '${tenantId}', 'Meine Symbole', 0, NOW(), NOW()) + `) + defaultCat = [{ id: newCatId }] + catsCreated++ + } + const catId = defaultCat[0].id + + // Migrate symbols: set name, svgPath, categoryId, migratedFromIconId where null + await prisma.$executeRawUnsafe(` + UPDATE tenant_symbols ts + SET + name = COALESCE(ts.name, ts."customName", ia.name, 'Unbenannt'), + "svgPath" = COALESCE(ts."svgPath", ia."fileKey"), + "categoryId" = COALESCE(ts."categoryId", '${catId}'), + "migratedFromIconId" = COALESCE(ts."migratedFromIconId", ts."iconId"), + "updatedAt" = NOW() + FROM icon_assets ia + WHERE ts."tenantId" = '${tenantId}' + AND ia.id = ts."iconId" + AND (ts.name IS NULL OR ts."svgPath" IS NULL OR ts."categoryId" IS NULL OR ts."migratedFromIconId" IS NULL) + `) + // Also handle symbols where iconId is already null (orphaned) — at least set category & name + await prisma.$executeRawUnsafe(` + UPDATE tenant_symbols + SET + name = COALESCE(name, "customName", 'Unbenannt'), + "categoryId" = COALESCE("categoryId", '${catId}'), + "updatedAt" = NOW() + WHERE "tenantId" = '${tenantId}' + AND (name IS NULL OR "categoryId" IS NULL) + `) + symsMigrated++ + } + console.log(` ✅ ${catsCreated} default categories created, ${symsMigrated} tenants processed`) + } catch (e) { + console.log(' Legacy migration skipped:', e.message) + } + console.log('✅ Database migrations complete') } diff --git a/src/components/admin/symbol-manager.tsx b/src/components/admin/symbol-manager.tsx index 7c02b6d..65f4d9f 100644 --- a/src/components/admin/symbol-manager.tsx +++ b/src/components/admin/symbol-manager.tsx @@ -121,8 +121,10 @@ export function SymbolManager() { } if (symRes.ok) { const s = await symRes.json() - setSymbolGroups(s.groups || []) - setFlatSymbols(s.symbols || []) + setSymbolGroups(s.categories || []) + // Flatten all symbols from categories for ungrouped / category-management views + const all = (s.categories || []).flatMap((c: any) => c.symbols || []) + setFlatSymbols(all) } if (tplRes.ok) { const t = await tplRes.json()