Automatically change template configuration to use a shared template as soon as a shared template is selected
authorThierry Florac <tflorac@ulthar.net>
Fri, 19 Mar 2021 11:53:42 +0100
changeset 286 9677eb0fc872
parent 285 27191e1724dc
child 287 a6ad7e5ff859
Automatically change template configuration to use a shared template as soon as a shared template is selected
src/pyams_portal/resources/js/portal.js
src/pyams_portal/resources/js/portal.min.js
src/pyams_portal/zmi/page.py
src/pyams_portal/zmi/templates/template-properties.pt
--- a/src/pyams_portal/resources/js/portal.js	Fri Mar 19 10:50:57 2021 +0100
+++ b/src/pyams_portal/resources/js/portal.js	Fri Mar 19 11:53:42 2021 +0100
@@ -15,6 +15,26 @@
 		},
 
 		/**
+		 * Templates configuration properties
+		 */
+		configuration: {
+
+			handleChange: true,
+
+			resetTemplate: function(event) {
+				PyAMS_portal.configuration.handleChange = false;
+			},
+
+			setSharedTemplate: function(event) {
+				if (PyAMS_portal.configuration.handleChange) {
+					var form = $(event.target).parents('form');
+					$('input[name="template_mode"]', form).val(['shared']);
+				}
+				PyAMS_portal.configuration.handleChange = true;
+			}
+		},
+
+		/**
 		 * Templates management
 		 */
 		template: {
--- a/src/pyams_portal/resources/js/portal.min.js	Fri Mar 19 10:50:57 2021 +0100
+++ b/src/pyams_portal/resources/js/portal.min.js	Fri Mar 19 11:53:42 2021 +0100
@@ -1,1 +1,1 @@
-!function(t,e){"use strict";var a=e.MyAMS,s={i18n:{CANT_DELETE_ROW_WITH_PORTLETS:"A row containing portlets can't be removed!",CANT_DELETE_SLOT_WITH_PORTLETS:"A slot containing portlets can't be removed!"},template:{initConfig:function(){var e=t("#portal_config");e.data("ams-allowed-change")&&(t(".rows",e).addClass("sortable"),t(".slots",e).addClass("sortable"),t(".slot",e).addClass("resizable"),t(".portlets",e).addClass("sortable"),a.plugins.enabled.sortable(e),a.plugins.enabled.resizable(e),t(".btn-row",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".rows"}),t(".rows",e).droppable({accept:".btn-row",drop:s.template.dropRowButton}),t(".btn-slot",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".slots"}),t(".slots",e).droppable({accept:".btn-slot",drop:s.template.dropSlotButton}),t(".btn-portlet",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".portlets"}),t(".portlets",e).droppable({accept:".btn-portlet",hoverClass:"portlets-hover",activeClass:"portlets-active",drop:s.template.dropPortletButton}))},selectDisplay:function(){var e=t(this).val();a.ajax.post("get-slots-width.json",{device:e},(function(a){var s=t("#portal_config");for(var o in s.removeClassPrefix("container-"),e&&s.addClass("container-"+e),t(".slot",s).removeClassPrefix("col-"),a)if(a.hasOwnProperty(o)){var l=a[o],r=t('.slot[data-ams-slot-name="'+o+'"]',s);if(e)r.addClass("col-"+l[e]);else for(var n in l)l.hasOwnProperty(n)&&r.addClass("col-"+n+"-"+l[n]);r.addClass(l.css)}}))},addRow:function(){return function(){t(this).parents(".btn-group").removeClass("open"),a.ajax.post("add-template-row.json",{},(function(e){var o=e.row_id,l=t(".rows","#portal_config");t("<div></div>").addClass("row context-menu").attr("data-ams-row-id",o).append(t("<strong></strong>").addClass("row_id label label-danger pull-left").text(o+1)).append(t("<strong></strong>").addClass("row_id label label-danger pull-right").text(o+1)).append(t("<div></div>").addClass("slots").sortable({placeholder:"slot-highlight",connectWith:".slots",over:s.template.overSlots,stop:s.template.sortSlots}).droppable({accept:".btn-slot",drop:s.template.dropSlotButton})).contextMenu({menuSelector:"#rowMenu",menuSelected:a.helpers.contextMenuHandler}).appendTo(l),l.sortable("refresh")}))}},dropRowButton:function(e,o){o.draggable.hasClass("already-dropped")||(o.draggable.addClass("already-dropped"),a.ajax.post("add-template-row.json",{},(function(e){var l=e.row_id,r=t(".rows","#portal_config");o.draggable.removeClassPrefix("btn").removeClassPrefix("ui-").removeClassPrefix("bg-").removeClass("already-dropped").removeAttr("style").addClass("row context-menu").attr("data-ams-row-id",l).empty().append(t("<strong></strong>").addClass("row_id label label-danger pull-left").text(l+1)).append(t("<strong></strong>").addClass("row_id label label-danger pull-right").text(l+1)).append(t("<div></div>").addClass("slots").sortable({placeholder:"slot-highlight",connectWith:".slots",over:s.template.overSlots,stop:s.template.sortSlots}).droppable({accept:".btn-slot",drop:s.template.dropSlotButton})).contextMenu({menuSelector:"#rowMenu",menuSelected:a.helpers.contextMenuHandler}),s.template.sortRows(),r.sortable("refresh")})))},overRows:function(e,a){t(a.placeholder).attr("class",t(a.item).attr("class")).removeClassPrefix("ui-").addClass("row-highlight").css("height",t(a.item).outerHeight())},sortRows:function(e,s){if(!s||!s.item.hasClass("already-dropped")){var o=t("#portal_config"),l=t(".row",o).listattr("data-ams-row-id");a.ajax.post("set-template-row-order.json",{rows:JSON.stringify(l)},(function(e){"success"===e.status&&t(".row",o).each((function(e){t(this).attr("data-ams-row-id",e),t(".row_id",t(this)).text(e+1)}))}))}},deleteRow:function(){return function(e){e=e.objectOrParentWithClass("row"),t(".portlet",e).exists()?a.skin.messageBox("error",{title:a.i18n.ERROR_OCCURED,content:s.i18n.CANT_DELETE_ROW_WITH_PORTLETS,icon:"fa fa-warning animated shake",timeout:5e3}):a.skin.bigBox({title:a.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+a.i18n.DELETE_WARNING,status:"info",buttons:a.i18n.BTN_OK_CANCEL},(function(s){s===a.i18n.BTN_OK&&a.ajax.post("delete-template-row.json",{row_id:e.data("ams-row-id")},(function(a){"success"===a.status&&(e.remove(),t(".row","#portal_config").each((function(e){t(this).removeData().attr("data-ams-row-id",e),t(".row_id",t(this)).text(e+1)})))}))}))}},addSlotCallback:function(e){var o=t(".slots",'.row[data-ams-row-id="'+e.row_id+'"]'),l=e.slot_name,r=t("<div></div>").addClass("slot context-menu no-padding col col-xs-12 col-sm-12 col-md-12 col-lg-12 resizable").attr("data-ams-slot-name",l).append(t("<div></div>").addClass("header padding-x-5").append('<i class="fa fa-fw fa-minus-square pull-right padding-top-2"    data-ams-click-handler="PyAMS_portal.template.switchSlot"></i>').append(l)).append(t("<div></div>").addClass("portlets").sortable({placeholder:"portlet-highlight",connectWith:".portlets",over:s.template.overPortlets,stop:s.template.sortPortlets}).droppable({accept:".btn-portlet",hoverClass:"portlets-hover",activeClass:"portlets-active",drop:s.template.dropPortletButton})).append(t("<div></div>").addClass("clearfix")).contextMenu({menuSelector:"#slotMenu",menuSelected:a.helpers.contextMenuHandler}),n=t(".btn-slot",o);n.exists()?(n.replaceWith(r),t(".slot",o).each((function(){t(this).removeData()})),s.template.sortSlots()):r.appendTo(o),r.resizable({start:s.template.startSlotResize,stop:s.template.stopSlotResize,handles:"e"}),o.sortable("refresh")},dropSlotButton:function(e,s){if(!s.draggable.hasClass("already-dropped")){s.draggable.addClass("already-dropped");var o=s.helper.parents(".row:first").data("ams-row-id");a.dialog.open("add-template-slot.html?add_form.widgets.row_id="+o,{},{hide:function(){t(".already-dropped").remove()}})}},startSlotResize:function(t,e){var a=e.element,s=a.parents(".slots:first"),o=(s.innerWidth()-110)/12,l=a.height();e.element.resizable("option","grid",[o,l]),e.element.resizable("option","minWidth",o),e.element.resizable("option","minHeight",l),e.element.resizable("option","maxWidth",s.innerWidth()),e.element.resizable("option","maxHeight",l)},stopSlotResize:function(e,s){var o=s.element,l=(o.parents(".slots:first").innerWidth()-10)/12,r=Math.round(t(o).width()/l),n=t("#device_selector").val();if(!n){var i=t("body").width();n=i>1170?"lg":i>970?"md":i>750?"sm":"xs"}a.ajax.post("set-slot-width.json",{slot_name:o.data("ams-slot-name"),device:n,width:r},(function(t){o.removeClassPrefix("col-"),o.removeAttr("style");var e=t[o.data("ams-slot-name")];n?o.addClass("col-"+n+"-"+e[n]):o.addClass("col-"+e[n]),o.addClass(e.css)}))},editSlot:function(){return function(t){t.hasClass("slot")||(t=t.parents(".slot")),a.dialog.open("slot-properties.html?slot.widgets.slot_name="+t.data("ams-slot-name"))}},editSlotCallback:function(e){var a=t('.slot[data-ams-slot-name="'+e.slot_name+'"]');a.attr("class","slot context-menu no-padding col");var s=t("#device_selector").val();if(s)a.addClass("col-"+e.width[s]);else for(s in e.width)e.width.hasOwnProperty(s)&&a.addClass("col-"+s+"-"+e.width[s]);a.addClass(e.css)},overSlots:function(e,a){t(a.placeholder).attr("class",t(a.item).attr("class")).removeClassPrefix("ui-").addClass("slot-highlight").css("height",t(a.item).outerHeight())},sortSlots:function(e,s){if(!s||!s.item.hasClass("already-dropped")){var o=t("#portal_config"),l={};t(".row",o).each((function(){var e=t(this),a=[];t(".slot",e).each((function(){a.push(t(this).data("ams-slot-name"))})),l[parseInt(e.attr("data-ams-row-id"))]=a})),a.ajax.post("set-template-slot-order.json",{order:JSON.stringify(l)})}},switchSlot:function(){var e=t(this),a=e.parents(".header").first().siblings(".portlets");a.hasClass("hidden")?(a.removeClass("hidden"),e.removeClass("fa-plus-square").addClass("fa-minus-square")):(a.addClass("hidden"),e.removeClass("fa-minus-square").addClass("fa-plus-square"))},deleteSlot:function(){return function(e){e=e.objectOrParentWithClass("slot"),t(".portlet",e).exists()?a.skin.messageBox("error",{title:a.i18n.ERROR_OCCURED,content:s.i18n.CANT_DELETE_SLOT_WITH_PORTLETS,icon:"fa fa-warning animated shake",timeout:5e3}):a.skin.bigBox({title:a.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+a.i18n.DELETE_WARNING,status:"info",buttons:a.i18n.BTN_OK_CANCEL},(function(s){s===a.i18n.BTN_OK&&a.ajax.post("delete-template-slot.json",{slot_name:e.data("ams-slot-name")},(function(a){"success"===a.status&&(e.remove(),t(".slot","#portal_config").each((function(){t(this).removeData()})))}))}))}},addPortletCallback:function(e){var o=t(".portlets",'.slot[data-ams-slot-name="'+e.slot_name+'"]'),l=t("<div></div>").addClass("portlet context-menu").attr("data-ams-portlet-id",e.portlet_id).append(t("<div></div>").addClass("header padding-x-5").append('<i class="fa fa-fw fa-minus-square pull-right padding-top-2"    data-ams-click-handler="PyAMS_portal.template.switchPortlet"></i>').append(e.label).append(" ").append('<i class="fa fa-fw fa-edit hint opaque align-base"    data-ams-url="PyAMS_portal.template.editPortlet"    data-ams-hint-gravity="se" data-ams-hint-offset="2"></i>')).append(t("<div></div>").addClass("preview").html(e.preview||"")).contextMenu({menuSelector:"#portletMenu",menuSelected:a.helpers.contextMenuHandler});a.initContent(t(".preview",l));var r=t(".btn-portlet",o);r.exists()?(r.replaceWith(l),t(".portlet",o).each((function(){t(this).removeData()})),s.template.sortPortlets(null,{item:l})):l.appendTo(o),o.sortable("refresh"),a.dialog.open("portlet-properties.html?portlet.widgets.portlet_id="+e.portlet_id)},dropPortletButton:function(e,s){if(!s.draggable.hasClass("already-dropped")){s.draggable.addClass("already-dropped");var o=s.draggable,l=t(this).parents(".slot:first");a.ajax.post("drag-template-portlet.json",{portlet_name:o.data("ams-portlet-name"),slot_name:l.data("ams-slot-name")},(function(t){a.ajax.handleJSON(t)}))}},submitPortletEditForm:function(){var e=t(this).parents("form").first();a.form.submit(e,{form_data:{autosubmit:!0}})},editPortlet:function(){return function(t){void 0===t&&(t=this),t.hasClass("portlet")||(t=t.parents(".portlet:first")),a.dialog.open("portlet-properties.html?portlet.widgets.portlet_id="+t.data("ams-portlet-id"))}},editPortletCallback:function(e){if(e.preview){var s=t("#portal_config"),o=t('.portlet[data-ams-portlet-id="'+e.portlet_id+'"]',s),l=t(".header",o);e.inherit_parent?t("i.chain",l).removeClass("fa-chain-broken"):t("i.chain",l).addClass("fa-chain-broken"),t(".preview",o).html(e.preview),a.initContent(t(".preview",o))}},overPortlets:function(e,a){t(a.placeholder).attr("class",t(a.item).attr("class")).removeClassPrefix("ui-").addClass("portlet-highlight").css("height",t(a.item).outerHeight())},sortPortlets:function(e,s){if(!s.item.hasClass("already-dropped")){var o=s.item,l=o.parents(".slot"),r=t(".portlet",l),n={from:o.data("ams-portlet-id"),to:{slot:l.data("ams-slot-name"),portlet_ids:r.listattr("data-ams-portlet-id")}};a.ajax.post("set-template-portlet-order.json",{order:JSON.stringify(n)})}},switchPortlet:function(){var e=t(this),a=e.parents(".header").first().siblings(".preview");a.hasClass("hidden")?(a.removeClass("hidden"),e.removeClass("fa-plus-square").addClass("fa-minus-square")):(a.addClass("hidden"),e.removeClass("fa-minus-square").addClass("fa-plus-square"))},deletePortlet:function(){return function(e){a.skin.bigBox({title:a.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+a.i18n.DELETE_WARNING,status:"info",buttons:a.i18n.BTN_OK_CANCEL},(function(s){s===a.i18n.BTN_OK&&(e.hasClass("portlet")||(e=e.parents(".portlet")),a.ajax.post("delete-template-portlet.json",{portlet_id:e.data("ams-portlet-id")},(function(a){"success"===a.status&&(e.remove(),t(".portlet","#portal_config").each((function(){t(this).removeData()})))})))}))}}}};e.PyAMS_portal=s;t("HTML");"en"!==a.lang&&a.getScript("/--static--/pyams_portal/js/i18n/"+a.lang+a.devext+".js")}(jQuery,this);
+!function(t,e){"use strict";var a=e.MyAMS,s={i18n:{CANT_DELETE_ROW_WITH_PORTLETS:"A row containing portlets can't be removed!",CANT_DELETE_SLOT_WITH_PORTLETS:"A slot containing portlets can't be removed!"},configuration:{handleChange:!0,resetTemplate:function(t){s.configuration.handleChange=!1},setSharedTemplate:function(e){if(s.configuration.handleChange){var a=t(e.target).parents("form");t('input[name="template_mode"]',a).val(["shared"])}s.configuration.handleChange=!0}},template:{initConfig:function(){var e=t("#portal_config");e.data("ams-allowed-change")&&(t(".rows",e).addClass("sortable"),t(".slots",e).addClass("sortable"),t(".slot",e).addClass("resizable"),t(".portlets",e).addClass("sortable"),a.plugins.enabled.sortable(e),a.plugins.enabled.resizable(e),t(".btn-row",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".rows"}),t(".rows",e).droppable({accept:".btn-row",drop:s.template.dropRowButton}),t(".btn-slot",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".slots"}),t(".slots",e).droppable({accept:".btn-slot",drop:s.template.dropSlotButton}),t(".btn-portlet",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".portlets"}),t(".portlets",e).droppable({accept:".btn-portlet",hoverClass:"portlets-hover",activeClass:"portlets-active",drop:s.template.dropPortletButton}))},selectDisplay:function(){var e=t(this).val();a.ajax.post("get-slots-width.json",{device:e},(function(a){var s=t("#portal_config");for(var o in s.removeClassPrefix("container-"),e&&s.addClass("container-"+e),t(".slot",s).removeClassPrefix("col-"),a)if(a.hasOwnProperty(o)){var l=a[o],r=t('.slot[data-ams-slot-name="'+o+'"]',s);if(e)r.addClass("col-"+l[e]);else for(var n in l)l.hasOwnProperty(n)&&r.addClass("col-"+n+"-"+l[n]);r.addClass(l.css)}}))},addRow:function(){return function(){t(this).parents(".btn-group").removeClass("open"),a.ajax.post("add-template-row.json",{},(function(e){var o=e.row_id,l=t(".rows","#portal_config");t("<div></div>").addClass("row context-menu").attr("data-ams-row-id",o).append(t("<strong></strong>").addClass("row_id label label-danger pull-left").text(o+1)).append(t("<strong></strong>").addClass("row_id label label-danger pull-right").text(o+1)).append(t("<div></div>").addClass("slots").sortable({placeholder:"slot-highlight",connectWith:".slots",over:s.template.overSlots,stop:s.template.sortSlots}).droppable({accept:".btn-slot",drop:s.template.dropSlotButton})).contextMenu({menuSelector:"#rowMenu",menuSelected:a.helpers.contextMenuHandler}).appendTo(l),l.sortable("refresh")}))}},dropRowButton:function(e,o){o.draggable.hasClass("already-dropped")||(o.draggable.addClass("already-dropped"),a.ajax.post("add-template-row.json",{},(function(e){var l=e.row_id,r=t(".rows","#portal_config");o.draggable.removeClassPrefix("btn").removeClassPrefix("ui-").removeClassPrefix("bg-").removeClass("already-dropped").removeAttr("style").addClass("row context-menu").attr("data-ams-row-id",l).empty().append(t("<strong></strong>").addClass("row_id label label-danger pull-left").text(l+1)).append(t("<strong></strong>").addClass("row_id label label-danger pull-right").text(l+1)).append(t("<div></div>").addClass("slots").sortable({placeholder:"slot-highlight",connectWith:".slots",over:s.template.overSlots,stop:s.template.sortSlots}).droppable({accept:".btn-slot",drop:s.template.dropSlotButton})).contextMenu({menuSelector:"#rowMenu",menuSelected:a.helpers.contextMenuHandler}),s.template.sortRows(),r.sortable("refresh")})))},overRows:function(e,a){t(a.placeholder).attr("class",t(a.item).attr("class")).removeClassPrefix("ui-").addClass("row-highlight").css("height",t(a.item).outerHeight())},sortRows:function(e,s){if(!s||!s.item.hasClass("already-dropped")){var o=t("#portal_config"),l=t(".row",o).listattr("data-ams-row-id");a.ajax.post("set-template-row-order.json",{rows:JSON.stringify(l)},(function(e){"success"===e.status&&t(".row",o).each((function(e){t(this).attr("data-ams-row-id",e),t(".row_id",t(this)).text(e+1)}))}))}},deleteRow:function(){return function(e){e=e.objectOrParentWithClass("row"),t(".portlet",e).exists()?a.skin.messageBox("error",{title:a.i18n.ERROR_OCCURED,content:s.i18n.CANT_DELETE_ROW_WITH_PORTLETS,icon:"fa fa-warning animated shake",timeout:5e3}):a.skin.bigBox({title:a.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+a.i18n.DELETE_WARNING,status:"info",buttons:a.i18n.BTN_OK_CANCEL},(function(s){s===a.i18n.BTN_OK&&a.ajax.post("delete-template-row.json",{row_id:e.data("ams-row-id")},(function(a){"success"===a.status&&(e.remove(),t(".row","#portal_config").each((function(e){t(this).removeData().attr("data-ams-row-id",e),t(".row_id",t(this)).text(e+1)})))}))}))}},addSlotCallback:function(e){var o=t(".slots",'.row[data-ams-row-id="'+e.row_id+'"]'),l=e.slot_name,r=t("<div></div>").addClass("slot context-menu no-padding col col-xs-12 col-sm-12 col-md-12 col-lg-12 resizable").attr("data-ams-slot-name",l).append(t("<div></div>").addClass("header padding-x-5").append('<i class="fa fa-fw fa-minus-square pull-right padding-top-2"    data-ams-click-handler="PyAMS_portal.template.switchSlot"></i>').append(l)).append(t("<div></div>").addClass("portlets").sortable({placeholder:"portlet-highlight",connectWith:".portlets",over:s.template.overPortlets,stop:s.template.sortPortlets}).droppable({accept:".btn-portlet",hoverClass:"portlets-hover",activeClass:"portlets-active",drop:s.template.dropPortletButton})).append(t("<div></div>").addClass("clearfix")).contextMenu({menuSelector:"#slotMenu",menuSelected:a.helpers.contextMenuHandler}),n=t(".btn-slot",o);n.exists()?(n.replaceWith(r),t(".slot",o).each((function(){t(this).removeData()})),s.template.sortSlots()):r.appendTo(o),r.resizable({start:s.template.startSlotResize,stop:s.template.stopSlotResize,handles:"e"}),o.sortable("refresh")},dropSlotButton:function(e,s){if(!s.draggable.hasClass("already-dropped")){s.draggable.addClass("already-dropped");var o=s.helper.parents(".row:first").data("ams-row-id");a.dialog.open("add-template-slot.html?add_form.widgets.row_id="+o,{},{hide:function(){t(".already-dropped").remove()}})}},startSlotResize:function(t,e){var a=e.element,s=a.parents(".slots:first"),o=(s.innerWidth()-110)/12,l=a.height();e.element.resizable("option","grid",[o,l]),e.element.resizable("option","minWidth",o),e.element.resizable("option","minHeight",l),e.element.resizable("option","maxWidth",s.innerWidth()),e.element.resizable("option","maxHeight",l)},stopSlotResize:function(e,s){var o=s.element,l=(o.parents(".slots:first").innerWidth()-10)/12,r=Math.round(t(o).width()/l),n=t("#device_selector").val();if(!n){var i=t("body").width();n=i>1170?"lg":i>970?"md":i>750?"sm":"xs"}a.ajax.post("set-slot-width.json",{slot_name:o.data("ams-slot-name"),device:n,width:r},(function(t){o.removeClassPrefix("col-"),o.removeAttr("style");var e=t[o.data("ams-slot-name")];n?o.addClass("col-"+n+"-"+e[n]):o.addClass("col-"+e[n]),o.addClass(e.css)}))},editSlot:function(){return function(t){t.hasClass("slot")||(t=t.parents(".slot")),a.dialog.open("slot-properties.html?slot.widgets.slot_name="+t.data("ams-slot-name"))}},editSlotCallback:function(e){var a=t('.slot[data-ams-slot-name="'+e.slot_name+'"]');a.attr("class","slot context-menu no-padding col");var s=t("#device_selector").val();if(s)a.addClass("col-"+e.width[s]);else for(s in e.width)e.width.hasOwnProperty(s)&&a.addClass("col-"+s+"-"+e.width[s]);a.addClass(e.css)},overSlots:function(e,a){t(a.placeholder).attr("class",t(a.item).attr("class")).removeClassPrefix("ui-").addClass("slot-highlight").css("height",t(a.item).outerHeight())},sortSlots:function(e,s){if(!s||!s.item.hasClass("already-dropped")){var o=t("#portal_config"),l={};t(".row",o).each((function(){var e=t(this),a=[];t(".slot",e).each((function(){a.push(t(this).data("ams-slot-name"))})),l[parseInt(e.attr("data-ams-row-id"))]=a})),a.ajax.post("set-template-slot-order.json",{order:JSON.stringify(l)})}},switchSlot:function(){var e=t(this),a=e.parents(".header").first().siblings(".portlets");a.hasClass("hidden")?(a.removeClass("hidden"),e.removeClass("fa-plus-square").addClass("fa-minus-square")):(a.addClass("hidden"),e.removeClass("fa-minus-square").addClass("fa-plus-square"))},deleteSlot:function(){return function(e){e=e.objectOrParentWithClass("slot"),t(".portlet",e).exists()?a.skin.messageBox("error",{title:a.i18n.ERROR_OCCURED,content:s.i18n.CANT_DELETE_SLOT_WITH_PORTLETS,icon:"fa fa-warning animated shake",timeout:5e3}):a.skin.bigBox({title:a.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+a.i18n.DELETE_WARNING,status:"info",buttons:a.i18n.BTN_OK_CANCEL},(function(s){s===a.i18n.BTN_OK&&a.ajax.post("delete-template-slot.json",{slot_name:e.data("ams-slot-name")},(function(a){"success"===a.status&&(e.remove(),t(".slot","#portal_config").each((function(){t(this).removeData()})))}))}))}},addPortletCallback:function(e){var o=t(".portlets",'.slot[data-ams-slot-name="'+e.slot_name+'"]'),l=t("<div></div>").addClass("portlet context-menu").attr("data-ams-portlet-id",e.portlet_id).append(t("<div></div>").addClass("header padding-x-5").append('<i class="fa fa-fw fa-minus-square pull-right padding-top-2"    data-ams-click-handler="PyAMS_portal.template.switchPortlet"></i>').append(e.label).append(" ").append('<i class="fa fa-fw fa-edit hint opaque align-base"    data-ams-url="PyAMS_portal.template.editPortlet"    data-ams-hint-gravity="se" data-ams-hint-offset="2"></i>')).append(t("<div></div>").addClass("preview").html(e.preview||"")).contextMenu({menuSelector:"#portletMenu",menuSelected:a.helpers.contextMenuHandler});a.initContent(t(".preview",l));var r=t(".btn-portlet",o);r.exists()?(r.replaceWith(l),t(".portlet",o).each((function(){t(this).removeData()})),s.template.sortPortlets(null,{item:l})):l.appendTo(o),o.sortable("refresh"),a.dialog.open("portlet-properties.html?portlet.widgets.portlet_id="+e.portlet_id)},dropPortletButton:function(e,s){if(!s.draggable.hasClass("already-dropped")){s.draggable.addClass("already-dropped");var o=s.draggable,l=t(this).parents(".slot:first");a.ajax.post("drag-template-portlet.json",{portlet_name:o.data("ams-portlet-name"),slot_name:l.data("ams-slot-name")},(function(t){a.ajax.handleJSON(t)}))}},submitPortletEditForm:function(){var e=t(this).parents("form").first();a.form.submit(e,{form_data:{autosubmit:!0}})},editPortlet:function(){return function(t){void 0===t&&(t=this),t.hasClass("portlet")||(t=t.parents(".portlet:first")),a.dialog.open("portlet-properties.html?portlet.widgets.portlet_id="+t.data("ams-portlet-id"))}},editPortletCallback:function(e){if(e.preview){var s=t("#portal_config"),o=t('.portlet[data-ams-portlet-id="'+e.portlet_id+'"]',s),l=t(".header",o);e.inherit_parent?t("i.chain",l).removeClass("fa-chain-broken"):t("i.chain",l).addClass("fa-chain-broken"),t(".preview",o).html(e.preview),a.initContent(t(".preview",o))}},overPortlets:function(e,a){t(a.placeholder).attr("class",t(a.item).attr("class")).removeClassPrefix("ui-").addClass("portlet-highlight").css("height",t(a.item).outerHeight())},sortPortlets:function(e,s){if(!s.item.hasClass("already-dropped")){var o=s.item,l=o.parents(".slot"),r=t(".portlet",l),n={from:o.data("ams-portlet-id"),to:{slot:l.data("ams-slot-name"),portlet_ids:r.listattr("data-ams-portlet-id")}};a.ajax.post("set-template-portlet-order.json",{order:JSON.stringify(n)})}},switchPortlet:function(){var e=t(this),a=e.parents(".header").first().siblings(".preview");a.hasClass("hidden")?(a.removeClass("hidden"),e.removeClass("fa-plus-square").addClass("fa-minus-square")):(a.addClass("hidden"),e.removeClass("fa-minus-square").addClass("fa-plus-square"))},deletePortlet:function(){return function(e){a.skin.bigBox({title:a.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+a.i18n.DELETE_WARNING,status:"info",buttons:a.i18n.BTN_OK_CANCEL},(function(s){s===a.i18n.BTN_OK&&(e.hasClass("portlet")||(e=e.parents(".portlet")),a.ajax.post("delete-template-portlet.json",{portlet_id:e.data("ams-portlet-id")},(function(a){"success"===a.status&&(e.remove(),t(".portlet","#portal_config").each((function(){t(this).removeData()})))})))}))}}}};e.PyAMS_portal=s;t("HTML");"en"!==a.lang&&a.getScript("/--static--/pyams_portal/js/i18n/"+a.lang+a.devext+".js")}(jQuery,this);
--- a/src/pyams_portal/zmi/page.py	Fri Mar 19 10:50:57 2021 +0100
+++ b/src/pyams_portal/zmi/page.py	Fri Mar 19 11:53:42 2021 +0100
@@ -23,6 +23,7 @@
 from pyams_skin.interfaces import IPageHeader, IInnerPage
 from pyams_skin.layer import IPyAMSLayer
 from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
+from pyams_utils.interfaces.data import IObjectData
 from pyams_zmi.interfaces.menu import ISiteManagementMenu
 from pyams_zmi.layer import IAdminLayer
 from z3c.form.interfaces import IDataExtractedEvent
@@ -45,7 +46,7 @@
 from pyramid.events import subscriber
 from pyramid.view import view_config
 from z3c.form import field
-from zope.interface import implementer, Interface, Invalid
+from zope.interface import alsoProvides, implementer, Interface, Invalid
 
 from pyams_portal import _
 
@@ -94,6 +95,15 @@
     def getContent(self):
         return IPortalPage(self.context)
 
+    def updateWidgets(self, prefix=None):
+        super().updateWidgets(prefix)
+        shared_template = self.widgets.get('shared_template')
+        if shared_template is not None:
+            shared_template.object_data = {
+                'ams-change-handler': "PyAMS_portal.configuration.setSharedTemplate"
+            }
+            alsoProvides(shared_template, IObjectData)
+
     def update_content(self, content, data):
         data = data.get(self, data)
         template_mode = self.request.params.get('template_mode')
--- a/src/pyams_portal/zmi/templates/template-properties.pt	Fri Mar 19 10:50:57 2021 +0100
+++ b/src/pyams_portal/zmi/templates/template-properties.pt	Fri Mar 19 11:53:42 2021 +0100
@@ -7,28 +7,31 @@
 		<tal:var content="structure provider:pyams.widget_title" />
 		<tal:var content="structure provider:pyams.toolbar" />
 	</header>
-	<div class="widget-body no-padding">
+	<div class="widget-body no-padding"
+		 data-ams-plugins="pyams_portal"
+		 data-ams-plugin-pyams_portal-src="${tales:resource_path('pyams_portal:pyams_portal')}">
 		<div tal:define="prefix provider:form_prefix"
 			 tal:replace="structure prefix">Form prefix</div>
 		<tal:var content="structure provider:form_help" />
-		<form method="post"
-			  data-async
-			  tal:attributes="id view.id;
-							  name view.name;
-							  action view.get_form_action();
-							  method view.method;
-							  enctype view.enctype;
-							  acceptCharset view.acceptCharset;
-							  accept view.accept;
-							  autocomplete view.autocomplete;
-							  class view.css_class;
-							  data-ams-data tales:object_data(view);
-							  data-ams-form-handler view.get_ajax_handler() | nothing;
-							  data-ams-form-options view.get_form_options() | nothing;
-							  data-ams-form-submit-target view.form_target | nothing;
-							  data-ams-form-download-target view.download_target | nothing;
-							  data-ams-warn-on-change view.warn_on_change;">
-			<div class="modal-viewport">
+		<form data-async
+			  id="${view.id}"
+			  name="${view.name}"
+			  action="${view.get_form_action()}"
+			  method="${view.method}"
+			  enctype="${view.enctype}"
+			  accept="${view.accept}"
+			  acceptCharset="${view.acceptCharset}"
+			  autocomplete="${view.autocomplete}"
+			  class="${view.css_class}"
+			  data-ams-data="${tales:object_data(view)}"
+			  data-ams-reset-handler="PyAMS_portal.configuration.resetTemplate"
+			  data-ams-reset-keep-default="true"
+			  data-ams-form-handler="${view.get_ajax_handler() | nothing}"
+			  data-ams-form-options="${view.get_form_options() | nothing}"
+			  data-ams-form-submit-target="${view.form_target | nothing}"
+			  data-ams-form-download-target="${view.download_target | nothing}"
+			  data-ams-warn-on-change="${view.warn_on_change}">
+			  <div class="modal-viewport">
 				<fieldset class="padding-x-20"
 						  tal:define="content view.getContent()">
 					<div class="widgets-prefix"