voidlabs / mosaico

Mosaico - Responsive Email Template Editor
https://mosaico.io
GNU General Public License v3.0
1.71k stars 502 forks source link

How to deliver a widget plugin with template #548

Closed skyslasher closed 4 years ago

skyslasher commented 4 years ago

Hello,

I am currently developing a template block that needs a custom property editor (realized with a widget plugin). It works OK, now I struggle with the best approach to deliver everything in one place. Currently one needs to modify the editor.html to inject the plugin, and place the template in a specific folder to make everything work. Is there a way to package the plugin in the template and that it gets loaded automatically when the template is used?

Thanks for any hint.

skyslasher commented 4 years ago

Hello,

I put everything together in a plugin with corresponding template for the CiviCRM Mosaico plugin. It took quite some hacks to implement everything with a simple CiviCRM plugin install, maybe some kind of interface can be implemented with vanilla Mosaico to make plugin enhancements easier.

Regards. Andreas

bago commented 4 years ago

"It took quite some hacks": please detail the hacks and whic kind of "interface" would help cleaning the mess.

I think template and widgets should not be tied against each other: mosaico should be able to edit any template made for mosaico, without the need for specific widgets. Specific widgets may help editing specific properties/blocks, but the 2 things should be very loosly coupled.

skyslasher commented 4 years ago

The goal of my plugin was: Provide a template block that automatically layouts a blogpost with images, title, authors and excerpt (up to full article length). This is a powerful feature of the MailPoet Wordpress plugin and saves hours of time in blog newsletter layouts.

Mosaico widgets modify CSS and HTML attributes, and the mapping of widgets to attributes is done in the template file. My automation process does not modify a specific attribute, but sets a bunch of attributes (image source, text, ...) automatically. These attributes should still be editable by the native widgets. So my starting point was to bind my widget wp-posts to a CSS variable in the template block header. This makes the widget appear in the content pane:

<style type="text/css"> @supports -ko-blockdefs { wppostid { label: Wordpress Post; widget: wp-posts } } </style>

and

<table class="vb-outer" width="100%" cellpadding="0" border="0" cellspacing="0" bgcolor="#bfbfbf" style="background-color: #bfbfbf; -ko-background-color: @externalBackgroundColor; -ko-attr-bgcolor: @externalBackgroundColor; --wp-post-id: 0; -ko---wp-post-id: @wppostid" data-ko-block="singleArticleBlock"></table>

I wonder if there is a cleaner way to implement this behavior.

Also, I took this implementation path because it was necessary to save the computed output of the plugin (image source, text, ...) into attributes. It would be more elegant if the plugin could compute the output from the post ID and the widget settings with current data (e.g. the modified blogpost text/title) when the template is loaded, and when the template is rendered for sending. I have not found a starting point for this.

Having template blocks with specific widgets can also implement more complex tasks, like displaying WooCommerce products simply by their product ID/SKU/GTIN, the next 1...n upcoming events from a CalDAV calendar feed, etc.

The other aspect is distribution. Currently, templates can easily be distributed by copying them into the correct path. For plugins, you need to modify the editor.html file. I wonder if there is a way of automating plugin inclusion like the search for different template files in a specific directory. I implemented this for the CiviCRM Mosaico plugin by hijacking a URL route and overriding the default behaviour, and currently discussing with @totten how to achieve a clean implementation there.

bago commented 4 years ago

That's the same approach we used to implement similar widgets for customers. I still don't think distributing widgets with the template is a good idea: otherwise, why don't we distribute the whole editor with the template?

IMO, templates are templates and they should not include code.

Your "enhanced" template should work even on a mosaico editor not supporting your specific widget: in that case people will have to fill in properties manually. If they have an editor with your advanced widget then they will be able to fill it automatically via the widget.

I never thought about "dynamic widgets": every time we got an implementation request it ended up being a "fill that block properties using that remote data and then let me change/fix things manually", so your first case.