Files
AtreidesAssetsFree/server/data/dashboard.js
T
2026-10-29 11:57:29 +01:00

125 lines
6.0 KiB
JavaScript

// Generated, do not edit. sha256:ebca807e87ebabedc0e0ca214ca3bec781ace05d2be4dc4ed8d664c767fe1d63
import * as db from '../db.js';
import { DASHBOARD } from '../../shared/config.js';
import { toSearchName } from '../../shared/search-name.js';
import { nowUtcIso } from '../../shared/time.js';
import { fail } from '../../shared/app-error.js';
export function listProfiles() {
return db.all(`SELECT * FROM DashboardProfile ORDER BY sortOrder, name`);
}
export function activeProfile() {
const rij = db.one(`SELECT * FROM DashboardProfile WHERE isActive = 1`);
if (!rij) throw new Error('No active dashboard profile: this data layer is supposed to prevent that.');
return rij;
}
function schrijfStandaardIndeling(profileId) {
for (const w of DASHBOARD.DEFAULT_LAYOUT) {
const def = DASHBOARD.WIDGETS[w.type];
if (!def) continue;
db.run(`INSERT INTO DashboardWidget (profileId, assetId, instanceKey, gridX, gridY, spanWidth, spanHeight, type, settings)
VALUES (?,NULL,?,?,0,?,NULL,?,NULL)`, [profileId, w.instId, w.x || 0, def.defaultSpan, w.type]);
}
}
export async function createProfile({ name, description = null }) {
const naam = String(name || '').trim();
if (!naam) fail('dashboard.nameRequired', null, 'A profile needs a name.');
const nu = nowUtcIso();
const volgend = db.one(`SELECT COALESCE(MAX(sortOrder), -1) + 1 AS n FROM DashboardProfile`).n;
db.run(`INSERT INTO DashboardProfile (name, searchName, description, sortOrder, isActive, isSystem, createdAt, updatedAt)
VALUES (?,?,?,?,0,0,?,?)`,
[naam, toSearchName(naam), description || null, volgend, nu, nu]);
const id = db.lastId();
schrijfStandaardIndeling(id);
await db.persist();
return id;
}
export async function renameProfile(id, { name, description = null }) {
const naam = String(name || '').trim();
if (!naam) fail('dashboard.nameRequired', null, 'A profile needs a name.');
const rij = db.one(`SELECT id FROM DashboardProfile WHERE id = ?`, [id]);
if (!rij) fail('dashboard.unknownProfile', { id }, `Dashboard profile #${id} does not exist.`);
db.run(`UPDATE DashboardProfile SET name = ?, searchName = ?, description = ?, updatedAt = ? WHERE id = ?`,
[naam, toSearchName(naam), description || null, nowUtcIso(), id]);
await db.persist();
}
export async function activateProfile(id) {
const rij = db.one(`SELECT id FROM DashboardProfile WHERE id = ?`, [id]);
if (!rij) fail('dashboard.unknownProfile', { id }, `Dashboard profile #${id} does not exist.`);
db.run(`UPDATE DashboardProfile SET isActive = 0, updatedAt = ? WHERE isActive = 1`, [nowUtcIso()]);
db.run(`UPDATE DashboardProfile SET isActive = 1, updatedAt = ? WHERE id = ?`, [nowUtcIso(), id]);
await db.persist();
}
export async function deleteProfile(id) {
const rij = db.one(`SELECT * FROM DashboardProfile WHERE id = ?`, [id]);
if (!rij) fail('dashboard.unknownProfile', { id }, `Dashboard profile #${id} does not exist.`);
if (rij.isSystem) {
await saveWidgets(id, null);
return;
}
if (rij.isActive) {
const opvolger = db.one(
`SELECT id FROM DashboardProfile WHERE id <> ? ORDER BY isSystem DESC, sortOrder, name LIMIT 1`, [id]);
if (!opvolger) fail('dashboard.lastNotDeletable', null, 'The last dashboard profile cannot be deleted.');
db.run(`UPDATE DashboardProfile SET isActive = 0, updatedAt = ? WHERE id = ?`, [nowUtcIso(), id]);
db.run(`UPDATE DashboardProfile SET isActive = 1, updatedAt = ? WHERE id = ?`, [nowUtcIso(), opvolger.id]);
}
db.run(`DELETE FROM DashboardProfile WHERE id = ?`, [id]);
await db.persist();
}
export function listWidgets(profileId) {
return db.all(`SELECT * FROM DashboardWidget WHERE profileId = ? ORDER BY gridY, gridX, instanceKey`, [profileId]);
}
function assertWidgetType(type) {
if (!DASHBOARD.WIDGETS[type]) {
throw new Error(`Unknown widget type '${type}'. Allowed: ${Object.keys(DASHBOARD.WIDGETS).join(', ')}.`);
}
}
export async function addWidget(profileId, { instanceKey, type, gridX = 0, gridY = 0, assetId = null, settings = null }) {
if (!db.one(`SELECT id FROM DashboardProfile WHERE id = ?`, [profileId])) {
fail('dashboard.unknownProfile', { id: profileId }, `Dashboard profile #${profileId} does not exist.`);
}
assertWidgetType(type);
const key = instanceKey || type;
if (db.one(`SELECT 1 AS x FROM DashboardWidget WHERE profileId = ? AND instanceKey = ?`, [profileId, key])) return false;
const json = settings && typeof settings === 'object' && Object.keys(settings).length ? JSON.stringify(settings) : null;
db.run(`INSERT INTO DashboardWidget (profileId, assetId, instanceKey, gridX, gridY, spanWidth, spanHeight, type, settings)
VALUES (?,?,?,?,?,?,NULL,?,?)`, [profileId, assetId, key, gridX, gridY, DASHBOARD.WIDGETS[type].defaultSpan, type, json]);
await db.persist();
return true;
}
export async function saveWidgets(profileId, widgets) {
const rij = db.one(`SELECT id FROM DashboardProfile WHERE id = ?`, [profileId]);
if (!rij) fail('dashboard.unknownProfile', { id: profileId }, `Dashboard profile #${profileId} does not exist.`);
if (widgets === null) {
db.run(`DELETE FROM DashboardWidget WHERE profileId = ?`, [profileId]);
schrijfStandaardIndeling(profileId);
await db.persist();
return;
}
const lijst = Array.isArray(widgets) ? widgets : [];
for (const w of lijst) assertWidgetType(w.type);
db.run(`DELETE FROM DashboardWidget WHERE profileId = ?`, [profileId]);
for (const w of lijst) {
const params = w.params && typeof w.params === 'object' ? { ...w.params } : {};
const assetId = params.assetId == null ? null : Number(params.assetId);
delete params.assetId;
const settings = Object.keys(params).length ? JSON.stringify(params) : null;
db.run(`INSERT INTO DashboardWidget (profileId, assetId, instanceKey, gridX, gridY, spanWidth, spanHeight, type, settings)
VALUES (?,?,?,?,?,?,?,?,?)`,
[profileId, assetId, w.instanceKey, w.gridX, w.gridY, w.spanWidth, w.spanHeight ?? null, w.type, settings]);
}
await db.persist();
}