Tutorial: Quellenverwaltung in zwei Steps aufteilen mit manuellem Weiterklick

Step 28 (Quellendetails): Cursor faehrt zum Info-Icon, Tooltip wird
angezeigt und bleibt stehen bis der Nutzer manuell auf Weiter klickt.
So hat der Nutzer Zeit, den Tooltip in Ruhe zu lesen.

Step 29 (Quellen verwalten): Cursor zeigt + Quelle Button und
Ausschliessen Button nacheinander, mit Erklaerungen in der Bubble.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
Claude Dev
2026-03-16 16:24:05 +01:00
Ursprung 6c72190f86
Commit 4aaf0c1d5e
2 geänderte Dateien mit 61 neuen und 32 gelöschten Zeilen

Datei anzeigen

@@ -764,7 +764,7 @@
<script src="/static/js/api_network.js?v=20260316a"></script> <script src="/static/js/api_network.js?v=20260316a"></script>
<script src="/static/js/network-graph.js?v=20260316a"></script> <script src="/static/js/network-graph.js?v=20260316a"></script>
<script src="/static/js/app_network.js?v=20260316a"></script> <script src="/static/js/app_network.js?v=20260316a"></script>
<script src="/static/js/tutorial.js?v=20260316m"></script> <script src="/static/js/tutorial.js?v=20260316n"></script>
<script src="/static/js/chat.js?v=20260316f"></script> <script src="/static/js/chat.js?v=20260316f"></script>
<script>document.addEventListener("DOMContentLoaded",function(){Chat.init();Tutorial.init()});</script> <script>document.addEventListener("DOMContentLoaded",function(){Chat.init();Tutorial.init()});</script>

Datei anzeigen

