From d164630bb8769b7ec3a4fcac634e07534e855ace Mon Sep 17 00:00:00 2001 From: EJClaw Date: Wed, 26 Aug 2026 23:40:56 +0900 Subject: [PATCH] feat(dashboard): drag-resizable event/error log dock height (persisted) Add a drag handle on the top edge of the bottom log dock so its height can be adjusted freely (80px .. 82vh), persisted in localStorage. Dock max-height raised to 90vh; syncDockPad keeps the page bottom padding in step so the last turn never hides behind the dock. Handle is hidden while the dock is collapsed. Co-Authored-By: Claude Opus 4.7 --- wsai/dashboard.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/wsai/dashboard.py b/wsai/dashboard.py index 669cffe..5f1c425 100644 --- a/wsai/dashboard.py +++ b/wsai/dashboard.py @@ -936,7 +936,13 @@ PAGE = r""" main{padding-bottom:46px} .logdock{position:fixed;left:0;right:0;bottom:0;z-index:15;background:#0a0e13; border-top:1px solid var(--line);display:flex;flex-direction:column; - max-height:45vh;box-shadow:0 -8px 24px rgba(0,0,0,.35)} + max-height:90vh;box-shadow:0 -8px 24px rgba(0,0,0,.35)} + .logresize{height:7px;cursor:ns-resize;background:#0d141c;border-bottom:1px solid var(--line); + flex:0 0 auto;touch-action:none} + .logresize:hover{background:#1d3d54} + .logresize::before{content:"";display:block;width:44px;height:3px;margin:2px auto 0; + border-radius:2px;background:#2a3a49} + .logdock.collapsed .logresize{display:none} .logbar{display:flex;align-items:center;gap:8px;padding:6px 12px;border-bottom:1px solid var(--line); background:#0d141c;flex-wrap:wrap} .logtoggle{background:none;border:none;color:var(--fg);font-size:12.5px;cursor:pointer;font-weight:600;padding:4px 6px} @@ -1071,6 +1077,7 @@ PAGE = r"""
아직 대화가 없습니다. 사용자가 말하면 여기에 단계별로 나타납니다.
+
@@ -1509,6 +1516,26 @@ $('logToggle').onclick = ()=>{ syncDockPad(); }; window.addEventListener('resize', syncDockPad); +// Drag the top edge of the log dock to resize its height (persisted). +(function(){ + const dock=$('logdock'), body=$('logbody'), handle=$('logResize'); + const KEY='wsai_logH'; + const maxH = ()=> Math.round(window.innerHeight*0.82); + function setH(px){ const h=Math.max(80, Math.min(maxH(), Math.round(px))); + body.style.height=h+'px'; localStorage.setItem(KEY, h); syncDockPad(); } + setH(parseInt(localStorage.getItem(KEY)||'180', 10)); + let startY=0, startH=0, dragging=false; + handle.addEventListener('pointerdown', (e)=>{ + if(dock.classList.contains('collapsed')) return; + dragging=true; startY=e.clientY; startH=body.offsetHeight; + try{ handle.setPointerCapture(e.pointerId); }catch(_){} + e.preventDefault(); + }); + handle.addEventListener('pointermove', (e)=>{ if(dragging) setH(startH + (startY - e.clientY)); }); + const end=(e)=>{ if(!dragging) return; dragging=false; try{ handle.releasePointerCapture(e.pointerId); }catch(_){} }; + handle.addEventListener('pointerup', end); + handle.addEventListener('pointercancel', end); +})(); $('logSearch').oninput = renderLogs; $('logLevel').onchange = renderLogs; $('logClear').onclick = async ()=>{