diff --git a/src/static/dashboard.html b/src/static/dashboard.html index be8de67..9d780b3 100644 --- a/src/static/dashboard.html +++ b/src/static/dashboard.html @@ -795,7 +795,6 @@ - diff --git a/src/static/js/app.js b/src/static/js/app.js index cc61164..5e920c9 100644 --- a/src/static/js/app.js +++ b/src/static/js/app.js @@ -2157,10 +2157,15 @@ const App = { const summaryEl = document.getElementById('summary-text'); const timestamp = document.getElementById('lagebild-timestamp')?.textContent || ''; if (summaryEl && summaryEl.innerHTML.trim()) { + // Clone innerHTML and make citation links clickable with full URL visible + let summaryHtml = summaryEl.innerHTML; + // Ensure citation links are styled for print (underlined, blue) + summaryHtml = summaryHtml.replace(/]*class="citation"[^>]*>(\[[^\]]+\])<\/a>/g, + '$2'); sections += '
' + '

Lagebild

' + (timestamp ? '

' + esc(timestamp) + '

' : '') - + '
' + summaryEl.innerHTML + '
' + + '
' + summaryHtml + '
' + '
'; } } @@ -2238,30 +2243,6 @@ const App = { } } - // === Karte === - if (tiles.includes('karte')) { - const mapContainer = document.getElementById('map-container'); - const mapEmpty = document.getElementById('map-empty'); - if (mapContainer && (!mapEmpty || mapEmpty.style.display === 'none')) { - const stats = document.getElementById('map-stats')?.textContent || ''; - // Try to capture map as canvas image - let mapImg = ''; - try { - const leafletPane = mapContainer.querySelector('.leaflet-container'); - if (leafletPane && typeof leafletPane.toDataURL === 'function') { - mapImg = ''; - } - } catch(e) {} - if (!mapImg) { - // Leaflet container is not a canvas, so we use a placeholder - mapImg = '
Die interaktive Karte kann nicht direkt in PDF exportiert werden. Nutzen Sie die Screenshot-Funktion Ihres Browsers (z.B. Strg+Shift+S in Firefox).
'; - } - sections += '

Geografische Verteilung

' - + (stats ? '

' + esc(stats) + '

' : '') - + mapImg + '
'; - } - } - // === Timeline === if (tiles.includes('timeline')) { const buckets = document.querySelectorAll('#timeline .ht-bucket'); @@ -2289,62 +2270,75 @@ const App = { if (!sections) { UI.showToast('Keine Inhalte zum Exportieren', 'warning'); return; } - const printHtml = '' -+ '\n' -+ '\n' -+ '\n' -+ '\n' + esc(title) + ' \u2014 AegisSight Export' -+ '\n' -+ '\n' -+ '\n' -+ '\n
' -+ '\n

' + esc(title) + '

' -+ '\n
AegisSight Monitor \u2014 Exportiert am ' + esc(now) + '
' -+ '\n
' -+ sections -+ '\n' -+ '\n'; + const css = ` +@page { margin: 18mm 15mm 18mm 15mm; size: A4; } +* { box-sizing: border-box; margin: 0; padding: 0; } +body { font-family: -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-size: 11pt; line-height: 1.55; color: #1a1a1a; background: #fff; padding: 0; } +a { color: #1a5276; } + +/* Header: compact, inline with content */ +.pdf-header { border-bottom: 2px solid #2c3e50; padding-bottom: 10px; margin-bottom: 16px; } +.pdf-header h1 { font-size: 18pt; font-weight: 700; color: #2c3e50; margin-bottom: 2px; } +.pdf-header .pdf-subtitle { font-size: 9pt; color: #666; } + +/* Sections */ +.pdf-section { margin-bottom: 22px; } +.pdf-section h2 { font-size: 13pt; font-weight: 600; color: #2c3e50; border-bottom: 1px solid #ccc; padding-bottom: 4px; margin-bottom: 10px; } +.pdf-section h4 { font-size: 10pt; font-weight: 600; color: #444; margin: 10px 0 3px; } +.pdf-meta { font-size: 9pt; color: #888; margin-bottom: 8px; } + +/* Lagebild content */ +.pdf-content { font-size: 10.5pt; line-height: 1.6; } +.pdf-content h3 { font-size: 11.5pt; font-weight: 600; color: #2c3e50; margin: 12px 0 5px; } +.pdf-content strong { font-weight: 600; } +.pdf-content ul { margin: 4px 0 4px 18px; } +.pdf-content li { margin-bottom: 2px; } +.pdf-content a, .pdf-content .citation { color: #1a5276; font-weight: 600; text-decoration: underline; cursor: pointer; } + +/* Quellen table */ +.pdf-table { width: 100%; border-collapse: collapse; font-size: 9.5pt; margin-bottom: 14px; } +.pdf-table th { background: #f0f0f0; text-align: left; padding: 5px 8px; border: 1px solid #ddd; font-weight: 600; font-size: 8.5pt; text-transform: uppercase; color: #555; } +.pdf-table td { padding: 4px 8px; border: 1px solid #ddd; } +.pdf-table tr:nth-child(even) { background: #fafafa; } +.pdf-article-list { font-size: 9.5pt; } +.pdf-article-item { padding: 1px 0; break-inside: avoid; } +.pdf-article-item a { color: #1a5276; text-decoration: none; } +.pdf-article-item a:hover { text-decoration: underline; } +.pdf-date { color: #888; font-size: 8.5pt; } + +/* Faktencheck */ +.pdf-fc-list { display: flex; flex-direction: column; gap: 10px; } +.pdf-fc-item { border: 1px solid #ddd; border-radius: 4px; padding: 8px 12px; break-inside: avoid; } +.pdf-fc-badge { display: inline-block; font-size: 7.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; padding: 1px 7px; border-radius: 3px; margin-bottom: 3px; } +.pdf-fc-confirmed { background: #d4edda; color: #155724; } +.pdf-fc-refuted { background: #f8d7da; color: #721c24; } +.pdf-fc-unverified { background: #fff3cd; color: #856404; } +.pdf-fc-claim { font-size: 10.5pt; margin-top: 3px; } +.pdf-fc-evidence { margin-top: 5px; font-size: 8.5pt; } +.pdf-fc-ev-link { color: #1a5276; text-decoration: underline; margin-right: 5px; } +.pdf-fc-ev-tag { background: #eee; padding: 1px 5px; border-radius: 3px; margin-right: 3px; } + +/* Timeline */ +.pdf-timeline h4 { color: #2c3e50; border-bottom: 1px solid #eee; padding-bottom: 2px; margin-top: 8px; } +.pdf-tl-item { padding: 1px 0; font-size: 9.5pt; break-inside: avoid; } +.pdf-tl-time { color: #888; font-size: 8.5pt; min-width: 36px; display: inline-block; } +.pdf-tl-source { color: #888; font-size: 8.5pt; } + +/* Footer */ +.pdf-footer { margin-top: 24px; padding-top: 8px; border-top: 1px solid #ddd; font-size: 8pt; color: #999; text-align: center; } +`; + + const printHtml = '\n\n\n\n' + + '' + esc(title) + ' \u2014 AegisSight Export\n' + + '\n' + + '\n\n' + + '
\n' + + '

' + esc(title) + '

\n' + + '
AegisSight Monitor \u2014 Exportiert am ' + esc(now) + '
\n' + + '
\n' + + sections + '\n' + + '\n' + + ''; const printWin = window.open('', '_blank', 'width=800,height=600'); if (!printWin) { UI.showToast('Popup blockiert \u2014 bitte Popup-Blocker deaktivieren', 'error'); return; } @@ -2354,7 +2348,6 @@ const App = { setTimeout(function() { try { printWin.focus(); printWin.print(); } catch(e) {} }, 500); }, - async exportIncident(format, scope) { this._closeExportDropdown(); if (!this.currentIncidentId) return;