feat(260929-dmx): Widget-Raster horizontal doppelt so fein (48 Spalten, Version 3)
- COLS lg 48 / md 40 / sm 24 / xs 16 / xxs 4, Zeilenhoehe und Abstand unveraendert - Migration stufenweise: v1->v2 wie bisher, v2->v3 nur x/w/minW/maxW x2 - Rueckfallwerte fuer Widgets ohne Eintrag auf 8 Einheiten Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,23 +1,35 @@
|
||||
/**
|
||||
* grid-layout-migration — einmalige Umrechnung gespeicherter Dashboard-
|
||||
* Anordnungen in die feineren Raster-Einheiten (quick-260916-bwo).
|
||||
* grid-layout-migration — einmalige, stufenweise Umrechnung gespeicherter
|
||||
* Dashboard-Anordnungen in die feineren Raster-Einheiten (quick-260916-bwo,
|
||||
* quick-260929-dmx).
|
||||
*
|
||||
* Warum: Das Raster wurde von 12 Spalten / 40 px Zeilenhoehe auf 24 Spalten /
|
||||
* 20 px verdoppelt (`dashboard-grid.tsx`). Eine in ALTEN Einheiten gespeicherte
|
||||
* Anordnung wuerde im neuen Raster halb so gross und an der halben Position
|
||||
* erscheinen. Deshalb werden `x, y, w, h` (und, falls vorhanden, `minW, minH,
|
||||
* maxW, maxH`) jedes Elements in jedem Breakpoint GENAU EINMAL mit 2
|
||||
* multipliziert.
|
||||
* Warum: Das Raster wurde zweimal feiner. Eine in ALTEN Einheiten gespeicherte
|
||||
* Anordnung wuerde im neuen Raster kleiner und an anderer Position erscheinen.
|
||||
* Deshalb wird jedes Element in jedem Breakpoint stufenweise umgerechnet,
|
||||
* jede Stufe GENAU EINMAL:
|
||||
*
|
||||
* Marker: Damit die Verdopplung nur einmal geschieht, traegt das gespeicherte
|
||||
* JSON den Schluessel `__gridVersion: 2`. Der Marker lebt NUR im persistierten
|
||||
* JSON (Spalte `DashboardLayout.layouts`, Json, kein Schema noetig) — nie im
|
||||
* Zustand des Stores, der mit `Object.keys` ueber die Breakpoints iteriert und
|
||||
* `.filter` auf jedem Wert aufruft (ein Zahlwert wuerde dort abstuerzen).
|
||||
* `migrateGridLayouts` entfernt den Marker beim Laden, `withGridVersion`
|
||||
* haengt ihn beim Speichern wieder an. Fehlt der Marker beim Speichern, wird
|
||||
* beim naechsten Laden ERNEUT verdoppelt — deshalb muss JEDER Speichervorgang
|
||||
* `withGridVersion` benutzen (T-BWO-02, Store-Tests pinnen das).
|
||||
* - Version 1 -> 2 (quick-260916-bwo): 12 Spalten / 40 px Zeilenhoehe wurden
|
||||
* 24 Spalten / 20 px. `x, y, w, h` (und, falls vorhanden, `minW, minH, maxW,
|
||||
* maxH`) werden mit 2 multipliziert.
|
||||
* - Version 2 -> 3 (quick-260929-dmx): NUR die Breite wurde noch einmal
|
||||
* verdoppelt (24 -> 48 Spalten am lg-Breakpoint, Zeilenhoehe und Abstand
|
||||
* unveraendert). Nur `x, w, minW, maxW` werden mit 2 multipliziert; `y, h,
|
||||
* minH, maxH` bleiben.
|
||||
*
|
||||
* Die Stufen sind kumulativ: eine Version-1-Anordnung durchlaeuft beide
|
||||
* (x/w/minW/maxW also x4, y/h/minH/maxH x2), eine Version-2-Anordnung nur die
|
||||
* zweite, eine Version-3-Anordnung keine.
|
||||
*
|
||||
* Marker: Damit jede Stufe nur einmal geschieht, traegt das gespeicherte JSON
|
||||
* den Schluessel `__gridVersion` (aktuell 3). Der Marker lebt NUR im
|
||||
* persistierten JSON (Spalte `DashboardLayout.layouts`, Json, kein Schema
|
||||
* noetig) — nie im Zustand des Stores, der mit `Object.keys` ueber die
|
||||
* Breakpoints iteriert und `.filter` auf jedem Wert aufruft (ein Zahlwert
|
||||
* wuerde dort abstuerzen). `migrateGridLayouts` entfernt den Marker beim
|
||||
* Laden, `withGridVersion` haengt ihn beim Speichern wieder an. Fehlt der
|
||||
* Marker beim Speichern, wird beim naechsten Laden ERNEUT umgerechnet —
|
||||
* deshalb muss JEDER Speichervorgang `withGridVersion` benutzen (T-BWO-02,
|
||||
* Store-Tests pinnen das).
|
||||
*
|
||||
* Idempotenz: `migrateGridLayouts(withGridVersion(migrateGridLayouts(alt).layouts))`
|
||||
* liefert dasselbe Ergebnis wie `migrateGridLayouts(alt)` mit `migrated: false`.
|
||||
@@ -28,7 +40,7 @@
|
||||
* React- oder Store-Abhaengigkeit.
|
||||
*/
|
||||
|
||||
export const GRID_VERSION = 2;
|
||||
export const GRID_VERSION = 3;
|
||||
export const GRID_VERSION_KEY = '__gridVersion';
|
||||
export const GRID_SCALE_FACTOR = 2;
|
||||
|
||||
@@ -43,7 +55,13 @@ export interface GridLayoutItem {
|
||||
|
||||
export type GridLayouts = Record<string, GridLayoutItem[]>;
|
||||
|
||||
const SCALED_FIELDS = ['x', 'y', 'w', 'h', 'minW', 'minH', 'maxW', 'maxH'] as const;
|
||||
/** Felder je Umrechnungsstufe; `from` ist die Version, von der die Stufe ausgeht. */
|
||||
const MIGRATION_STEPS: ReadonlyArray<{ from: number; fields: readonly string[] }> = [
|
||||
// 1 -> 2 (quick-260916-bwo): Spalten UND Zeilen verdoppelt.
|
||||
{ from: 1, fields: ['x', 'y', 'w', 'h', 'minW', 'minH', 'maxW', 'maxH'] },
|
||||
// 2 -> 3 (quick-260929-dmx): nur die Breite verdoppelt.
|
||||
{ from: 2, fields: ['x', 'w', 'minW', 'maxW'] },
|
||||
];
|
||||
|
||||
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
@@ -62,7 +80,8 @@ export function migrateGridLayouts(raw: unknown): { layouts: GridLayouts; migrat
|
||||
const markerValue = raw[GRID_VERSION_KEY];
|
||||
// Nur eine Zahl ist ein Marker; alles andere (fehlend, Zeichenkette) zaehlt als alt.
|
||||
const version = typeof markerValue === 'number' ? markerValue : 1;
|
||||
const needsScaling = version < GRID_VERSION;
|
||||
const steps = MIGRATION_STEPS.filter((step) => version <= step.from);
|
||||
const needsScaling = steps.length > 0;
|
||||
|
||||
const layouts: GridLayouts = {};
|
||||
let migrated = false;
|
||||
@@ -75,10 +94,12 @@ export function migrateGridLayouts(raw: unknown): { layouts: GridLayouts; migrat
|
||||
layouts[key] = value.map((item) => {
|
||||
const copy = { ...(item as GridLayoutItem) };
|
||||
if (needsScaling) {
|
||||
for (const field of SCALED_FIELDS) {
|
||||
const n = copy[field];
|
||||
if (typeof n === 'number') {
|
||||
copy[field] = n * GRID_SCALE_FACTOR;
|
||||
for (const step of steps) {
|
||||
for (const field of step.fields) {
|
||||
const n = copy[field];
|
||||
if (typeof n === 'number') {
|
||||
copy[field] = n * GRID_SCALE_FACTOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
migrated = true;
|
||||
|
||||
Reference in New Issue
Block a user