From 39eec2582847a677196e1935b46e7fadb65d0aec Mon Sep 17 00:00:00 2001 From: duffyduck Date: Tue, 12 May 2026 15:06:45 +0200 Subject: [PATCH] =?UTF-8?q?feat(diag):=20Memory-Druckansicht=20=E2=80=94?= =?UTF-8?q?=20Strg+P=20=E2=86=92=20als=20PDF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer Button "📄 Drucken / PDF" im Gehirn-Tab oeffnet eine sauber formatierte Print-View in neuem Tab. Druck-CSS optimiert (page-break- inside:avoid pro Entry, schwarze Borders fuer Print, Action-Bar wird versteckt). Aktueller Type+Pinned-Filter wird respektiert. Browser-eigenes "Als PDF speichern" greift dann — kein Tool noetig. Co-Authored-By: Claude Opus 4.7 (1M context) --- diagnostic/index.html | 115 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/diagnostic/index.html b/diagnostic/index.html index 3af9d85..312eefa 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -812,6 +812,7 @@

Memories

+
@@ -3583,6 +3584,120 @@ el.innerHTML = (html + extra) || '(Keine bekannten Typen gefunden)'; } + async function printBrainMemory() { + // Aktuellen Filter respektieren, damit Stefan z.B. "nur pinned" drucken kann. + const typeFilter = document.getElementById('brain-filter-type')?.value || ''; + const pinnedFilter = document.getElementById('brain-filter-pinned')?.value || 'all'; + try { + const params = new URLSearchParams({ limit: '2000' }); + if (typeFilter) params.set('type', typeFilter); + const r = await fetch('/api/brain/memory/list?' + params.toString()); + if (!r.ok) throw new Error('HTTP ' + r.status); + let items = await r.json(); + if (pinnedFilter === 'pinned') items = items.filter(m => m.pinned); + else if (pinnedFilter === 'cold') items = items.filter(m => !m.pinned); + + // Items nach Type gruppieren, Reihenfolge aus BRAIN_TYPE_ORDER + const byType = {}; + items.forEach(m => { (byType[m.type] = byType[m.type] || []).push(m); }); + const knownTypes = BRAIN_TYPE_ORDER.filter(t => byType[t]); + const unknownTypes = Object.keys(byType).filter(t => !BRAIN_TYPE_ORDER.includes(t)); + const allTypes = [...knownTypes, ...unknownTypes]; + + const filterDesc = [ + typeFilter ? `Typ: ${BRAIN_TYPE_LABELS[typeFilter] || typeFilter}` : 'alle Typen', + pinnedFilter === 'pinned' ? 'nur pinned' : (pinnedFilter === 'cold' ? 'nur cold' : 'pinned + cold'), + ].join(' · '); + const printedAt = new Date().toLocaleString('de-DE', { dateStyle: 'medium', timeStyle: 'short' }); + + const escapeForHtml = (s) => String(s == null ? '' : s) + .replace(/&/g, '&').replace(//g, '>'); + + const renderItem = (m) => { + const pin = m.pinned ? '📌 ' : ''; + const cat = m.category ? `[${escapeForHtml(m.category)}]` : ''; + const tags = (m.tags || []).length + ? `
${m.tags.map(t => `${escapeForHtml(t)}`).join(' ')}
` + : ''; + return ` +
+
${pin}${escapeForHtml(m.title || '(ohne Titel)')} ${cat}
+
${escapeForHtml(m.content || '')}
+ ${tags} +
`; + }; + + const sections = allTypes.map(t => { + const label = BRAIN_TYPE_LABELS[t] || t; + const fixed = BRAIN_TYPE_INFO[t]?.fixed ? 'FEST im System-Prompt' : ''; + const entries = byType[t].map(renderItem).join(''); + return ` +
+

${escapeForHtml(label)} (${byType[t].length}) ${fixed}

+ ${entries} +
`; + }).join(''); + + const html = ` + + + +ARIA Gehirn — Druckansicht (${printedAt}) + + + +
+
+

ARIA Gehirn — Druckansicht

+
${escapeForHtml(printedAt)}
+
+
Filter: ${escapeForHtml(filterDesc)} · ${items.length} Eintrag${items.length === 1 ? '' : 'e'}
+ ${sections || '
Keine Eintraege fuer diesen Filter.
'} + +`; + + const win = window.open('', '_blank'); + if (!win) { + alert('Popup blockiert — bitte Popups für Diagnostic erlauben und nochmal klicken.'); + return; + } + win.document.open(); + win.document.write(html); + win.document.close(); + } catch (e) { + alert('Druckansicht konnte nicht geladen werden: ' + e.message); + } + } + function _updateCategoryDatalist(items) { const dl = document.getElementById('memory-category-suggestions'); if (!dl) return;