diff --git a/src/static/dashboard.html b/src/static/dashboard.html index 67dd5cc..97ebdc8 100644 --- a/src/static/dashboard.html +++ b/src/static/dashboard.html @@ -764,7 +764,7 @@ - + diff --git a/src/static/js/tutorial.js b/src/static/js/tutorial.js index c015343..02d1e21 100644 --- a/src/static/js/tutorial.js +++ b/src/static/js/tutorial.js @@ -964,17 +964,14 @@ const Tutorial = { } }, }, - // 22 - Quellen Modal (mit Cursor-Demo) + // 22 - Quellen Modal: Info-Icon + Tooltip { id: 'sources-modal', target: '#modal-sources .modal', - title: 'Quellen verwalten', - text: 'Die Quellenverwaltung zeigt alle konfigurierten Nachrichtenquellen.

' - + 'Info-Symbol (i) - Zeigt Typ, Sprache und Ausrichtung der Quelle
' - + 'Kategorie-Badge - Farbige Kennzeichnung der Quellkategorie
' - + 'Ausschlie\u00dfen - Quelle f\u00fcr einzelne Lagen sperren
' - + '+ Quelle - Neue Quellen per URL hinzuf\u00fcgen

' - + 'Beobachten Sie, wie die Quellendetails angezeigt werden:', + title: 'Quellendetails anzeigen', + text: 'Jede Quelle hat ein Info-Symbol (i), das Details wie Typ, Sprache und ' + + 'Ausrichtung anzeigt. Beobachten Sie den Tooltip:

' + + 'Klicken Sie auf Weiter, wenn Sie den Tooltip gelesen haben.', position: 'left', disableNav: true, onEnter: function() { @@ -985,21 +982,48 @@ const Tutorial = { } } if (overlay) overlay.style.zIndex = '9002'; - // Warten bis Quellen geladen, dann Demo starten Tutorial._stepTimeout(function() { - Tutorial._simulateSourcesDemo(); + Tutorial._simulateSourcesInfoIcon(); }, 1500); }, + onExit: function() { + var tip = document.getElementById('tutorial-tooltip'); + if (tip) tip.remove(); + Tutorial._clearSubHighlights(); + Tutorial._hideCursor(); + }, + }, + // 23 - Quellen Modal: Aktionen + { + id: 'sources-modal-actions', + target: '#modal-sources .modal', + title: 'Quellen verwalten', + text: '+ Quelle - Neue Quellen per URL oder Domain hinzuf\u00fcgen. ' + + 'Der Monitor erkennt RSS-Feeds automatisch.

' + + 'Ausschlie\u00dfen - Sperrt eine Quelle f\u00fcr einzelne Lagen, ' + + 'ohne sie global zu deaktivieren.

