inclide craft
This commit is contained in:
@@ -2,16 +2,19 @@
|
||||
// Öffnen, Befüllen, Speichern (mit Live-HTML), Preview – Race-Schutz & Lade-Overlay.
|
||||
|
||||
import { apiUpdate, apiList, apiGet, toast, apiAction } from './api.js';
|
||||
import { initCraftEditor } from './craft-editor.js';
|
||||
|
||||
export function initEditor() {
|
||||
// ... (Alle Konstanten bleiben unverändert) ...
|
||||
const dlg = document.getElementById('editorDialog');
|
||||
const iframe = document.getElementById('editorFrame');
|
||||
const btnSave = document.getElementById('btn-save');
|
||||
const btnPreview = document.getElementById('btn-preview');
|
||||
const btnTest = document.getElementById('btn-test');
|
||||
const btnClose = document.getElementById('btn-close');
|
||||
const btnClear = document.getElementById('btn-clear-main');
|
||||
const btnSave = document.getElementById('btn-save');
|
||||
const btnPreview = document.getElementById('btn-preview');
|
||||
const btnTest = document.getElementById('btn-test');
|
||||
const btnClose = document.getElementById('btn-close');
|
||||
const btnClear = document.getElementById('btn-clear-main');
|
||||
const editorSelect = document.getElementById('editorTypeSelect');
|
||||
const craftEditor = initCraftEditor();
|
||||
|
||||
const prevDlg = document.getElementById('previewDialog');
|
||||
const sendDlg = document.getElementById('sendTestDialog');
|
||||
@@ -26,11 +29,12 @@ export function initEditor() {
|
||||
const prevFrame = document.getElementById('previewFrame');
|
||||
const btnPrevClose = document.getElementById('btn-close-preview');
|
||||
|
||||
let current = null; // { resource, id, name }
|
||||
let bridgeListener = null;
|
||||
let reqToken = 0; // steigender Token pro Öffnen -> ignoriert verspätete Events
|
||||
let senderOptions = [];
|
||||
let senderLoadPromise = null;
|
||||
let current = null; // { resource, id, name }
|
||||
let bridgeListener = null;
|
||||
let reqToken = 0; // steigender Token pro Öffnen -> ignoriert verspätete Events
|
||||
let senderOptions = [];
|
||||
let senderLoadPromise = null;
|
||||
let currentEditorType = 'grapesjs';
|
||||
|
||||
const ok = (m) => toast(m, true);
|
||||
const err = (m) => toast(m, false);
|
||||
@@ -69,20 +73,23 @@ export function initEditor() {
|
||||
</html>`;
|
||||
}
|
||||
|
||||
async function readEditedHtml() {
|
||||
const win = iframe?.contentWindow;
|
||||
const doc = iframe?.contentDocument;
|
||||
if (!win || !doc) return '';
|
||||
async function readEditedHtml() {
|
||||
if (currentEditorType === 'craftjs') {
|
||||
return craftEditor ? craftEditor.getContent() : '';
|
||||
}
|
||||
const win = iframe?.contentWindow;
|
||||
const doc = iframe?.contentDocument;
|
||||
if (!win || !doc) return '';
|
||||
|
||||
const ed = win.__gjs || (win.grapesjs && win.grapesjs.editors && win.grapesjs.editors[0]) || null;
|
||||
if (ed && typeof ed.getHtml === 'function') {
|
||||
const html = ed.getHtml();
|
||||
const css = (typeof ed.getCss === 'function') ? ed.getCss() : '';
|
||||
return css ? `<style>${css}</style>\n${html}` : html;
|
||||
}
|
||||
const root = doc.querySelector('#gjs') || doc.body || doc.documentElement;
|
||||
return root ? root.innerHTML : '';
|
||||
}
|
||||
const ed = win.__gjs || (win.grapesjs && win.grapesjs.editors && win.grapesjs.editors[0]) || null;
|
||||
if (ed && typeof ed.getHtml === 'function') {
|
||||
const html = ed.getHtml();
|
||||
const css = (typeof ed.getCss === 'function') ? ed.getCss() : '';
|
||||
return css ? `<style>${css}</style>\n${html}` : html;
|
||||
}
|
||||
const root = doc.querySelector('#gjs') || doc.body || doc.documentElement;
|
||||
return root ? root.innerHTML : '';
|
||||
}
|
||||
|
||||
function waitForEditor(maxMs = 8000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -98,7 +105,7 @@ export function initEditor() {
|
||||
}
|
||||
|
||||
// 🚨 NEUE FUNKTION: Delegiert das Kommando an den Editor im iFrame
|
||||
async function delegateCommand(commandName) {
|
||||
async function delegateCommand(commandName) {
|
||||
try {
|
||||
const editor = await waitForEditor(3000);
|
||||
if (editor.Commands.has(commandName)) {
|
||||
@@ -114,9 +121,9 @@ export function initEditor() {
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// ... (hideReadyBadge bleibt unverändert) ...
|
||||
function hideReadyBadge(doc) {
|
||||
}
|
||||
// ... (hideReadyBadge bleibt unverändert) ...
|
||||
function hideReadyBadge(doc) {
|
||||
if (!doc) return;
|
||||
const kill = () => {
|
||||
const el = doc.getElementById('badge');
|
||||
@@ -143,7 +150,40 @@ export function initEditor() {
|
||||
setTimeout(() => { kill(); /* hideByText(doc); */ }, 150);
|
||||
setTimeout(() => { kill(); /* hideByText(doc); */ }, 500);
|
||||
setTimeout(() => { kill(); /* hideByText(doc); */ }, 1200);
|
||||
}
|
||||
}
|
||||
|
||||
function extractCraftHtml(craftJson, fallbackHtml) {
|
||||
if (!craftJson) return fallbackHtml || '';
|
||||
try {
|
||||
const parsed = typeof craftJson === 'string' ? JSON.parse(craftJson) : craftJson;
|
||||
if (parsed && typeof parsed.html === 'string') {
|
||||
return parsed.html;
|
||||
}
|
||||
} catch {}
|
||||
return fallbackHtml || '';
|
||||
}
|
||||
|
||||
function looksCraftSerialized(payload) {
|
||||
if (!payload) return false;
|
||||
try {
|
||||
const parsed = typeof payload === 'string' ? JSON.parse(payload) : payload;
|
||||
return !!(parsed && typeof parsed === 'object' && parsed.ROOT);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function setEditorType(nextType) {
|
||||
currentEditorType = nextType === 'craftjs' ? 'craftjs' : 'grapesjs';
|
||||
if (editorSelect) editorSelect.value = currentEditorType;
|
||||
if (currentEditorType === 'craftjs') {
|
||||
iframe?.classList?.add('hidden');
|
||||
craftEditor?.show();
|
||||
} else {
|
||||
craftEditor?.hide();
|
||||
iframe?.classList?.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// ... (Lade-Overlay bleibt unverändert) ...
|
||||
let veilEl = null;
|
||||
@@ -328,6 +368,9 @@ export function initEditor() {
|
||||
let hasJson = false;
|
||||
let jsonState = '';
|
||||
|
||||
let editorType = 'grapesjs';
|
||||
let craftJson = '';
|
||||
|
||||
await Promise.all([
|
||||
(async() => {
|
||||
try {
|
||||
@@ -342,12 +385,34 @@ export function initEditor() {
|
||||
if (!fresh && !looksJson) {
|
||||
fresh = rawContent;
|
||||
}
|
||||
editorType = String(row?.editor_type ?? row?.item?.editor_type ?? 'grapesjs').toLowerCase();
|
||||
craftJson = row?.craft_json ?? row?.item?.craft_json ?? '';
|
||||
} catch {}
|
||||
})(),
|
||||
})(),
|
||||
(async() => { snippets = await buildSnippetsForContext(current); })(),
|
||||
(async() => { refLib = await buildRefLibForContext(current); })()
|
||||
]);
|
||||
|
||||
editorType = editorType === 'craftjs' ? 'craftjs' : 'grapesjs';
|
||||
setEditorType(editorType);
|
||||
if (editorType === 'craftjs') {
|
||||
const craftHtml = extractCraftHtml(craftJson, fresh);
|
||||
craftEditor?.setContent(craftHtml, craftJson);
|
||||
hideVeil();
|
||||
if (dlg && typeof dlg.showModal === 'function') dlg.showModal();
|
||||
if (!looksCraftSerialized(craftJson) && craftEditor?.serializeFromHtml) {
|
||||
const seed = craftEditor.serializeFromHtml(craftHtml);
|
||||
try {
|
||||
await apiUpdate(current.resource, current.id, {
|
||||
editor_type: 'craftjs',
|
||||
html: craftHtml,
|
||||
craft_json: seed
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// iFrame-Load -> Bridge-Ready abhören
|
||||
iframe.onload = function () {
|
||||
if (myToken !== reqToken) return;
|
||||
@@ -417,21 +482,37 @@ export function initEditor() {
|
||||
dlg?.showModal?.();
|
||||
}
|
||||
|
||||
// ---------- Speichern (DELEGIERT) ----------
|
||||
// 🚨 KORRIGIERT: Delegiert Speichern an den iFrame, der die JSON-Daten holt!
|
||||
async function save() {
|
||||
if (!current?.id) return err('Keine aktive ID');
|
||||
// ---------- Speichern (DELEGIERT) ----------
|
||||
// 🚨 KORRIGIERT: Delegiert Speichern an den iFrame, der die JSON-Daten holt!
|
||||
async function save() {
|
||||
if (!current?.id) return err('Keine aktive ID');
|
||||
|
||||
return delegateCommand('save-data');
|
||||
}
|
||||
if (currentEditorType === 'craftjs') {
|
||||
const html = craftEditor ? craftEditor.getContent() : '';
|
||||
const craftJson = craftEditor && craftEditor.getCraftJson
|
||||
? craftEditor.getCraftJson()
|
||||
: JSON.stringify({ html });
|
||||
const payload = { html, craft_json: craftJson, editor_type: 'craftjs' };
|
||||
const res = await apiUpdate(current.resource, current.id, payload);
|
||||
if (res?.ok) ok('Gespeichert');
|
||||
else err(res?.error || 'Speichern fehlgeschlagen');
|
||||
return res?.ok;
|
||||
}
|
||||
|
||||
return delegateCommand('save-data');
|
||||
}
|
||||
|
||||
// ... (Der Rest der Funktionen bleibt unverändert) ...
|
||||
async function clearEditor() {
|
||||
const win = iframe?.contentWindow;
|
||||
const ed = win?.__gjs || (win?.grapesjs && win.grapesjs.editors && win.grapesjs.editors[0]) || null;
|
||||
if (ed) {
|
||||
ed.setComponents('');
|
||||
ed.setStyle('');
|
||||
async function clearEditor() {
|
||||
if (currentEditorType === 'craftjs') {
|
||||
craftEditor?.clear();
|
||||
return;
|
||||
}
|
||||
const win = iframe?.contentWindow;
|
||||
const ed = win?.__gjs || (win?.grapesjs && win.grapesjs.editors && win.grapesjs.editors[0]) || null;
|
||||
if (ed) {
|
||||
ed.setComponents('');
|
||||
ed.setStyle('');
|
||||
} else {
|
||||
writeHtmlToFrame('');
|
||||
}
|
||||
@@ -485,7 +566,7 @@ export function initEditor() {
|
||||
}
|
||||
function closePreview(){ prevDlg?.close?.(); }
|
||||
|
||||
function close() {
|
||||
function close() {
|
||||
// nächstes Öffnen invalidiert laufende asyncs
|
||||
reqToken++;
|
||||
|
||||
@@ -503,17 +584,64 @@ export function initEditor() {
|
||||
current = null;
|
||||
window.__currentItemId = undefined;
|
||||
window.__currentEditorCtx = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons
|
||||
btnSave && (btnSave.onclick = save);
|
||||
btnClear && (btnClear.onclick = clearEditor);
|
||||
btnClose && (btnClose.onclick = close);
|
||||
async function switchEditor(nextType) {
|
||||
if (!current?.id) return;
|
||||
const target = nextType === 'craftjs' ? 'craftjs' : 'grapesjs';
|
||||
if (target === currentEditorType) return;
|
||||
const confirmed = window.confirm('Editor wechseln? Ungespeicherte Änderungen gehen verloren.');
|
||||
if (!confirmed) {
|
||||
if (editorSelect) editorSelect.value = currentEditorType;
|
||||
return;
|
||||
}
|
||||
if (currentEditorType === 'grapesjs' && target === 'craftjs') {
|
||||
const html = await readEditedHtml();
|
||||
const craftJson = craftEditor && craftEditor.serializeFromHtml
|
||||
? craftEditor.serializeFromHtml(html)
|
||||
: JSON.stringify({ html });
|
||||
const res = await apiUpdate(current.resource, current.id, {
|
||||
editor_type: 'craftjs',
|
||||
html,
|
||||
craft_json: craftJson
|
||||
});
|
||||
if (!res?.ok) {
|
||||
err(res?.error || 'Editorwechsel fehlgeschlagen');
|
||||
if (editorSelect) editorSelect.value = currentEditorType;
|
||||
return;
|
||||
}
|
||||
setEditorType('craftjs');
|
||||
craftEditor?.setContent(html, craftJson);
|
||||
iframe.src = 'about:blank#' + Date.now();
|
||||
ok('Editor gewechselt');
|
||||
return;
|
||||
}
|
||||
if (currentEditorType === 'craftjs' && target === 'grapesjs') {
|
||||
const html = craftEditor ? craftEditor.getContent() : '';
|
||||
const res = await apiUpdate(current.resource, current.id, {
|
||||
editor_type: 'grapesjs',
|
||||
html
|
||||
});
|
||||
if (!res?.ok) {
|
||||
err(res?.error || 'Editorwechsel fehlgeschlagen');
|
||||
if (editorSelect) editorSelect.value = currentEditorType;
|
||||
return;
|
||||
}
|
||||
ok('Editor gewechselt');
|
||||
await open({ id: current.id, name: current.name }, current.resource);
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons
|
||||
btnSave && (btnSave.onclick = save);
|
||||
btnClear && (btnClear.onclick = clearEditor);
|
||||
btnClose && (btnClose.onclick = close);
|
||||
btnPrevClose && (btnPrevClose.onclick = closePreview);
|
||||
btnPreview && (btnPreview.onclick = openPreview);
|
||||
btnTest && (btnTest.onclick = openSend);
|
||||
btnCancelSend&& (btnCancelSend.onclick= closeSend);
|
||||
sendForm && (sendForm.onsubmit = doSend);
|
||||
btnPreview && (btnPreview.onclick = openPreview);
|
||||
btnTest && (btnTest.onclick = openSend);
|
||||
btnCancelSend&& (btnCancelSend.onclick= closeSend);
|
||||
sendForm && (sendForm.onsubmit = doSend);
|
||||
editorSelect && (editorSelect.onchange = () => switchEditor(editorSelect.value));
|
||||
|
||||
window.AdminTestSend = window.AdminTestSend || {};
|
||||
window.AdminTestSend.open = (opts = {}) => {
|
||||
|
||||
Reference in New Issue
Block a user