import BaseService from './BaseService.js'; import UserDashboard from '../models/community/user_dashboard.js'; import WidgetType from '../models/type/widget_type.js'; import { DASHBOARD_WIDGET_TYPE_DEFAULTS } from '../utils/initializeWidgetTypes.js'; class DashboardService extends BaseService { /** * Liste aller möglichen (verfügbaren) Widget-Typen. * Merge: Code-Defaults (immer) + DB-Zeilen; fehlende Defaults erscheinen mit synthetischer id, * damit neue Widgets nach Deploy sofort unter „Widget hinzufügen“ sichtbar sind. * @returns {Promise>} */ async getAvailableWidgets() { const rows = await WidgetType.findAll({ order: [['orderId', 'ASC'], ['id', 'ASC']], attributes: ['id', 'label', 'endpoint', 'description', 'orderId'] }); const dbByEndpoint = new Map(rows.map((r) => [r.endpoint, r])); const defaultEndpoints = new Set(DASHBOARD_WIDGET_TYPE_DEFAULTS.map((d) => d.endpoint)); const sortedDefaults = [...DASHBOARD_WIDGET_TYPE_DEFAULTS].sort( (a, b) => (a.orderId || 0) - (b.orderId || 0) ); const ordered = []; for (const def of sortedDefaults) { const existing = dbByEndpoint.get(def.endpoint); if (existing) { ordered.push({ id: existing.id, label: existing.label, endpoint: existing.endpoint, description: existing.description ?? null, orderId: existing.orderId }); } else { ordered.push({ id: `ep:${def.endpoint}`, label: def.label, endpoint: def.endpoint, description: def.description ?? null, orderId: def.orderId ?? 0 }); } } for (const r of rows) { if (!defaultEndpoints.has(r.endpoint)) { ordered.push({ id: r.id, label: r.label, endpoint: r.endpoint, description: r.description ?? null, orderId: r.orderId }); } } return ordered; } /** * @param {string} hashedUserId * @returns {Promise<{ widgets: Array<{ id: string, title: string, endpoint: string }> }>} */ async getConfig(hashedUserId) { const user = await this.getUserByHashedId(hashedUserId); const row = await UserDashboard.findOne({ where: { userId: user.id } }); const config = row?.config ?? { widgets: [] }; if (!Array.isArray(config.widgets)) config.widgets = []; return config; } /** * @param {string} hashedUserId * @param {{ widgets: Array<{ id: string, title: string, endpoint: string }> }} config */ async setConfig(hashedUserId, config) { const user = await this.getUserByHashedId(hashedUserId); const widgets = Array.isArray(config?.widgets) ? config.widgets : []; const sanitized = widgets.map(w => ({ id: String(w?.id ?? ''), title: String(w?.title ?? ''), endpoint: String(w?.endpoint ?? '') })).filter(w => w.id && (w.title || w.endpoint)); const payload = { widgets: sanitized }; const existing = await UserDashboard.findOne({ where: { userId: user.id } }); if (existing) { await existing.update({ config: payload }); } else { await UserDashboard.create({ userId: user.id, config: payload }); } return { widgets: sanitized }; } } export default new DashboardService();