' + + 'Kategorie-Badge - Farbige Kennzeichnung der Quellkategorie ' + + '(Nachrichtenagentur, \u00d6ffentlich-Rechtlich, etc.)', + position: 'left', + disableNav: true, + onEnter: function() { + var overlay = document.getElementById('modal-sources'); + if (overlay && !overlay.classList.contains('active')) { + if (typeof App !== 'undefined' && App.openSourceManagement) { + App.openSourceManagement(); + } + } + if (overlay) overlay.style.zIndex = '9002'; + Tutorial._simulateSourcesActions(); + }, onExit: function() { var overlay = document.getElementById('modal-sources'); if (overlay) { overlay.classList.remove('active'); overlay.style.zIndex = ''; } - // Tooltip entfernen falls manuell erzeugt - var tip = document.getElementById('tutorial-tooltip'); - if (tip) tip.remove(); Tutorial._clearSubHighlights(); + Tutorial._hideCursor(); }, }, // 23 - Chat @@ -1951,7 +1975,8 @@ const Tutorial = { // ----------------------------------------------------------------------- // Quellenverwaltung-Demo: Info-Icon hover + Tooltip zeigen // ----------------------------------------------------------------------- - async _simulateSourcesDemo() { + // Quellen-Demo Teil 1: Info-Icon + Tooltip, dann Weiter-Button + async _simulateSourcesInfoIcon() { this._demoRunning = true; // Warten bis Quellen geladen sind @@ -1970,7 +1995,7 @@ const Tutorial = { return; } - // 1. Cursor zum ersten Info-Icon + // Cursor zum Info-Icon var rect = infoIcon.getBoundingClientRect(); var targetX = rect.left + rect.width / 2; var targetY = rect.top + rect.height / 2; @@ -1980,10 +2005,10 @@ const Tutorial = { await this._animateCursor(targetX - 80, targetY - 60, targetX, targetY, 600); await this._wait(200); - // 2. Info-Icon highlighten + // Info-Icon highlighten this._highlightSub('#sources-list .info-icon'); - // 3. Tooltip manuell anzeigen (da pointer-events blockiert sind) + // Tooltip manuell anzeigen var tooltipText = infoIcon.getAttribute('data-tooltip') || ''; if (tooltipText) { var tooltip = document.createElement('div'); @@ -1994,38 +2019,42 @@ const Tutorial = { + 'pointer-events:none;'; tooltip.textContent = tooltipText; document.body.appendChild(tooltip); - - // Tooltip unter dem Icon positionieren tooltip.style.left = Math.max(8, rect.left - 20) + 'px'; tooltip.style.top = (rect.bottom + 8) + 'px'; } - await this._wait(3000); + // Demo fertig - Weiter-Button einblenden, Tooltip bleibt stehen + this._demoRunning = false; + this._enableNavAfterDemo(); + }, - // 4. Tooltip entfernen - var tip = document.getElementById('tutorial-tooltip'); - if (tip) tip.remove(); - this._clearSubHighlights(); + // Quellen-Demo Teil 2: + Quelle und Ausschlie\u00dfen Buttons + async _simulateSourcesActions() { + this._demoRunning = true; - // 5. Zum "+ Quelle" Button + // Zum "+ Quelle" Button var addBtn = document.querySelector('.sources-toolbar-actions .btn-primary'); if (addBtn) { var addRect = addBtn.getBoundingClientRect(); - await this._animateCursor(targetX, targetY, addRect.left + addRect.width / 2, addRect.top + addRect.height / 2, 500); + this._showCursor(addRect.left - 40, addRect.top - 30, 'default'); + await this._wait(300); + await this._animateCursor(addRect.left - 40, addRect.top - 30, + addRect.left + addRect.width / 2, addRect.top + addRect.height / 2, 500); this._highlightSub('.sources-toolbar-actions .btn-primary'); - await this._wait(2000); + await this._wait(2500); this._clearSubHighlights(); } - // 6. Zum "Ausschlie\u00dfen" Button der ersten Quelle + // Zum "Ausschlie\u00dfen" Button der ersten Quelle var excludeBtn = document.querySelector('#sources-list .source-group-actions .btn-secondary'); if (excludeBtn) { var exRect = excludeBtn.getBoundingClientRect(); - var prevRect = addBtn ? addBtn.getBoundingClientRect() : rect; - await this._animateCursor(prevRect.left + prevRect.width / 2, prevRect.top + prevRect.height / 2, + var prevX = addBtn ? addBtn.getBoundingClientRect().left + addBtn.getBoundingClientRect().width / 2 : exRect.left; + var prevY = addBtn ? addBtn.getBoundingClientRect().top + addBtn.getBoundingClientRect().height / 2 : exRect.top; + await this._animateCursor(prevX, prevY, exRect.left + exRect.width / 2, exRect.top + exRect.height / 2, 500); this._highlightSub('#sources-list .source-group-actions .btn-secondary'); - await this._wait(2000); + await this._wait(2500); this._clearSubHighlights(); }