diff --git a/web/themes/default/app.js b/web/themes/default/app.js index b843bd7..58c7845 100644 --- a/web/themes/default/app.js +++ b/web/themes/default/app.js @@ -329,43 +329,46 @@ function initPrinters(){ var idx=window._printerIndex||1; _activePrinter=_printers.find(function(p){return String(p.id)===String(idx)})||_printers[0]||null; renderPrinterDropdown(); - _initDashboardPowerCard(); }).catch(function(){}); } -// ── Dashboard Power Switch (Issue: hard to find + poorly visible in the +// ── Header Power Switch (Issue: hard to find + poorly visible in the // Printers tab; mirrors togglePrinterPower()/​_refreshPrinterPowerIcon() for -// the active printer, on a second, more prominent toggle on the Dashboard) ── -function _initDashboardPowerCard(){ - var card=document.getElementById('card-power'); - if(!card)return; - if(!_activePrinter||!_activePrinter.has_power_control){card.style.display='none';return;} - card.style.display=''; - _refreshDashboardPower(); +// the currently active printer, right next to its name/status in the header +// so it works the same in single- and multi-printer setups - switching the +// active printer via the dropdown re-evaluates has_power_control for the +// newly active one instead of a fixed dashboard card tied to whichever +// printer happened to be active on page load) ── +function _initHeaderPower(){ + var wrap=document.getElementById('h-power-wrap'); + if(!wrap)return; + if(!_activePrinter||!_activePrinter.has_power_control){wrap.style.display='none';return;} + wrap.style.display='flex'; + _refreshHeaderPower(); } -function _refreshDashboardPower(){ +function _refreshHeaderPower(){ if(!_activePrinter||!_activePrinter.has_power_control)return; var bridgeUrl=(_activePrinter.bridge_url||'').replace(/\/+$/,''); fetch(bridgeUrl+'/kx/printers/'+encodeURIComponent(_activePrinter.id)+'/power-status',{signal:AbortSignal.timeout(5000)}) .then(function(r){return r.json()}) .then(function(d){ - var onBtn=document.getElementById('d-power-on'), offBtn=document.getElementById('d-power-off'); + var onBtn=document.getElementById('h-power-on'), offBtn=document.getElementById('h-power-off'); if(!onBtn||!offBtn)return; onBtn.classList.toggle('spd-active',d.state==='on'); offBtn.classList.toggle('spd-active',d.state==='off'); }) .catch(function(){/* status endpoint optional - toggle just stays neutral */}); } -function setDashboardPower(action){ +function setHeaderPower(action){ if(!_activePrinter)return; if(action==='off'&&!confirm(T.printers_power_off_confirm||'Turn printer power off? Make sure no print is running.'))return; - var onBtn=document.getElementById('d-power-on'), offBtn=document.getElementById('d-power-off'); + var onBtn=document.getElementById('h-power-on'), offBtn=document.getElementById('h-power-off'); if(onBtn)onBtn.style.opacity='0.5'; if(offBtn)offBtn.style.opacity='0.5'; post('/kx/printers/'+encodeURIComponent(_activePrinter.id)+'/power',{action:action}).then(function(){ if(onBtn)onBtn.style.opacity='1'; if(offBtn)offBtn.style.opacity='1'; - setTimeout(_refreshDashboardPower,1500); + setTimeout(_refreshHeaderPower,1500); }).catch(function(e){ if(onBtn)onBtn.style.opacity='1'; if(offBtn)offBtn.style.opacity='1'; @@ -395,6 +398,7 @@ function renderPrinterDropdown(){ if(wrap)wrap.style.display='none'; if(single)single.style.display=''; } + _initHeaderPower(); } function togglePrinterDropdown(){ var menu=document.getElementById('printer-dropdown-menu'); @@ -460,9 +464,8 @@ function applyLang(){ setText('d-card-temps',T.card_temps); setText('d-card-lightfan',T.card_light_fan); setText('d-card-speed',T.card_speed); - setText('d-card-power',T.card_power); - setText('d-power-lbl-on',T.printers_power_on_short||'An'); - setText('d-power-lbl-off',T.printers_power_off_short||'Aus'); + setText('h-power-lbl-on',T.printers_power_on_short||'An'); + setText('h-power-lbl-off',T.printers_power_off_short||'Aus'); setText('d-card-cam',T.card_cam); setText('d-card-ams',T.panel_ams_title); setText('d-lbl-elapsed',T.lbl_elapsed); @@ -2137,7 +2140,7 @@ var pollTimer; }).catch(function(){}); poll();pollTimer=setInterval(poll,ms); setInterval(_loadSpoolmanStatus,30000); - setInterval(_refreshDashboardPower,30000); + setInterval(_refreshHeaderPower,30000); // initDashGrid() is called at the very end of the file, after all the // DASH_* var declarations below have executed (they are hoisted but not yet // assigned at this point in the IIFE). @@ -2154,7 +2157,7 @@ var pollTimer; // - columnOpts.breakpoints -> 1-column below 700px GRID width (sidebar-aware) var DASH_STORAGE_KEY='dashLayout'; var DASH_LAYOUT_VERSION=3; // v1/v2 = older editors; discard those states -var DASH_CARD_KEYS=['camera','progress','temps','motion','speed','power','fan','ams']; +var DASH_CARD_KEYS=['camera','progress','temps','motion','speed','fan','ams']; // Layout arrays in GridStack save()/load() format. cellHeight=60px. var DASH_DEFAULT_LAYOUT=[ {id:'camera', x:0,y:0, w:12,h:7}, @@ -2162,9 +2165,8 @@ var DASH_DEFAULT_LAYOUT=[ {id:'temps', x:0,y:13,w:6, h:7}, {id:'motion', x:6,y:13,w:6, h:7}, {id:'speed', x:0,y:20,w:6, h:3}, - {id:'power', x:6,y:20,w:6, h:3}, - {id:'fan', x:0,y:23,w:6, h:3}, - {id:'ams', x:0,y:26,w:12,h:4}, + {id:'fan', x:6,y:20,w:6, h:3}, + {id:'ams', x:0,y:23,w:12,h:4}, ]; // "Wide desktop" preset (Blaim, Issue #89): big camera left, settings center, // motion right. @@ -2242,20 +2244,6 @@ function initDashGrid(){ var item=_dashItem(n.id); if(item){_dashGrid.removeWidget(item,false);item.style.display='none';} }); - // Cards added after a user's layout was already saved (e.g. the "power" - // card) never appear otherwise: load(...,false) only updates ids already - // present in the saved layout, it never adds new ones. Append any missing - // known card next to its default-layout neighbour instead of silently - // dropping it - the alternative (bumping DASH_LAYOUT_VERSION) would wipe - // every user's custom layout just to surface one new card. - var known={}; - state.layout.forEach(function(n){known[n.id]=true;}); - _dashHidden.forEach(function(n){known[n.id]=true;}); - DASH_DEFAULT_LAYOUT.forEach(function(def){ - if(known[def.id])return; - var item=_dashItem(def.id); - if(item)_dashGrid.addWidget(item,{x:def.x,y:def.y,w:def.w,h:def.h}); - }); }else{ _dashGrid.load(DASH_DEFAULT_LAYOUT,false); } diff --git a/web/themes/default/index.html b/web/themes/default/index.html index 644ead4..e47a7f1 100644 --- a/web/themes/default/index.html +++ b/web/themes/default/index.html @@ -35,6 +35,10 @@
Anycubic Kobra X
+
Standby
@@ -335,21 +339,6 @@ - - -
🌀 Lüfter
diff --git a/web/themes/default/style.css b/web/themes/default/style.css index 3e1a248..c7e6853 100644 --- a/web/themes/default/style.css +++ b/web/themes/default/style.css @@ -202,6 +202,10 @@ main{flex:1;overflow-y:auto;padding:20px} .spd-btn .spd-icon{font-size:22px} .spd-bar{height:4px;border-radius:2px;background:var(--border);margin-top:10px;overflow:hidden} .spd-bar-fill{height:100%;border-radius:2px;background:linear-gradient(90deg,var(--accent2),var(--accent));transition:width .3s} +.h-power-btn{border:1.5px solid transparent;background:none;color:var(--txt2); + border-radius:5px;padding:3px 8px;font-size:12px;font-weight:600;cursor:pointer;transition:all .15s} +.h-power-btn:hover{color:var(--txt)} +.h-power-btn.spd-active{border-color:var(--accent);background:rgba(0,200,255,.12);color:var(--accent)} /* ── TIME CARDS ── */ .time-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-top:8px}