Quellenübersicht: Detail-Liste mit Nummer, Datum und Link
Aufklapp-Liste pro Quelle zeigt jetzt: 1. fortlaufende Nummer (gold, monospace) 2. Datum + Uhrzeit (klein, dezent grau, monospace) 3. Headline als Link zum Originalartikel Drei-Spalten-Grid (Nummer | Datum | Headline). Auf schmalem Viewport (<600px) klappt das Datum unter die Nummer. Bei research-Lagen wird published_at bevorzugt, sonst collected_at. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -1755,8 +1755,12 @@ a.dev-source-pill:hover {
|
|||||||
.source-overview-detail-list li {
|
.source-overview-detail-list li {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
padding: 2px 0;
|
padding: 4px 0;
|
||||||
border-top: 1px dashed var(--border);
|
border-top: 1px dashed var(--border);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto 1fr;
|
||||||
|
gap: var(--sp-md);
|
||||||
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
.source-overview-detail-list li:first-child { border-top: none; }
|
.source-overview-detail-list li:first-child { border-top: none; }
|
||||||
.source-overview-detail-list li a {
|
.source-overview-detail-list li a {
|
||||||
@@ -1767,6 +1771,33 @@ a.dev-source-pill:hover {
|
|||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
.source-overview-detail-num {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent);
|
||||||
|
min-width: 32px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.source-overview-detail-date {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.source-overview-detail-headline {
|
||||||
|
min-width: 0;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.source-overview-detail-list li {
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
}
|
||||||
|
.source-overview-detail-date {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
margin-left: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.source-overview-detail { animation: none; }
|
.source-overview-detail { animation: none; }
|
||||||
.source-overview-item { transition: none; }
|
.source-overview-item { transition: none; }
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<link rel="stylesheet" href="/static/vendor/leaflet.css">
|
<link rel="stylesheet" href="/static/vendor/leaflet.css">
|
||||||
<link rel="stylesheet" href="/static/vendor/MarkerCluster.css">
|
<link rel="stylesheet" href="/static/vendor/MarkerCluster.css">
|
||||||
<link rel="stylesheet" href="/static/vendor/MarkerCluster.Default.css">
|
<link rel="stylesheet" href="/static/vendor/MarkerCluster.Default.css">
|
||||||
<link rel="stylesheet" href="/static/css/style.css?v=20260501f">
|
<link rel="stylesheet" href="/static/css/style.css?v=20260501g">
|
||||||
<style>
|
<style>
|
||||||
/* Export Modal Radio */
|
/* Export Modal Radio */
|
||||||
.export-radio { display:flex; align-items:center; gap:10px; padding:8px 12px; cursor:pointer; border-radius:var(--radius-sm); transition:background 0.15s; border:1px solid transparent; margin-bottom:4px; }
|
.export-radio { display:flex; align-items:center; gap:10px; padding:8px 12px; cursor:pointer; border-radius:var(--radius-sm); transition:background 0.15s; border:1px solid transparent; margin-bottom:4px; }
|
||||||
@@ -647,7 +647,7 @@
|
|||||||
<script src="/static/js/components.js?v=20260427a"></script>
|
<script src="/static/js/components.js?v=20260427a"></script>
|
||||||
<script src="/static/js/layout.js?v=20260316b"></script>
|
<script src="/static/js/layout.js?v=20260316b"></script>
|
||||||
<script src="/static/js/pipeline.js?v=20260501a"></script>
|
<script src="/static/js/pipeline.js?v=20260501a"></script>
|
||||||
<script src="/static/js/app.js?v=20260501f"></script>
|
<script src="/static/js/app.js?v=20260501g"></script>
|
||||||
<script src="/static/js/cluster-data.js?v=20260322f"></script>
|
<script src="/static/js/cluster-data.js?v=20260322f"></script>
|
||||||
<script src="/static/js/tutorial.js?v=20260316z"></script>
|
<script src="/static/js/tutorial.js?v=20260316z"></script>
|
||||||
<script src="/static/js/chat.js?v=20260422a"></script>
|
<script src="/static/js/chat.js?v=20260422a"></script>
|
||||||
|
|||||||
@@ -889,11 +889,13 @@ const App = {
|
|||||||
el.classList.add('active');
|
el.classList.add('active');
|
||||||
el.setAttribute('aria-expanded', 'true');
|
el.setAttribute('aria-expanded', 'true');
|
||||||
|
|
||||||
|
const type = this._currentIncidentType;
|
||||||
|
const getDate = (a) => (type === 'research' && a.published_at) ? a.published_at : (a.collected_at || a.published_at);
|
||||||
const articles = (this._currentArticles || [])
|
const articles = (this._currentArticles || [])
|
||||||
.filter(a => (a.source || 'Unbekannt') === sourceName)
|
.filter(a => (a.source || 'Unbekannt') === sourceName)
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
const ta = new Date(a.collected_at || a.published_at || 0).getTime();
|
const ta = new Date(getDate(a) || 0).getTime();
|
||||||
const tb = new Date(b.collected_at || b.published_at || 0).getTime();
|
const tb = new Date(getDate(b) || 0).getTime();
|
||||||
return tb - ta;
|
return tb - ta;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -902,14 +904,30 @@ const App = {
|
|||||||
if (articles.length === 0) {
|
if (articles.length === 0) {
|
||||||
detail.innerHTML = '<div class="source-overview-detail-empty">Keine Artikel gefunden.</div>';
|
detail.innerHTML = '<div class="source-overview-detail-empty">Keine Artikel gefunden.</div>';
|
||||||
} else {
|
} else {
|
||||||
const items = articles.map(a => {
|
const fmtDate = (ts) => {
|
||||||
|
if (!ts) return '—';
|
||||||
|
try {
|
||||||
|
const d = new Date(ts);
|
||||||
|
if (isNaN(d.getTime())) return '—';
|
||||||
|
return d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: '2-digit', timeZone: TIMEZONE })
|
||||||
|
+ ' '
|
||||||
|
+ d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', timeZone: TIMEZONE });
|
||||||
|
} catch (e) { return '—'; }
|
||||||
|
};
|
||||||
|
const items = articles.map((a, i) => {
|
||||||
|
const num = i + 1;
|
||||||
|
const dateStr = fmtDate(getDate(a));
|
||||||
const headline = UI.escape(a.headline_de || a.headline || '(ohne Titel)');
|
const headline = UI.escape(a.headline_de || a.headline || '(ohne Titel)');
|
||||||
if (a.source_url) {
|
const inner = a.source_url
|
||||||
return `<li><a href="${UI.escape(a.source_url)}" target="_blank" rel="noopener">${headline}</a></li>`;
|
? `<a href="${UI.escape(a.source_url)}" target="_blank" rel="noopener">${headline}</a>`
|
||||||
}
|
: headline;
|
||||||
return `<li>${headline}</li>`;
|
return `<li>
|
||||||
|
<span class="source-overview-detail-num">${num}.</span>
|
||||||
|
<span class="source-overview-detail-date">${UI.escape(dateStr)}</span>
|
||||||
|
<span class="source-overview-detail-headline">${inner}</span>
|
||||||
|
</li>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
detail.innerHTML = `<ul class="source-overview-detail-list">${items}</ul>`;
|
detail.innerHTML = `<ol class="source-overview-detail-list">${items}</ol>`;
|
||||||
}
|
}
|
||||||
el.insertAdjacentElement('afterend', detail);
|
el.insertAdjacentElement('afterend', detail);
|
||||||
},
|
},
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren