adasd
This commit is contained in:
@@ -59,21 +59,79 @@ async function openContentEditor(item, section) {
|
||||
}
|
||||
}
|
||||
|
||||
async function openTemplateEditor(item, section) {
|
||||
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');
|
||||
async function openTemplateManager(item, section) {
|
||||
const dlg = document.getElementById('manageTemplateDialog');
|
||||
const inpName = document.getElementById('manage_tpl_name');
|
||||
const inpApiName = document.getElementById('manage_tpl_api_name');
|
||||
const apiWrap = document.getElementById('manage_tpl_api_wrap');
|
||||
const apiWarn = document.getElementById('manage_tpl_api_warn');
|
||||
const badge = document.getElementById('manage_tpl_badge');
|
||||
const versionsWrap = document.getElementById('manage_tpl_versions');
|
||||
const previewFrame = document.getElementById('manage_tpl_preview');
|
||||
const btnClose = document.getElementById('manageTemplateClose');
|
||||
const btnSave = document.getElementById('manageTemplateSave');
|
||||
const btnDelete = document.getElementById('manageTemplateDelete');
|
||||
const deleteHint = document.getElementById('manage_tpl_delete_hint');
|
||||
|
||||
const detail = await fetchContentItem(item.id, section.id).catch(() => ({}));
|
||||
const row = detail?.item || detail?.data || detail || {};
|
||||
const initialApi = row.api_name || '';
|
||||
|
||||
if (badge) badge.textContent = `ID ${item.id}`;
|
||||
if (inpName) inpName.value = row.name || '';
|
||||
if (inpApiName) inpApiName.value = initialApi;
|
||||
if (apiWarn) apiWarn.classList.add('hidden');
|
||||
if (apiWrap) apiWrap.classList.toggle('hidden', !section?.is_template);
|
||||
|
||||
let versions = [];
|
||||
let activeId = 0;
|
||||
|
||||
const renderPreview = (html) => {
|
||||
if (!previewFrame) return;
|
||||
previewFrame.srcdoc = '<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"></head><body>' + (html || '<em>(leer)</em>') + '</body></html>';
|
||||
};
|
||||
|
||||
const updateDeleteState = () => {
|
||||
const hasActive = !!activeId;
|
||||
if (btnDelete) btnDelete.disabled = hasActive;
|
||||
if (deleteHint) {
|
||||
deleteHint.textContent = hasActive
|
||||
? 'Aktive Version vorhanden – Löschen deaktiviert.'
|
||||
: 'Nur möglich, wenn keine aktive Version existiert.';
|
||||
}
|
||||
};
|
||||
|
||||
const loadVersions = async () => {
|
||||
const res = await apiAction('content_versions.list', { method: 'GET', data: { content_id: item.id } }).catch(() => ({}));
|
||||
versions = Array.isArray(res?.items) ? res.items : [];
|
||||
activeId = 0;
|
||||
versions.forEach(v => {
|
||||
if (Number(v.is_active) === 1) activeId = Number(v.id || 0);
|
||||
});
|
||||
renderVersions();
|
||||
updateDeleteState();
|
||||
};
|
||||
|
||||
const renderVersions = () => {
|
||||
if (!versionsWrap) return;
|
||||
if (!versions.length) {
|
||||
versionsWrap.innerHTML = '<div class=\"text-xs text-slate-500\">Keine Versionen vorhanden</div>';
|
||||
return;
|
||||
}
|
||||
versionsWrap.innerHTML = versions.map(v => {
|
||||
const isActive = Number(v.is_active) === 1;
|
||||
const label = `${isActive ? '✓ ' : ''}#${v.version_no} – ${formatVersionDate(v.created_at)}` + (isActive ? ' (aktiv)' : '');
|
||||
return `<div class=\"flex items-center gap-2 border rounded-lg px-3 py-2\" data-version-row=\"${v.id}\">
|
||||
<div class=\"text-xs text-slate-600\">${label}</div>
|
||||
<div class=\"ms-auto flex gap-2\">
|
||||
<button class=\"btn\" data-version-preview=\"${v.id}\">Vorschau</button>
|
||||
<button class=\"btn\" data-version-edit=\"${v.id}\">Bearbeiten</button>
|
||||
${isActive ? `<button class=\"btn\" data-version-deactivate=\"${v.id}\">Deaktivieren</button>` : `<button class=\"btn\" data-version-activate=\"${v.id}\">Aktivieren</button>`}
|
||||
<button class=\"btn btn-danger\" data-version-delete=\"${v.id}\" ${isActive ? 'disabled' : ''}>Löschen</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
};
|
||||
|
||||
const onApiInput = () => {
|
||||
if (!inpApiName) return;
|
||||
@@ -84,33 +142,97 @@ async function openTemplateEditor(item, section) {
|
||||
}
|
||||
};
|
||||
|
||||
function cleanup() {
|
||||
form && form.removeEventListener('submit', onSubmit);
|
||||
btnCancel && (btnCancel.onclick = null);
|
||||
const cleanup = () => {
|
||||
inpApiName && inpApiName.removeEventListener('input', onApiInput);
|
||||
}
|
||||
versionsWrap && versionsWrap.removeEventListener('click', onVersionsClick);
|
||||
if (btnClose) btnClose.onclick = null;
|
||||
if (btnSave) btnSave.onclick = null;
|
||||
if (btnDelete) btnDelete.onclick = null;
|
||||
};
|
||||
|
||||
async function onSubmit(ev) {
|
||||
ev.preventDefault();
|
||||
const onSave = async () => {
|
||||
try {
|
||||
const res = await apiUpdate('content', item.id, {
|
||||
const payload = {
|
||||
name: inpName ? inpName.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();
|
||||
if (typeof window.loadList === 'function') window.loadList(section);
|
||||
};
|
||||
if (section?.is_template) {
|
||||
payload.api_name = inpApiName ? inpApiName.value : '';
|
||||
}
|
||||
const res = await apiUpdate('content', item.id, payload);
|
||||
toast(res && res.ok ? 'Gespeichert' : 'Speichern fehlgeschlagen', !!(res && res.ok));
|
||||
if (res?.ok && typeof window.loadList === 'function') window.loadList(section);
|
||||
} catch {
|
||||
toast('Speichern fehlgeschlagen', false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onDeleteItem = async () => {
|
||||
if (activeId) return;
|
||||
if (!confirm('Template wirklich löschen?')) return;
|
||||
const res = await apiAction('content.delete', { method: 'POST', data: { id: item.id, section_id: section.id } });
|
||||
toast(res && res.ok ? 'Gelöscht' : 'Löschen fehlgeschlagen', !!(res && res.ok), { duration: 3000 });
|
||||
dlg && dlg.close();
|
||||
if (typeof window.loadList === 'function') window.loadList(section);
|
||||
};
|
||||
|
||||
const onVersionsClick = async (ev) => {
|
||||
const target = ev.target;
|
||||
if (!target || !target.dataset) return;
|
||||
const vid = Number(target.dataset.versionPreview || target.dataset.versionEdit || target.dataset.versionActivate || target.dataset.versionDeactivate || target.dataset.versionDelete || 0);
|
||||
if (!vid) return;
|
||||
|
||||
if (target.dataset.versionPreview !== undefined) {
|
||||
const res = await apiAction('content_versions.get', { method: 'GET', data: { id: vid, content_id: item.id } }).catch(() => ({}));
|
||||
const html = res?.item?.html || res?.item?.content || res?.html || res?.content || '';
|
||||
renderPreview(html);
|
||||
return;
|
||||
}
|
||||
if (target.dataset.versionEdit !== undefined) {
|
||||
dlg && dlg.close();
|
||||
const versionItem = { ...item, version_id: vid };
|
||||
openContentEditor(versionItem, section);
|
||||
return;
|
||||
}
|
||||
if (target.dataset.versionActivate !== undefined) {
|
||||
const res = await apiAction('content_versions.activate', { method: 'POST', data: { id: vid } });
|
||||
toast(res && res.ok ? 'Version aktiviert' : 'Aktivieren fehlgeschlagen', !!(res && res.ok));
|
||||
await loadVersions();
|
||||
return;
|
||||
}
|
||||
if (target.dataset.versionDeactivate !== undefined) {
|
||||
const res = await apiAction('content_versions.deactivate', { method: 'POST', data: { content_id: item.id } });
|
||||
toast(res && res.ok ? 'Aktive Version deaktiviert' : 'Deaktivieren fehlgeschlagen', !!(res && res.ok));
|
||||
await loadVersions();
|
||||
return;
|
||||
}
|
||||
if (target.dataset.versionDelete !== undefined) {
|
||||
const versionRow = versions.find(v => Number(v.id) === vid);
|
||||
if (versionRow && Number(versionRow.is_active) === 1) return;
|
||||
if (!confirm('Version wirklich löschen?')) return;
|
||||
const res = await apiAction('content_versions.delete', { method: 'POST', data: { id: vid, content_id: item.id } });
|
||||
toast(res && res.ok ? 'Version gelöscht' : 'Löschen fehlgeschlagen', !!(res && res.ok));
|
||||
await loadVersions();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
inpApiName && inpApiName.addEventListener('input', onApiInput);
|
||||
form && form.addEventListener('submit', onSubmit, { once: false });
|
||||
btnCancel && (btnCancel.onclick = () => { dlg && dlg.close(); cleanup(); });
|
||||
btnClose && (btnClose.onclick = () => { dlg && dlg.close(); cleanup(); });
|
||||
btnSave && (btnSave.onclick = onSave);
|
||||
btnDelete && (btnDelete.onclick = onDeleteItem);
|
||||
versionsWrap && versionsWrap.addEventListener('click', onVersionsClick);
|
||||
|
||||
await loadVersions();
|
||||
if (activeId) {
|
||||
const res = await apiAction('content_versions.get', { method: 'GET', data: { id: activeId, content_id: item.id } }).catch(() => ({}));
|
||||
const html = res?.item?.html || res?.item?.content || res?.html || res?.content || '';
|
||||
renderPreview(html);
|
||||
} else {
|
||||
renderPreview('');
|
||||
}
|
||||
|
||||
dlg && dlg.addEventListener('close', cleanup, { once: true });
|
||||
dlg && dlg.showModal();
|
||||
}
|
||||
|
||||
@@ -262,8 +384,8 @@ export async function loadList(section) {
|
||||
<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 openBtn = `<button class='btn' data-open='${item.id}'>Bearbeiten</button>`;
|
||||
const editTplBtn = isTemplate ? `<button class='btn' data-edit='${item.id}'>Verwaltung</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>`;
|
||||
@@ -341,26 +463,31 @@ export async function loadList(section) {
|
||||
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);
|
||||
if (item) openTemplateManager(item, section);
|
||||
}));
|
||||
|
||||
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 obj = await apiAction('content.get', { method: 'GET', data: { id, section_id: section.id, active_only: 1 } });
|
||||
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();
|
||||
}));
|
||||
|
||||
scope.querySelectorAll('[data-test]').forEach(btn => btn.addEventListener('click', () => {
|
||||
scope.querySelectorAll('[data-test]').forEach(btn => btn.addEventListener('click', async () => {
|
||||
const id = Number(btn.dataset.test || 0);
|
||||
const nm = btn.dataset.name || '';
|
||||
if (!id) {
|
||||
toast('Testversand: Ungültige ID', false);
|
||||
return;
|
||||
}
|
||||
const activeCheck = await apiAction('content.get', { method: 'GET', data: { id, section_id: section.id, active_only: 1 } }).catch(() => ({}));
|
||||
if (!activeCheck?.active_version_id && !activeCheck?.item?.active_version_id) {
|
||||
toast('Testversand nur mit aktiver Version möglich.', false);
|
||||
return;
|
||||
}
|
||||
if (window.AdminTestSend && typeof window.AdminTestSend.open === 'function') {
|
||||
window.AdminTestSend.open({ id, name: nm });
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user