Replace masonry grid with an absolute-positioned 12-col canvas: drag to move, corner to resize, per-card free/overlap toggle (Alt = no-snap). Geometry persisted (migration 027: dashboard_layout.geom + extras). Two new addable decorative cards: blank spacer + animated blackflame (canvas particle flame). Old layout auto-migrates by flow-placement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
29 lines
1.0 KiB
JavaScript
29 lines
1.0 KiB
JavaScript
import { pool } from '../pool.js';
|
|
|
|
const DEFAULTS = { card_order: [], hidden: [], sizes: {}, geom: {}, extras: [] };
|
|
|
|
export async function get() {
|
|
const { rows } = await pool.query(
|
|
`SELECT card_order, hidden, sizes, geom, extras
|
|
FROM dashboard_layout WHERE owner_key = 'owner'`
|
|
);
|
|
return rows[0] || { ...DEFAULTS };
|
|
}
|
|
|
|
export async function put({ card_order = [], hidden = [], sizes = {}, geom = {}, extras = [] }) {
|
|
await pool.query(
|
|
`INSERT INTO dashboard_layout (owner_key, card_order, hidden, sizes, geom, extras, updated_at)
|
|
VALUES ('owner', $1::jsonb, $2::jsonb, $3::jsonb, $4::jsonb, $5::jsonb, now())
|
|
ON CONFLICT (owner_key) DO UPDATE
|
|
SET card_order = EXCLUDED.card_order,
|
|
hidden = EXCLUDED.hidden,
|
|
sizes = EXCLUDED.sizes,
|
|
geom = EXCLUDED.geom,
|
|
extras = EXCLUDED.extras,
|
|
updated_at = now()`,
|
|
[JSON.stringify(card_order), JSON.stringify(hidden), JSON.stringify(sizes),
|
|
JSON.stringify(geom), JSON.stringify(extras)]
|
|
);
|
|
return get();
|
|
}
|