hotfix(1.4.2): admin empty + legacy symbol migration
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 20m44s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 20m44s
This commit is contained in:
@@ -3,6 +3,12 @@
|
|||||||
Alle nennenswerten Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
|
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/).
|
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
|
## [1.4.1] – 2026-05-20 — Hotfix: Production 500 & Null-Crash
|
||||||
|
|
||||||
### Behoben
|
### Behoben
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lageplan",
|
"name": "lageplan",
|
||||||
"version": "1.4.1",
|
"version": "1.4.2",
|
||||||
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -344,6 +344,62 @@ async function migrate() {
|
|||||||
console.log(' Unique constraint drop skipped:', e.message)
|
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')
|
console.log('✅ Database migrations complete')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,8 +121,10 @@ export function SymbolManager() {
|
|||||||
}
|
}
|
||||||
if (symRes.ok) {
|
if (symRes.ok) {
|
||||||
const s = await symRes.json()
|
const s = await symRes.json()
|
||||||
setSymbolGroups(s.groups || [])
|
setSymbolGroups(s.categories || [])
|
||||||
setFlatSymbols(s.symbols || [])
|
// Flatten all symbols from categories for ungrouped / category-management views
|
||||||
|
const all = (s.categories || []).flatMap((c: any) => c.symbols || [])
|
||||||
|
setFlatSymbols(all)
|
||||||
}
|
}
|
||||||
if (tplRes.ok) {
|
if (tplRes.ok) {
|
||||||
const t = await tplRes.json()
|
const t = await tplRes.json()
|
||||||
|
|||||||
Reference in New Issue
Block a user