Promote develop → main (2026-07-25 22:22 UTC) #16
@@ -928,47 +928,75 @@ input[type="date"].filter-select { padding: 6px 10px; }
|
||||
.health-run-item { display: inline-flex; align-items: center; gap: 8px; }
|
||||
.health-run-item #healthRunInfo { font-size: 12px; }
|
||||
|
||||
/* Checkbox-Filterleisten (Standard fuer alle Filter im Portal) */
|
||||
/* Checkbox-Dropdowns (Standard fuer alle Filter im Portal) */
|
||||
.filter-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 10px 14px;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.filter-dd { position: relative; }
|
||||
.filter-dd-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 7px 12px;
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.filter-dd-btn:hover { background: var(--bg-tertiary); }
|
||||
.filter-dd-btn.has-selection { border-color: var(--accent); }
|
||||
.filter-dd-count {
|
||||
background: var(--accent);
|
||||
color: #1A1A1A; /* Text auf Gold immer dunkel (ON_ACCENT) */
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
padding: 0 6px;
|
||||
line-height: 16px;
|
||||
}
|
||||
.filter-dd-caret { font-size: 10px; color: var(--text-secondary); }
|
||||
.filter-dd-panel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
left: 0;
|
||||
z-index: 60;
|
||||
min-width: 210px;
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
padding: 8px;
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.filter-group {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 4px 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.filter-group-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.4px;
|
||||
min-width: 92px;
|
||||
cursor: default;
|
||||
}
|
||||
.filter-dd.open .filter-dd-panel { display: flex; }
|
||||
[data-theme="light"] .filter-dd-panel { box-shadow: 0 8px 24px rgba(26, 26, 26, 0.18); }
|
||||
.filter-check {
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
gap: 7px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
padding: 2px 7px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 6px;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.filter-check:hover { background: var(--bg-tertiary); }
|
||||
.filter-check input {
|
||||
accent-color: var(--accent);
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Checkbox-Spalte: nur sichtbar bei Herkunfts-Filter "Kundenquellen" */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>AegisSight Monitor-Verwaltung</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
||||
<link rel="apple-touch-icon" href="/static/favicon.svg">
|
||||
<link rel="stylesheet" href="/static/css/style.css?v=20260725k">
|
||||
<link rel="stylesheet" href="/static/css/style.css?v=20260725l">
|
||||
<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>
|
||||
@@ -970,7 +970,7 @@
|
||||
</div>
|
||||
|
||||
<script src="/static/js/a11y.js?v=20260725a"></script>
|
||||
<script src="/static/js/app.js?v=20260725t"></script>
|
||||
<script src="/static/js/app.js?v=20260725u"></script>
|
||||
<script src="/static/js/sources.js?v=20260725e"></script>
|
||||
<script src="/static/js/aufgaben.js?v=20260725b"></script>
|
||||
<script src="/static/js/x-scraper.js?v=20260522a"></script>
|
||||
|
||||
@@ -1375,18 +1375,30 @@ function populateSelect(el, items, allLabel) {
|
||||
if (current && items.some(it => it.key === current)) el.value = current;
|
||||
}
|
||||
|
||||
// Checkbox-Filtergruppe (Standard für alle Filter im Portal, statt Dropdowns).
|
||||
// Checkbox-Dropdown (Standard für alle Filter im Portal). Ein Knopf mit dem
|
||||
// Filternamen klappt eine Liste von Checkboxen auf (Mehrfachauswahl).
|
||||
// selected ist ein Set mit den angehakten Keys. Nichts angehakt = keine
|
||||
// Einschränkung. onChange wird nach jedem Toggle aufgerufen.
|
||||
// Einschränkung. onChange wird nach jedem Toggle aufgerufen, das Panel
|
||||
// bleibt dabei offen.
|
||||
function renderFilterGroup(container, title, items, selected, onChange) {
|
||||
if (!container) return;
|
||||
const wrap = document.createElement("div");
|
||||
wrap.className = "filter-group";
|
||||
const lbl = document.createElement("span");
|
||||
lbl.className = "filter-group-label";
|
||||
lbl.textContent = title;
|
||||
lbl.title = "Nichts angehakt = alle";
|
||||
wrap.appendChild(lbl);
|
||||
wrap.className = "filter-dd";
|
||||
|
||||
const btn = document.createElement("button");
|
||||
btn.type = "button";
|
||||
btn.className = "filter-dd-btn";
|
||||
btn.title = "Nichts angehakt = alle";
|
||||
const updateBtn = () => {
|
||||
btn.innerHTML = esc(title)
|
||||
+ (selected.size ? ` <span class="filter-dd-count">${selected.size}</span>` : "")
|
||||
+ ' <span class="filter-dd-caret">▾</span>';
|
||||
btn.classList.toggle("has-selection", selected.size > 0);
|
||||
};
|
||||
updateBtn();
|
||||
|
||||
const panel = document.createElement("div");
|
||||
panel.className = "filter-dd-panel";
|
||||
(items || []).forEach((it) => {
|
||||
const label = document.createElement("label");
|
||||
label.className = "filter-check";
|
||||
@@ -1396,15 +1408,41 @@ function renderFilterGroup(container, title, items, selected, onChange) {
|
||||
cb.addEventListener("change", () => {
|
||||
if (cb.checked) selected.add(it.key);
|
||||
else selected.delete(it.key);
|
||||
updateBtn();
|
||||
onChange();
|
||||
});
|
||||
label.appendChild(cb);
|
||||
label.appendChild(document.createTextNode(it.label));
|
||||
wrap.appendChild(label);
|
||||
panel.appendChild(label);
|
||||
});
|
||||
if (!(items || []).length) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "text-muted";
|
||||
empty.style.fontSize = "12px";
|
||||
empty.textContent = "Keine Werte vorhanden";
|
||||
panel.appendChild(empty);
|
||||
}
|
||||
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const wasOpen = wrap.classList.contains("open");
|
||||
closeAllFilterDropdowns();
|
||||
if (!wasOpen) wrap.classList.add("open");
|
||||
});
|
||||
panel.addEventListener("click", (e) => e.stopPropagation());
|
||||
|
||||
wrap.appendChild(btn);
|
||||
wrap.appendChild(panel);
|
||||
container.appendChild(wrap);
|
||||
}
|
||||
|
||||
function closeAllFilterDropdowns() {
|
||||
document.querySelectorAll(".filter-dd.open").forEach((el) => el.classList.remove("open"));
|
||||
}
|
||||
|
||||
// Klick irgendwo anders schließt offene Filter-Dropdowns
|
||||
document.addEventListener("click", () => closeAllFilterDropdowns());
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Beim Page-Load Meta einmalig laden (asynchron, blockiert nicht)
|
||||
if (window.API && (localStorage.getItem("token") || window.location.pathname === "/dashboard")) {
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren