Updated template layout
authorThierry Florac <thierry.florac@onf.fr>
Tue, 26 Jun 2018 12:11:24 +0200
changeset 140 95bee9c0ae3f
parent 139 e93775177b43
child 141 2ac6f3379d14
Updated template layout
src/pyams_portal/resources/css/portal.css
src/pyams_portal/resources/css/portal.min.css
src/pyams_portal/resources/js/portal.js
src/pyams_portal/resources/js/portal.min.js
src/pyams_portal/resources/less/portal.less
src/pyams_portal/zmi/layout.py
src/pyams_portal/zmi/templates/layout.pt
--- a/src/pyams_portal/resources/css/portal.css	Tue Jun 26 08:47:39 2018 +0200
+++ b/src/pyams_portal/resources/css/portal.css	Tue Jun 26 12:11:24 2018 +0200
@@ -16,8 +16,13 @@
 }
 #portal_config .row > .row_id {
   position: absolute;
-  right: 2px;
-  top: -1.6em;
+  top: -1.5em;
+}
+#portal_config .row > .row_id.pull-left {
+  left: 0.3em;
+}
+#portal_config .row > .row_id.pull-right {
+  right: 0.3em;
 }
 #portal_config .row .slot {
   margin: 3px 0;
--- a/src/pyams_portal/resources/css/portal.min.css	Tue Jun 26 08:47:39 2018 +0200
+++ b/src/pyams_portal/resources/css/portal.min.css	Tue Jun 26 12:11:24 2018 +0200
@@ -1,1 +1,1 @@
-#portal_config{padding-right:0;padding-left:0}#portal_config .rows{min-height:15px}#portal_config .row{position:relative;margin:5px 0;padding:2px 4px;border:1px solid rgba(199,81,0,0.4);border-top-width:1.5em;min-height:20px;cursor:move}#portal_config .row>.row_id{position:absolute;right:2px;top:-1.6em}#portal_config .row .slot{margin:3px 0;padding:3px;border:1px solid rgba(98,120,128,0.65);border-bottom-width:6px;min-height:20px!important}#portal_config .row .slot>.header{background-color:rgba(98,120,128,0.6);color:white}#portal_config .row .portlet{margin:3px 0;padding:3px;border:1px solid rgba(98,120,128,0.6);min-height:20px!important}#portal_config .row .portlet>.header{background-color:rgba(92,109,115,0.8);color:white}#portal_config .row-highlight{margin:5px 0;border:1px solid #c75100;min-height:40px}#portal_config .slots{min-height:15px}#portal_config .slot-highlight{margin:3px 0;border:1px solid #7b939c;min-height:40px}#portal_config .portlets{min-height:15px}#portal_config .portlets-hover{background-color:silver}#portal_config .portlets-active{background-color:silver}#portal_config .portlet-highlight{margin:0;border:1px solid #7b939c;min-height:40px}#portal_config.container .col-12{float:left;width:100%!important}#portal_config.container .col-11{float:left;width:91.66666667%!important}#portal_config.container .col-10{float:left;width:83.33333333%!important}#portal_config.container .col-9{float:left;width:75%!important}#portal_config.container .col-8{float:left;width:66.66666667%!important}#portal_config.container .col-7{float:left;width:58.33333333%!important}#portal_config.container .col-6{float:left;width:50%!important}#portal_config.container .col-5{float:left;width:41.66666667%!important}#portal_config.container .col-4{float:left;width:33.33333333%!important}#portal_config.container .col-3{float:left;width:25%!important}#portal_config.container .col-2{float:left;width:16.66666667%!important}#portal_config.container .col-1{float:left;width:8.33333333%!important}#portal_config.container .col-0{float:left;width:100%!important;opacity:.5}#portal_config.container .col-0>.portlets{display:none}#portal_config.container-xs{max-width:750px!important}#portal_config.container-sm{width:750px!important}#portal_config.container-md{width:970px!important}#portal_config.container-lg{width:1170px!important}
\ No newline at end of file
+#portal_config{padding-right:0;padding-left:0}#portal_config .rows{min-height:15px}#portal_config .row{position:relative;margin:5px 0;padding:2px 4px;border:1px solid rgba(199,81,0,.4);border-top-width:1.5em;min-height:20px;cursor:move}#portal_config .row>.row_id{position:absolute;top:-1.5em}#portal_config .row>.row_id.pull-left{left:.3em}#portal_config .row>.row_id.pull-right{right:.3em}#portal_config .row .slot{margin:3px 0;padding:3px;border:1px solid rgba(98,120,128,.65);border-bottom-width:6px;min-height:20px!important}#portal_config .row .slot>.header{background-color:rgba(98,120,128,.6);color:#fff}#portal_config .row .portlet{margin:3px 0;padding:3px;border:1px solid rgba(98,120,128,.6);min-height:20px!important}#portal_config .row .portlet>.header{background-color:rgba(92,109,115,.8);color:#fff}#portal_config .row-highlight{margin:5px 0;border:1px solid #c75100;min-height:40px}#portal_config .slots{min-height:15px}#portal_config .slot-highlight{margin:3px 0;border:1px solid #7b939c;min-height:40px}#portal_config .portlets{min-height:15px}#portal_config .portlets-hover{background-color:silver}#portal_config .portlets-active{background-color:silver}#portal_config .portlet-highlight{margin:0;border:1px solid #7b939c;min-height:40px}#portal_config.container .col-12{float:left;width:100%!important}#portal_config.container .col-11{float:left;width:91.66666667%!important}#portal_config.container .col-10{float:left;width:83.33333333%!important}#portal_config.container .col-9{float:left;width:75%!important}#portal_config.container .col-8{float:left;width:66.66666667%!important}#portal_config.container .col-7{float:left;width:58.33333333%!important}#portal_config.container .col-6{float:left;width:50%!important}#portal_config.container .col-5{float:left;width:41.66666667%!important}#portal_config.container .col-4{float:left;width:33.33333333%!important}#portal_config.container .col-3{float:left;width:25%!important}#portal_config.container .col-2{float:left;width:16.66666667%!important}#portal_config.container .col-1{float:left;width:8.33333333%!important}#portal_config.container .col-0{float:left;width:100%!important;opacity:.5}#portal_config.container .col-0>.portlets{display:none}#portal_config.container-xs{max-width:750px!important}#portal_config.container-sm{width:750px!important}#portal_config.container-md{width:970px!important}#portal_config.container-lg{width:1170px!important}
--- a/src/pyams_portal/resources/js/portal.js	Tue Jun 26 08:47:39 2018 +0200
+++ b/src/pyams_portal/resources/js/portal.js	Tue Jun 26 12:11:24 2018 +0200
@@ -107,8 +107,10 @@
 						var rows = $('.rows', '#portal_config');
 						$('<div></div>').addClass('row context-menu')
 										.attr('data-ams-row-id', row_id)
-										.append($('<span></span>').addClass('row_id label label-success pull-right')
-																  .text(row_id))
+										.append($('<strong></strong>').addClass('row_id label label-success pull-left')
+																	  .text(row_id))
+										.append($('<strong></strong>').addClass('row_id label label-success pull-right')
+																	  .text(row_id))
 										.append($('<div></div>').addClass('slots')
 																.sortable({
 																	placeholder: 'slot-highlight',
@@ -145,8 +147,10 @@
 								.addClass('row context-menu')
 								.attr('data-ams-row-id', row_id)
 								.empty()
-								.append($('<span></span>').addClass('row_id label label-success pull-right')
-														  .text(row_id))
+								.append($('<strong></strong>').addClass('row_id label label-success pull-left')
+															  .text(row_id))
+								.append($('<strong></strong>').addClass('row_id label label-success pull-right')
+															  .text(row_id))
 								.append($('<div></div>').addClass('slots')
 														.sortable({
 															placeholder: 'slot-highlight',
@@ -186,7 +190,7 @@
 									if (result.status === 'success') {
 										$('.row', config).each(function (index) {
 											$(this).attr('data-ams-row-id', index);
-											$('span.row_id', $(this)).text(index);
+											$('.row_id', $(this)).text(index);
 										});
 									}
 								});
@@ -212,7 +216,7 @@
 													$('.row', '#portal_config').each(function (index) {
 														$(this).removeData()
 															   .attr('data-ams-row-id', index);
-														$('span.row_id', $(this)).text(index);
+														$('.row_id', $(this)).text(index);
 													});
 												}
 											});
--- a/src/pyams_portal/resources/js/portal.min.js	Tue Jun 26 08:47:39 2018 +0200
+++ b/src/pyams_portal/resources/js/portal.min.js	Tue Jun 26 12:11:24 2018 +0200
@@ -1,1 +1,1 @@
-!function(n,t){"use strict";var i=t.MyAMS,l={template:{initConfig:function(){var t=n("#portal_config");t.data("ams-allowed-change")&&(n(".rows",t).addClass("sortable"),n(".slots",t).addClass("sortable"),n(".slot",t).addClass("resizable"),n(".portlets",t).addClass("sortable"),i.plugins.enabled.sortable(t),i.plugins.enabled.resizable(t),n(".btn-row",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".rows"}),n(".rows",t).droppable({accept:".btn-row",drop:l.template.dropRowButton}),n(".btn-slot",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".slots"}),n(".slots",t).droppable({accept:".btn-slot",drop:l.template.dropSlotButton}),n(".btn-portlet",".btn-toolbar").draggable({cursor:"move",helper:"clone",revert:"invalid",connectToSortable:".portlets"}),n(".portlets",t).droppable({accept:".btn-portlet",hoverClass:"portlets-hover",activeClass:"portlets-active",drop:l.template.dropPortletButton}))},selectDisplay:function(){var r=n(this).val();i.ajax.post("get-slots-width.json",{device:r},function(t){var e=n("#portal_config");for(var a in e.removeClassPrefix("container-"),r&&e.addClass("container-"+r),n(".slot",e).removeClassPrefix("col-"),t)if(t.hasOwnProperty(a)){var s=t[a],o=n('.slot[data-ams-slot-name="'+a+'"]',e);if(r)o.addClass("col-"+s[r]);else for(var l in s)s.hasOwnProperty(l)&&o.addClass("col-"+l+"-"+s[l])}})},addRow:function(){return function(){n(this).parents(".btn-group").removeClass("open"),i.ajax.post("add-template-row.json",{},function(t){var e=t.row_id,a=n(".rows","#portal_config");n("<div></div>").addClass("row context-menu").attr("data-ams-row-id",e).append(n("<span></span>").addClass("row_id label label-success pull-right").text(e)).append(n("<div></div>").addClass("slots").sortable({placeholder:"slot-highlight",connectWith:".slots",over:l.template.overSlots,stop:l.template.sortSlots}).droppable({accept:".btn-slot",drop:l.template.dropSlotButton})).contextMenu({menuSelector:"#rowMenu",menuSelected:i.helpers.contextMenuHandler}).appendTo(a),a.sortable("refresh")})}},dropRowButton:function(t,s){s.draggable.hasClass("already-dropped")||(s.draggable.addClass("already-dropped"),i.ajax.post("add-template-row.json",{},function(t){var e=t.row_id,a=n(".rows","#portal_config");s.draggable.removeClassPrefix("btn").removeClassPrefix("ui-").removeClass("already-dropped").removeAttr("style").addClass("row context-menu").attr("data-ams-row-id",e).empty().append(n("<span></span>").addClass("row_id label label-success pull-right").text(e)).append(n("<div></div>").addClass("slots").sortable({placeholder:"slot-highlight",connectWith:".slots",over:l.template.overSlots,stop:l.template.sortSlots}).droppable({accept:".btn-slot",drop:l.template.dropSlotButton})).contextMenu({menuSelector:"#rowMenu",menuSelected:i.helpers.contextMenuHandler}),l.template.sortRows(),a.sortable("refresh")}))},overRows:function(t,e){n(e.placeholder).attr("class",n(e.item).attr("class")).removeClassPrefix("ui-").addClass("row-highlight").css("height",n(e.item).outerHeight())},sortRows:function(t,e){if(!e||!e.item.hasClass("already-dropped")){var a=n("#portal_config"),s=n(".row",a).listattr("data-ams-row-id");i.ajax.post("set-template-row-order.json",{rows:JSON.stringify(s)},function(t){"success"===t.status&&n(".row",a).each(function(t){n(this).attr("data-ams-row-id",t),n("span.row_id",n(this)).text(t)})})}},deleteRow:function(){return function(e){i.skin.bigBox({title:i.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+i.i18n.DELETE_WARNING,status:"info",buttons:i.i18n.BTN_OK_CANCEL},function(t){t===i.i18n.BTN_OK&&(e.hasClass("row")||(e=e.parents(".row")),i.ajax.post("delete-template-row.json",{row_id:e.data("ams-row-id")},function(t){"success"===t.status&&(e.remove(),n(".row","#portal_config").each(function(t){n(this).removeData().attr("data-ams-row-id",t),n("span.row_id",n(this)).text(t)}))}))})}},addSlotCallback:function(t){var e=n(".slots",'.row[data-ams-row-id="'+t.row_id+'"]'),a=t.slot_name,s=n("<div></div>").addClass("slot context-menu col col-xs-12 col-sm-12 col-md-12 col-lg-12 resizable").attr("data-ams-slot-name",a).append(n("<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(a)).append(n("<div></div>").addClass("portlets").sortable({placeholder:"portlet-highlight",connectWith:".portlets",over:l.template.overPortlets,stop:l.template.sortPortlets}).droppable({accept:".btn-portlet",hoverClass:"portlets-hover",activeClass:"portlets-active",drop:l.template.dropPortletButton})).append(n("<div></div>").addClass("clearfix")).contextMenu({menuSelector:"#slotMenu",menuSelected:i.helpers.contextMenuHandler}),o=n(".btn-slot",e);o.exists()?(o.replaceWith(s),n(".slot",e).each(function(){n(this).removeData()}),l.template.sortSlots()):s.appendTo(e),s.resizable({start:l.template.startSlotResize,stop:l.template.stopSlotResize,handles:"e"}),e.sortable("refresh")},dropSlotButton:function(t,e){if(!e.draggable.hasClass("already-dropped")){e.draggable.addClass("already-dropped");var a=e.helper.parents(".row:first").data("ams-row-id");i.dialog.open("add-template-slot.html?add_form.widgets.row_id="+a)}},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(t,e){var a=e.element,s=(a.parents(".slots:first").innerWidth()-10)/12,o=Math.round(n(a).width()/s),l=n("#device_selector").val();if(!l){var r=n("body").width();l=1170<r?"lg":970<r?"md":750<r?"sm":"xs"}i.ajax.post("set-slot-width.json",{slot_name:a.data("ams-slot-name"),device:l,width:o},function(t){a.removeClassPrefix("col-"),a.removeAttr("style");var e=t[a.data("ams-slot-name")];l?a.addClass("col-"+l+"-"+e[l]):a.addClass("col-"+e[l])})},editSlot:function(){return function(t){t.hasClass("slot")||(t=t.parents(".slot")),i.dialog.open("slot-properties.html?slot.widgets.slot_name="+t.data("ams-slot-name"))}},editSlotCallback:function(t){var e=n('.slot[data-ams-slot-name="'+t.slot_name+'"]');e.attr("class","slot context-menu col");var a=n("#device_selector").val();if(a)e.addClass("col-"+t.width[a]);else for(a in t.width)t.width.hasOwnProperty(a)&&e.addClass("col-"+a+"-"+t.width[a])},overSlots:function(t,e){n(e.placeholder).attr("class",n(e.item).attr("class")).removeClassPrefix("ui-").addClass("slot-highlight").css("height",n(e.item).outerHeight())},sortSlots:function(t,e){if(!e||!e.item.hasClass("already-dropped")){var a=n("#portal_config"),s={};n(".row",a).each(function(){var t=n(this),e=[];n(".slot",t).each(function(){e.push(n(this).data("ams-slot-name"))}),s[parseInt(t.attr("data-ams-row-id"))]=e}),i.ajax.post("set-template-slot-order.json",{order:JSON.stringify(s)})}},switchSlot:function(){var t=n(this),e=t.parents(".header").first().siblings(".portlets");e.hasClass("hidden")?(e.removeClass("hidden"),t.removeClass("fa-plus-square").addClass("fa-minus-square")):(e.addClass("hidden"),t.removeClass("fa-minus-square").addClass("fa-plus-square"))},deleteSlot:function(){return function(e){i.skin.bigBox({title:i.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+i.i18n.DELETE_WARNING,status:"info",buttons:i.i18n.BTN_OK_CANCEL},function(t){t===i.i18n.BTN_OK&&(e.hasClass("slot")||(e=e.parents(".slot")),i.ajax.post("delete-template-slot.json",{slot_name:e.data("ams-slot-name")},function(t){"success"===t.status&&(e.remove(),n(".slot","#portal_config").each(function(){n(this).removeData()}))}))})}},addPortletCallback:function(t){var e=n(".portlets",'.slot[data-ams-slot-name="'+t.slot_name+'"]'),a=n("<div></div>").addClass("portlet context-menu").attr("data-ams-portlet-id",t.portlet_id).append(n("<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(t.label)).append(n("<div></div>").addClass("preview").html(t.preview||"")).contextMenu({menuSelector:"#portletMenu",menuSelected:i.helpers.contextMenuHandler});i.initContent(n(".preview",a));var s=n(".btn-portlet",e);s.exists()?(s.replaceWith(a),n(".portlet",e).each(function(){n(this).removeData()}),l.template.sortPortlets(null,{item:a})):a.appendTo(e),e.sortable("refresh"),i.dialog.open("portlet-properties.html?portlet.widgets.portlet_id="+t.portlet_id)},dropPortletButton:function(t,e){if(!e.draggable.hasClass("already-dropped")){e.draggable.addClass("already-dropped");var a=e.draggable,s=n(this).parents(".slot:first");i.ajax.post("drag-template-portlet.json",{portlet_name:a.data("ams-portlet-name"),slot_name:s.data("ams-slot-name")},function(t){i.ajax.handleJSON(t)})}},submitPortletEditForm:function(){var t=n(this).parents("form").first();i.form.submit(t,{form_data:{autosubmit:!0}})},editPortlet:function(){return function(t){t.hasClass("portlet")||(t=t.parents(".portlet:first")),i.dialog.open("portlet-properties.html?portlet.widgets.portlet_id="+t.data("ams-portlet-id"))}},editPortletCallback:function(t){if(t.preview){var e=n("#portal_config"),a=n('.portlet[data-ams-portlet-id="'+t.portlet_id+'"]',e),s=n(".header",a);t.inherit_parent?n("i.chain",s).removeClass("fa-chain-broken"):n("i.chain",s).addClass("fa-chain-broken"),n(".preview",a).html(t.preview),i.initContent(n(".preview",a))}},overPortlets:function(t,e){n(e.placeholder).attr("class",n(e.item).attr("class")).removeClassPrefix("ui-").addClass("portlet-highlight").css("height",n(e.item).outerHeight())},sortPortlets:function(t,e){if(!e.item.hasClass("already-dropped")){var a=e.item,s=a.parents(".slot"),o=n(".portlet",s),l={from:a.data("ams-portlet-id"),to:{slot:s.data("ams-slot-name"),portlet_ids:o.listattr("data-ams-portlet-id")}};i.ajax.post("set-template-portlet-order.json",{order:JSON.stringify(l)})}},switchPortlet:function(){var t=n(this),e=t.parents(".header").first().siblings(".preview");e.hasClass("hidden")?(e.removeClass("hidden"),t.removeClass("fa-plus-square").addClass("fa-minus-square")):(e.addClass("hidden"),t.removeClass("fa-minus-square").addClass("fa-plus-square"))},deletePortlet:function(){return function(e){i.skin.bigBox({title:i.i18n.WARNING,content:'<i class="text-danger fa fa-2x fa-bell"></i>&nbsp; '+i.i18n.DELETE_WARNING,status:"info",buttons:i.i18n.BTN_OK_CANCEL},function(t){t===i.i18n.BTN_OK&&(e.hasClass("portlet")||(e=e.parents(".portlet")),i.ajax.post("delete-template-portlet.json",{portlet_id:e.data("ams-portlet-id")},function(t){"success"===t.status&&(e.remove(),n(".portlet","#portal_config").each(function(){n(this).removeData()}))}))})}}}};t.PyAMS_portal=l}(jQuery,this);
+!function(t,e){"use strict";var a=e.MyAMS,s={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");s.removeClassPrefix("container-"),e&&s.addClass("container-"+e),t(".slot",s).removeClassPrefix("col-");for(var o in 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])}})},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-success pull-left").text(o)).append(t("<strong></strong>").addClass("row_id label label-success pull-right").text(o)).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-").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-success pull-left").text(l)).append(t("<strong></strong>").addClass("row_id label label-success pull-right").text(l)).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)})})}},deleteRow: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("row")||(e=e.parents(".row")),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)}))}))})}},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 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(t,e){if(!e.draggable.hasClass("already-dropped")){e.draggable.addClass("already-dropped");var s=e.helper.parents(".row:first").data("ams-row-id");a.dialog.open("add-template-slot.html?add_form.widgets.row_id="+s)}},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])})},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 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])},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){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("slot")||(e=e.parents(".slot")),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(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){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}(jQuery,this);
--- a/src/pyams_portal/resources/less/portal.less	Tue Jun 26 08:47:39 2018 +0200
+++ b/src/pyams_portal/resources/less/portal.less	Tue Jun 26 12:11:24 2018 +0200
@@ -17,8 +17,14 @@
 
 		> .row_id {
 			position: absolute;
-			right: 2px;
-			top: -1.6em;
+			top: -1.5em;
+
+			&.pull-left {
+				left: 0.3em;
+			}
+			&.pull-right {
+				right: 0.3em;
+			}
 		}
 		.slot {
 			margin: 3px 0;
--- a/src/pyams_portal/zmi/layout.py	Tue Jun 26 08:47:39 2018 +0200
+++ b/src/pyams_portal/zmi/layout.py	Tue Jun 26 12:11:24 2018 +0200
@@ -382,7 +382,7 @@
     """Portal template portlet add menu"""
 
     label = _("Add portlet...")
-    label_css_class = 'fa fa-fw fa-columns'
+    label_css_class = 'fa fa-fw fa-window-restore'
     url = 'add-template-portlet.html'
     modal_target = True
 
@@ -400,7 +400,7 @@
         return translate(_("« {0} »  portal template")).format(self.context.name)
 
     legend = _("Add portlet")
-    icon_css_class = 'fa fa-fw fa-columns'
+    icon_css_class = 'fa fa-fw fa-window-restore'
 
     fields = field.Fields(IPortletAddingInfo)
     edit_permission = None
--- a/src/pyams_portal/zmi/templates/layout.pt	Tue Jun 26 08:47:39 2018 +0200
+++ b/src/pyams_portal/zmi/templates/layout.pt	Tue Jun 26 12:11:24 2018 +0200
@@ -77,8 +77,10 @@
 						 data-ams-contextmenu-selector="#rowMenu"
 						 tal:repeat="row range(template_config.rows)"
 						 tal:attributes="data-ams-row-id row;">
-						<span class="row_id label label-success pull-right"
-							  tal:content="row"></span>
+						<strong class="row_id label label-success pull-left"
+								tal:content="row"></strong>
+						<strong class="row_id label label-success pull-right"
+								tal:content="row"></strong>
 						<div class="slots"
 							 data-ams-sortable-placeholder="slot-highlight"
 							 data-ams-sortable-connectwith=".slots"