feat: Implement layout persistence for card positions and rotation, loading from and saving to the database.

This commit is contained in:
2025-11-26 20:24:00 +01:00
parent 6157a4f571
commit 39e3ac2a87
4 changed files with 92 additions and 6 deletions
+80 -5
View File
@@ -1,4 +1,5 @@
import { constrainDimensions } from './utils/layoutUtils';
import { fetchLayoutRecords, upsertLayoutRecords } from './db';
export interface LayoutCardState {
id: string;
@@ -225,6 +226,10 @@ export class LayoutStore {
items = new Map<string, LayoutCard>();
zCounter = 100;
private savedLayouts = new Map<string, { x: number, y: number, rotation: number, z: number }>();
private tenantId: string | null = null;
private viewId: string | null = null;
initialize(id: string, ref: HTMLElement | null, config: {
width: number;
height: number;
@@ -238,10 +243,27 @@ export class LayoutStore {
);
if (!card) {
// Apply defaults if not provided
const x = Math.random() * 500;
const y = Math.random() * 500;
const rotation = Math.random() * 10 - 5;
// Check for saved layout
const saved = this.savedLayouts.get(id);
let x, y, rotation, z;
if (saved) {
x = saved.x;
y = saved.y;
rotation = saved.rotation;
z = saved.z;
// Ensure zCounter is higher than any loaded z
if (z >= this.zCounter) {
this.zCounter = z + 1;
}
} else {
// Apply defaults if not provided
x = Math.random() * 500;
y = Math.random() * 500;
rotation = Math.random() * 10 - 5;
z = this.zCounter++;
}
card = new LayoutCard(id, this, {
x,
@@ -249,7 +271,7 @@ export class LayoutStore {
rotation,
width,
height,
z: this.zCounter++
z
}, ref);
this.items.set(id, card);
} else {
@@ -319,4 +341,57 @@ export class LayoutStore {
getSnapshot() {
return Array.from(this.items.values()).map(card => card.toSnapshot());
}
async loadLayout(tenantId: string, viewId: string) {
this.tenantId = tenantId;
this.viewId = viewId;
const records = await fetchLayoutRecords({ tenantId, viewId });
this.savedLayouts.clear();
let maxZ = this.zCounter;
for (const record of records) {
if (record.documentId && record.centerX !== undefined && record.centerY !== undefined) {
this.savedLayouts.set(record.documentId, {
x: record.centerX,
y: record.centerY,
rotation: record.rotation || 0,
z: record.zIndex || 0
});
if (record.zIndex && record.zIndex >= maxZ) {
maxZ = record.zIndex + 1;
}
}
}
this.zCounter = maxZ;
// Apply to existing items if any (though usually this runs before items are created)
for (const [id, card] of this.items) {
const saved = this.savedLayouts.get(id);
if (saved) {
card.update(saved);
}
}
}
async saveLayout() {
if (!this.tenantId || !this.viewId) return;
const entries = Array.from(this.items.values()).map(card => ({
documentId: card.id,
centerX: card.x,
centerY: card.y,
rotation: card.rotation,
zIndex: card.z,
updatedAt: Date.now()
}));
await upsertLayoutRecords({
tenantId: this.tenantId,
viewId: this.viewId,
entries
});
}
}