Upload new version
This commit is contained in:
@@ -1,57 +1,53 @@
|
||||
import { apiList, apiGet, apiDelete, apiUpdate, apiAction, toast } from './api.js';
|
||||
import { apiAction, 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 `<div class="mt-3 text-sm text-rose-600">
|
||||
Dieses Element wird aktuell verwendet in: <strong>${parts.join(', ')}</strong>.<br>
|
||||
Das Löschen entfernt diese Referenzen.
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function esc(s=''){
|
||||
function esc(s = '') {
|
||||
return String(s)
|
||||
.replace(/&/g,'&')
|
||||
.replace(/</g,'<')
|
||||
.replace(/>/g,'>')
|
||||
.replace(/"/g,'"')
|
||||
.replace(/'/g,''');
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function normalizeApiName(v=''){
|
||||
function normalizeApiName(v = '') {
|
||||
return String(v)
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g,'-')
|
||||
.replace(/[^a-z0-9_-]+/g,'-')
|
||||
.replace(/-+/g,'-')
|
||||
.replace(/^-|-$/g,'');
|
||||
.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 || '';
|
||||
async function fetchContentList(sectionId) {
|
||||
const res = await apiAction('content.list', { method: 'GET', data: { section_id: sectionId } });
|
||||
return Array.isArray(res?.items) ? res.items : [];
|
||||
}
|
||||
|
||||
async function fetchContentItem(id, sectionId) {
|
||||
return await apiAction('content.get', { method: 'GET', data: { id, section_id: sectionId } });
|
||||
}
|
||||
|
||||
async function openContentEditor(item, section) {
|
||||
const id = Number(item?.id || 0);
|
||||
const name = item?.name || '';
|
||||
if (!id) return;
|
||||
const detail = await fetchContentItem(id, section.id).catch(() => ({}));
|
||||
const html = detail?.html ?? detail?.item?.html ?? detail?.content ?? '';
|
||||
|
||||
window.__currentItemId = id;
|
||||
window.__currentEditorCtx = { id, mode: section.slug, section };
|
||||
|
||||
if (window.EditorUI && typeof window.EditorUI.open === 'function') {
|
||||
window.EditorUI.open({ id: Number(id), name }, 'snippets');
|
||||
return;
|
||||
window.EditorUI.open({ id, name, html, section }, 'content');
|
||||
} else if (window.__openEditor) {
|
||||
window.__openEditor({ resource: 'content', id, name, html, section });
|
||||
} else {
|
||||
toast('Editor ist nicht initialisiert.', false);
|
||||
}
|
||||
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){
|
||||
async function openTemplateEditor(item, section) {
|
||||
const dlg = document.getElementById('editTemplateDialog');
|
||||
const form = document.getElementById('editTemplateForm');
|
||||
const inpName = document.getElementById('edit_tpl_name');
|
||||
@@ -59,9 +55,8 @@ async function openTemplateEditor(id){
|
||||
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 detail = await fetchContentItem(item.id, section.id).catch(() => ({}));
|
||||
const row = detail?.item || detail?.data || detail || {};
|
||||
const initialApi = row.api_name || '';
|
||||
|
||||
if (inpName) inpName.value = row.name || '';
|
||||
@@ -77,48 +72,61 @@ async function openTemplateEditor(id){
|
||||
}
|
||||
};
|
||||
|
||||
function cleanup(){
|
||||
function cleanup() {
|
||||
form && form.removeEventListener('submit', onSubmit);
|
||||
btnCancel && (btnCancel.onclick = null);
|
||||
inpApiName && inpApiName.removeEventListener('input', onApiInput);
|
||||
}
|
||||
|
||||
async function onSubmit(ev){
|
||||
async function onSubmit(ev) {
|
||||
ev.preventDefault();
|
||||
try{
|
||||
const res = await apiUpdate('templates', id, {
|
||||
try {
|
||||
const res = await apiUpdate('content', item.id, {
|
||||
name: inpName ? inpName.value : '',
|
||||
api_name: inpApiName ? inpApiName.value : ''
|
||||
api_name: inpApiName ? inpApiName.value : '',
|
||||
section_id: section.id,
|
||||
});
|
||||
toast(res && res.ok ? 'Template gespeichert' : 'Speichern fehlgeschlagen', !!(res && res.ok));
|
||||
dlg && dlg.close();
|
||||
cleanup();
|
||||
loadList('templates');
|
||||
}catch(e){
|
||||
if (typeof window.loadList === 'function') window.loadList(section);
|
||||
} catch {
|
||||
toast('Speichern fehlgeschlagen', false);
|
||||
}
|
||||
}
|
||||
|
||||
inpApiName && inpApiName.addEventListener('input', onApiInput);
|
||||
form && form.addEventListener('submit', onSubmit, { once:false });
|
||||
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;
|
||||
export async function loadList(section) {
|
||||
const el = document.getElementById('view-content');
|
||||
if (typeof section === 'string') {
|
||||
const sections = window.__sectionsConfig || [];
|
||||
section = sections.find(s => String(s.slug || '').toLowerCase() === section.toLowerCase())
|
||||
|| sections.find(s => String(s.name || '').toLowerCase() === section.toLowerCase())
|
||||
|| null;
|
||||
} else if (typeof section === 'number') {
|
||||
const sections = window.__sectionsConfig || [];
|
||||
section = sections.find(s => Number(s.id) === section) || null;
|
||||
}
|
||||
section = section || window.__activeSection || null;
|
||||
if (!el || !section) return;
|
||||
|
||||
const label = resource.charAt(0).toUpperCase()+resource.slice(1);
|
||||
el.innerHTML=`<div class='rounded-2xl border bg-white overflow-hidden'>
|
||||
const label = section.name || 'Section';
|
||||
const isTemplate = Number(section.is_template) === 1;
|
||||
el.innerHTML = `<div class='rounded-2xl border bg-white overflow-hidden'>
|
||||
<div class='px-4 py-2 border-b bg-gray-50 text-sm font-medium flex items-center gap-3'>
|
||||
<span>${label}</span>
|
||||
<span>${esc(label)}</span>
|
||||
<div class='ms-auto flex items-center gap-2'>
|
||||
<div class='flex items-center gap-1'>
|
||||
<input id='filter-${resource}' class='input text-sm' placeholder='Suche Name/API' />
|
||||
<button id='filter-${resource}-reset' class='btn' type='button' title='Suche zurücksetzen'>×</button>
|
||||
<input id='filter-section' class='input text-sm' placeholder='Suche Name${isTemplate ? '/API' : ''}' />
|
||||
<button id='filter-section-reset' class='btn' type='button' title='Suche zurücksetzen'>×</button>
|
||||
</div>
|
||||
<select id='sort-${resource}' class='input text-sm'>
|
||||
<select id='sort-section' class='input text-sm'>
|
||||
<option value='created_asc'>Erstelldatum (aufsteigend)</option>
|
||||
<option value='name_asc'>Name A–Z</option>
|
||||
<option value='name_desc'>Name Z–A</option>
|
||||
@@ -126,16 +134,22 @@ export async function loadList(resource){
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id='list-${resource}' class='divide-y'>Lade …</div></div>`;
|
||||
<div id='list-section' class='divide-y'>Lade …</div></div>`;
|
||||
|
||||
const data=await apiList(resource);
|
||||
const list=el.querySelector(`#list-${resource}`);
|
||||
const filterInput=el.querySelector(`#filter-${resource}`);
|
||||
const filterReset=el.querySelector(`#filter-${resource}-reset`);
|
||||
const sortSelect=el.querySelector(`#sort-${resource}`);
|
||||
let data = [];
|
||||
try {
|
||||
data = await fetchContentList(section.id);
|
||||
} catch (err) {
|
||||
list.innerHTML = `<div class='p-4 text-sm text-gray-500'>${esc(err.message || 'Laden fehlgeschlagen')}</div>`;
|
||||
return;
|
||||
}
|
||||
const list = el.querySelector('#list-section');
|
||||
const filterInput = el.querySelector('#filter-section');
|
||||
const filterReset = el.querySelector('#filter-section-reset');
|
||||
const sortSelect = el.querySelector('#sort-section');
|
||||
|
||||
if(!Array.isArray(data)||data.length===0){
|
||||
list.innerHTML=`<div class='p-4 text-sm text-gray-500'>Keine Einträge</div>`;
|
||||
if (!Array.isArray(data) || data.length === 0) {
|
||||
list.innerHTML = `<div class='p-4 text-sm text-gray-500'>Keine Einträge</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -159,65 +173,48 @@ export async function loadList(resource){
|
||||
return listCopy.sort(compareByName);
|
||||
}
|
||||
if (key === 'name_desc') {
|
||||
return listCopy.sort((a,b)=>compareByName(b,a));
|
||||
return listCopy.sort((a, b) => compareByName(b, a));
|
||||
}
|
||||
if (key === 'updated_desc') {
|
||||
return listCopy.sort((a,b)=>parseDate(b.updated_at) - parseDate(a.updated_at));
|
||||
return listCopy.sort((a, b) => parseDate(b.updated_at) - parseDate(a.updated_at));
|
||||
}
|
||||
return listCopy.sort((a,b)=>parseDate(a.created_at) - parseDate(b.created_at));
|
||||
return listCopy.sort((a, b) => parseDate(a.created_at) - parseDate(b.created_at));
|
||||
}
|
||||
|
||||
function matchesQuery(item, query) {
|
||||
if (!query) return true;
|
||||
const q = query.toLowerCase();
|
||||
const name = String(item?.name || '').toLowerCase();
|
||||
const api = resource === 'templates' ? String(item?.api_name || '').toLowerCase() : '';
|
||||
const api = isTemplate ? String(item?.api_name || '').toLowerCase() : '';
|
||||
return name.includes(q) || (api && api.includes(q));
|
||||
}
|
||||
|
||||
function parentBadge(r,it){
|
||||
if(r==='sections'&&it.template_id) return `<span class="chip"><span class="dot"></span> Template #${it.template_id}${it.template_name ? ' · '+esc(it.template_name) : ''}</span>`;
|
||||
if(r==='blocks'&&it.section_id) return `<span class="chip"><span class="dot"></span> Section #${it.section_id}${it.section_name ? ' · '+esc(it.section_name) : ''}</span>`;
|
||||
if(r==='snippets'&&it.block_id) return `<span class="chip"><span class="dot"></span> Block #${it.block_id}${it.block_name ? ' · '+esc(it.block_name) : ''}</span>`;
|
||||
return '<span class="chip"><span class="dot"></span> frei</span>';
|
||||
function render(items) {
|
||||
list.innerHTML = items.map(item => {
|
||||
const name = esc(item.name || '');
|
||||
const apiName = isTemplate ? esc(item.api_name || '') : '';
|
||||
const apiLine = (isTemplate && apiName) ? `<div class='text-xs text-slate-500'>API: ${apiName}</div>` : '';
|
||||
const nameCell = `<div class='min-w-48'>
|
||||
<div class='font-medium truncate' title="${name}">${name || '(ohne Name)'}</div>
|
||||
${apiLine}
|
||||
</div>`;
|
||||
const openBtn = `<button class='btn' data-open='${item.id}'>Im Editor öffnen</button>`;
|
||||
const editTplBtn = isTemplate ? `<button class='btn' data-edit='${item.id}'>Bearbeiten</button>` : '';
|
||||
const testBtn = isTemplate ? `<button class='btn' data-test='${item.id}' data-name='${name}'>Testversand</button>` : '';
|
||||
const prevBtn = `<button class='btn' data-preview='${item.id}'>Vorschau</button>`;
|
||||
const delBtn = `<button class='btn btn-danger' data-del='${item.id}' data-name='${name}'>Löschen</button>`;
|
||||
|
||||
return `<div class='p-3 flex items-center gap-3'>
|
||||
${nameCell}
|
||||
<div class='text-xs text-gray-500'>#${item.id}</div>
|
||||
<div class='ms-auto flex gap-2'>${[openBtn, editTplBtn, testBtn, prevBtn, delBtn].filter(Boolean).join('')}</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
bindListHandlers(list);
|
||||
}
|
||||
|
||||
function render(items){
|
||||
list.innerHTML=items.map(item=>{
|
||||
const name = esc(item.name||'');
|
||||
const apiName = resource==='templates' ? esc(item.api_name||'') : '';
|
||||
const apiLine = (resource==='templates' && apiName) ? `<div class='text-xs text-slate-500'>API: ${apiName}</div>` : '';
|
||||
const nameCell = `<div class='min-w-48'>
|
||||
<div class='font-medium truncate' title="${name}">${name || '(ohne Name)'}</div>
|
||||
${apiLine}
|
||||
</div>`;
|
||||
const openBtn = (['templates','sections','blocks'].includes(resource))
|
||||
? `<button class='btn' data-open='${resource}:${item.id}'>Im E-Mail-Editor öffnen</button>` : '';
|
||||
|
||||
const editBtn = (resource==='snippets')
|
||||
? `<button class='btn' data-edit='snippets:${item.id}'>Im Editor</button>` : '';
|
||||
|
||||
const editTplBtn = (resource==='templates')
|
||||
? `<button class='btn' data-edit='templates:${item.id}'>Bearbeiten</button>` : '';
|
||||
|
||||
const testBtn = resource==='templates'
|
||||
? `<button class='btn' data-test='${item.id}' data-name='${name}'>Testversand</button>` : '';
|
||||
|
||||
const prevBtn = `<button class='btn' data-preview='${resource}:${item.id}'>Vorschau</button>`;
|
||||
const delBtn = `<button class='btn btn-danger' data-del='${resource}:${item.id}' data-name='${name}'>Löschen</button>`;
|
||||
|
||||
return `<div class='p-3 flex items-center gap-3'>
|
||||
${nameCell}
|
||||
<div class='text-xs text-gray-500'>#${item.id}</div>
|
||||
<div class='text-xs'>${parentBadge(resource,item)}</div>
|
||||
<div class='ms-auto flex gap-2'>${[openBtn, editBtn, editTplBtn, testBtn, prevBtn, delBtn].filter(Boolean).join('')}</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
bindListHandlers(list, resource);
|
||||
}
|
||||
|
||||
function applyFilter(){
|
||||
function applyFilter() {
|
||||
const query = (filterInput?.value || '').trim();
|
||||
const sortKey = sortSelect?.value || sortDefault;
|
||||
const filtered = data.filter(item => matchesQuery(item, query));
|
||||
@@ -225,16 +222,14 @@ export async function loadList(resource){
|
||||
render(sorted);
|
||||
}
|
||||
|
||||
async function persistSort(nextValue){
|
||||
async function persistSort(nextValue) {
|
||||
window.__listSortDefault = nextValue;
|
||||
try {
|
||||
await apiAction('account.settings.update', { method: 'POST', data: { list_sort: nextValue } });
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if (filterInput) {
|
||||
filterInput.addEventListener('input', applyFilter);
|
||||
}
|
||||
if (filterInput) filterInput.addEventListener('input', applyFilter);
|
||||
if (filterReset) {
|
||||
filterReset.addEventListener('click', () => {
|
||||
if (filterInput) {
|
||||
@@ -254,100 +249,81 @@ export async function loadList(resource){
|
||||
|
||||
applyFilter();
|
||||
|
||||
const delDlg=document.getElementById('deleteDialog'),
|
||||
delText=document.getElementById('deleteText'),
|
||||
delForm=document.getElementById('deleteForm'),
|
||||
delCancel=document.getElementById('deleteCancel');
|
||||
function bindListHandlers(scope) {
|
||||
scope.querySelectorAll('[data-open]').forEach(btn => btn.addEventListener('click', () => {
|
||||
const id = Number(btn.dataset.open || 0);
|
||||
const item = data.find(it => Number(it.id) === id);
|
||||
if (!item) return;
|
||||
openContentEditor(item, section);
|
||||
}));
|
||||
|
||||
let pending=null;
|
||||
delCancel && (delCancel.onclick=()=>{pending=null;delDlg.close();});
|
||||
scope.querySelectorAll('[data-edit]').forEach(btn => btn.addEventListener('click', () => {
|
||||
const id = Number(btn.dataset.edit || 0);
|
||||
const item = data.find(it => Number(it.id) === id);
|
||||
if (item) openTemplateEditor(item, section);
|
||||
}));
|
||||
|
||||
// --- Editor öffnen (ANPASSUNG) -----------------------------------------
|
||||
function bindListHandlers(scope, resName){
|
||||
scope.querySelectorAll('[data-open]').forEach(b=>b.addEventListener('click', async ()=>{
|
||||
const [res,id]=b.dataset.open.split(':');
|
||||
const prevDlg = document.getElementById('previewDialog');
|
||||
const prevFrame = document.getElementById('previewFrame');
|
||||
scope.querySelectorAll('[data-preview]').forEach(btn => btn.addEventListener('click', async () => {
|
||||
const id = Number(btn.dataset.preview || 0);
|
||||
const obj = await fetchContentItem(id, section.id);
|
||||
const html = (obj?.html || obj?.content || '<em>(leer)</em>');
|
||||
prevFrame.srcdoc = '<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head><body>' + html + '</body></html>';
|
||||
prevDlg.showModal();
|
||||
}));
|
||||
|
||||
// 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 ?? '') : '';
|
||||
scope.querySelectorAll('[data-test]').forEach(btn => btn.addEventListener('click', () => {
|
||||
const id = Number(btn.dataset.test || 0);
|
||||
const nm = btn.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);
|
||||
}
|
||||
}));
|
||||
|
||||
// Globale Kontexte (werden von Editor/anderen Modulen genutzt)
|
||||
window.__currentItemId = Number(id);
|
||||
window.__currentEditorCtx = { id:Number(id), mode:res };
|
||||
const delDlg = document.getElementById('deleteDialog');
|
||||
const delText = document.getElementById('deleteText');
|
||||
const delForm = document.getElementById('deleteForm');
|
||||
const delCancel = document.getElementById('deleteCancel');
|
||||
let pending = null;
|
||||
|
||||
// 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);
|
||||
}
|
||||
}));
|
||||
// -----------------------------------------------------------------------
|
||||
delCancel && (delCancel.onclick = () => { pending = null; delDlg.close(); });
|
||||
|
||||
// edit snippet
|
||||
scope.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);
|
||||
}));
|
||||
scope.querySelectorAll('[data-del]').forEach(btn => btn.addEventListener('click', () => {
|
||||
const id = Number(btn.dataset.del || 0);
|
||||
const nm = btn.dataset.name || '';
|
||||
pending = { id, name: nm };
|
||||
if (delText) {
|
||||
delText.innerHTML = `Soll <strong>${nm || '(ohne Name)'} #${id}</strong> wirklich gelöscht werden?`;
|
||||
}
|
||||
delDlg.showModal();
|
||||
}));
|
||||
|
||||
// preview
|
||||
const prevDlg=document.getElementById('previewDialog'), prevFrame=document.getElementById('previewFrame');
|
||||
scope.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||'<em>(leer)</em)');
|
||||
prevFrame.srcdoc='<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head><body>'+html+'</body></html>';
|
||||
prevDlg.showModal();
|
||||
}));
|
||||
|
||||
// test send (templates only)
|
||||
scope.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
|
||||
scope.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 <strong>${nm || '(ohne Name)'} #${id}</strong> aus <strong>${res}</strong> wirklich gelöscht werden?<br><span class="text-rose-600">Achtung:</span> Kinder-Elemente werden <em>nicht</em> automatisch mit gelöscht.${usageWarn}`);
|
||||
delDlg.showModal();
|
||||
}));
|
||||
delForm && (delForm.onsubmit = async (ev) => {
|
||||
ev.preventDefault();
|
||||
if (!pending) return delDlg.close();
|
||||
const res = await apiAction('content.delete', { method: 'POST', data: { id: pending.id, section_id: section.id } });
|
||||
delDlg.close();
|
||||
toast(res && res.ok ? 'Gelöscht' : 'Löschen fehlgeschlagen', !!(res && res.ok), { duration: 3000 });
|
||||
loadList(section);
|
||||
});
|
||||
}
|
||||
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)
|
||||
export function initLists() {
|
||||
if (window.__sectionsReady && typeof window.__sectionsReady.then === 'function') {
|
||||
window.__sectionsReady.then(() => {
|
||||
if (window.__activeSection) loadList(window.__activeSection);
|
||||
});
|
||||
} else if (window.__activeSection) {
|
||||
loadList(window.__activeSection);
|
||||
}
|
||||
window.__reloadList = loadList;
|
||||
// Backwards compat (falls woanders genutzt)
|
||||
window.loadList = loadList;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user