@@ -964,17 +964,14 @@ const Tutorial = {
} }
}, },
}, },
// 22 - Quellen Modal (mit Cursor-Demo) // 22 - Quellen Modal: Info-Icon + Tooltip
{ {
id: 'sources-modal', id: 'sources-modal',
target: '#modal-sources .modal', target: '#modal-sources .modal',
title: 'Quellen verwalten', title: 'Quellendetails anzeigen',
text: 'Die Quellenverwaltung zeigt alle konfigurierten Nachrichtenquellen.<br><br>' text: 'Jede Quelle hat ein <strong>Info-Symbol (i)</strong>, das Details wie Typ, Sprache und '
+ '<strong>Info-Symbol (i)</strong> - Zeigt Typ, Sprache und Ausrichtung der Quelle<br>' + 'Ausrichtung anzeigt. Beobachten Sie den Tooltip:<br><br>'
+ '<strong>Kategorie-Badge</strong> - Farbige Kennzeichnung der Quellkategorie<br>' + 'Klicken Sie auf <strong>Weiter</strong>, wenn Sie den Tooltip gelesen haben.',
+ '<strong>Ausschlie\u00dfen</strong> - Quelle f\u00fcr einzelne Lagen sperren<br>'
+ '<strong>+ Quelle</strong> - Neue Quellen per URL hinzuf\u00fcgen<br><br>'
+ 'Beobachten Sie, wie die Quellendetails angezeigt werden:',
position: 'left', position: 'left',
disableNav: true, disableNav: true,
onEnter: function() { onEnter: function() {
@@ -985,21 +982,48 @@ const Tutorial = {
} }
} }
if (overlay) overlay.style.zIndex = '9002'; if (overlay) overlay.style.zIndex = '9002';
// Warten bis Quellen geladen, dann Demo starten
Tutorial._stepTimeout(function() { Tutorial._stepTimeout(function() {
Tutorial._simulateSourcesDemo(); Tutorial._simulateSourcesInfoIcon();
}, 1500); }, 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: '<strong>+ Quelle</strong> - Neue Quellen per URL oder Domain hinzuf\u00fcgen. '
+ 'Der Monitor erkennt RSS-Feeds automatisch.<br><br>'
+ '<strong>Ausschlie\u00dfen</strong> - Sperrt eine Quelle f\u00fcr einzelne Lagen, '
+ 'ohne sie global zu deaktivieren.<br><br>'
+ '<strong>Kategorie-Badge</strong> - 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() { onExit: function() {
var overlay = document.getElementById('modal-sources'); var overlay = document.getElementById('modal-sources');
if (overlay) { if (overlay) {
overlay.classList.remove('active'); overlay.classList.remove('active');
overlay.style.zIndex = ''; overlay.style.zIndex = '';
} }
// Tooltip entfernen falls manuell erzeugt
var tip = document.getElementById('tutorial-tooltip');
if (tip) tip.remove();
Tutorial._clearSubHighlights(); Tutorial._clearSubHighlights();
Tutorial._hideCursor();
}, },
}, },
// 23 - Chat // 23 - Chat
@@ -1951,7 +1975,8 @@ const Tutorial = {
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Quellenverwaltung-Demo: Info-Icon hover + Tooltip zeigen // Quellenverwaltung-Demo: Info-Icon hover + Tooltip zeigen
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
async _simulateSourcesDemo() { // Quellen-Demo Teil 1: Info-Icon + Tooltip, dann Weiter-Button
async _simulateSourcesInfoIcon() {
this._demoRunning = true; this._demoRunning = true;
// Warten bis Quellen geladen sind // Warten bis Quellen geladen sind
@@ -1970,7 +1995,7 @@ const Tutorial = {
return; return;
} }
// 1. Cursor zum ersten Info-Icon // Cursor zum Info-Icon
var rect = infoIcon.getBoundingClientRect(); var rect = infoIcon.getBoundingClientRect();
var targetX = rect.left + rect.width / 2; var targetX = rect.left + rect.width / 2;
var targetY = rect.top + rect.height / 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._animateCursor(targetX - 80, targetY - 60, targetX, targetY, 600);
await this._wait(200); await this._wait(200);
// 2. Info-Icon highlighten // Info-Icon highlighten
this._highlightSub('#sources-list .info-icon'); this._highlightSub('#sources-list .info-icon');
// 3. Tooltip manuell anzeigen (da pointer-events blockiert sind) // Tooltip manuell anzeigen
var tooltipText = infoIcon.getAttribute('data-tooltip') || ''; var tooltipText = infoIcon.getAttribute('data-tooltip') || '';
if (tooltipText) { if (tooltipText) {
var tooltip = document.createElement('div'); var tooltip = document.createElement('div');
@@ -1994,38 +2019,42 @@ const Tutorial = {
+ 'pointer-events:none;'; + 'pointer-events:none;';
tooltip.textContent = tooltipText; tooltip.textContent = tooltipText;
document.body.appendChild(tooltip); document.body.appendChild(tooltip);
// Tooltip unter dem Icon positionieren
tooltip.style.left = Math.max(8, rect.left - 20) + 'px'; tooltip.style.left = Math.max(8, rect.left - 20) + 'px';
tooltip.style.top = (rect.bottom + 8) + '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 // Quellen-Demo Teil 2: + Quelle und Ausschlie\u00dfen Buttons
var tip = document.getElementById('tutorial-tooltip'); async _simulateSourcesActions() {
if (tip) tip.remove(); this._demoRunning = true;
this._clearSubHighlights();
// 5. Zum "+ Quelle" Button // Zum "+ Quelle" Button
var addBtn = document.querySelector('.sources-toolbar-actions .btn-primary'); var addBtn = document.querySelector('.sources-toolbar-actions .btn-primary');
if (addBtn) { if (addBtn) {
var addRect = addBtn.getBoundingClientRect(); 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'); this._highlightSub('.sources-toolbar-actions .btn-primary');
await this._wait(2000); await this._wait(2500);
this._clearSubHighlights(); 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'); var excludeBtn = document.querySelector('#sources-list .source-group-actions .btn-secondary');
if (excludeBtn) { if (excludeBtn) {
var exRect = excludeBtn.getBoundingClientRect(); var exRect = excludeBtn.getBoundingClientRect();
var prevRect = addBtn ? addBtn.getBoundingClientRect() : rect; var prevX = addBtn ? addBtn.getBoundingClientRect().left + addBtn.getBoundingClientRect().width / 2 : exRect.left;
await this._animateCursor(prevRect.left + prevRect.width / 2, prevRect.top + prevRect.height / 2, 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); exRect.left + exRect.width / 2, exRect.top + exRect.height / 2, 500);
this._highlightSub('#sources-list .source-group-actions .btn-secondary'); this._highlightSub('#sources-list .source-group-actions .btn-secondary');
await this._wait(2000); await this._wait(2500);
this._clearSubHighlights(); this._clearSubHighlights();
} }