From 27e31ed19d4311fe218bdfdcd5c58c98392b3bac Mon Sep 17 00:00:00 2001 From: Nigel van Keulen Date: Tue, 14 May 2024 01:37:01 +0200 Subject: [PATCH] Wagtail Chooser Support --- README.md | 1 - setup.cfg | 2 +- wagtail_editorjs/__init__.py | 2 +- wagtail_editorjs/features/blocks.py | 23 +++++++++--- wagtail_editorjs/registry/feature_registry.py | 4 ++- wagtail_editorjs/registry/features/base.py | 8 +++++ .../js/tools/wagtail-block.js | 35 ++++++++++++------- 7 files changed, 54 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 7416e41..8c92b8e 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,6 @@ It is **not** allowed to be or include: * A `StreamBlock` (mainly due to styling issues) * A `ListBlock` (mainly due to styling issues) -* Any type of `ChooserBlock` (cannot initialize) * A `RichTextBlock` (cannot initialize) *Help with these issues is highly appreciated!* diff --git a/setup.cfg b/setup.cfg index bc3ac20..ac12161 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = wagtail_editorjs -version = 1.6.4 +version = 1.6.5rc1 description = EditorJS as a widget for Wagtail, with Page- and Image chooser support long_description = file: README.md long_description_content_type = text/markdown diff --git a/wagtail_editorjs/__init__.py b/wagtail_editorjs/__init__.py index 8189314..1da4029 100644 --- a/wagtail_editorjs/__init__.py +++ b/wagtail_editorjs/__init__.py @@ -11,5 +11,5 @@ -__version__ = '1.6.4' +__version__ = '1.6.5rc1' VERSION = pv.LooseVersion(__version__) diff --git a/wagtail_editorjs/features/blocks.py b/wagtail_editorjs/features/blocks.py index 0d1480b..e275754 100644 --- a/wagtail_editorjs/features/blocks.py +++ b/wagtail_editorjs/features/blocks.py @@ -314,9 +314,6 @@ def __init__(self, if not isinstance(block, blocks.Block) and issubclass(block, blocks.Block): block = block() - if not isinstance(block, (blocks.StructBlock, blocks.FieldBlock)): - raise TypeError("block must be an instance of EditorJSFeatureStructBlock or FieldBlock") - self.block = block self.block.set_name( @@ -397,9 +394,25 @@ def validate(self, data: Any): if "block" not in data["data"]: raise forms.ValidationError("Invalid block value") - self.block.clean( - data["data"]["block"], + try: + data["data"]["block"] = self.block.get_prep_value( + self.block.clean(self.block.to_python(data["data"]["block"])) + ) + except blocks.StreamBlockValidationError as e: + raise e + except blocks.list_block.ListBlockValidationError as e: + raise e + except blocks.struct_block.StructBlockValidationError as e: + raise e + except Exception as e: + raise e + + def value_for_form(self, value: dict) -> dict: + value = super().value_for_form(value) + value["data"]["block"] = self.block.get_form_state( + self.block.to_python(value["data"]["block"]) ) + return value def render_block_data(self, block: EditorJSBlock, context=None) -> EditorJSElement: value: blocks.StructValue = self.block.to_python(block["data"]["block"]) diff --git a/wagtail_editorjs/registry/feature_registry.py b/wagtail_editorjs/registry/feature_registry.py index 546084c..617f823 100644 --- a/wagtail_editorjs/registry/feature_registry.py +++ b/wagtail_editorjs/registry/feature_registry.py @@ -185,7 +185,7 @@ def prepare_value(self, tools: list[str], data: dict): if key not in tools: del tunes[key] - blocks[i] = item + blocks[i] = self[block_type].value_for_form(item) data["blocks"] = list(filter(None, blocks)) return data @@ -232,6 +232,8 @@ def validate_for_tools(self, tools: list[str], data: dict): if item["type"] == tool: tool_mapping.validate(item) + data["blocks"] = block_list + return data diff --git a/wagtail_editorjs/registry/features/base.py b/wagtail_editorjs/registry/features/base.py index f6bf514..ecc2528 100644 --- a/wagtail_editorjs/registry/features/base.py +++ b/wagtail_editorjs/registry/features/base.py @@ -107,6 +107,14 @@ def __init__(self, self.allowed_tags = set(allowed_tags) self.allowed_attributes = allowed_attributes + def value_for_form(self, value: dict) -> dict: + """ + Prepare the value for the feature. + This is useful for when you need to modify the data + before it is passed to the frontend. + """ + return value + def init_static(self, css, js): css = css or [] js = js or [] diff --git a/wagtail_editorjs/static/wagtail_editorjs/js/tools/wagtail-block.js b/wagtail_editorjs/static/wagtail_editorjs/js/tools/wagtail-block.js index 6997fb9..2d6a0ee 100644 --- a/wagtail_editorjs/static/wagtail_editorjs/js/tools/wagtail-block.js +++ b/wagtail_editorjs/static/wagtail_editorjs/js/tools/wagtail-block.js @@ -49,25 +49,36 @@ const element = this.wrapperElement.querySelector(`#${this.blockPrefix}`); const id = element.id; - +// if (!window.telepath) { - console.error('Telepath is not defined'); - return; + console.error('Telepath is not defined'); + return; } - +// // const dataValue = JSON.parse(element.getAttribute('data-w-block-data-value')); // const argumentsValue = JSON.parse(element.getAttribute('data-w-block-arguments-value')); + if (element.dataset.controller) { + delete element.dataset.controller; + } const dataValue = JSON.parse(element.dataset.wBlockDataValue); const argumentsValue = JSON.parse(element.dataset.wBlockArgumentsValue); this.blockDef = telepath.unpack(dataValue); - this.block = this.blockDef.render( - element, id, ...argumentsValue, - ) - - if (this.data) { - this.block.setState(this.data["block"]); - } + this.wrapperElement.addEventListener('DOMNodeInserted', (e) => { + if (!(e.relatedNode.firstElementChild == this.wrapperElement)) { + return; + } + + // Wait for the element block to be rendered by the browser + setTimeout(() => { + this.block = this.blockDef.render( + element, id, ...argumentsValue, + ) + if (this.data) { + this.block.setState(this.data["block"]); + } + }, 0); + }); return super.render(); } @@ -81,7 +92,7 @@ if (!this.block.getState) { console.error('Block does not have a getState method', this.block) } else { - this.data["block"] = this.block.getState(); + this.data["block"] = this.block.getValue(); } return this.data || {}; }