Refactor event handling in CalendarView: Simplify event update and creation logic by removing unnecessary response handling. Implement event reloading after save and delete operations to ensure a clean state. This enhancement improves the reliability of event management in the calendar.
This commit is contained in:
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
const NEWS_BASE = 'https://newsdata.io/api/1/news';
|
const NEWS_BASE = 'https://newsdata.io/api/1/news';
|
||||||
|
|
||||||
|
// Cache für News-Ergebnisse (pro Sprache/Kategorie)
|
||||||
|
const newsCache = new Map();
|
||||||
|
const CACHE_TTL = 5 * 60 * 1000; // 5 Minuten Cache
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {number} options.counter - 0 = erste Seite, 1 = zweite, … (für Pagination/nextPage)
|
* @param {number} options.counter - 0 = erste Seite, 1 = zweite, … (für Pagination/nextPage)
|
||||||
@@ -13,7 +17,7 @@ const NEWS_BASE = 'https://newsdata.io/api/1/news';
|
|||||||
* @param {string} [options.category] - z. B. top, technology
|
* @param {string} [options.category] - z. B. top, technology
|
||||||
* @returns {Promise<{ results: Array, nextPage: string|null }>}
|
* @returns {Promise<{ results: Array, nextPage: string|null }>}
|
||||||
*/
|
*/
|
||||||
async function fetchNewsPage({ counter, language = 'de', category = 'top', nextPageToken = null }) {
|
async function fetchNewsPage({ language = 'de', category = 'top', nextPageToken = null }) {
|
||||||
const apiKey = process.env.NEWSDATA_IO_API_KEY;
|
const apiKey = process.env.NEWSDATA_IO_API_KEY;
|
||||||
if (!apiKey || !apiKey.trim()) {
|
if (!apiKey || !apiKey.trim()) {
|
||||||
throw new Error('NEWSDATA_IO_API_KEY is not set in .env');
|
throw new Error('NEWSDATA_IO_API_KEY is not set in .env');
|
||||||
@@ -37,9 +41,64 @@ async function fetchNewsPage({ counter, language = 'de', category = 'top', nextP
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holt gecachte Artikel oder lädt sie von der API
|
||||||
|
*/
|
||||||
|
async function getCachedNews({ language = 'de', category = 'top', minArticles = 10 }) {
|
||||||
|
const cacheKey = `${language}:${category}`;
|
||||||
|
const cached = newsCache.get(cacheKey);
|
||||||
|
|
||||||
|
// Cache gültig?
|
||||||
|
if (cached && (Date.now() - cached.timestamp) < CACHE_TTL) {
|
||||||
|
// Wenn wir mehr Artikel brauchen, erweitern
|
||||||
|
if (cached.articles.length >= minArticles) {
|
||||||
|
return cached.articles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neue Daten laden
|
||||||
|
const collected = cached?.articles || [];
|
||||||
|
let nextPageToken = cached?.nextPage || null;
|
||||||
|
|
||||||
|
while (collected.length < minArticles) {
|
||||||
|
try {
|
||||||
|
const page = await fetchNewsPage({
|
||||||
|
language,
|
||||||
|
category,
|
||||||
|
nextPageToken: nextPageToken || undefined
|
||||||
|
});
|
||||||
|
const items = page.results ?? [];
|
||||||
|
|
||||||
|
// Duplikate vermeiden (nach title)
|
||||||
|
const existingTitles = new Set(collected.map(a => a.title));
|
||||||
|
for (const item of items) {
|
||||||
|
if (!existingTitles.has(item.title)) {
|
||||||
|
collected.push(item);
|
||||||
|
existingTitles.add(item.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextPageToken = page.nextPage ?? null;
|
||||||
|
if (items.length === 0 || !nextPageToken) break;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('News fetch error:', error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache aktualisieren
|
||||||
|
newsCache.set(cacheKey, {
|
||||||
|
articles: collected,
|
||||||
|
nextPage: nextPageToken,
|
||||||
|
timestamp: Date.now()
|
||||||
|
});
|
||||||
|
|
||||||
|
return collected;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Liefert den N-ten Artikel (counter = 0, 1, 2, …) für das N-te News-Widget.
|
* 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.
|
* Nutzt Cache, damit mehrere Widgets unterschiedliche Artikel bekommen.
|
||||||
*
|
*
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {number} options.counter - Index des Artikels (0 = erster, 1 = zweiter, …)
|
* @param {number} options.counter - Index des Artikels (0 = erster, 1 = zweiter, …)
|
||||||
@@ -49,22 +108,15 @@ async function fetchNewsPage({ counter, language = 'de', category = 'top', nextP
|
|||||||
*/
|
*/
|
||||||
async function getNews({ counter = 0, language = 'de', category = 'top' }) {
|
async function getNews({ counter = 0, language = 'de', category = 'top' }) {
|
||||||
const neededIndex = Math.max(0, counter);
|
const neededIndex = Math.max(0, counter);
|
||||||
const collected = [];
|
|
||||||
let nextPageToken = null;
|
|
||||||
|
|
||||||
while (collected.length <= neededIndex) {
|
// Mindestens so viele Artikel laden wie benötigt
|
||||||
const page = await fetchNewsPage({
|
const articles = await getCachedNews({
|
||||||
language,
|
language,
|
||||||
category,
|
category,
|
||||||
nextPageToken: nextPageToken || undefined
|
minArticles: neededIndex + 1
|
||||||
});
|
});
|
||||||
const items = page.results ?? [];
|
|
||||||
collected.push(...items);
|
|
||||||
nextPageToken = page.nextPage ?? null;
|
|
||||||
if (items.length === 0 || !nextPageToken) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const single = collected[neededIndex] ? [collected[neededIndex]] : [];
|
const single = articles[neededIndex] ? [articles[neededIndex]] : [];
|
||||||
return { results: single, nextPage: null };
|
return { results: single, nextPage: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user