feat(dashboard): auf jedem Bildschirm dasselbe Bild – Leinwand je Reiter, massstaeblich skaliert
Je Reiter wird die Flaeche des ersten Desktop-Bildschirms als __canvas im Layout-JSON gespeichert (ohne API/DB-Aenderung, GRID_VERSION bleibt 3). Das Raster rendert in Leinwandbreite und wird per transform: scale(min(bw/cw, bh/ch)) eingepasst, Schrift eingeschlossen, ohne Scrollen; unter 768 px wie bisher. Ziehen/Groesse aendern unter Skalierung ueber eine eigene Positionsstrategie (createScaledStrategy aus react-grid-layout 2.2.3 rechnet den Rasterversatz falsch). Im Browser nachgewiesen: 1920x1080 -> 1366x768 (Faktor 0,66), Ziehen +200 px folgt der Maus, 700 px ohne Skalierung. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
GRID_CANVAS_KEY,
|
||||
GRID_SCALE_FACTOR,
|
||||
GRID_VERSION,
|
||||
GRID_VERSION_KEY,
|
||||
@@ -192,10 +193,30 @@ describe('grid-layout-migration (quick-260916-bwo)', () => {
|
||||
expect(r.layouts.sm[0]).toEqual({ i: 'a', x: 4, y: 2, w: 4, h: 2 });
|
||||
expect(r.migrated).toBe(true);
|
||||
|
||||
expect(migrateGridLayouts(null)).toEqual({ layouts: {}, migrated: false, newer: false });
|
||||
expect(migrateGridLayouts(undefined)).toEqual({ layouts: {}, migrated: false, newer: false });
|
||||
expect(migrateGridLayouts(42)).toEqual({ layouts: {}, migrated: false, newer: false });
|
||||
expect(migrateGridLayouts([1, 2])).toEqual({ layouts: {}, migrated: false, newer: false });
|
||||
expect(migrateGridLayouts(null)).toEqual({
|
||||
layouts: {},
|
||||
migrated: false,
|
||||
newer: false,
|
||||
canvas: null,
|
||||
});
|
||||
expect(migrateGridLayouts(undefined)).toEqual({
|
||||
layouts: {},
|
||||
migrated: false,
|
||||
newer: false,
|
||||
canvas: null,
|
||||
});
|
||||
expect(migrateGridLayouts(42)).toEqual({
|
||||
layouts: {},
|
||||
migrated: false,
|
||||
newer: false,
|
||||
canvas: null,
|
||||
});
|
||||
expect(migrateGridLayouts([1, 2])).toEqual({
|
||||
layouts: {},
|
||||
migrated: false,
|
||||
newer: false,
|
||||
canvas: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('Test 8 (quick-260930): nur eine HOEHERE Marke meldet newer — v1/v2/v3 nicht', () => {
|
||||
@@ -209,3 +230,58 @@ describe('grid-layout-migration (quick-260916-bwo)', () => {
|
||||
expect(future.layouts).toEqual(alt);
|
||||
});
|
||||
});
|
||||
|
||||
describe('grid-layout-migration: Leinwand `__canvas` (Dashboard wie ein Bild mitskalieren)', () => {
|
||||
const v3 = () => ({ lg: [{ i: 'a', x: 0, y: 0, w: 8, h: 4 }], [GRID_VERSION_KEY]: GRID_VERSION });
|
||||
|
||||
it('liest eine gueltige Leinwand und laesst sie aus `layouts` heraus', () => {
|
||||
const r = migrateGridLayouts({ ...v3(), [GRID_CANVAS_KEY]: { w: 1600, h: 820 } });
|
||||
expect(r.canvas).toEqual({ w: 1600, h: 820 });
|
||||
expect(Object.keys(r.layouts)).toEqual(['lg']);
|
||||
expect(r.migrated).toBe(false);
|
||||
});
|
||||
|
||||
it('fehlende oder ungueltige Werte -> null', () => {
|
||||
const bad: unknown[] = [
|
||||
undefined,
|
||||
null,
|
||||
'x',
|
||||
[1600, 800],
|
||||
{ w: 1600 },
|
||||
{ w: '1600', h: 800 },
|
||||
{ w: Number.NaN, h: 800 },
|
||||
{ w: Number.POSITIVE_INFINITY, h: 800 },
|
||||
{ w: 767, h: 800 },
|
||||
{ w: 1600, h: 199 },
|
||||
];
|
||||
for (const value of bad) {
|
||||
expect(migrateGridLayouts({ ...v3(), [GRID_CANVAS_KEY]: value }).canvas).toBeNull();
|
||||
}
|
||||
// Grenzwerte sind gueltig.
|
||||
expect(migrateGridLayouts({ ...v3(), [GRID_CANVAS_KEY]: { w: 768, h: 200 } }).canvas).toEqual({
|
||||
w: 768,
|
||||
h: 200,
|
||||
});
|
||||
});
|
||||
|
||||
it('withGridVersion schreibt die Leinwand nur, wenn eine da ist', () => {
|
||||
const { layouts } = migrateGridLayouts(v3());
|
||||
expect(withGridVersion(layouts)).not.toHaveProperty(GRID_CANVAS_KEY);
|
||||
expect(withGridVersion(layouts, null)).not.toHaveProperty(GRID_CANVAS_KEY);
|
||||
expect(withGridVersion(layouts, { w: 1920, h: 950 })).toEqual({
|
||||
...layouts,
|
||||
[GRID_VERSION_KEY]: GRID_VERSION,
|
||||
[GRID_CANVAS_KEY]: { w: 1920, h: 950 },
|
||||
});
|
||||
});
|
||||
|
||||
it('Idempotenz mit Leinwand: Laden -> Speichern -> Laden liefert dasselbe, nichts skaliert', () => {
|
||||
const once = migrateGridLayouts({ ...altLayouts(), [GRID_CANVAS_KEY]: { w: 1400, h: 700 } });
|
||||
expect(once.migrated).toBe(true);
|
||||
expect(once.canvas).toEqual({ w: 1400, h: 700 });
|
||||
const twice = migrateGridLayouts(withGridVersion(once.layouts, once.canvas));
|
||||
expect(twice.migrated).toBe(false);
|
||||
expect(twice.layouts).toEqual(once.layouts);
|
||||
expect(twice.canvas).toEqual(once.canvas);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user