build: sources for v0.9.19
This commit is contained in:
@@ -312,6 +312,17 @@ function applyLang(){
|
||||
setText('modal-sec-print',T.settings_print);
|
||||
setText('modal-sec-poll',T.settings_poll);
|
||||
setText('modal-sec-version',T.settings_version);
|
||||
// Custom-Profile-Import (Issue #41)
|
||||
setText('modal-sec-orca-profiles',T.orca_profile_section);
|
||||
setText('orca-profiles-hint',T.orca_profile_hint);
|
||||
setText('lbl-orca-profiles-import',T.orca_profile_import_btn);
|
||||
setText('lbl-slot-profile-import',T.orca_profile_import_link);
|
||||
setText('profile-import-title',T.orca_profile_import_title);
|
||||
setText('profile-import-dropmsg',T.orca_profile_dropmsg);
|
||||
setText('profile-import-list-label',T.orca_profile_list_label);
|
||||
// Hilfe-Text mit Inline-HTML — innerHTML statt setText
|
||||
var helpEl=document.getElementById('profile-import-help');
|
||||
if(helpEl && T.orca_profile_help_html) helpEl.innerHTML=T.orca_profile_help_html;
|
||||
setText('btn-save-settings',T.settings_save);
|
||||
setText('lbl-printer-name',T.settings_printer_name);
|
||||
setText('lbl-printer-ip',T.settings_printer_ip);
|
||||
@@ -903,11 +914,110 @@ function openSettings(){
|
||||
var cl=document.getElementById('update-changelog');if(cl)cl.style.display='none';
|
||||
_updateTag='';_updateUrl='';
|
||||
document.getElementById('settings-modal').classList.add('open');
|
||||
// Custom-Profile-Liste laden (Issue #41 — Verwaltung von User-importierten
|
||||
// OrcaSlicer-Filament-Profilen)
|
||||
refreshUserProfileList();
|
||||
}
|
||||
function closeSettings(){
|
||||
document.getElementById('settings-modal').classList.remove('open');
|
||||
}
|
||||
|
||||
// ── Custom Filament Profile Import (Issue #41) ──
|
||||
function refreshUserProfileList(){
|
||||
var listEl=document.getElementById('orca-profiles-list');
|
||||
if(!listEl) return;
|
||||
fetch(_apiUrl('/kx/filament/profiles/user')).then(function(r){return r.json();}).then(function(d){
|
||||
var profs=(d && d.result)||[];
|
||||
if(!profs.length){
|
||||
listEl.innerHTML='<i style="color:var(--txt2)">'+(tr('orca_profile_user_empty')||'– keine –')+'</i>';
|
||||
return;
|
||||
}
|
||||
listEl.innerHTML=profs.map(function(p){
|
||||
var label=p.vendor+' / '+p.name+' ('+p.type+')';
|
||||
return '<div style="display:flex;justify-content:space-between;align-items:center;padding:3px 0;border-bottom:1px solid var(--border)">'
|
||||
+'<span>★ '+label+'</span>'
|
||||
+'<button onclick="deleteUserProfile(\''+encodeURIComponent(p.vendor)+'\',\''+encodeURIComponent(p.name)+'\')" '
|
||||
+'style="background:none;border:none;color:var(--err);cursor:pointer;font-size:14px" title="löschen">🗑</button>'
|
||||
+'</div>';
|
||||
}).join('');
|
||||
}).catch(function(){});
|
||||
}
|
||||
function deleteUserProfile(vendor, name){
|
||||
fetch(_apiUrl('/kx/filament/profiles/user?vendor='+vendor+'&name='+name), {method:'DELETE'})
|
||||
.then(function(r){return r.json();})
|
||||
.then(function(){
|
||||
_orcaFilamentCache=null;
|
||||
refreshUserProfileList();
|
||||
// Falls Import-Dialog offen ist, dort auch refreshen
|
||||
refreshImportDialogList();
|
||||
});
|
||||
}
|
||||
function openProfileImport(){
|
||||
document.getElementById('profile-import-status').textContent='';
|
||||
refreshImportDialogList();
|
||||
document.getElementById('profile-import-modal').classList.add('open');
|
||||
}
|
||||
function closeProfileImport(){
|
||||
document.getElementById('profile-import-modal').classList.remove('open');
|
||||
}
|
||||
function refreshImportDialogList(){
|
||||
var el=document.getElementById('profile-import-list');
|
||||
if(!el) return;
|
||||
fetch(_apiUrl('/kx/filament/profiles/user')).then(function(r){return r.json();}).then(function(d){
|
||||
var profs=(d && d.result)||[];
|
||||
if(!profs.length){
|
||||
el.innerHTML='<i style="color:var(--txt2)">'+(tr('orca_profile_user_empty')||'– keine –')+'</i>';
|
||||
return;
|
||||
}
|
||||
el.innerHTML=profs.map(function(p){
|
||||
var label=p.vendor+' / '+p.name+' ('+p.type+')';
|
||||
return '<div style="display:flex;justify-content:space-between;align-items:center;padding:4px 6px;border-bottom:1px solid var(--border)">'
|
||||
+'<span>★ '+label+'</span>'
|
||||
+'<button onclick="deleteUserProfile(\''+encodeURIComponent(p.vendor)+'\',\''+encodeURIComponent(p.name)+'\')" '
|
||||
+'style="background:none;border:none;color:var(--err);cursor:pointer;font-size:14px" title="löschen">🗑</button>'
|
||||
+'</div>';
|
||||
}).join('');
|
||||
}).catch(function(){});
|
||||
}
|
||||
function doProfileImportUpload(files){
|
||||
if(!files || !files.length) return;
|
||||
var status=document.getElementById('profile-import-status');
|
||||
status.textContent=(tr('orca_profile_uploading')||'Lade hoch…');
|
||||
status.style.color='var(--txt2)';
|
||||
var done=0, totalAdded=0, totalSkipped=0;
|
||||
function _one(idx){
|
||||
if(idx>=files.length){
|
||||
status.textContent=(tr('orca_profile_done')||'Importiert')+': '+totalAdded
|
||||
+(totalSkipped?' / '+totalSkipped+' '+(tr('orca_profile_skipped')||'übersprungen'):'');
|
||||
status.style.color='var(--ok)';
|
||||
_orcaFilamentCache=null;
|
||||
refreshImportDialogList();
|
||||
refreshUserProfileList();
|
||||
// Wenn Slot-Edit offen ist, Dropdown gleich neu befüllen
|
||||
var mat=document.getElementById('slot-edit-mat');
|
||||
if(mat && document.getElementById('slot-edit-modal').classList.contains('open')){
|
||||
_fillSlotProfileDropdown(mat.value, '', '');
|
||||
}
|
||||
return;
|
||||
}
|
||||
var fd=new FormData();
|
||||
fd.append('file', files[idx]);
|
||||
fetch(_apiUrl('/kx/filament/profiles/user'), {method:'POST', body:fd})
|
||||
.then(function(r){return r.json();})
|
||||
.then(function(d){
|
||||
totalAdded += (d.added||0);
|
||||
totalSkipped += (d.skipped||0);
|
||||
done++;
|
||||
_one(idx+1);
|
||||
})
|
||||
.catch(function(e){
|
||||
status.textContent='Fehler: '+e;
|
||||
status.style.color='var(--err)';
|
||||
});
|
||||
}
|
||||
_one(0);
|
||||
}
|
||||
|
||||
// ── AMS Slot Edit ──
|
||||
var _slotEditIndex=-1;
|
||||
var _slotEditLoaded=false;
|
||||
@@ -949,21 +1059,31 @@ function _fillSlotProfileDropdown(material, currentVendor, currentName){
|
||||
return matU==='' || pt===matU || pt.startsWith(matU+'-') || pt.startsWith(matU+' ');
|
||||
});
|
||||
sel.innerHTML='<option value="">'+tr('slot_edit_profile_default')+'</option>';
|
||||
// Gruppieren nach Vendor
|
||||
// User-Profile (is_user) zuerst — eigene Optgroup '★ Eigene' an erster Stelle.
|
||||
var userProfs=matched.filter(function(p){return p.is_user;});
|
||||
var systemProfs=matched.filter(function(p){return !p.is_user;});
|
||||
function _appendOption(g, p){
|
||||
var o=document.createElement('option');
|
||||
o.value=_profileKey(p.vendor, p.name);
|
||||
o.dataset.vendor=p.vendor;
|
||||
o.dataset.name=p.name;
|
||||
o.dataset.id=p.id || '';
|
||||
o.textContent=(p.is_user?'★ ':'')+p.name;
|
||||
if(o.value===wantKey) o.selected=true;
|
||||
g.appendChild(o);
|
||||
}
|
||||
if(userProfs.length){
|
||||
var gUser=document.createElement('optgroup');
|
||||
gUser.label='★ '+(tr('orca_profile_user_label')||'Eigene Profile');
|
||||
userProfs.forEach(function(p){ _appendOption(gUser, p); });
|
||||
sel.appendChild(gUser);
|
||||
}
|
||||
// System-Profile nach Vendor gruppieren
|
||||
var byVendor={};
|
||||
matched.forEach(function(p){ (byVendor[p.vendor]=byVendor[p.vendor]||[]).push(p); });
|
||||
systemProfs.forEach(function(p){ (byVendor[p.vendor]=byVendor[p.vendor]||[]).push(p); });
|
||||
Object.keys(byVendor).sort().forEach(function(v){
|
||||
var g=document.createElement('optgroup'); g.label=v;
|
||||
byVendor[v].forEach(function(p){
|
||||
var o=document.createElement('option');
|
||||
o.value=_profileKey(p.vendor, p.name);
|
||||
o.dataset.vendor=p.vendor;
|
||||
o.dataset.name=p.name;
|
||||
o.dataset.id=p.id || '';
|
||||
o.textContent=p.name;
|
||||
if(o.value===wantKey) o.selected=true;
|
||||
g.appendChild(o);
|
||||
});
|
||||
byVendor[v].forEach(function(p){ _appendOption(g, p); });
|
||||
sel.appendChild(g);
|
||||
});
|
||||
});
|
||||
@@ -1112,6 +1232,10 @@ function saveSlotEdit(){
|
||||
closeSlotEdit();
|
||||
var profSuffix=newProfName?(' ['+newProfVendor+' '+newProfName+']'):'';
|
||||
clog(tr('slot_edit_ok')+' '+(slotIdx+1)+': '+mat+' '+hex+profSuffix,'msg-ok');
|
||||
// Sofortiges Re-Render mit aktuellem _slotProfileMap (poll() ist async
|
||||
// und re-rendert beim nächsten Tick — wir wollen aber dass die Vendor-
|
||||
// Badge JETZT direkt sichtbar wird).
|
||||
if(typeof applyState==='function') applyState();
|
||||
if(typeof poll==='function') poll();
|
||||
})
|
||||
.catch(function(e){clog('Fehler: '+e,'msg-err');});
|
||||
|
||||
@@ -121,6 +121,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- OrcaSlicer-Profile (Custom-Profile-Import, Issue #41) -->
|
||||
<div>
|
||||
<div class="modal-section" id="modal-sec-orca-profiles">OrcaSlicer-Profile</div>
|
||||
<div style="font-size:11px;color:var(--txt2);margin-bottom:8px" id="orca-profiles-hint">
|
||||
Eigene Profile aus OrcaSlicer importieren (User-Dir öffnen via Help → Show Configuration Folder)
|
||||
</div>
|
||||
<div id="orca-profiles-list" style="margin-bottom:8px;font-size:12px;color:var(--txt2)"></div>
|
||||
<button class="btn btn-sm" id="btn-orca-profiles-import" onclick="openProfileImport()"
|
||||
style="background:var(--raised);color:var(--txt)">
|
||||
⬆ <span id="lbl-orca-profiles-import">Profile importieren</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="modal-section" id="modal-sec-version">Version</div>
|
||||
<div class="update-row">
|
||||
@@ -170,12 +183,42 @@
|
||||
<option value="" id="slot-profile-default-opt"></option>
|
||||
</select>
|
||||
<div style="font-size:11px;color:var(--txt2);margin-top:4px" id="slot-profile-hint"></div>
|
||||
<a href="#" onclick="event.preventDefault();openProfileImport()"
|
||||
style="display:inline-block;margin-top:6px;font-size:11px;color:var(--accent);text-decoration:none"
|
||||
id="lbl-slot-profile-import">★ Eigene Profile importieren…</a>
|
||||
</div>
|
||||
<button class="btn" id="btn-slot-edit-feed" style="width:100%;margin-bottom:8px" onclick="slotEditFeed()"></button>
|
||||
<button class="modal-save" id="btn-slot-edit-save" onclick="saveSlotEdit()"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ ORCA-PROFILE-IMPORT-DIALOG (Issue #41) ═══ -->
|
||||
<div class="modal-overlay" id="profile-import-modal" onclick="if(event.target===this)closeProfileImport()">
|
||||
<div class="modal-box" style="max-width:480px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px">
|
||||
<div style="font-size:16px;font-weight:600" id="profile-import-title">Eigene OrcaSlicer-Profile importieren</div>
|
||||
<button onclick="closeProfileImport()" style="background:none;border:none;color:var(--txt2);font-size:20px;cursor:pointer">×</button>
|
||||
</div>
|
||||
<div style="font-size:12px;color:var(--txt2);margin-bottom:12px;line-height:1.5" id="profile-import-help">
|
||||
Lade ein <b>ZIP</b> deines OrcaSlicer-Filament-Ordners oder einzelne <b>.json</b>-Files hoch.<br>
|
||||
In OrcaSlicer: <i>Help → Show Configuration Folder → user/<id>/filament/</i>
|
||||
</div>
|
||||
<div id="profile-import-drop" style="border:2px dashed var(--border);border-radius:8px;padding:24px;text-align:center;cursor:pointer;margin-bottom:12px"
|
||||
ondragover="event.preventDefault();this.style.borderColor='var(--accent)'"
|
||||
ondragleave="this.style.borderColor='var(--border)'"
|
||||
ondrop="event.preventDefault();this.style.borderColor='var(--border)';doProfileImportUpload(event.dataTransfer.files)"
|
||||
onclick="document.getElementById('profile-import-file').click()">
|
||||
<div style="font-size:32px;margin-bottom:8px">⬆</div>
|
||||
<div style="font-size:13px;color:var(--txt2)" id="profile-import-dropmsg">Hierher ziehen oder klicken</div>
|
||||
<input type="file" id="profile-import-file" accept=".zip,.json" multiple
|
||||
style="display:none" onchange="doProfileImportUpload(this.files);this.value=''">
|
||||
</div>
|
||||
<div id="profile-import-status" style="font-size:12px;margin-bottom:12px;min-height:18px"></div>
|
||||
<div style="font-size:11px;color:var(--txt2);margin-bottom:6px" id="profile-import-list-label">Aktuell importiert</div>
|
||||
<div id="profile-import-list" style="max-height:240px;overflow-y:auto;font-size:12px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout">
|
||||
<nav class="sidebar">
|
||||
<button class="nav-btn active" onclick="showPanel('dashboard')" id="nb-dashboard">
|
||||
|
||||
@@ -164,6 +164,19 @@
|
||||
"slot_edit_profile": "OrcaSlicer-Profil",
|
||||
"slot_edit_profile_hint": "Sendet beim OrcaSlicer-Sync die konkrete Marke statt nur „Generic\"",
|
||||
"slot_edit_profile_default": "— Generic (Default) —",
|
||||
"orca_profile_section": "OrcaSlicer-Profile",
|
||||
"orca_profile_hint": "Eigene Profile aus OrcaSlicer importieren (User-Dir öffnen via Help → Show Configuration Folder)",
|
||||
"orca_profile_import_btn": "Profile importieren",
|
||||
"orca_profile_import_link": "★ Eigene Profile importieren…",
|
||||
"orca_profile_import_title": "Eigene OrcaSlicer-Profile importieren",
|
||||
"orca_profile_help_html": "Lade ein <b>ZIP</b> deines OrcaSlicer-Filament-Ordners oder einzelne <b>.json</b>-Files hoch.<br>In OrcaSlicer: <i>Help → Show Configuration Folder → user/<id>/filament/</i>",
|
||||
"orca_profile_dropmsg": "Hierher ziehen oder klicken",
|
||||
"orca_profile_list_label": "Aktuell importiert",
|
||||
"orca_profile_user_label": "Eigene Profile",
|
||||
"orca_profile_user_empty": "– keine –",
|
||||
"orca_profile_uploading": "Lade hoch…",
|
||||
"orca_profile_done": "Importiert",
|
||||
"orca_profile_skipped": "übersprungen",
|
||||
"log_dir_all": "Alle",
|
||||
"log_lvl_label": "Level:",
|
||||
"file_ready_btn": "▶ Druck starten",
|
||||
|
||||
@@ -164,6 +164,19 @@
|
||||
"slot_edit_profile": "OrcaSlicer profile",
|
||||
"slot_edit_profile_hint": "Sent on OrcaSlicer sync as the specific brand instead of just \"Generic\"",
|
||||
"slot_edit_profile_default": "— Generic (default) —",
|
||||
"orca_profile_section": "OrcaSlicer Profiles",
|
||||
"orca_profile_hint": "Import your own OrcaSlicer filament profiles (open the user dir via Help → Show Configuration Folder)",
|
||||
"orca_profile_import_btn": "Import profiles",
|
||||
"orca_profile_import_link": "★ Import own profiles…",
|
||||
"orca_profile_import_title": "Import your OrcaSlicer profiles",
|
||||
"orca_profile_help_html": "Upload a <b>ZIP</b> of your OrcaSlicer filament folder or single <b>.json</b> files.<br>In OrcaSlicer: <i>Help → Show Configuration Folder → user/<id>/filament/</i>",
|
||||
"orca_profile_dropmsg": "Drop here or click",
|
||||
"orca_profile_list_label": "Currently imported",
|
||||
"orca_profile_user_label": "Own profiles",
|
||||
"orca_profile_user_empty": "– none –",
|
||||
"orca_profile_uploading": "Uploading…",
|
||||
"orca_profile_done": "Imported",
|
||||
"orca_profile_skipped": "skipped",
|
||||
"log_dir_all": "All",
|
||||
"log_lvl_label": "Level:",
|
||||
"file_ready_btn": "▶ Start Print",
|
||||
|
||||
@@ -164,6 +164,19 @@
|
||||
"slot_edit_profile": "Perfil de OrcaSlicer",
|
||||
"slot_edit_profile_hint": "Envía al sincronizar con OrcaSlicer la marca concreta en lugar de solo \"Generic\"",
|
||||
"slot_edit_profile_default": "— Genérico (Predeterminado) —",
|
||||
"orca_profile_section": "Perfiles de OrcaSlicer",
|
||||
"orca_profile_hint": "Importa tus propios perfiles de filamento de OrcaSlicer (abre el directorio del usuario vía Help → Show Configuration Folder)",
|
||||
"orca_profile_import_btn": "Importar perfiles",
|
||||
"orca_profile_import_link": "★ Importar perfiles propios…",
|
||||
"orca_profile_import_title": "Importar tus perfiles de OrcaSlicer",
|
||||
"orca_profile_help_html": "Sube un <b>ZIP</b> de tu carpeta de filamentos de OrcaSlicer o archivos <b>.json</b> sueltos.<br>En OrcaSlicer: <i>Help → Show Configuration Folder → user/<id>/filament/</i>",
|
||||
"orca_profile_dropmsg": "Suelta aquí o haz clic",
|
||||
"orca_profile_list_label": "Actualmente importados",
|
||||
"orca_profile_user_label": "Perfiles propios",
|
||||
"orca_profile_user_empty": "– ninguno –",
|
||||
"orca_profile_uploading": "Subiendo…",
|
||||
"orca_profile_done": "Importado",
|
||||
"orca_profile_skipped": "omitido",
|
||||
"log_dir_all": "Todos",
|
||||
"log_lvl_label": "Nivel:",
|
||||
"file_ready_btn": "▶ Iniciar impresión",
|
||||
|
||||
@@ -164,6 +164,19 @@
|
||||
"slot_edit_profile": "OrcaSlicer 配置",
|
||||
"slot_edit_profile_hint": "在 OrcaSlicer 同步时发送具体品牌,而不仅仅是“Generic”",
|
||||
"slot_edit_profile_default": "— 通用 (默认) —",
|
||||
"orca_profile_section": "OrcaSlicer 配置",
|
||||
"orca_profile_hint": "导入你自己的 OrcaSlicer 耗材配置(在 Help → Show Configuration Folder 打开用户目录)",
|
||||
"orca_profile_import_btn": "导入配置",
|
||||
"orca_profile_import_link": "★ 导入自己的配置…",
|
||||
"orca_profile_import_title": "导入你的 OrcaSlicer 配置",
|
||||
"orca_profile_help_html": "上传 OrcaSlicer 耗材文件夹的 <b>ZIP</b> 或单个 <b>.json</b> 文件。<br>在 OrcaSlicer 中: <i>Help → Show Configuration Folder → user/<id>/filament/</i>",
|
||||
"orca_profile_dropmsg": "拖到此处或点击",
|
||||
"orca_profile_list_label": "已导入",
|
||||
"orca_profile_user_label": "自己的配置",
|
||||
"orca_profile_user_empty": "– 无 –",
|
||||
"orca_profile_uploading": "上传中…",
|
||||
"orca_profile_done": "已导入",
|
||||
"orca_profile_skipped": "跳过",
|
||||
"log_dir_all": "全部",
|
||||
"log_lvl_label": "级别:",
|
||||
"file_ready_btn": "▶ 开始打印",
|
||||
|
||||
Reference in New Issue
Block a user