'use strict'; function identityRow(identity={kind:'serial',value:''}) { return `
${field('identity_kind','Identität',identity.kind,{type:'select',options:[{value:'serial',label:'Seriennummer'},{value:'uuid',label:'System-UUID'},{value:'mac',label:'MAC-Adresse'}]})}${field('identity_value','Wert',identity.value,{required:true})}
`; } function identitiesEditor(identities=[]) { return `

Hardware erkennen

Mindestens eine Kennung ordnet diesen Server beim Start zu.

${(identities.length?identities:[{kind:'serial',value:''}]).map(identityRow).join('')}
`; } function readIdentities(container) { const identities=[...container.querySelectorAll('[data-identity-row]')].map(row=>({kind:row.querySelector('[name="identity_kind"]').value,value:row.querySelector('[name="identity_value"]').value.trim()})); if(!identities.length||identities.some(item=>!item.value))throw new Error('Bitte mindestens eine vollständige Hardware-Kennung eintragen.'); return identities; } function wireHostRows(container) { if(container.dataset.hostRowsBound)return; container.dataset.hostRowsBound='true'; container.addEventListener('click',event=>{ const button=event.target.closest('[data-host-action]'); if(!button)return; event.preventDefault(); if(button.dataset.hostAction==='remove-identity')button.closest('[data-identity-row]').remove(); if(button.dataset.hostAction==='add-identity')button.closest('[data-identities]').querySelector('[data-identity-rows]').insertAdjacentHTML('beforeend',identityRow()); if(button.dataset.hostAction==='remove-host')button.closest('[data-import-host]').remove(); if(button.dataset.hostAction==='add-host')container.querySelector('[data-import-hosts]').insertAdjacentHTML('beforeend',importHostRow()); }); } async function graphicalHostForm(existing=null,discovery=null) { const [profiles,isos,secrets]=await Promise.all([api('/profiles'),api('/iso-records'),api('/secrets')]); const h=existing||discovery||{}; const withMissing=(items,id)=>id&&!items.some(item=>item.id===id)?[...items,{id,name:'Bestehende Zuordnung (nicht mehr verfügbar)'}]:items; const fields=`

Server

${field('fqdn','Vollständiger Hostname (FQDN)',h.fqdn,{required:true,placeholder:'pve-01.example.net'})}${field('site','Standort',h.site,{required:true,placeholder:'Rechenzentrum Berlin'})}${field('management_ip','Management-IP mit Präfix',h.management_ip,{placeholder:'192.0.2.10/24',hint:'Zum Erfassen optional; vor der Installation erforderlich.',full:true})}${dataEditor('host-tags',arr(h.tags),{label:'Tags',schema:{type:'array',items:{type:'string'}}})}
${identitiesEditor(arr(h.identities))}

Installation zuweisen

${field('installation_profile_id','Installationsprofil',h.installation_profile_id,{type:'select',options:selectObjects(withMissing(arr(profiles).filter(p=>p.kind==='installation'&&p.status==='published'),h.installation_profile_id),'Noch nicht zuweisen')})}${field('postinstall_profile_id','Postinstallationsprofil',h.postinstall_profile_id,{type:'select',options:selectObjects(withMissing(arr(profiles).filter(p=>p.kind==='postinstall'&&p.status==='published'),h.postinstall_profile_id),'Noch nicht zuweisen')})}${field('iso_id','Installationsmedium',h.iso_id,{type:'select',full:true,options:selectObjects(withMissing(arr(isos),h.iso_id),'Noch nicht zuweisen')})}
Abweichende Einstellungen für diesen Server

Ohne Abweichung gelten die Werte des zugewiesenen Profils.

${installationEditor(h.overrides||{},{prefix:'host-override',override:true,secrets:arr(secrets)})}
`; showModal(existing?'Server bearbeiten':'Server hinzufügen',form(fields,existing?'Änderungen speichern':'Server anlegen'),async data=>{ const body={fqdn:data.get('fqdn'),site:data.get('site'),management_ip:data.get('management_ip')||null,tags:readDataEditor(modal,'host-tags'),identities:readIdentities(modal),installation_profile_id:data.get('installation_profile_id')||null,postinstall_profile_id:data.get('postinstall_profile_id')||null,iso_id:data.get('iso_id')||null,overrides:readInstallationEditor(modal,'host-override',h.overrides||{})}; if(existing){for(const key of Object.keys(body))if(JSON.stringify(body[key])===JSON.stringify(existing[key]??null))delete body[key];if(!Object.keys(body).length){closeModal();toast('Keine Änderungen vorhanden.');return;}body.expected_version=existing.version;} await api(existing?`/hosts/${encodeURIComponent(existing.id)}`:'/hosts',{method:existing?'PATCH':'POST',body});closeModal();toast(existing?'Server aktualisiert.':'Server wurde angelegt.');await refresh(); },'INVENTAR'); wireDataEditors(modal); wireHostRows(modal); wireInstallationEditor(modal,'host-override'); } function importHostRow() { return `

Server

${field('import_fqdn','Vollständiger Hostname','',{required:true,placeholder:'pve-01.example.net'})}${field('import_ip','Management-IP mit Präfix','',{placeholder:'192.0.2.10/24'})}${identitiesEditor()}
`; } async function graphicalHostImport() { const [profiles,isos]=await Promise.all([api('/profiles'),api('/iso-records')]); const fields=field('site','Gemeinsamer Standort','',{required:true,full:true})+field('installation_profile_id','Installationsprofil','',{type:'select',options:selectObjects(arr(profiles).filter(p=>p.kind==='installation'&&p.status==='published'),'Noch nicht zuweisen')})+field('postinstall_profile_id','Postinstallationsprofil','',{type:'select',options:selectObjects(arr(profiles).filter(p=>p.kind==='postinstall'&&p.status==='published'),'Noch nicht zuweisen')})+field('iso_id','Installationsmedium','',{type:'select',full:true,options:selectObjects(arr(isos),'Noch nicht zuweisen')})+`
${importHostRow()}
`; showModal('Mehrere Server erfassen',form(fields,'Server anlegen'),async data=>{ const rows=[...modal.querySelectorAll('[data-import-host]')]; if(!rows.length||rows.length>100)throw new Error('Bitte zwischen einem und 100 Servern erfassen.'); const common={site:data.get('site'),installation_profile_id:data.get('installation_profile_id')||null,postinstall_profile_id:data.get('postinstall_profile_id')||null,iso_id:data.get('iso_id')||null}; const hosts=rows.map(row=>({...common,fqdn:row.querySelector('[name="import_fqdn"]').value,management_ip:row.querySelector('[name="import_ip"]').value||null,identities:readIdentities(row)})); await api('/hosts/import',{method:'POST',body:hosts});closeModal();toast(`${hosts.length} Server angelegt.`);await refresh(); },'SERVERINVENTAR'); wireHostRows(modal); }