app/javascript/panda/cms/controllers/editor_form_controller.js in panda-cms-0.7.0 vs app/javascript/panda/cms/controllers/editor_form_controller.js in panda-cms-0.7.2
- old
+ new
@@ -1,17 +1,39 @@
import { Controller } from "@hotwired/stimulus";
+import { EDITOR_JS_RESOURCES, EDITOR_JS_CSS } from "panda/cms/editor/editor_js_config";
+import { ResourceLoader } from "panda/cms/editor/resource_loader";
export default class extends Controller {
static targets = ["editorContainer", "hiddenField"];
static values = {
editorId: String,
};
connect() {
- this.initializeEditor();
+ this.loadEditorResources();
}
+ async loadEditorResources() {
+ try {
+ // First load EditorJS core
+ const editorCore = EDITOR_JS_RESOURCES[0];
+ await ResourceLoader.loadScript(document, document.head, editorCore);
+
+ // Load CSS
+ await ResourceLoader.embedCSS(document, document.head, EDITOR_JS_CSS);
+
+ // Then load all tools sequentially
+ for (const resource of EDITOR_JS_RESOURCES.slice(1)) {
+ await ResourceLoader.loadScript(document, document.head, resource);
+ }
+
+ await this.initializeEditor();
+ } catch (error) {
+ console.error("[Panda CMS] Failed to load editor resources:", error);
+ }
+ }
+
async initializeEditor() {
if (this.editor) return;
try {
const holderId =
@@ -24,43 +46,144 @@
this.editorContainerTarget.appendChild(holderDiv);
const { getEditorConfig } = await import(
"panda/cms/editor/editor_js_config"
);
- const config = getEditorConfig(holderId, this.getInitialContent());
- editor_content_post;
+ // Get initial content before creating config
+ const initialContent = this.getInitialContent();
+ console.debug("[Panda CMS] Using initial content:", initialContent);
- this.editor = new EditorJS({
- ...config,
+ const config = {
+ ...getEditorConfig(holderId, initialContent),
holder: holderId,
+ data: initialContent,
autofocus: false,
minHeight: 1,
logLevel: "ERROR",
onChange: () => {
if (!this.editor) return;
this.editor.save().then((outputData) => {
outputData.source = "editorJS";
- this.hiddenFieldTarget.value = JSON.stringify(outputData);
+ const jsonString = JSON.stringify(outputData);
+ // Store both base64 and regular JSON
+ this.editorContainerTarget.dataset.editablePreviousData = btoa(jsonString);
+ this.editorContainerTarget.dataset.editableContent = jsonString;
+ this.hiddenFieldTarget.value = jsonString;
});
},
- });
+ onReady: () => {
+ console.debug("[Panda CMS] Editor ready with content:", initialContent);
+ this.editorContainerTarget.dataset.editorInitialized = "true";
+ holderDiv.dataset.editorInitialized = "true";
+ // Add a class to indicate the editor is ready
+ holderDiv.classList.add("editor-ready");
+ // Dispatch an event when editor is ready
+ this.editorContainerTarget.dispatchEvent(new CustomEvent("editor:ready"));
+ },
+ tools: {
+ paragraph: {
+ class: window.Paragraph,
+ inlineToolbar: true
+ },
+ header: {
+ class: window.Header,
+ inlineToolbar: true
+ },
+ list: {
+ class: window.NestedList,
+ inlineToolbar: true,
+ config: {
+ defaultStyle: 'unordered',
+ enableLineBreaks: true
+ }
+ },
+ quote: {
+ class: window.Quote,
+ inlineToolbar: true
+ },
+ table: {
+ class: window.Table,
+ inlineToolbar: true
+ }
+ }
+ };
+
+ // Ensure EditorJS is available
+ const EditorJS = window.EditorJS;
+ if (!EditorJS) {
+ throw new Error("EditorJS not loaded");
+ }
+
+ this.editor = new EditorJS(config);
+
+ // Wait for editor to be ready
+ await this.editor.isReady;
+ console.debug("[Panda CMS] Editor initialized successfully");
+ this.editorContainerTarget.dataset.editorInitialized = "true";
+ holderDiv.dataset.editorInitialized = "true";
+ // Add a class to indicate the editor is ready
+ holderDiv.classList.add("editor-ready");
+ // Dispatch an event when editor is ready
+ this.editorContainerTarget.dispatchEvent(new CustomEvent("editor:ready"));
+
} catch (error) {
console.error("[Panda CMS] Editor setup failed:", error);
+ this.editorContainerTarget.dataset.editorInitialized = "false";
+ if (holderDiv) {
+ holderDiv.dataset.editorInitialized = "false";
+ holderDiv.classList.remove("editor-ready");
+ }
}
}
getInitialContent() {
try {
- const value = this.hiddenFieldTarget.value;
- if (value && value !== "{}") {
- const data = JSON.parse(value);
- if (data.blocks) return data;
+ const initialContent = this.hiddenFieldTarget.getAttribute("data-initial-content");
+ if (initialContent && initialContent !== "{}") {
+ try {
+ // First try to decode as base64
+ try {
+ const decodedData = atob(initialContent);
+ const data = JSON.parse(decodedData);
+ if (data.blocks) return data;
+ } catch (e) {
+ // If base64 decode fails, try direct JSON parse
+ const data = JSON.parse(initialContent);
+ if (data.blocks) return data;
+ }
+ } catch (e) {
+ console.error("[Panda CMS] Failed to parse content:", e);
+ }
}
+
+ // Try to get content from the editor container's data attributes
+ const previousData = this.editorContainerTarget.dataset.editablePreviousData;
+ const editorContent = this.editorContainerTarget.dataset.editableContent;
+
+ if (previousData) {
+ try {
+ const decodedData = atob(previousData);
+ const data = JSON.parse(decodedData);
+ if (data.blocks) return data;
+ } catch (e) {
+ console.debug("[Panda CMS] Failed to parse base64 data:", e);
+ }
+ }
+
+ if (editorContent && editorContent !== "{}") {
+ try {
+ const data = JSON.parse(editorContent);
+ if (data.blocks) return data;
+ } catch (e) {
+ console.debug("[Panda CMS] Failed to parse editor content:", e);
+ }
+ }
} catch (e) {
console.warn("[Panda CMS] Could not parse initial content:", e);
}
+ // Return default content if nothing else works
return {
time: Date.now(),
blocks: [{ type: "paragraph", data: { text: "" } }],
version: "2.28.2",
source: "editorJS",