import { apiList, apiGet, apiDelete, apiUpdate, toast } from './api.js'; function formatUsage(usage){ if (!usage || !usage.total) return ''; const parts=[]; if (usage.templates) parts.push(`${usage.templates} Template${usage.templates!==1?'s':''}`); if (usage.sections) parts.push(`${usage.sections} Section${usage.sections!==1?'s':''}`); if (usage.blocks) parts.push(`${usage.blocks} Block${usage.blocks!==1?'s':''}`); if (usage.snippets) parts.push(`${usage.snippets} Snippet${usage.snippets!==1?'s':''}`); if (!parts.length) return ''; return `
Dieses Element wird aktuell verwendet in: ${parts.join(', ')}.
Das Löschen entfernt diese Referenzen.
`; } function esc(s=''){ return String(s) .replace(/&/g,'&') .replace(//g,'>') .replace(/"/g,'"') .replace(/'/g,'''); } function normalizeApiName(v=''){ return String(v) .trim() .toLowerCase() .replace(/\s+/g,'-') .replace(/[^a-z0-9_-]+/g,'-') .replace(/-+/g,'-') .replace(/^-|-$/g,''); } async function openSnippetEditor(id){ let resp = {}; try { resp = await apiGet('snippets', id) || {}; } catch(e){} const row = resp?.item || resp?.data || resp || {}; const name = row?.name || ''; if (window.EditorUI && typeof window.EditorUI.open === 'function') { window.EditorUI.open({ id: Number(id), name }, 'snippets'); return; } if (window.__openEditor) { window.__openEditor({ resource: 'snippets', id: Number(id), name }); return; } console.warn('Kein Editor-Entry-Point gefunden (EditorUI.open / __openEditor).'); toast('Editor ist nicht initialisiert.', false); } async function openTemplateEditor(id){ const dlg = document.getElementById('editTemplateDialog'); const form = document.getElementById('editTemplateForm'); const inpName = document.getElementById('edit_tpl_name'); const inpApiName = document.getElementById('edit_tpl_api_name'); const apiWarn = document.getElementById('edit_tpl_api_warn'); const btnCancel = document.getElementById('editTemplateCancel'); let resp = {}; try { resp = await apiGet('templates', id) || {}; } catch(e){} const row = resp?.item || resp?.data || resp || {}; const initialApi = row.api_name || ''; if (inpName) inpName.value = row.name || ''; if (inpApiName) inpApiName.value = initialApi; if (apiWarn) apiWarn.classList.add('hidden'); const onApiInput = () => { if (!inpApiName) return; const next = normalizeApiName(inpApiName.value); if (next !== inpApiName.value) inpApiName.value = next; if (apiWarn) { apiWarn.classList.toggle('hidden', inpApiName.value.trim() === initialApi); } }; function cleanup(){ form && form.removeEventListener('submit', onSubmit); btnCancel && (btnCancel.onclick = null); inpApiName && inpApiName.removeEventListener('input', onApiInput); } async function onSubmit(ev){ ev.preventDefault(); try{ const res = await apiUpdate('templates', id, { name: inpName ? inpName.value : '', api_name: inpApiName ? inpApiName.value : '' }); toast(res && res.ok ? 'Template gespeichert' : 'Speichern fehlgeschlagen', !!(res && res.ok)); dlg && dlg.close(); cleanup(); loadList('templates'); }catch(e){ toast('Speichern fehlgeschlagen', false); } } inpApiName && inpApiName.addEventListener('input', onApiInput); form && form.addEventListener('submit', onSubmit, { once:false }); btnCancel && (btnCancel.onclick = () => { dlg && dlg.close(); cleanup(); }); dlg && dlg.showModal(); } export async function loadList(resource){ const el=document.getElementById(`view-${resource}`); if(!el) return; el.innerHTML=`
${resource.charAt(0).toUpperCase()+resource.slice(1)}
Lade …
`; const data=await apiList(resource); const list=el.querySelector(`#list-${resource}`); if(!Array.isArray(data)||data.length===0){ list.innerHTML=`
Keine Einträge
`; return; } function parentBadge(r,it){ if(r==='sections'&&it.template_id) return ` Template #${it.template_id}${it.template_name ? ' · '+esc(it.template_name) : ''}`; if(r==='blocks'&&it.section_id) return ` Section #${it.section_id}${it.section_name ? ' · '+esc(it.section_name) : ''}`; if(r==='snippets'&&it.block_id) return ` Block #${it.block_id}${it.block_name ? ' · '+esc(it.block_name) : ''}`; return ' frei'; } list.innerHTML=data.map(item=>{ const name = esc(item.name||''); const apiName = resource==='templates' ? esc(item.api_name||'') : ''; const apiLine = (resource==='templates' && apiName) ? `
API: ${apiName}
` : ''; const nameCell = `
${name || '(ohne Name)'}
${apiLine}
`; const openBtn = (['templates','sections','blocks'].includes(resource)) ? `` : ''; const editBtn = (resource==='snippets') ? `` : ''; const editTplBtn = (resource==='templates') ? `` : ''; const testBtn = resource==='templates' ? `` : ''; const prevBtn = ``; const delBtn = ``; return `
${nameCell}
#${item.id}
${parentBadge(resource,item)}
${[openBtn, editBtn, editTplBtn, testBtn, prevBtn, delBtn].filter(Boolean).join('')}
`; }).join(''); // --- Editor öffnen (ANPASSUNG) ----------------------------------------- list.querySelectorAll('[data-open]').forEach(b=>b.addEventListener('click', async ()=>{ const [res,id]=b.dataset.open.split(':'); // Detail laden, um Name + aktuellen HTML/Content zu haben const obj = await apiGet(res,id); const name = obj?.name || ''; const html = obj ? (obj.html ?? obj.content ?? '') : ''; // Globale Kontexte (werden von Editor/anderen Modulen genutzt) window.__currentItemId = Number(id); window.__currentEditorCtx = { id:Number(id), mode:res }; // Bevorzugt EditorUI.open nutzen; Fallback: __openEditor (Bestand) if (window.EditorUI && typeof window.EditorUI.open === 'function') { window.EditorUI.open({ id:Number(id), name, html }, res); } else if (window.__openEditor) { window.__openEditor({ resource:res, id:Number(id), name, html }); } else { console.warn('Kein Editor-Entry-Point gefunden (EditorUI.open / __openEditor).'); toast('Editor ist nicht initialisiert.', false); } })); // ----------------------------------------------------------------------- // edit snippet list.querySelectorAll('[data-edit]').forEach(b=>b.addEventListener('click', async ()=>{ const [res, id] = b.dataset.edit.split(':'); if (res === 'snippets') await openSnippetEditor(id); if (res === 'templates') await openTemplateEditor(id); })); // preview const prevDlg=document.getElementById('previewDialog'), prevFrame=document.getElementById('previewFrame'); list.querySelectorAll('[data-preview]').forEach(b=>b.addEventListener('click', async ()=>{ const [res,id]=b.dataset.preview.split(':'); const obj=await apiGet(res,id); const html=(obj?.html||obj?.content||'(leer)'; prevDlg.showModal(); })); // test send (templates only) list.querySelectorAll('[data-test]').forEach(b=>b.addEventListener('click', ()=>{ const id = Number(b.dataset.test || '0'); const nm = b.dataset.name || ''; if (!id) { toast('Testversand: Ungültige ID', false); return; } if (window.AdminTestSend && typeof window.AdminTestSend.open === 'function') { window.AdminTestSend.open({ id, name: nm }); } else { toast('Testversand ist aktuell nicht verfügbar.', false); } })); // delete const delDlg=document.getElementById('deleteDialog'), delText=document.getElementById('deleteText'), delForm=document.getElementById('deleteForm'), delCancel=document.getElementById('deleteCancel'); let pending=null; delCancel && (delCancel.onclick=()=>{pending=null;delDlg.close();}); list.querySelectorAll('[data-del]').forEach(b=>b.addEventListener('click', async ()=>{ const [res,id]=b.dataset.del.split(':'); const nm=b.dataset.name||''; let usage = null; try { const detail = await apiGet(res, id); usage = detail?.usage || null; } catch {} pending={res,id,nm,usage}; const usageWarn = formatUsage(usage); delText && (delText.innerHTML=`Soll ${nm || '(ohne Name)'} #${id} aus ${res} wirklich gelöscht werden?
Achtung: Kinder-Elemente werden nicht automatisch mit gelöscht.${usageWarn}`); delDlg.showModal(); })); delForm && (delForm.onsubmit=async(e)=>{ e.preventDefault(); if(!pending) return delDlg.close(); const r=await apiDelete(pending.res,pending.id); delDlg.close(); toast(r&&r.ok?'Gelöscht':'Löschen fehlgeschlagen', !!(r&&r.ok), {duration:3000}); loadList(resource); }); } export function initLists(){ loadList('templates'); // Public reload helper (wird vom Snippet-Editor genutzt) window.__reloadList = loadList; // Backwards compat (falls woanders genutzt) window.loadList = loadList; }