Refactor dashboard widget management: Update dashboardService to handle user-specific widget configurations with create and update logic. Enhance LoggedInView to support adding the same widget type and display error messages for save operations. Ensure effective endpoint handling for widgets and improve UI interactions.
This commit is contained in:
@@ -45,10 +45,13 @@ class DashboardService extends BaseService {
|
||||
title: String(w?.title ?? ''),
|
||||
endpoint: String(w?.endpoint ?? '')
|
||||
})).filter(w => w.id && (w.title || w.endpoint));
|
||||
await UserDashboard.upsert({
|
||||
userId: user.id,
|
||||
config: { widgets: sanitized }
|
||||
}, { conflictFields: ['userId'] });
|
||||
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 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,33 +38,34 @@ async function fetchNewsPage({ counter, language = 'de', category = 'top', nextP
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert die Seite für das „counter.“-te Widget (0 = erste Seite, 1 = zweite, …).
|
||||
* Ruft die API ggf. mehrfach auf (nextPage), damit jede Widget-Instanz andere Artikel bekommt.
|
||||
* Liefert den N-ten Artikel (counter = 0, 1, 2, …) für das N-te News-Widget.
|
||||
* Lädt ggf. mehrere Seiten, bis genug Artikel vorhanden sind; jede Widget-Instanz bekommt einen anderen Artikel.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {number} options.counter
|
||||
* @param {number} options.counter - Index des Artikels (0 = erster, 1 = zweiter, …)
|
||||
* @param {string} [options.language]
|
||||
* @param {string} [options.category]
|
||||
* @returns {Promise<{ results: Array, nextPage: string|null }>}
|
||||
*/
|
||||
async function getNews({ counter = 0, language = 'de', category = 'top' }) {
|
||||
const neededIndex = Math.max(0, counter);
|
||||
const collected = [];
|
||||
let nextPageToken = null;
|
||||
let lastResult = { results: [], nextPage: null };
|
||||
|
||||
for (let i = 0; i <= counter; i++) {
|
||||
lastResult = await fetchNewsPage({
|
||||
counter: i,
|
||||
while (collected.length <= neededIndex) {
|
||||
const page = await fetchNewsPage({
|
||||
language,
|
||||
category,
|
||||
nextPageToken: nextPageToken || undefined
|
||||
});
|
||||
nextPageToken = lastResult.nextPage;
|
||||
if (!nextPageToken && i < counter) {
|
||||
break;
|
||||
}
|
||||
const items = page.results ?? [];
|
||||
collected.push(...items);
|
||||
nextPageToken = page.nextPage ?? null;
|
||||
if (items.length === 0 || !nextPageToken) break;
|
||||
}
|
||||
|
||||
return lastResult;
|
||||
const single = collected[neededIndex] ? [collected[neededIndex]] : [];
|
||||
return { results: single, nextPage: null };
|
||||
}
|
||||
|
||||
export default { getNews };
|
||||
|
||||
@@ -108,6 +108,23 @@ const syncDatabase = async () => {
|
||||
console.warn('⚠️ Konnte type.widget_type nicht anlegen:', e?.message || e);
|
||||
}
|
||||
|
||||
// Dashboard: Benutzer-Konfiguration (Widgets pro User)
|
||||
console.log("Ensuring user_dashboard table exists...");
|
||||
try {
|
||||
await sequelize.query(`
|
||||
CREATE TABLE IF NOT EXISTS community.user_dashboard (
|
||||
user_id INTEGER NOT NULL PRIMARY KEY,
|
||||
config JSONB NOT NULL DEFAULT '{"widgets":[]}'::jsonb,
|
||||
CONSTRAINT user_dashboard_user_fk
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES community."user"(id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
} catch (e) {
|
||||
console.warn('⚠️ Konnte community.user_dashboard nicht anlegen:', e?.message || e);
|
||||
}
|
||||
|
||||
// Vokabeltrainer: Tabellen sicherstellen (auch ohne manuell ausgeführte Migrations)
|
||||
// Hintergrund: In Produktion sind Schema-Updates deaktiviert, und Migrations werden nicht automatisch ausgeführt.
|
||||
// Damit API/Menu nicht mit "relation does not exist" (42P01) scheitert, legen wir die Tabellen idempotent an.
|
||||
|
||||
Reference in New Issue
Block a user