From 5a154f896b5216b1782ade9ec21deefd3ea8c63c Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Fri, 1 May 2026 03:13:29 +0200 Subject: [PATCH] aasdsd --- modules/fx-rates/assets/fx-rates.css | 23 ++++++ modules/fx-rates/assets/fx-rates.js | 102 ++++++++++----------------- modules/fx-rates/pages/index.php | 57 ++------------- 3 files changed, 63 insertions(+), 119 deletions(-) diff --git a/modules/fx-rates/assets/fx-rates.css b/modules/fx-rates/assets/fx-rates.css index c16282a..60e8e0d 100644 --- a/modules/fx-rates/assets/fx-rates.css +++ b/modules/fx-rates/assets/fx-rates.css @@ -138,3 +138,26 @@ font-size: 0.95rem; text-align: right; } + +.fx-history-date { + display: inline-flex; + align-items: center; + gap: 0.45rem; +} + +.fx-info-button { + width: 1.4rem; + height: 1.4rem; + border: 1px solid #d0d7e2; + border-radius: 999px; + background: #fff; + color: #5b6573; + font-size: 0.78rem; + font-weight: 700; + line-height: 1; + cursor: help; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0; +} diff --git a/modules/fx-rates/assets/fx-rates.js b/modules/fx-rates/assets/fx-rates.js index 5cae1c0..5137cb7 100644 --- a/modules/fx-rates/assets/fx-rates.js +++ b/modules/fx-rates/assets/fx-rates.js @@ -7,10 +7,8 @@ const page = JSON.parse(root.dataset.page || '{}'); const settings = page.settings || {}; const nodes = { - ratesBody: root.querySelector('[data-bind="rates-body"]'), historyHead: root.querySelector('[data-bind="history-head"]'), historyBody: root.querySelector('[data-bind="history-body"]'), - fetchesBody: root.querySelector('[data-bind="fetches-body"]'), convertResult: root.querySelector('[data-bind="convert-result"]'), convertFrom: root.querySelector('select[name="convert_from"]'), convertTo: root.querySelector('select[name="convert_to"]'), @@ -99,51 +97,12 @@ }); }; - const renderSnapshot = (snapshot) => { - const rates = snapshot && snapshot.rates ? snapshot.rates : null; - const entries = rates ? Object.entries(rates) : []; - const visibleCurrencies = preferredCurrencies.length - ? new Set(preferredCurrencies) - : null; - if (!nodes.ratesBody) { - return; - } - - const filteredEntries = visibleCurrencies - ? entries.filter(([code]) => visibleCurrencies.has(String(code || '').trim().toUpperCase())) - : entries; - - if (!filteredEntries.length) { - nodes.ratesBody.innerHTML = 'Noch keine Wechselkurse fuer die ausgewaehlten Waehrungen gespeichert.'; - return; - } - - nodes.ratesBody.innerHTML = filteredEntries.map(([code, rate]) => { - const formatted = typeof rate === 'number' - ? rate.toLocaleString('de-DE', { maximumFractionDigits: 8 }) - : 'n/a'; - return `${code}${formatted}`; - }).join(''); - }; - - const renderFetches = (fetches) => { - if (!nodes.fetchesBody) { - return; - } - const entries = Array.isArray(fetches) ? fetches : []; - if (!entries.length) { - nodes.fetchesBody.innerHTML = 'Noch keine Abrufe vorhanden.'; - return; - } - nodes.fetchesBody.innerHTML = entries.map((entry) => ` - - ${entry?.fetched_at_display || entry?.fetched_at || ''} - ${entry?.base_currency || ''} - ${entry?.provider || ''} - ${entry?.trigger_source_label || entry?.trigger_source || ''} - - `).join(''); - }; + const escapeHtml = (value) => String(value || '') + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", '''); const renderHistory = (rows, currencies) => { if (!nodes.historyHead || !nodes.historyBody) { @@ -172,7 +131,19 @@ nodes.historyBody.innerHTML = entries.map((entry) => ` - ${entry.label} + +
+ ${entry.label} + ${entry.fetch ? ` + + ` : ''} +
+ ${series.map((currency) => { const value = entry.rates?.[currency]; if (typeof value !== 'number' || !Number.isFinite(value)) { @@ -201,21 +172,6 @@ return payload.data; }; - const loadLatest = async () => { - const base = String( - settings.display_base_currency || settings.default_base_currency || 'EUR' - ).trim().toUpperCase(); - const query = new URLSearchParams(); - query.set('base', base); - if (preferredCurrencies.length) { - query.set('symbols', preferredCurrencies.join(',')); - } - - const data = await request(`/latest?${query.toString()}`); - renderSnapshot(data); - return data; - }; - const loadHistory = async () => { const base = String( settings.display_base_currency || settings.default_base_currency || 'EUR' @@ -236,7 +192,21 @@ return { currency, rows: Array.isArray(rows) ? rows : [] }; })); + const recentFetches = Array.isArray(page.recent_fetches) ? page.recent_fetches : []; const byDate = new Map(); + recentFetches.forEach((fetch) => { + const key = String(fetch?.fetched_at || '').trim(); + if (!key || byDate.has(key)) { + return; + } + byDate.set(key, { + sortKey: key, + label: fetch?.fetched_at_display || fetch?.fetched_at || key, + fetch, + rates: base !== '' ? { [base]: 1 } : {}, + }); + }); + histories.forEach(({ currency, rows }) => { rows.forEach((row) => { const key = String(row?.fetched_at || row?.rate_date || '').trim(); @@ -247,6 +217,7 @@ byDate.set(key, { sortKey: key, label: row?.fetched_at_display || row?.fetched_at || row?.rate_date || key, + fetch: recentFetches.find((fetch) => String(fetch?.fetched_at || '').trim() === key) || null, rates: base !== '' ? { [base]: 1 } : {}, }); } @@ -258,7 +229,8 @@ }); const mergedRows = Array.from(byDate.values()) - .sort((left, right) => String(left.sortKey).localeCompare(String(right.sortKey))); + .sort((left, right) => String(right.sortKey).localeCompare(String(left.sortKey))) + .slice(0, 15); renderHistory(mergedRows, selectedCurrencies); }; @@ -305,10 +277,8 @@ }); }); - renderFetches(page.recent_fetches || []); bindManualRefreshAction(); - loadLatest().catch(() => {}); loadHistory().catch(() => { renderHistory([], preferredCurrencies); }); diff --git a/modules/fx-rates/pages/index.php b/modules/fx-rates/pages/index.php index 601aaa7..04a87e5 100644 --- a/modules/fx-rates/pages/index.php +++ b/modules/fx-rates/pages/index.php @@ -51,7 +51,7 @@ if ((string) ($_GET['refresh'] ?? '') === '1') { } $latest = $service->latestStatus(); -$recentFetches = $service->recentFetches(12); +$recentFetches = $service->recentFetches(15); $pageData = json_encode([ 'settings' => $settings, 'latest' => $latest, @@ -110,33 +110,14 @@ $pageData = json_encode([
-

Letzte Kurse

-

Letzter gespeicherter Snapshot, umgerechnet auf .

+

Kursverlauf

+

Neueste Abrufe zuerst. Verlauf der bevorzugten Waehrungen relativ zur Anzeige-Basiswaehrung.

-
Letzter Abruf:
Anzeige-Basis:
-
Snapshot-Basis:
+
Letzter Abruf:
-
- - - - - - - - - - -
WaehrungKurs
Noch keine Daten geladen.
-
-
- -
-

Kursverlauf

-

Chronologischer Verlauf der bevorzugten Waehrungen relativ zur Anzeige-Basiswaehrung.

@@ -151,36 +132,6 @@ $pageData = json_encode([
- -
-

Letzte Abrufe

-
- - - - - - - - - - - - - - - - - - - - - - - -
DatumBasisProviderAusloeser
Noch keine Abrufe vorhanden.
-
-