diff --git a/.env.example b/.env.example index a30bdd2..aa0393a 100644 --- a/.env.example +++ b/.env.example @@ -51,16 +51,20 @@ GLPI_KB_LIMIT=500 GLPI_KB_SYNC_INTERVAL=10m GLPI_KB_SOURCE=GLPI Knowledge Base -# Runtime controls. These defaults can later be changed live in the web UI. -# Empty category lists mean "all categories". Values are comma-separated. +# Runtime controls. Boolean/view/performance values are WebUI defaults. +# Source lists are initial WebUI defaults only; runtime-settings.json takes precedence afterwards. +# Empty lists mean unrestricted. Values must exactly match the KB JSON source field. BRAIN_LEARNING_ENABLED=true BRAIN_THINKING_ENABLED=true -BRAIN_LEARNING_CATEGORIES= -BRAIN_DISPLAY_CATEGORIES= -BRAIN_THINKING_CATEGORIES= -BRAIN_DEFAULT_VIEW=neural +# Initial exact source selections; empty = all sources. +BRAIN_LEARNING_SOURCES= +BRAIN_DISPLAY_SOURCES= +BRAIN_THINKING_SOURCES= +BRAIN_DEFAULT_VIEW=neural # neural | honeycomb | constellation # 0 = unbegrenzt; Webinterface kann den Wert zur Laufzeit ändern BRAIN_MAX_DISPLAY_NODES=0 +# Browser-Rendering auf 30 FPS, geringere DPR und reduzierte Effektkosten optimieren. +BRAIN_LOW_POWER_MODE=false # Sequential enrichment BRAIN_AUTO_ENRICH=true diff --git a/CHANGELOG-FILTER-PANEL-SCROLL.md b/CHANGELOG-FILTER-PANEL-SCROLL.md new file mode 100644 index 0000000..0c472d0 --- /dev/null +++ b/CHANGELOG-FILTER-PANEL-SCROLL.md @@ -0,0 +1,13 @@ +# Filter panel scroll fix + +## Änderung + +Die Inhalte der Seitenleiste **FILTER / BRAIN CONTROL** liegen jetzt in einem eigenen vertikal scrollbaren Bereich. + +- Kopfzeile und Schaltfläche **ÜBERNEHMEN** bleiben erreichbar. +- Betriebsmodi, Performance, SearXNG-Diagnose und alle Source-Filter können unabhängig von der Bildschirmhöhe erreicht werden. +- Mausrad, Touch-Scrollen und Tastaturfokus werden unterstützt. +- Eine schmale, zum UI passende Scrollbar ist in Firefox und Chromium sichtbar. +- Horizontales Überlaufen wird unterdrückt; das Scrollen bleibt auf die Seitenleiste begrenzt. + +Es wurden keine Runtime-, Filter- oder Backend-Semantiken verändert. diff --git a/SHA256SUMS.txt b/SHA256SUMS.txt index 8a6f449..5917455 100644 --- a/SHA256SUMS.txt +++ b/SHA256SUMS.txt @@ -1,6 +1,7 @@ 478e5158150ff119d661f1d9dcd02565ac9181db77b666289b860d45ed92b896 ./.env.example 8955cfbeff229e73f0cad664863ff21711c270a4233c3225680c89aa6268a901 ./ARCHITECTURE.md 2bc149241c2d25f755e4a0470dc517f646527ee3e98d3a6c2e7798639bd70866 ./CHANGELOG-CONSTELLATION-ECO-TRANSITIONS.md +933cdaeae7895e31d2281d591a75f23f07e7c41d356638654bac4f5e7a20a069 ./CHANGELOG-FILTER-PANEL-SCROLL.md 213ac897cd415bbeb9764a847843b9eff366983cf25bb3cbce4efa4c04b9e5f5 ./CHANGELOG-GLPI-POOL-PERSISTENCE.md e2f1f0400999cb59b8be09bc2743e06e0a0b2ecdc44a583af7c9a08b70d8509e ./CHANGELOG-GPU-NODE-LIMIT.md a317376127be1e47b9ec9f0781fcfebdcbf7fccfaeb7840d9241f9586048fadb ./CHANGELOG-GROUNDED-KNOWLEDGE-SYNTHESIS.md @@ -80,8 +81,8 @@ e7138877303bcc07c429323c4792fed112d8c16d35fd44222fe144ab0b69344f ./internal/res a46b953c22fb2aef112b11ba65c61bda1e1582903e39489c2d081d17519ebd9d ./internal/research/searxng.go 2f82e80ad91590f419b1bbb19647b5191596e97c4d765e8736c1867ad899d457 ./internal/research/searxng_test.go 500aa5830effdb248b08bf5e25d58920ab9a5bdb49ca8b18265f02435e2ccaf7 ./internal/web/server.go -e601277536f59c6064e643726a44cebaf67b2a8aad54039f45ff75dddd9b4a5d ./internal/web/server_test.go -5a1c81aa6e77e1408f3cfa86f9ad2c3dc6345b7d451a02e5c9524d0917bdc682 ./internal/web/static/app.css +12c30cf7d223e413abc69579eda36971a2d1f69a7e5973005ee31783fba9bf4b ./internal/web/server_test.go +752659210dcf681329c29dbb33a0c02a628b950c897d3dc88b9eb50afd343a8a ./internal/web/static/app.css ecc55c4fad6d1b470ae5d546798339e1d1a63d47c1b21a311340b1458dee9e7e ./internal/web/static/app.js -4446cd59b91abb9e81b74ff66b1fb1aee63f891c36829c192c83308313653f94 ./internal/web/static/index.html +238d5fd766f9cb2e947d333251ba9e933aa66f81b792b1196fd138426f401ca9 ./internal/web/static/index.html 83aded814b6225395935e61fe957963c3c470f368fc9089f505b6de23e959115 ./preview.png diff --git a/internal/web/server_test.go b/internal/web/server_test.go index 17615bf..5c58b39 100644 --- a/internal/web/server_test.go +++ b/internal/web/server_test.go @@ -129,3 +129,37 @@ func TestResearchDiagnosticAPI(t *testing.T) { t.Fatalf("unexpected status: %#v", status) } } + +func TestSettingsPanelContentIsScrollable(t *testing.T) { + broker := activity.New(4) + h := (&Server{Broker: broker}).Handler() + + res := httptest.NewRecorder() + h.ServeHTTP(res, httptest.NewRequest(http.MethodGet, "/", nil)) + if res.Code != http.StatusOK { + t.Fatalf("GET / returned %d: %s", res.Code, res.Body.String()) + } + body := res.Body.String() + if !strings.Contains(body, `class="settings-scroll"`) { + t.Fatal("settings panel is missing its scroll container") + } + if !strings.Contains(body, `class="settings-footer"`) { + t.Fatal("settings footer is missing") + } + + res = httptest.NewRecorder() + h.ServeHTTP(res, httptest.NewRequest(http.MethodGet, "/app.css", nil)) + if res.Code != http.StatusOK { + t.Fatalf("GET /app.css returned %d: %s", res.Code, res.Body.String()) + } + css := res.Body.String() + for _, expected := range []string{ + ".settings-scroll{flex:1;min-height:0;overflow-y:auto", + "overscroll-behavior:contain", + ".settings-footer{flex:0 0 auto", + } { + if !strings.Contains(css, expected) { + t.Fatalf("scroll CSS is missing %q", expected) + } + } +} diff --git a/internal/web/static/app.css b/internal/web/static/app.css index c562f5e..34e391c 100644 --- a/internal/web/static/app.css +++ b/internal/web/static/app.css @@ -36,13 +36,13 @@ html,body{margin:0;width:100%;height:100%;overflow:hidden;background:radial-grad body.honeycomb-view .legend{opacity:.58}body.honeycomb-view .mode-status small:after{content:" · Honeycomb"} .settings-backdrop{position:fixed;inset:0;z-index:20;background:rgba(0,3,9,.55);backdrop-filter:blur(3px)} .settings-panel{position:fixed;z-index:21;right:18px;top:18px;bottom:18px;width:min(460px,calc(100vw - 36px));border-radius:20px;padding:16px;display:flex;flex-direction:column;overflow:hidden} -.settings-header{display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line);padding:2px 2px 13px}.settings-header strong{display:block;font-size:12px;letter-spacing:.17em}.settings-header small{display:block;margin-top:4px;color:var(--muted);font-size:10px}.settings-header button{border:0;background:transparent;color:var(--muted);font-size:24px;cursor:pointer;padding:0 5px} +.settings-header{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line);padding:2px 2px 13px}.settings-header strong{display:block;font-size:12px;letter-spacing:.17em}.settings-header small{display:block;margin-top:4px;color:var(--muted);font-size:10px}.settings-header button{border:0;background:transparent;color:var(--muted);font-size:24px;cursor:pointer;padding:0 5px} .settings-section{padding:14px 2px;border-bottom:1px solid var(--line)}.settings-section h2{font-size:10px;letter-spacing:.17em;text-transform:uppercase;color:#9eb5c6;margin:0 0 10px}.settings-section-title{display:flex;justify-content:space-between;align-items:center}.settings-section-title span{font-size:9px;color:#668094} .switch-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:9px 10px;margin:7px 0;border:1px solid rgba(133,200,255,.1);border-radius:12px;background:rgba(255,255,255,.022);cursor:pointer}.switch-row b{display:block;font-size:11px}.switch-row small{display:block;margin-top:3px;color:#718b9e;font-size:9px;line-height:1.35}.switch-row input{appearance:none;width:38px;height:21px;border-radius:999px;background:rgba(119,146,168,.25);position:relative;cursor:pointer;flex:0 0 auto;outline:1px solid rgba(255,255,255,.06)}.switch-row input:after{content:"";position:absolute;width:15px;height:15px;left:3px;top:3px;border-radius:50%;background:#8196a7;transition:transform .2s,background .2s,box-shadow .2s}.switch-row input:checked{background:rgba(82,231,255,.19)}.switch-row input:checked:after{transform:translateX(17px);background:var(--cyan);box-shadow:0 0 10px rgba(82,231,255,.7)} .view-selector{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:10px}.view-selector button{border:1px solid rgba(133,200,255,.12);background:rgba(255,255,255,.025);color:#738da1;border-radius:10px;padding:9px;font-size:10px;font-weight:700;letter-spacing:.1em;cursor:pointer}.view-selector button.active{color:var(--green);border-color:rgba(93,255,189,.24);background:rgba(93,255,189,.07)} -.category-settings{flex:1;min-height:0;overflow:auto;padding-right:5px}.filter-search{display:block;margin-bottom:12px}.filter-search span{display:block;font-size:9px;color:#6d879a;margin-bottom:5px}.filter-search input{width:100%;border:1px solid rgba(133,200,255,.14);background:rgba(2,8,17,.6);color:var(--text);border-radius:10px;padding:9px 10px;outline:0}.filter-search input:focus{border-color:rgba(82,231,255,.38);box-shadow:0 0 0 3px rgba(82,231,255,.06)} +.settings-scroll{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding-right:7px;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:rgba(82,231,255,.28) transparent}.settings-scroll::-webkit-scrollbar{width:8px}.settings-scroll::-webkit-scrollbar-track{background:transparent}.settings-scroll::-webkit-scrollbar-thumb{border:2px solid transparent;border-radius:999px;background:rgba(82,231,255,.24);background-clip:padding-box}.settings-scroll::-webkit-scrollbar-thumb:hover{background:rgba(82,231,255,.42);background-clip:padding-box}.settings-scroll:focus-visible{outline:1px solid rgba(82,231,255,.28);outline-offset:3px;border-radius:10px}.settings-scroll .settings-section:last-child{border-bottom:0;padding-bottom:20px}.filter-search{display:block;margin-bottom:12px}.filter-search span{display:block;font-size:9px;color:#6d879a;margin-bottom:5px}.filter-search input{width:100%;border:1px solid rgba(133,200,255,.14);background:rgba(2,8,17,.6);color:var(--text);border-radius:10px;padding:9px 10px;outline:0}.filter-search input:focus{border-color:rgba(82,231,255,.38);box-shadow:0 0 0 3px rgba(82,231,255,.06)} .filter-block{margin:12px 0 16px}.filter-heading{display:flex;align-items:center;justify-content:space-between;margin-bottom:7px}.filter-heading b{display:block;font-size:10px;color:#c8d9e4}.filter-heading small{display:block;margin-top:2px;color:#607b90;font-size:9px}.filter-heading button{border:1px solid rgba(82,231,255,.13);background:rgba(82,231,255,.04);color:#87a8bc;border-radius:8px;padding:5px 8px;font-size:8px;letter-spacing:.08em;cursor:pointer}.source-list{display:flex;flex-wrap:wrap;gap:5px;max-height:128px;overflow:auto;padding:1px}.source-option{position:relative}.source-option input{position:absolute;opacity:0;pointer-events:none}.source-option span{display:block;border:1px solid rgba(133,200,255,.12);background:rgba(255,255,255,.022);color:#7893a6;border-radius:999px;padding:5px 8px;font-size:9px;cursor:pointer;white-space:nowrap}.source-option input:checked+span{color:#dffaff;border-color:rgba(82,231,255,.32);background:rgba(82,231,255,.11);box-shadow:0 0 12px rgba(82,231,255,.05)}.source-option em{font-style:normal;opacity:.58;margin-left:4px} -.settings-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-top:13px}.settings-footer span{font-size:9px;color:#7f9aac;line-height:1.35}.settings-footer button{border:1px solid rgba(82,231,255,.3);background:rgba(82,231,255,.1);color:var(--cyan);border-radius:11px;padding:10px 13px;font-size:9px;font-weight:800;letter-spacing:.13em;cursor:pointer}.settings-footer button:disabled{opacity:.5;cursor:wait} +.settings-footer{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:12px;padding-top:13px}.settings-footer span{font-size:9px;color:#7f9aac;line-height:1.35}.settings-footer button{border:1px solid rgba(82,231,255,.3);background:rgba(82,231,255,.1);color:var(--cyan);border-radius:11px;padding:10px 13px;font-size:9px;font-weight:800;letter-spacing:.13em;cursor:pointer}.settings-footer button:disabled{opacity:.5;cursor:wait} @media(max-width:1100px){.dock{max-width:calc(100vw - 40px)}.settings-panel{right:10px;top:10px;bottom:10px}} @media(max-width:780px){.settings-panel{left:10px;width:auto}.dock{max-width:calc(100vw - 20px)}.dock-separator{display:none}} diff --git a/internal/web/static/index.html b/internal/web/static/index.html index 6c7976e..a548c9d 100644 --- a/internal/web/static/index.html +++ b/internal/web/static/index.html @@ -79,6 +79,7 @@ +

Betriebsmodi

+