nightly: 0.9.27-nightly1

This commit is contained in:
2026-06-23 15:05:40 +02:00
parent 710c4831c2
commit d20308cf2c
7 changed files with 295 additions and 37 deletions

View File

@@ -44,6 +44,62 @@ var ACE_DRY_PRESETS={
custom_3:{name:'Custom 3',temp:45,duration_sec:4*3600}
};
// Spoolman state
var _spoolmanStatus={configured:false,server:'',sync_rate:0,slot_spools:{}};
var _spoolmanSpools=[];
var _slotSpoolMap={}; // {String(global_index): spoolman_spool_id} — last committed assignment
function _loadSpoolmanStatus(){
fetch(_apiUrl('/kx/spoolman/status')).then(function(r){return r.json();}).then(function(d){
_spoolmanStatus=d;
_slotSpoolMap=d.slot_spools||{};
}).catch(function(){});
}
function _buildSpoolmanSection(){
var sec=document.getElementById('fd-spoolman-section');
var rows=document.getElementById('fd-spoolman-rows');
var loading=document.getElementById('fd-spoolman-loading');
if(!sec||!rows)return;
if(!_spoolmanStatus.configured){sec.style.display='none';return;}
sec.style.display='';
rows.innerHTML='';
if(loading)loading.style.display='';
var usedSlots={};
document.querySelectorAll('#fd-slots select').forEach(function(sel){
var idx=parseInt(sel.value);
if(idx>=0){
var slot=(_amsSlots||[]).find(function(s){return s.slot_index===idx;});
if(slot&&!usedSlots[idx])usedSlots[idx]=slot;
}
});
fetch(_apiUrl('/kx/spoolman/spools')).then(function(r){return r.json();}).then(function(d){
if(loading)loading.style.display='none';
_spoolmanSpools=d.spools||[];
var slotKeys=Object.keys(usedSlots).map(Number).sort(function(a,b){return a-b;});
if(!slotKeys.length){rows.innerHTML='<span style="font-size:11px;color:var(--txt2)"></span>';return;}
rows.innerHTML=slotKeys.map(function(idx){
var slot=usedSlots[idx];
var col=(slot.color_hex||'#888');
var currentSpool=_slotSpoolMap[String(idx)]||'';
var opts='<option value=""></option>'+_spoolmanSpools.map(function(sp){
var rem=sp.remaining_weight!=null?' ('+sp.remaining_weight.toFixed(0)+'g)':'';
var vendor=sp.filament&&sp.filament.vendor?sp.filament.vendor+' ':'';
var name=sp.filament&&sp.filament.name?sp.filament.name:'Spool';
return '<option value="'+sp.id+'"'+(sp.id==currentSpool?' selected':'')+'>'+
escHtml('#'+sp.id+' '+vendor+name+rem)+'</option>';
}).join('');
return '<div style="display:flex;align-items:center;gap:8px;font-size:12px">'+
'<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:'+col+';border:1px solid var(--border);flex-shrink:0"></span>'+
'<span style="color:var(--txt2);min-width:46px">Slot '+(idx+1)+'</span>'+
'<select data-spool-slot="'+idx+'" style="flex:1;padding:3px 6px;border-radius:6px;border:1px solid var(--border);background:var(--raised);color:var(--txt);font-size:12px">'+
opts+'</select></div>';
}).join('');
}).catch(function(){if(loading)loading.style.display='none';});
}
function _aceAutoRefillGet(aceId){return !!aceAutoRefillPrefs[String(aceId)];}
function _aceAutoRefillSet(aceId,on){
aceAutoRefillPrefs[String(aceId)]=!!on;
@@ -2494,6 +2550,7 @@ function openFilamentDialog(slots){
_amsSlots=slots
.filter(function(s){return s.status==='loaded';})
.sort(function(a,b){return (a.slot_index||0)-(b.slot_index||0);});
_loadSpoolmanStatus();
var dlg=document.getElementById('filament-dialog');
var title=document.getElementById('fd-title');
var body=document.getElementById('fd-slots');
@@ -2623,6 +2680,8 @@ function openFilamentDialog(slots){
}).join('');
}
if(dlg)dlg.classList.add('open');
// Spoolman-Section nach Slot-Render aufbauen (braucht die selects im DOM)
setTimeout(_buildSpoolmanSection, 0);
}
function closeFilamentDialog(){
@@ -2675,6 +2734,17 @@ function confirmFilamentPrint(){
var excludedObjects=_printObjects.filter(function(o){return o.skip;}).map(function(o){return o.name;});
var fdAlEl=document.getElementById('fd-auto-leveling');
var fdAutoLeveling=fdAlEl?( fdAlEl.checked?1:0):(S.auto_leveling===undefined?1:S.auto_leveling?1:0);
// Spoolman: Slot→Spool-Mapping aus Dialog sammeln und senden
if(_spoolmanStatus.configured){
var slotMap={};
document.querySelectorAll('[data-spool-slot]').forEach(function(sel){
var idx=sel.dataset.spoolSlot;
var val=parseInt(sel.value);
if(val>0)slotMap[idx]=val;
});
_slotSpoolMap=slotMap;
post('/kx/spoolman/active-spool',{slot_map:slotMap}).catch(function(){});
}
closeFilamentDialog();
if(_filamentDialogMode==='banner'){
// Banner-Modus: /kx/print bevorzugen wenn _storeFileId bekannt (gleicher Pfad wie File-Browser).

View File

@@ -646,6 +646,13 @@
<label for="fd-auto-leveling" style="margin:0;cursor:pointer;font-size:13px" id="fd-lbl-auto-leveling">Auto-Leveling</label>
</div>
</div>
<div id="fd-spoolman-section" style="display:none;margin-bottom:16px;border-top:1px solid var(--border);padding-top:12px">
<p style="font-size:12px;color:var(--txt2);margin-bottom:8px;display:flex;align-items:center;gap:6px">
<span id="fd-spoolman-lbl">🧵 Spoolman</span>
<span id="fd-spoolman-loading" style="display:none;font-size:10px"></span>
</p>
<div id="fd-spoolman-rows" style="display:flex;flex-direction:column;gap:6px"></div>
</div>
<div style="display:flex;gap:8px;justify-content:flex-end">
<button id="fd-cancel" onclick="closeFilamentDialog()" style="padding:8px 16px;background:var(--raised);border:1px solid var(--border);border-radius:8px;color:var(--txt);cursor:pointer">Abbrechen</button>
<button id="fd-print" onclick="confirmFilamentPrint()" style="padding:8px 18px;background:var(--accent);color:#fff;border:none;border-radius:8px;cursor:pointer;font-weight:600">▶ Drucken</button>