refactor(klassifikation): Klassifikation aus Monitor entfernt — Pflege jetzt in der Verwaltung
Endpoints unter /api/sources/classification/* weg, Service-Module (source_classifier, external_reputation) gelöscht. Quellen-Modal verliert Tab Klassifikations-Review, Klassifikations-Section in der Edit-Form, alle Bulk-Buttons (Sync, Klassifikation starten, Bulk-Approve). API-Methoden in api.js entfernt, alignment-Helper raus, saveSource entschlackt. Read-Only bleibt: Filter-Dropdowns über der Quellenliste (Politik, Medientyp, Reliability, Externe Reputation, Alignment) und Inline-Badges (_renderClassificationBadges + Label-Maps in components.js). Kunde sieht nur freigegebene Werte. GET /api/sources liefert weiter Klassifikations-Felder + alignments für die Anzeige; SourceCreate/SourceUpdate akzeptieren keine Klassifikations-Felder mehr. Bulk-Klassifikations-Skripte entfernt — Pflege läuft über Verwaltungs-UI.
Dieser Commit ist enthalten in:
@@ -1119,71 +1119,6 @@ const UI = {
|
||||
sonstige: 'sonstige',
|
||||
},
|
||||
|
||||
/**
|
||||
* Eintrag in der Klassifikations-Review-Queue.
|
||||
* Zeigt Diff zwischen aktuellem Wert und LLM-Vorschlag.
|
||||
*/
|
||||
renderClassificationQueueItem(item) {
|
||||
const cur = item.current || {};
|
||||
const prop = item.proposed || {};
|
||||
const conf = prop.confidence || 0;
|
||||
const confPct = Math.round(conf * 100);
|
||||
const confClass = conf >= 0.85 ? 'high' : (conf >= 0.7 ? 'medium' : 'low');
|
||||
|
||||
const diffRow = (label, currentVal, proposedVal, formatter) => {
|
||||
const fmt = formatter || (v => v == null || v === '' ? '–' : String(v));
|
||||
const c = fmt(currentVal);
|
||||
const p = fmt(proposedVal);
|
||||
const changed = c !== p;
|
||||
return `<div class="review-diff-row${changed ? ' changed' : ''}">
|
||||
<span class="review-diff-label">${this.escape(label)}</span>
|
||||
<span class="review-diff-current">${this.escape(c)}</span>
|
||||
<span class="review-diff-arrow">→</span>
|
||||
<span class="review-diff-proposed">${this.escape(p)}</span>
|
||||
</div>`;
|
||||
};
|
||||
|
||||
const polFmt = v => (v && v !== 'na') ? (this._politicalLabels[v]?.full || v) : '–';
|
||||
const mtFmt = v => (v && v !== 'sonstige') ? (this._mediaTypeLabels[v] || v) : (v === 'sonstige' ? 'Sonstige' : '–');
|
||||
const relFmt = v => (v && v !== 'na') ? (this._reliabilityLabels[v] || v) : '–';
|
||||
const stateFmt = v => v ? 'ja' : 'nein';
|
||||
const ccFmt = v => v || '–';
|
||||
const alignFmt = v => (Array.isArray(v) && v.length > 0)
|
||||
? v.map(a => this._alignmentLabels[a] || a).join(', ')
|
||||
: '–';
|
||||
|
||||
const globalBadge = item.is_global ? '<span class="review-global-badge">Grundquelle</span>' : '';
|
||||
const reasoning = prop.reasoning ? this.escape(prop.reasoning) : '';
|
||||
|
||||
return `<div class="review-card" data-source-id="${item.id}">
|
||||
<div class="review-card-header">
|
||||
<div class="review-card-title">
|
||||
<span class="review-card-name">${this.escape(item.name)}</span>
|
||||
${globalBadge}
|
||||
<span class="review-card-domain">${this.escape(item.domain || '')}</span>
|
||||
</div>
|
||||
<div class="review-card-confidence conf-${confClass}" title="LLM-Konfidenz">
|
||||
<span class="conf-value">${confPct}%</span>
|
||||
<span class="conf-label">Konfidenz</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="review-card-diff">
|
||||
${diffRow('Politik', cur.political_orientation, prop.political_orientation, polFmt)}
|
||||
${diffRow('Medientyp', cur.media_type, prop.media_type, mtFmt)}
|
||||
${diffRow('Glaubwürdigkeit', cur.reliability, prop.reliability, relFmt)}
|
||||
${diffRow('Staatsnah', cur.state_affiliated, prop.state_affiliated, stateFmt)}
|
||||
${diffRow('Land', cur.country_code, prop.country_code, ccFmt)}
|
||||
${diffRow('Geopol. Nähe', cur.alignments, prop.alignments, alignFmt)}
|
||||
</div>
|
||||
${reasoning ? `<div class="review-card-reasoning"><strong>Begründung:</strong> ${reasoning}</div>` : ''}
|
||||
<div class="review-card-actions">
|
||||
<button class="btn btn-small btn-primary" onclick="App.approveClassification(${item.id})">Übernehmen</button>
|
||||
<button class="btn btn-small btn-secondary" onclick="App.rejectClassification(${item.id})">Verwerfen</button>
|
||||
<button class="btn btn-small btn-secondary" data-reclassify-id="${item.id}" onclick="App.reclassifySource(${item.id})">Neu klassifizieren</button>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
_renderClassificationBadges(feed) {
|
||||
const parts = [];
|
||||
const pol = feed.political_orientation;
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren