feat(i18n): Aktionsleiste + Sidebar (Quellen, Feedback, Archiv, Stats, Empty-States)
- 5 Action-Buttons im Header (Aktualisieren/Bearbeiten/Bericht exportieren/Archivieren/Loeschen) via data-i18n. - Sidebar Archiv-Section, Quellen-Button, Feedback-Button, title- Attribute via data-i18n + data-i18n-attr. - Sidebar-Stats 0 Quellen / 0 Artikel: app.js.updateSidebarStats baut die Suffixe ueber T() zusammen. - Empty-States Kein Live-Monitoring / Keine Deep-Research (inkl. eigene-Filter-Varianten) lokalisiert. - Cache-Buster app.js auf v=20260513g.
Dieser Commit ist enthalten in:
@@ -117,19 +117,19 @@
|
|||||||
<div class="sidebar-section">
|
<div class="sidebar-section">
|
||||||
<h2 class="sidebar-section-title collapsible" onclick="App.toggleSidebarSection('archived-incidents')" role="button" tabindex="0" aria-expanded="false">
|
<h2 class="sidebar-section-title collapsible" onclick="App.toggleSidebarSection('archived-incidents')" role="button" tabindex="0" aria-expanded="false">
|
||||||
<span class="sidebar-chevron" id="chevron-archived-incidents" aria-hidden="true">▾</span>
|
<span class="sidebar-chevron" id="chevron-archived-incidents" aria-hidden="true">▾</span>
|
||||||
Archiv
|
<span data-i18n="sidebar.archive">Archiv</span>
|
||||||
<span class="sidebar-section-count" id="count-archived-incidents"></span>
|
<span class="sidebar-section-count" id="count-archived-incidents"></span>
|
||||||
</h2>
|
</h2>
|
||||||
<div id="archived-incidents" aria-live="polite" style="display:none;"></div>
|
<div id="archived-incidents" aria-live="polite" style="display:none;"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar-sources-link">
|
<div class="sidebar-sources-link">
|
||||||
<button class="btn btn-secondary btn-full btn-small" onclick="App.openSourceManagement()" title="Quellen verwalten">
|
<button class="btn btn-secondary btn-full btn-small" onclick="App.openSourceManagement()" title="Quellen verwalten" data-i18n-attr="title:sidebar.manage_sources_title">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg>
|
||||||
<span>Quellen</span>
|
<span data-i18n="sidebar.sources">Quellen</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary btn-full btn-small sidebar-feedback-btn" onclick="App.openFeedback()" title="Feedback senden">
|
<button class="btn btn-secondary btn-full btn-small sidebar-feedback-btn" onclick="App.openFeedback()" title="Feedback senden" data-i18n-attr="title:sidebar.feedback_title">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-10 5L2 7"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-10 5L2 7"/></svg>
|
||||||
<span>Feedback</span>
|
<span data-i18n="sidebar.feedback">Feedback</span>
|
||||||
</button>
|
</button>
|
||||||
<!-- Tutorial-Einstieg temporaer deaktiviert (Ueberarbeitung) - reaktivieren durch Entfernen der Kommentarzeichen:
|
<!-- Tutorial-Einstieg temporaer deaktiviert (Ueberarbeitung) - reaktivieren durch Entfernen der Kommentarzeichen:
|
||||||
<button class="btn btn-secondary btn-full btn-small" onclick="Tutorial.start()" title="Interaktiven Rundgang starten">Rundgang starten</button>
|
<button class="btn btn-secondary btn-full btn-small" onclick="Tutorial.start()" title="Interaktiven Rundgang starten">Rundgang starten</button>
|
||||||
@@ -165,11 +165,11 @@
|
|||||||
<h2 class="incident-header-title" id="incident-title"></h2>
|
<h2 class="incident-header-title" id="incident-title"></h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="incident-header-actions">
|
<div class="incident-header-actions">
|
||||||
<button class="btn btn-primary btn-small" id="refresh-btn">Aktualisieren</button>
|
<button class="btn btn-primary btn-small" id="refresh-btn" data-i18n="action.refresh">Aktualisieren</button>
|
||||||
<button class="btn btn-secondary btn-small" id="edit-incident-btn">Bearbeiten</button>
|
<button class="btn btn-secondary btn-small" id="edit-incident-btn" data-i18n="action.edit">Bearbeiten</button>
|
||||||
<button class="btn btn-secondary btn-small" onclick="App.openExportModal()" data-i18n="modal.export.title">Bericht exportieren</button>
|
<button class="btn btn-secondary btn-small" onclick="App.openExportModal()" data-i18n="action.export">Bericht exportieren</button>
|
||||||
<button class="btn btn-secondary btn-small" id="archive-incident-btn">Archivieren</button>
|
<button class="btn btn-secondary btn-small" id="archive-incident-btn" data-i18n="action.archive">Archivieren</button>
|
||||||
<button class="btn btn-danger btn-small" id="delete-incident-btn">Löschen</button>
|
<button class="btn btn-danger btn-small" id="delete-incident-btn" data-i18n="action.delete">Löschen</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="incident-header-row2">
|
<div class="incident-header-row2">
|
||||||
@@ -729,7 +729,7 @@
|
|||||||
<script src="/static/js/components.js?v=20260513d"></script>
|
<script src="/static/js/components.js?v=20260513d"></script>
|
||||||
<script src="/static/js/layout.js?v=20260513f"></script>
|
<script src="/static/js/layout.js?v=20260513f"></script>
|
||||||
<script src="/static/js/pipeline.js?v=20260513d"></script>
|
<script src="/static/js/pipeline.js?v=20260513d"></script>
|
||||||
<script src="/static/js/app.js?v=20260513f"></script>
|
<script src="/static/js/app.js?v=20260513g"></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>
|
||||||
|
|||||||
@@ -1,6 +1,22 @@
|
|||||||
{
|
{
|
||||||
"sidebar.live_monitoring": "Live-Monitoring",
|
"sidebar.live_monitoring": "Live-Monitoring",
|
||||||
"sidebar.research": "Recherchen",
|
"sidebar.research": "Recherchen",
|
||||||
|
"sidebar.archive": "Archiv",
|
||||||
|
"sidebar.sources": "Quellen",
|
||||||
|
"sidebar.feedback": "Feedback",
|
||||||
|
"sidebar.manage_sources_title": "Quellen verwalten",
|
||||||
|
"sidebar.feedback_title": "Feedback senden",
|
||||||
|
"sidebar.stat.sources_suffix": "Quellen",
|
||||||
|
"sidebar.stat.articles_suffix": "Artikel",
|
||||||
|
"sidebar.empty_adhoc": "Kein Live-Monitoring",
|
||||||
|
"sidebar.empty_adhoc_mine": "Kein eigenes Live-Monitoring",
|
||||||
|
"sidebar.empty_research": "Keine Deep-Research",
|
||||||
|
"sidebar.empty_research_mine": "Keine eigenen Deep-Research",
|
||||||
|
"action.refresh": "Aktualisieren",
|
||||||
|
"action.edit": "Bearbeiten",
|
||||||
|
"action.export": "Bericht exportieren",
|
||||||
|
"action.archive": "Archivieren",
|
||||||
|
"action.delete": "Löschen",
|
||||||
"sidebar.empty": "Keine Lagen vorhanden",
|
"sidebar.empty": "Keine Lagen vorhanden",
|
||||||
"header.logout": "Abmelden",
|
"header.logout": "Abmelden",
|
||||||
"header.new_incident": "+ Neuer Fall",
|
"header.new_incident": "+ Neuer Fall",
|
||||||
|
|||||||
@@ -1,6 +1,22 @@
|
|||||||
{
|
{
|
||||||
"sidebar.live_monitoring": "Live monitoring",
|
"sidebar.live_monitoring": "Live monitoring",
|
||||||
"sidebar.research": "Research",
|
"sidebar.research": "Research",
|
||||||
|
"sidebar.archive": "Archive",
|
||||||
|
"sidebar.sources": "Sources",
|
||||||
|
"sidebar.feedback": "Feedback",
|
||||||
|
"sidebar.manage_sources_title": "Manage sources",
|
||||||
|
"sidebar.feedback_title": "Send feedback",
|
||||||
|
"sidebar.stat.sources_suffix": "sources",
|
||||||
|
"sidebar.stat.articles_suffix": "articles",
|
||||||
|
"sidebar.empty_adhoc": "No live monitoring",
|
||||||
|
"sidebar.empty_adhoc_mine": "No own live monitoring",
|
||||||
|
"sidebar.empty_research": "No deep research",
|
||||||
|
"sidebar.empty_research_mine": "No own deep research",
|
||||||
|
"action.refresh": "Refresh",
|
||||||
|
"action.edit": "Edit",
|
||||||
|
"action.export": "Export report",
|
||||||
|
"action.archive": "Archive",
|
||||||
|
"action.delete": "Delete",
|
||||||
"sidebar.empty": "No situations yet",
|
"sidebar.empty": "No situations yet",
|
||||||
"header.logout": "Sign out",
|
"header.logout": "Sign out",
|
||||||
"header.new_incident": "+ New situation",
|
"header.new_incident": "+ New situation",
|
||||||
|
|||||||
@@ -695,8 +695,13 @@ const App = {
|
|||||||
const activeResearch = filtered.filter(i => i.status === 'active' && i.type === 'research');
|
const activeResearch = filtered.filter(i => i.status === 'active' && i.type === 'research');
|
||||||
const archived = filtered.filter(i => i.status === 'archived');
|
const archived = filtered.filter(i => i.status === 'archived');
|
||||||
|
|
||||||
const emptyLabelAdhoc = this._sidebarFilter === 'mine' ? 'Kein eigenes Live-Monitoring' : 'Kein Live-Monitoring';
|
const _tEmpty = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
|
||||||
const emptyLabelResearch = this._sidebarFilter === 'mine' ? 'Keine eigenen Deep-Research' : 'Keine Deep-Research';
|
const emptyLabelAdhoc = this._sidebarFilter === 'mine'
|
||||||
|
? _tEmpty('sidebar.empty_adhoc_mine', 'Kein eigenes Live-Monitoring')
|
||||||
|
: _tEmpty('sidebar.empty_adhoc', 'Kein Live-Monitoring');
|
||||||
|
const emptyLabelResearch = this._sidebarFilter === 'mine'
|
||||||
|
? _tEmpty('sidebar.empty_research_mine', 'Keine eigenen Deep-Research')
|
||||||
|
: _tEmpty('sidebar.empty_research', 'Keine Deep-Research');
|
||||||
|
|
||||||
activeContainer.innerHTML = activeAdhoc.length
|
activeContainer.innerHTML = activeAdhoc.length
|
||||||
? activeAdhoc.map(i => UI.renderIncidentItem(i, i.id === this.currentIncidentId)).join('')
|
? activeAdhoc.map(i => UI.renderIncidentItem(i, i.id === this.currentIncidentId)).join('')
|
||||||
@@ -2607,20 +2612,23 @@ async handleRefresh() {
|
|||||||
// === Sidebar-Stats ===
|
// === Sidebar-Stats ===
|
||||||
|
|
||||||
async updateSidebarStats() {
|
async updateSidebarStats() {
|
||||||
|
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
|
||||||
|
const lblSources = _t('sidebar.stat.sources_suffix', 'Quellen');
|
||||||
|
const lblArticles = _t('sidebar.stat.articles_suffix', 'Artikel');
|
||||||
try {
|
try {
|
||||||
const stats = await API.getSourceStats();
|
const stats = await API.getSourceStats();
|
||||||
const srcCount = document.getElementById('stat-sources-count');
|
const srcCount = document.getElementById('stat-sources-count');
|
||||||
const artCount = document.getElementById('stat-articles-count');
|
const artCount = document.getElementById('stat-articles-count');
|
||||||
if (srcCount) srcCount.textContent = `${stats.total_sources} Quellen`;
|
if (srcCount) srcCount.textContent = `${stats.total_sources} ${lblSources}`;
|
||||||
if (artCount) artCount.textContent = `${stats.total_articles} Artikel`;
|
if (artCount) artCount.textContent = `${stats.total_articles} ${lblArticles}`;
|
||||||
} catch {
|
} catch {
|
||||||
// Fallback: aus Lagen berechnen
|
// Fallback: aus Lagen berechnen
|
||||||
const totalArticles = this.incidents.reduce((sum, i) => sum + i.article_count, 0);
|
const totalArticles = this.incidents.reduce((sum, i) => sum + i.article_count, 0);
|
||||||
const totalSources = this.incidents.reduce((sum, i) => sum + i.source_count, 0);
|
const totalSources = this.incidents.reduce((sum, i) => sum + i.source_count, 0);
|
||||||
const srcCount = document.getElementById('stat-sources-count');
|
const srcCount = document.getElementById('stat-sources-count');
|
||||||
const artCount = document.getElementById('stat-articles-count');
|
const artCount = document.getElementById('stat-articles-count');
|
||||||
if (srcCount) srcCount.textContent = `${totalSources} Quellen`;
|
if (srcCount) srcCount.textContent = `${totalSources} ${lblSources}`;
|
||||||
if (artCount) artCount.textContent = `${totalArticles} Artikel`;
|
if (artCount) artCount.textContent = `${totalArticles} ${lblArticles}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren