/* /assets/js/bridge/categorization-cleanup.js (FINAL & LOG-KONTROLLIERT) */ (function(B){ if (!B || typeof grapesjs === 'undefined') return; // 🛑 NEUER NAME: Dies wird das Plugin in GrapesJS registrieren const PluginName = 'bridge-categorization-cleanup'; // ---------------------------------------------------------------------- // 🎯 NEU: LOKALE LOG-KONFIGURATION UND WRAPPER // ---------------------------------------------------------------------- // Setzen Sie dies auf 'false' in der config.js oder hier, um alle Logs NUR für dieses Plugin zu deaktivieren. if (B.LOG_CONFIG && B.LOG_CONFIG.PLUGINS) { B.LOG_CONFIG.PLUGINS[PluginName] = false; // <-- HIER IST IHR SCHALTER } // NEUER LOKALER WRAPPER, der die zentrale B.log Funktion verwendet: const log = (type, message, color = '#228B22', logType = 'info', force = false) => { // Wir verwenden B.log, das die B.LOG_CONFIG.PLUGINS[PluginName] prüft if (typeof B.log === 'function') { B.log(PluginName, `[${type}] ${message}`, color, logType, force); } else if (logType === 'error') { // Fallback für kritische Fehler, wenn B.log fehlt (sollte nicht passieren) console.error(`%c[${PluginName} - ${type}] %c${message}`, `color:red; font-weight:bold;`, 'color:inherit;'); } }; // ---------------------------------------------------------------------- // 🛑 WICHTIG: Liste aller unerwünschten IDs/Labels const UNWANTED_UNCATEGORIZED_ID = 'Uncategorized'; // Fügen Sie die gängigen IDs des gjs-preset-newsletter hinzu const PRESET_UNWANTED_IDS = ['Basic', 'Layout', 'Extra', 'Components', 'Forms']; // Alle IDs, die gelöscht werden müssen. Enthält NICHT mehr 'Bibliothek'. const ALL_FORBIDDEN_CAT_IDS = [UNWANTED_UNCATEGORIZED_ID, ...PRESET_UNWANTED_IDS]; const UNWANTED_BLOCK_ID = 'gjs-lbr-block-disabled'; const UNWANTED_BLOCK_LABEL = 'Bibliothek-disabled'; const FALLBACK_CATEGORY_ID = 'mysnips'; const CUSTOM_BLOCK_IDS = (window.BridgeBlocksCustom && window.BridgeBlocksCustom.IDS) || []; let normalizationRunCount = 0; let normalizationIsRunning = false; let maxNormalizationRuns = 5; // ---------------------------------------------------------------------- // HILFSFUNKTION: Entfernt hartnäckige Kategorie-DOM-Elemente // ---------------------------------------------------------------------- const zapUnwantedCategoryDom = (editor) => { const blocksPanelEl = editor.BlockManager.getContainer(); if (blocksPanelEl) { let removedCount = 0; blocksPanelEl.querySelectorAll('.gjs-block-cat').forEach(catEl => { const catTitleEl = catEl.querySelector('.gjs-title'); if (catTitleEl) { const catTitle = catTitleEl.textContent.trim(); // Prüft, ob der Titel eine der unerwünschten IDs ist (z.B. 'Basic') if (ALL_FORBIDDEN_CAT_IDS.includes(catTitle)) { catEl.remove(); removedCount++; } } }); if (removedCount > 0) { log('DOM FIX', `${removedCount} unerwünschte Kategorie-DOM-Elemente entfernt.`, 'orange', 'warn'); } } }; // ---------------------------------------------------------------------- // Hilfsfunktion: Erzwingt das Neu-Rendern der Block-View // ---------------------------------------------------------------------- const renderBlocks = (editor) => { zapUnwantedCategoryDom(editor); log('RENDER', 'DOM-Cleanup ausgeführt.', 'green'); }; // ---------------------------------------------------------------------- // 1. Funktion zum Ausblenden/Normalisieren der Kategorien (Kernlogik) // ---------------------------------------------------------------------- const normalizeCategories = (editor) => { if (normalizationIsRunning || normalizationRunCount >= maxNormalizationRuns) { if (normalizationRunCount >= maxNormalizationRuns) { log('SKIP', `normalizeCategories übersprungen: Maximale Läufe (${maxNormalizationRuns}) erreicht.`, 'red', 'warn'); } else { log('SKIP', 'normalizeCategories übersprungen: Läuft bereits.', 'red', 'warn'); } return; } normalizationIsRunning = true; normalizationRunCount++; // Nur das Start-Log kann eine Gruppen-Markierung sein log('START', `Starte normalizeCategories Run #${normalizationRunCount}`, '#191970'); const bm = editor.BlockManager; const config = B.CATEGORY_CONFIG || {}; const configuredCategoryIds = Object.keys(config); log('CONFIG', `Konfigurierte Kategorie-IDs: ${configuredCategoryIds.join(', ')}`, '#555555'); // --- A. Explizites Erstellen der Kategorien (Sicherheits-Fallback) --- const catsToEnsure = new Set(configuredCategoryIds); catsToEnsure.forEach(catId => { const catConf = config[catId]; if (!catConf) return; if (!bm.getCategories().get(catId)) { bm.getCategories().add({ id: catId, label: catConf.label, open: catConf.open !== false, order: catConf.ord || 999 }); log('CAT FALLBACK', `Kategorie '${catId}' fehlte und wurde JETZT erstellt!`, 'red', 'error'); } }); // --- B. Zwangszuweisung der Blöcke und Bereinigung von Blöcken --- bm.getAll().each(block => { const id = block.get('id'); const label = block.get('label'); let catId = block.get('category'); if (typeof catId === 'object' && catId.id) { catId = catId.id; } // 1. Lösche unerwünschten hartnäckigen Block (DEAKTIVIERT) if (id === UNWANTED_BLOCK_ID || label === UNWANTED_BLOCK_LABEL) { // ... (Block removal logic commented out) // log('BLOCK REMOVE', `Lösche unerwünschten Block: ${id}`, 'red', 'warn'); // bm.remove(id); } // 2. Setze Blöcke ohne oder mit unerwünschter/unbekannter Kategorie auf den Fallback (mysnips) const isUnconfiguredOrForbidden = !catId || !configuredCategoryIds.includes(catId) || ALL_FORBIDDEN_CAT_IDS.includes(catId); if (isUnconfiguredOrForbidden) { if (id) { log('BLOCK FIX', `Block '${id}' ('${label}') verschoben nach '${FALLBACK_CATEGORY_ID}' (Ursprüngliche Kat ID: ${catId || 'keine/leer'}).`, 'orange', 'warn'); block.set('category', FALLBACK_CATEGORY_ID); } } else { log('BLOCK OK', `Block '${id}' ('${label}') bleibt in Kategorie '${catId}'.`, 'green'); } // 3. Custom Blocks schützen if (CUSTOM_BLOCK_IDS.includes(id) && catId !== 'bausteine') { log('BLOCK FIX', `Custom Block '${id}' auf 'bausteine' korrigiert.`, 'orange', 'warn'); block.set('category', 'bausteine'); } }); // --- C. Kategorien erzwingen, Label korrigieren und Löschen von Modellen --- const categories = bm.getCategories().models || bm.getCategories(); let visibleCategories = []; categories.forEach(catModel => { const catId = catModel.get('id'); const catConf = config[catId]; // 1. Aggressives Löschen von unerwünschten Preset-Kategorien if (ALL_FORBIDDEN_CAT_IDS.includes(catId)) { log('CAT REMOVE', `Lösche unerwünschtes Category Model: ${catId} (Da in ALL_FORBIDDEN_CAT_IDS).`, 'red', 'error'); bm.getCategories().remove(catModel); return; } const activeConf = catConf; // 2. Finde eine existierende, aber nicht konfigurierte Kategorie, und blende sie aus if (!activeConf && catId) { log('CAT HIDE', `Kategorie '${catId}' existiert, ist aber nicht in CATEGORY_CONFIG. Wird ausgeblendet.`, 'orange', 'warn'); catModel.set('visible', false); catModel.set('open', false); return; } // 3. Korrigiere Label, Sortierung und Sichtbarkeit (Konfigurierte Kategorien) if (activeConf) { const oldLabel = catModel.get('label'); const newLabel = activeConf.label; const visibility = true; if (oldLabel !== newLabel) { log('CAT UPDATE', `Korrigiere Label von '${catId}' von '${oldLabel}' auf '${newLabel}'.`, '#00BFFF'); catModel.set('label', newLabel, { silent: true }); } catModel.set('visible', visibility); catModel.set('open', activeConf.open !== false); catModel.set('order', activeConf.ord || 999); visibleCategories.push(catId); log('CAT FINAL', `Kategorie '${catId}' auf Visible: ${visibility}, Order: ${catModel.get('order')}.`, 'green'); } }); // --- D. Cleanup und Neu-Sortierung erzwingen --- categories.sort((a, b) => (a.get('order') || 999) - (b.get('order') || 999)); B.sortBlocksByPrefixAndLabel && B.sortBlocksByPrefixAndLabel(bm.getAll().models); // DOM Cleanup wird über renderBlocks aufgerufen renderBlocks(editor); log('END', `Kategorisierung abgeschlossen. Sichtbare Kategorien (Modelle): ${visibleCategories.sort().join(', ')}.`, 'green', 'info', true); // FINAL Log ist forced=true für Abschlussmeldung normalizationIsRunning = false; }; // ---------------------------------------------------------------------- // GrapesJS Plugin Registrierung // ---------------------------------------------------------------------- grapesjs.plugins.add(PluginName, (editor, opts = {}) => { const bm = editor.BlockManager; // 1. Initialer, verspäteter Lauf bei Ladevorgang editor.on('load', () => { setTimeout(() => { log('FINAL RUN', `Starte finalen Normalisierungslauf nach 2500ms.`, 'orange', 'warn'); normalizeCategories(editor); }, 2500); }); // 2. WATCHDOG gegen Label-Überschreibung oder unerwünschte Adds bm.getCategories().on('add change:label', (categoryModel) => { const catId = categoryModel.get('id'); const newLabel = categoryModel.get('label'); const expectedLabel = B.CATEGORY_CONFIG?.[catId]?.label; // WATCHDOG-ADD if (ALL_FORBIDDEN_CAT_IDS.includes(catId)) { log('WATCHDOG-ADD', `Unerwünschte Kategorie '${catId}' wurde hinzugefügt! Starte Sofort-Korrektur.`, 'red', 'error'); bm.getCategories().remove(categoryModel); setTimeout(() => normalizeCategories(editor), 1); } // WATCHDOG-LABEL if (expectedLabel && newLabel !== expectedLabel) { log('WATCHDOG-CHANGE', `Externe Label-Manipulation von '${catId}' erkannt: Korrigiere von '${newLabel}' auf '${expectedLabel}'.`, 'orange', 'warn'); categoryModel.set('label', expectedLabel, { silent: true }); setTimeout(() => normalizeCategories(editor), 1); } }); // Exporte beibehalten, falls sie in bridge-core.js verwendet werden B.normalizeCategories = normalizeCategories; B.renderBlocks = renderBlocks; log('INIT', 'Master-Koordinator registriert.', '#008080'); }); })(window.BridgeParts || (window.BridgeParts = {}));