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();
}