diff --git a/Umsetzung Neue UI/01_ZIELBILD_DESKTOP_UI.md b/Umsetzung Neue UI/01_ZIELBILD_DESKTOP_UI.md new file mode 100644 index 0000000..dd5dd32 --- /dev/null +++ b/Umsetzung Neue UI/01_ZIELBILD_DESKTOP_UI.md @@ -0,0 +1,70 @@ +# Zielbild Desktop UI + +## Produktidee + +Die neue Oberfläche soll sich wie ein Desktop-System verhalten, nicht wie eine klassische Admin-Webseite. + +Die Oberfläche besteht aus: + +- Desktop-Fläche +- frei platzierbaren App-Icons +- Fenster-Manager +- Statusleiste oder Dock +- Startmenü oder Hauptmenü +- Mini-Widget-Bereich +- Skin-System + +## Bedienmodell + +- Root `/` ist immer die Desktop-Oberfläche +- Apps werden als Fenster geöffnet +- Widgets können auf dem Desktop oder in einer Leiste erscheinen +- persönliche Startseite ist immer das persönliche Desktop-Dashboard +- für nicht eingeloggte Nutzer kann ein öffentliches Desktop-Home angezeigt werden + +## Skins + +Es gibt zunächst drei Skins: + +- `Windows` +- `Apple` +- `Linux` + +Wichtig: + +- Das sind Skins, keine drei getrennten Implementierungen +- Verhalten und Optik sollen sich an echten Desktop-Systemen orientieren +- die technische Basis bleibt aber eine gemeinsame `Desktop Shell` + +## Kernbausteine + +- `Desktop Shell` +- `Window Manager` +- `Dock oder Taskbar` +- `System Tray` +- `Widget Zones` +- `App Registry` +- `Theme and Skin Engine` +- `Desktop Settings` + +## Öffentliche und persönliche Nutzung + +- Admin kann ein globales öffentliches Desktop-Home-Dashboard anlegen +- eingeloggte Nutzer sehen ihren persönlichen Desktop +- Nutzer können mehrere persönliche Dashboards oder Workspaces haben + +## Inhalte + +Der Desktop soll langfristig enthalten können: + +- klassische Nexus-Module +- Links +- eingebettete Webseiten +- Apps +- globale Widgets +- persönliche Linklisten +- spätere Integrationsdaten per API + +## Technische Leitidee + +Nicht das alte Nexus-Layout erweitern, sondern eine neue Frontend- und UX-Schicht bauen, die bestehende Kernlogik später konsumiert. diff --git a/Umsetzung Neue UI/02_ORDNERSTRUKTUR_UND_GRUNDREGELN.md b/Umsetzung Neue UI/02_ORDNERSTRUKTUR_UND_GRUNDREGELN.md new file mode 100644 index 0000000..28ee79f --- /dev/null +++ b/Umsetzung Neue UI/02_ORDNERSTRUKTUR_UND_GRUNDREGELN.md @@ -0,0 +1,87 @@ +# Ordnerstruktur und Grundregeln + +## Grundsatz + +Die Ordnerstruktur soll sich so nah wie sinnvoll an der bestehenden Nexus-Struktur orientieren. + +## Beibehaltene Strukturidee + +- `/public/` -> Web Root, globale Assets und Einstieg +- `/api/` -> Backend- und API-Endpunkte +- `/src/` -> Kernlogik, Services, Utilities +- `/config/` -> Umgebungs-Configs +- `/modules//` -> klassische Module +- `/partials/structure/` -> globale Layout-Bausteine +- `/partials/landingpages/` -> Seiten oder Views +- `/tools/` -> Worker, CLI, Hilfstools +- `/debug/` -> Debug-Ausgaben + +## Neue zusätzliche Bereiche für die Desktop-UI + +Empfohlene Ergänzungen: + +- `/src/Desktop/` + - Window Manager + - Desktop Registry + - Skin Resolver + - Widget Layout Engine +- `/public/assets/desktop/` + - globale Desktop-CSS + - JavaScript für Fenster, Dock, Tray, Desktop-Interaktion +- `/partials/desktop/` + - Desktop Shell + - Window Templates + - Dock + - Tray + - Menu + +Optional für die Übergangsphase: + +- `/Old-Nexus/` + - komplette Altbasis zur Sichtprüfung und als Entwicklungserinnerung + - nur temporär + +## Wichtige Regel + +Die klassische Modulstruktur bleibt erhalten. + +Das bedeutet: + +- Module bleiben unter `/modules//` +- der neue Desktop-Layer ist nur die neue Oberfläche +- Module dürfen nicht ungeordnet in den Desktop-Core verschoben werden +- gemeinsame Desktop-Mechaniken liegen nicht in Modulen, sondern im globalen Kern + +## Trennung + +Es gibt drei Ebenen: + +1. globales System +2. Desktop-UI-Schicht +3. klassische Module + +## Was nicht passieren soll + +- keine Vermischung von Fenster-Manager-Code mit Modulbusinesslogik +- keine Skin-spezifischen Sonderlösungen in einzelnen Modulen +- keine harte Kopplung zwischen alter Seitenstruktur und neuem Desktop-Verhalten +- keine technische Abhängigkeit zu `Old-Nexus/` +- keine Includes, Imports, Autoloading-Pfade oder Assets aus `Old-Nexus/` + +## Architekturregel + +Die neue Oberfläche muss so gebaut sein, dass: + +- Module später als Fenster gerendert werden können +- Apps, Widgets und Seitenmodule aus einer gemeinsamen Registry kommen +- Skins ausschließlich Layout, Stil und Interaktionsdetails definieren + +## Sonderregel für `Old-Nexus/` + +Wenn `Old-Nexus/` im neuen Projekt vorhanden ist, dann gilt verbindlich: + +- nur lesen und vergleichen +- niemals direkt einbinden +- niemals als Referenzpfad im Produktivcode verwenden +- niemals als Dauerbestandteil der neuen Architektur einplanen +- nach Abschluss der Umsetzung wieder entfernen diff --git a/Umsetzung Neue UI/03_MIGRATION_BESTEHENDE_MODULE.md b/Umsetzung Neue UI/03_MIGRATION_BESTEHENDE_MODULE.md new file mode 100644 index 0000000..033cc79 --- /dev/null +++ b/Umsetzung Neue UI/03_MIGRATION_BESTEHENDE_MODULE.md @@ -0,0 +1,81 @@ +# Migration bestehende Module + +## Ziel + +Die bestehenden Module aus dem alten Nexus sollen als Basis in `desktop.kusche.berlin` verfügbar sein, damit sie dort später in die neue Oberfläche überführt werden können. + +## Wichtige Regel + +Die Übernahme erfolgt zweistufig: + +1. Rohkopie als Referenzbasis +2. anschließende separate Anpassung im neuen Projekt + +## Empfohlener Zielordner im neuen Projekt + +- `temp/nexus-module-import/` + +## Was kopiert werden soll + +Mindestens: + +- `/modules/` +- relevante globale Dokumentationsdateien +- gegebenenfalls Referenzdateien aus `/src/`, wenn Modul-Helfer benötigt werden + +Zusätzlich möglich: + +- kompletter Altstand unter `Old-Nexus/` + +## Was zunächst nicht aktiv umgebaut werden soll + +- keine direkten Eingriffe in das alte Nexus-Projekt +- keine halb fertige Mischform aus alter UI und neuer Desktop-UI +- keine automatische Massenmigration ohne Sichtprüfung pro Modul +- keine technische Nutzung von `Old-Nexus/` im neuen Produktivcode + +## Ziel nach dem Kopieren + +Im neuen Projekt gibt es: + +- die neue Desktop-Shell +- die importierten Module als Rohbasis +- optional `Old-Nexus/` als reine Sicht- und Erinnerungsbasis +- eine schrittweise Anbindung pro Modul an das neue Fenstersystem + +## Empfohlener Migrationsablauf je Modul + +1. Modul aus Import-Basis prüfen +2. benötigte Assets und Seiten identifizieren +3. Modul in neue App-Registry eintragen +4. Modul als Desktop-App definieren +5. Modulansichten in Fensterlogik integrieren +6. Skin-Verhalten testen + +## Wichtig für spätere Umsetzung + +Module werden nicht einfach als alte Seite verlinkt, sondern: + +- als App registriert +- im Desktop geöffnet +- mit Fenstertitel, Icon, Startverhalten und optionalen Widget-Anknüpfungen beschrieben + +Wenn `Old-Nexus/` vorhanden ist: + +- nur zum Nachschlagen alter Lösungswege verwenden +- keine Pfadabhängigkeit darauf erzeugen +- nichts daraus zur Laufzeit laden +- nichts daraus direkt includen oder importieren + +## Mögliche App-Metadaten je Modul + +- `app_id` +- `title` +- `icon` +- `entry_route` +- `window_mode` +- `default_width` +- `default_height` +- `supports_widget` +- `supports_tray` +- `module_name` diff --git a/Umsetzung Neue UI/04_UMSETZUNGSPLAN_V1.md b/Umsetzung Neue UI/04_UMSETZUNGSPLAN_V1.md new file mode 100644 index 0000000..83ff85f --- /dev/null +++ b/Umsetzung Neue UI/04_UMSETZUNGSPLAN_V1.md @@ -0,0 +1,75 @@ +# Umsetzungsplan V1 + +## Phase 1: Fundament + +- neues Projekt technisch vorbereiten +- bestehende Ordnerstruktur anlegen +- Desktop Shell als Root-Oberfläche bauen +- Skin-System mit `Windows`, `Apple`, `Linux` vorbereiten +- Keycloak-Anbindung einhängen + +## Phase 2: Desktop-Grundfunktionen + +- Desktop-Hintergrund +- App-Icons +- frei verschiebbare Icons +- Dock oder Taskbar +- Statusbereich +- Uhr +- erstes Hauptmenü + +## Phase 3: Fenster-Manager + +- Fenster öffnen und schließen +- Fenster fokussieren +- Fenster minimieren +- Fenster maximieren +- z-index-Verwaltung +- Position und Größe merken + +## Phase 4: Inhaltssystem + +- App Registry +- Widget Registry +- Seitenmodule +- persönliche Linklisten +- öffentliches Home-Dashboard +- persönliche Workspaces + +## Phase 5: Admin-Bereiche + +- globale Einstellungen +- Widget-Verwaltung +- Integrationen +- Suchmaschinen +- Apps +- öffentliches Home-Dashboard + +## Phase 6: Modul-Anbindung + +- importierte Nexus-Module sichten +- erste Module als Apps in der Desktop-Shell öffnen +- Fenstertauglichkeit je Modul prüfen +- langfristig modulweise an neues UX-Modell anpassen + +## V1-Minimalziel + +V1 ist erreicht, wenn: + +- Root die Desktop-Oberfläche ist +- Login vorhanden ist +- Desktop-Skins umschaltbar sind +- Apps als Fenster geöffnet werden können +- Admin globale Apps, Widgets, Integrationen und Suchmaschinen verwalten kann +- mindestens ein persönlicher Desktop pro Nutzer funktioniert +- ein öffentliches Home-Dashboard existiert + +## Spätere Ausbaustufen + +- echte API-Datenquellen für Widgets +- Benachrichtigungen +- Kontextmenüs +- Multi-Workspace +- Drag-and-drop Widget-Layout +- Desktop-Shortcuts +- Datei- oder Objektverwaltung diff --git a/Umsetzung Neue UI/05_KEYCLOAK_LOGIN_UND_DESKTOP_LOGIN.md b/Umsetzung Neue UI/05_KEYCLOAK_LOGIN_UND_DESKTOP_LOGIN.md new file mode 100644 index 0000000..11f9268 --- /dev/null +++ b/Umsetzung Neue UI/05_KEYCLOAK_LOGIN_UND_DESKTOP_LOGIN.md @@ -0,0 +1,48 @@ +# Keycloak Login und Desktop Login + +## Ziel + +Nexus beziehungsweise `desktop.kusche.berlin` soll einen eigenen Login-Screen erhalten, der optisch wie ein Desktop-Login wirkt. + +## Technische Grundlage + +Keycloak bleibt weiterhin das Auth-System. + +Für `desktop.kusche.berlin` soll aber ein eigenes Keycloak-Theme verwendet werden. + +## Wichtige Leitlinie + +- technisch bleibt der Login ein Keycloak-Login +- optisch wird er als eigenständiger Desktop-Login gebrandet +- das Theme soll nur für diese Anwendung gelten + +## Zieloptik + +Der Login darf sich an Desktop-Systemen orientieren: + +- Hintergrundbild oder Wallpaper +- zentrierte Login-Kachel +- Benutzerwahl oder Benutzeranzeige +- große Uhr oder Statusanzeige +- Desktop-artige Übergänge + +## Was im neuen Projekt vorbereitet werden soll + +- Branding-Farben +- Logos +- Desktop-Login-Konzept +- Übergabepunkte für Keycloak-Theme +- Beschreibung der gewünschten UX + +## Was später am Keycloak-System zu tun ist + +- eigenes Login-Theme anlegen +- Theme dem Nexus-Client oder Realm zuordnen +- Templates, CSS und Assets anpassen +- Desktop-Login visuell mit der Shell abstimmen + +## Wichtig + +Das Login-Theme gehört technisch nicht in die normale Desktop-Shell, sondern in das Keycloak-Theme-System. + +Trotzdem soll es gestalterisch so wirken, als gehöre es direkt zu `desktop.kusche.berlin`. diff --git a/Umsetzung Neue UI/06_STARTPROMPT_NEUE_SESSION.md b/Umsetzung Neue UI/06_STARTPROMPT_NEUE_SESSION.md new file mode 100644 index 0000000..ee0eb96 --- /dev/null +++ b/Umsetzung Neue UI/06_STARTPROMPT_NEUE_SESSION.md @@ -0,0 +1,44 @@ +# Startprompt für neue Session + +Nutze den folgenden Prompt in der neuen Session im Projekt `desktop.kusche.berlin`. + +```text +Bitte arbeite ausschließlich im neuen Projekt `desktop.kusche.berlin`. + +Wichtige Einstiegsdatei: +- `START_HIER.md` + +Lies danach in dieser Reihenfolge: +- `01_ZIELBILD_DESKTOP_UI.md` +- `02_ORDNERSTRUKTUR_UND_GRUNDREGELN.md` +- `03_MIGRATION_BESTEHENDE_MODULE.md` +- `04_UMSETZUNGSPLAN_V1.md` +- `05_KEYCLOAK_LOGIN_UND_DESKTOP_LOGIN.md` + +Rahmenbedingungen: +- Die bestehende Ordnerstruktur soll sich an Nexus orientieren. +- Die neuen Dateien im Projekt beschreiben das Zielbild verbindlich. +- Die Umsetzung erfolgt ausschließlich im neuen Projekt. +- Die bestehenden Nexus-Module sollen als Basis aus einer Import-Struktur verfügbar gemacht werden. +- Falls ein Ordner `Old-Nexus/` vorhanden ist, dient er ausschließlich als menschliche Referenz und Erinnerung an das alte System. +- `Old-Nexus/` darf niemals technisch eingebunden, importiert, included oder als Asset-/Code-Referenz verwendet werden. +- Die eigentliche Anpassung der Module erfolgt danach separat im neuen Projekt. +- Die neue Oberfläche ist eine Desktop-Shell, keine klassische Website. +- Root `/` soll die Desktop-Oberfläche sein. +- Skins sollen als `Windows`, `Apple`, `Linux` angelegt werden, technisch aber auf einer gemeinsamen Shell beruhen. +- Spätere Modul-Anbindung muss vorbereitet werden, aber die Shell ist zuerst zu bauen. + +Erste Aufgabe: +1. Projektstruktur im neuen Projekt prüfen. +2. Falls nötig die Zielstruktur anlegen. +3. Eine V1-Desktop-Shell scaffolden. +4. Skin-System vorbereiten. +5. Fenster-Manager, Dock oder Taskbar und Desktop-Icons als Kern aufsetzen. +6. Danach die Import-Basis der alten Module in `temp/nexus-module-import/` vorbereiten. + +Wichtig: +- keine Arbeiten mehr im alten Nexus durchführen +- keine Modulmigration im Blindflug +- keine Vermischung von alter Website-Navigation und neuer Desktop-Interaktion +- `Old-Nexus/` nur lesen, nie technisch verwenden +``` diff --git a/Umsetzung Neue UI/START_HIER.md b/Umsetzung Neue UI/START_HIER.md new file mode 100644 index 0000000..a60afcc --- /dev/null +++ b/Umsetzung Neue UI/START_HIER.md @@ -0,0 +1,62 @@ +# Start Hier + +Diese Datei ist der Einstieg für die Umsetzung der neuen Desktop-Oberfläche in `desktop.kusche.berlin`. + +## Ziel + +Nexus soll als neue Oberfläche nicht mehr wie eine klassische Website aufgebaut sein, sondern wie ein Desktop-System: + +- Desktop-Shell als Hauptoberfläche +- Fenster für Apps und Widgets +- Skin-System für `Windows`, `Apple`, `Linux` +- persönliche Dashboards +- öffentliches Home-Dashboard für nicht eingeloggte Nutzer +- globale Verwaltung für Widgets, Integrationen, Suchmaschinen und Apps + +Die bestehenden klassischen Module aus Nexus sollen später in diese neue Oberfläche überführt werden, aber die Umsetzung erfolgt ausschließlich im neuen Projekt. + +## Reihenfolge der Dokumente + +Bitte diese Dateien in genau dieser Reihenfolge lesen: + +1. `START_HIER.md` +2. `01_ZIELBILD_DESKTOP_UI.md` +3. `02_ORDNERSTRUKTUR_UND_GRUNDREGELN.md` +4. `03_MIGRATION_BESTEHENDE_MODULE.md` +5. `04_UMSETZUNGSPLAN_V1.md` +6. `05_KEYCLOAK_LOGIN_UND_DESKTOP_LOGIN.md` +7. `06_STARTPROMPT_NEUE_SESSION.md` + +## Wichtig + +- Die bestehende Ordnerlogik aus Nexus soll grundsätzlich beibehalten werden. +- Die Umsetzung erfolgt **nicht** mehr im alten Nexus-Projekt. +- Die bestehenden Module aus Nexus dienen als Basis und Referenz, sollen aber in `desktop.kusche.berlin` separat weiterentwickelt werden. +- Der neue UI-Layer ist eine neue Anwendungsschicht, kein Theme-Umbau des alten Systems. + +## Erwartetes Vorgehen im neuen Projekt + +- zuerst Architektur und Shell anlegen +- dann Desktop-Grundsystem bauen +- dann globale Verwaltungsseiten +- dann klassische Module schrittweise in die neue Shell einhängen + +## Basisübernahme aus Nexus + +Im neuen Projekt sollte ein temporärer Import-Ordner angelegt werden, zum Beispiel: + +- `temp/nexus-module-import/` + +Dorthin werden die bestehenden Module aus Nexus zunächst nur kopiert, damit die Basis verfügbar ist. Die eigentliche Anpassung erfolgt danach separat im neuen Projekt. + +## Old-Nexus + +Zusätzlich kann im neuen Projekt ein Ordner `Old-Nexus/` liegen, in dem das alte System vollständig enthalten ist. + +Wichtige Regel: + +- `Old-Nexus/` dient ausschließlich als menschliche Referenz und Erinnerung an die alte Entwicklung +- dort dürfen Beispiele, frühere Funktionen, Strukturen oder Hilfslogik nachgesehen werden +- `Old-Nexus/` darf aber niemals als technische Laufzeit- oder Build-Abhängigkeit verwendet werden +- es dürfen keine Includes, keine Imports, keine Asset-Referenzen, keine Pfadverweise und keine direkte Code-Nutzung auf `Old-Nexus/` zeigen +- der Ordner ist nur temporär und wird nach der Umsetzung wieder gelöscht diff --git a/modules/mining-checker/assets/js/app.js b/modules/mining-checker/assets/js/app.js index 1478240..0b8553d 100644 --- a/modules/mining-checker/assets/js/app.js +++ b/modules/mining-checker/assets/js/app.js @@ -259,8 +259,8 @@ const requestOptions = options && typeof options === 'object' ? { ...options } : {}; const debugEnabled = !!debugBus.enabled; const timeoutMs = typeof requestOptions.timeoutMs === 'number' - ? (debugEnabled ? Math.max(requestOptions.timeoutMs, 20000) : requestOptions.timeoutMs) - : (debugEnabled ? 20000 : 8000); + ? (debugEnabled ? Math.max(requestOptions.timeoutMs, 30000) : requestOptions.timeoutMs) + : (debugEnabled ? 30000 : 20000); delete requestOptions.timeoutMs; const controller = new AbortController(); @@ -1203,7 +1203,8 @@ } } - async function loadBootstrap(key) { + async function loadBootstrap(key, options) { + const suppressError = !!(options && options.suppressError); const cacheKey = `${key}:${activeTab || 'overview'}`; const cachedPayload = bootstrapCacheRef.current.get(cacheKey) || null; @@ -1219,18 +1220,20 @@ loadGuardTriggered = true; setLoading(false); setPayload((previous) => previous || cachedPayload || normalizeBootstrap(null, key)); - setError((previous) => previous || 'Bootstrap-Request haengt oder braucht zu lange.'); - }, 12000); + if (!suppressError) { + setError((previous) => previous || 'Bootstrap-Request haengt oder braucht zu lange.'); + } + }, 30000); try { if (schemaStatus.missing_count > 0 || schemaStatus.pending_upgrade_count > 0) { setPayload(normalizeBootstrap(null, key)); setError('Mining-Checker Schema ist noch nicht initialisiert. Bitte im Tab Settings die Datenbank initialisieren.'); - return; + return false; } const params = new URLSearchParams({ view: activeTab || 'overview' }); - const data = await request(`${apiBase}/projects/${encodeURIComponent(key)}/bootstrap?${params.toString()}`, { timeoutMs: 10000 }); + const data = await request(`${apiBase}/projects/${encodeURIComponent(key)}/bootstrap?${params.toString()}`, { timeoutMs: 25000 }); const normalized = normalizeBootstrap(data, key); bootstrapCacheRef.current.set(cacheKey, normalized); setPayload(normalized); @@ -1251,9 +1254,13 @@ ...previous, currency: normalized.settings.currencies?.[0]?.code || previous.currency || 'EUR', })); + return true; } catch (err) { - setError(err.message); + if (!suppressError) { + setError(err.message); + } setPayload(normalizeBootstrap(null, key)); + return false; } finally { window.clearTimeout(loadGuard); if (!loadGuardTriggered) { @@ -1262,6 +1269,17 @@ } } + async function reloadBootstrapAfterMutation(successMessage) { + const refreshed = await loadBootstrap(projectKey, { suppressError: true }); + if (!refreshed) { + setError('Speichern war erfolgreich, aber die Ansicht konnte nicht automatisch aktualisiert werden.'); + if (successMessage) { + setMessage(successMessage); + } + } + return refreshed; + } + useEffect(() => { loadBootstrap(projectKey); }, [projectKey, activeTab]); @@ -1415,7 +1433,7 @@ source: 'manual', }); setOcrPreview(null); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation(fromPreview ? 'OCR-Vorschlag bestaetigt und gespeichert.' : 'Messpunkt gespeichert.'); } catch (err) { setError(err.message); } finally { @@ -1444,7 +1462,7 @@ }); setMessage('Wallet-Snapshot gespeichert.'); setOcrPreview(null); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Wallet-Snapshot gespeichert.'); } catch (err) { setError(err.message); } finally { @@ -1469,7 +1487,7 @@ method: 'DELETE', }); setMessage('Messpunkt geloescht.'); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Messpunkt geloescht.'); } catch (err) { setError(err.message); } finally { @@ -1500,7 +1518,7 @@ if (!result.error_count) { setImportForm((previous) => ({ ...previous, rows_text: '' })); } - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation(`Import abgeschlossen: ${summary}.`); } catch (err) { setError(err.message); } finally { @@ -1561,7 +1579,7 @@ }), }); setMessage('Dashboard gespeichert.'); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Dashboard gespeichert.'); } catch (err) { setError(err.message); } finally { @@ -1590,7 +1608,7 @@ }), }); setMessage('Settings gespeichert.'); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Settings gespeichert.'); } catch (err) { setError(err.message); } finally { @@ -1647,7 +1665,7 @@ setMessage('Ziel gespeichert.'); setTargetForm({ label: '', target_amount_fiat: '', currency: currencies[0]?.code || 'EUR', miner_offer_id: '', is_active: true, sort_order: 0 }); setTargetModalOpen(false); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Ziel gespeichert.'); } catch (err) { setError(err.message); } finally { @@ -1668,7 +1686,7 @@ method: 'DELETE', }); setMessage('Ziel geloescht.'); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Ziel geloescht.'); } catch (err) { setError(err.message); } finally { @@ -1690,7 +1708,7 @@ body: JSON.stringify({ auto_renew: !row.auto_renew }), }); setMessage(`Automatische Verlängerung ${row.auto_renew ? 'deaktiviert' : 'aktiviert'}.`); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation(`Automatische Verlaengerung ${row.auto_renew ? 'deaktiviert' : 'aktiviert'}.`); } catch (err) { setError(err.message); } finally { @@ -1725,7 +1743,7 @@ is_active: true, }); setCostPlanModalOpen(false); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Miner gespeichert.'); } catch (err) { setError(err.message); } finally { @@ -1746,7 +1764,7 @@ setMessage('Auszahlung gespeichert.'); setPayoutForm({ payout_at: '', coins_amount: '', payout_currency: currentSettings.crypto_currency || 'DOGE', note: '' }); setPayoutModalOpen(false); - await loadBootstrap(projectKey); + await reloadBootstrapAfterMutation('Auszahlung gespeichert.'); } catch (err) { setError(err.message); } finally { diff --git a/modules/mining-checker/src/Api/Router.php b/modules/mining-checker/src/Api/Router.php index 635b29f..5e4a364 100644 --- a/modules/mining-checker/src/Api/Router.php +++ b/modules/mining-checker/src/Api/Router.php @@ -21,7 +21,7 @@ final class Router { private const BOOTSTRAP_MEASUREMENT_LIMIT = 150; private const BOOTSTRAP_SNAPSHOT_LIMIT = 40; - private const LONG_REQUEST_BUDGET_SECONDS = 8.0; + private const LONG_REQUEST_BUDGET_SECONDS = 20.0; private const OVERVIEW_WINDOW_DAYS = 15; private const FX_FETCH_MAX_AGE_HOURS = 3.0; private const BASE_OFFER_SPEEDS = [