feat(ui): schwebende Scroll-Leiste + breitere Inhaltsflaeche
- Die Quellenliste hat jetzt eine dauerhaft sichtbare Scroll-Leiste, die am unteren Bildschirmrand schwebt, solange die Tabelle im Bild ist (Proxy-Element, beidseitig synchronisiert, blendet sich aus wenn nichts zu scrollen ist). Scroll-Leisten der Tabellen sind sichtbarer gestylt, Daumen faerbt sich beim Ueberfahren gold. - app-content von 1200 auf 1720 Pixel Maximalbreite. Ein breiteres Fenster zeigt jetzt wirklich mehr Tabelle statt leerer Raender. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -257,7 +257,8 @@ input:focus, select:focus, textarea:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.app-content {
|
.app-content {
|
||||||
max-width: 1200px;
|
/* Breite Bildschirme ausnutzen. Ein groesseres Fenster zeigt mehr Tabelle. */
|
||||||
|
max-width: 1720px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
@@ -1017,6 +1018,31 @@ table.show-select .select-col { display: table-cell; }
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Schwebende Scroll-Leiste: bleibt am unteren Bildschirmrand sichtbar,
|
||||||
|
solange die Tabelle im Bild ist (Proxy, synchron zum echten Container) */
|
||||||
|
.hscroll-proxy {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
height: 14px;
|
||||||
|
z-index: 5;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
.hscroll-proxy > div { height: 1px; }
|
||||||
|
.hscroll-proxy::-webkit-scrollbar,
|
||||||
|
.table-wrap::-webkit-scrollbar { height: 11px; }
|
||||||
|
.hscroll-proxy::-webkit-scrollbar-thumb,
|
||||||
|
.table-wrap::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 2px solid var(--bg-secondary);
|
||||||
|
}
|
||||||
|
.hscroll-proxy::-webkit-scrollbar-thumb:hover,
|
||||||
|
.table-wrap::-webkit-scrollbar-thumb:hover { background: var(--accent); }
|
||||||
|
.hscroll-proxy::-webkit-scrollbar-track,
|
||||||
|
.table-wrap::-webkit-scrollbar-track { background: var(--bg-secondary); }
|
||||||
|
|
||||||
/* Health-Details in der Ausklapp-Zeile */
|
/* Health-Details in der Ausklapp-Zeile */
|
||||||
.src-notes-text { margin-bottom: 8px; }
|
.src-notes-text { margin-bottom: 8px; }
|
||||||
.health-detail-head {
|
.health-detail-head {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<title>AegisSight Monitor-Verwaltung</title>
|
<title>AegisSight Monitor-Verwaltung</title>
|
||||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
||||||
<link rel="apple-touch-icon" href="/static/favicon.svg">
|
<link rel="apple-touch-icon" href="/static/favicon.svg">
|
||||||
<link rel="stylesheet" href="/static/css/style.css?v=20260725n">
|
<link rel="stylesheet" href="/static/css/style.css?v=20260725o">
|
||||||
<script>(function(){var t=localStorage.getItem('portal_theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');try{var a=JSON.parse(localStorage.getItem('osint_a11y')||'{}');Object.keys(a).forEach(function(k){if(a[k])document.documentElement.setAttribute('data-a11y-'+k,'true');});}catch(e){}})()</script>
|
<script>(function(){var t=localStorage.getItem('portal_theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');try{var a=JSON.parse(localStorage.getItem('osint_a11y')||'{}');Object.keys(a).forEach(function(k){if(a[k])document.documentElement.setAttribute('data-a11y-'+k,'true');});}catch(e){}})()</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -987,8 +987,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/a11y.js?v=20260725a"></script>
|
<script src="/static/js/a11y.js?v=20260725a"></script>
|
||||||
<script src="/static/js/app.js?v=20260725w"></script>
|
<script src="/static/js/app.js?v=20260725x"></script>
|
||||||
<script src="/static/js/sources.js?v=20260725g"></script>
|
<script src="/static/js/sources.js?v=20260725h"></script>
|
||||||
<script src="/static/js/aufgaben.js?v=20260725d"></script>
|
<script src="/static/js/aufgaben.js?v=20260725d"></script>
|
||||||
<script src="/static/js/x-scraper.js?v=20260725c"></script>
|
<script src="/static/js/x-scraper.js?v=20260725c"></script>
|
||||||
<script src="/static/js/audit.js?v=20260725a"></script>
|
<script src="/static/js/audit.js?v=20260725a"></script>
|
||||||
|
|||||||
@@ -1496,6 +1496,40 @@ function enableDragScroll(el) {
|
|||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Immer sichtbare Scroll-Leiste am unteren Bildschirmrand für breite
|
||||||
|
// Tabellen. Ein Proxy-Element spiegelt die Scroll-Position in beide
|
||||||
|
// Richtungen und blendet sich aus, wenn nichts zu scrollen ist.
|
||||||
|
function attachFloatingScrollbar(wrap) {
|
||||||
|
if (!wrap || wrap.dataset.hscroll === "1") return;
|
||||||
|
wrap.dataset.hscroll = "1";
|
||||||
|
const proxy = document.createElement("div");
|
||||||
|
proxy.className = "hscroll-proxy";
|
||||||
|
const spacer = document.createElement("div");
|
||||||
|
proxy.appendChild(spacer);
|
||||||
|
wrap.parentNode.insertBefore(proxy, wrap.nextSibling);
|
||||||
|
|
||||||
|
const sync = () => {
|
||||||
|
spacer.style.width = wrap.scrollWidth + "px";
|
||||||
|
proxy.style.display = wrap.scrollWidth > wrap.clientWidth + 2 ? "" : "none";
|
||||||
|
};
|
||||||
|
let lock = false;
|
||||||
|
proxy.addEventListener("scroll", () => {
|
||||||
|
if (lock) return;
|
||||||
|
lock = true;
|
||||||
|
wrap.scrollLeft = proxy.scrollLeft;
|
||||||
|
lock = false;
|
||||||
|
});
|
||||||
|
wrap.addEventListener("scroll", () => {
|
||||||
|
if (lock) return;
|
||||||
|
lock = true;
|
||||||
|
proxy.scrollLeft = wrap.scrollLeft;
|
||||||
|
lock = false;
|
||||||
|
});
|
||||||
|
if (typeof ResizeObserver === "function") new ResizeObserver(sync).observe(wrap);
|
||||||
|
if (typeof MutationObserver === "function") new MutationObserver(sync).observe(wrap, { childList: true, subtree: true });
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
// Beim Page-Load Meta einmalig laden (asynchron, blockiert nicht)
|
// Beim Page-Load Meta einmalig laden (asynchron, blockiert nicht)
|
||||||
if (window.API && (localStorage.getItem("token") || window.location.pathname === "/dashboard")) {
|
if (window.API && (localStorage.getItem("token") || window.location.pathname === "/dashboard")) {
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
if (typeof enableDragScroll === "function") {
|
if (typeof enableDragScroll === "function") {
|
||||||
enableDragScroll(document.getElementById("unifiedTableWrap"));
|
enableDragScroll(document.getElementById("unifiedTableWrap"));
|
||||||
}
|
}
|
||||||
|
if (typeof attachFloatingScrollbar === "function") {
|
||||||
|
attachFloatingScrollbar(document.getElementById("unifiedTableWrap"));
|
||||||
|
}
|
||||||
|
|
||||||
// Beim Tab-Wechsel auf "Quellen" laden (+ Aufgaben-Badge aktualisieren)
|
// Beim Tab-Wechsel auf "Quellen" laden (+ Aufgaben-Badge aktualisieren)
|
||||||
document.querySelectorAll('.nav-tab[data-section="sources"]').forEach((tab) => {
|
document.querySelectorAll('.nav-tab[data-section="sources"]').forEach((tab) => {
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren