diff --git a/public/assets/js/api.js b/public/assets/js/api.js index c7953ac..b8203b7 100644 --- a/public/assets/js/api.js +++ b/public/assets/js/api.js @@ -17,7 +17,7 @@ async function parseJsonSafe(res) { } } -// ... oberer Teil unverändert ... +// ...ss oberer Teil unverändert ... /** zentraler Fetch-Wrapper: Credentials, no-store, 401→Login */ async function apiFetch(url, init = {}) { diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 4caf1ac..f6f2dc5 100644 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -18,7 +18,7 @@ async function ensureAuthenticated() { window.location.href = '/login.php'; return false; } - // ✅ nur für eingeloggte Nutzer: UI freigeben + // ✅ nur für eingeloggte Nutzer: UI freigebensss document.documentElement.classList.remove('auth-pending'); const appRoot = document.getElementById('app'); if (appRoot && appRoot.hasAttribute('hidden')) appRoot.removeAttribute('hidden'); diff --git a/public/assets/js/bridge/blocks-api.js b/public/assets/js/bridge/blocks-api.js index 3f5c661..8d62221 100644 --- a/public/assets/js/bridge/blocks-api.js +++ b/public/assets/js/bridge/blocks-api.js @@ -303,11 +303,60 @@ setPreviewHtml(html) { const safeHtml = html || this.renderError('Referenz lädt …'); - this.set('rawHtml', safeHtml); + const alreadyDecorated = /^\s*<[^>]+data-lib-ref="1"/i.test(safeHtml); + let decoratedHtml = safeHtml; + if (!alreadyDecorated) { + const kind = this.get('lib-kind') || ''; + const id = this.get('lib-id') || ''; + const attrs = [ + 'data-lib-ref="1"', + kind ? `data-lib-kind="${kind}"` : '', + id ? `data-lib-id="${id}"` : '', + ].filter(Boolean).join(' '); + decoratedHtml = `
${safeHtml}
`; + } + this.set('rawHtml', decoratedHtml); const comps = this.components(); if (comps && comps.length) comps.reset([]); this.trigger('preview:update'); }, + populatePlaceholder(el) { + if (!el || el.__libHydrated) return; + const kind = el.getAttribute('data-lib-kind'); + const id = el.getAttribute('data-lib-id'); + if (!kind || !id) return; + el.setAttribute('data-lib-ref', '1'); + const applyHtml = (html) => { + if (typeof html === 'string' && html.length) { + el.innerHTML = html; + this.decoratePlaceholder(el, kind, id); + this.hydrateNestedReferences(el); + el.__libHydrated = true; + } + }; + const cached = this.getCachedApiItem(kind, id); + if (cached && cached.html) { + applyHtml(cached.html); + } + this.fetchReference(kind, id).then((item) => { + if (item && item.html) applyHtml(item.html); + }); + }, + + decoratePlaceholder(el, kind, id) { + el.setAttribute('data-lib-ref', '1'); + if (kind) el.setAttribute('data-lib-kind', kind); + if (id) el.setAttribute('data-lib-id', id); + el.setAttribute('contenteditable', 'false'); + el.style.pointerEvents = 'none'; + el.style.userSelect = 'none'; + }, + + hydrateNestedReferences(root) { + if (!root) return; + const placeholders = root.querySelectorAll('[data-lib-kind][data-lib-id]'); + placeholders.forEach((node) => this.populatePlaceholder(node)); + }, reloadComponentContent(opts = {}) { const kind = this.get('lib-kind'); @@ -337,11 +386,11 @@ } else { log(`RELOAD FEHLER: Inhalt ${kind}/${id} nicht gefunden.`, '#dc3545', 'error', true); this.setPreviewHtml( - this.renderError(`🛑 Fehler: Inhalt für ${kind}/${id} nicht gefunden.`) - ); - } - }) - .catch((error) => { + this.renderError(`🛑 Fehler: Inhalt für ${kind}/${id} nicht gefunden.`) + ); + } + }) + .catch((error) => { log('RELOAD FETCH ERROR', error?.message || String(error), '#dc3545', 'error', true); this.setPreviewHtml(this.renderError('🛑 Fehler beim Laden der Referenz.')); }); @@ -383,6 +432,7 @@ wrap.style.pointerEvents = 'none'; wrap.style.userSelect = 'none'; this.el.appendChild(wrap); + this.model.hydrateNestedReferences(wrap); }, });