src/pyams_portal/resources/js/portal.js
changeset 0 6f99128c6d48
child 5 670b7956c689
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_portal/resources/js/portal.js	Wed Jun 17 09:58:33 2015 +0200
@@ -0,0 +1,495 @@
+(function($) {
+
+	window.PyAMS_portal = {
+
+		/**
+		 * Templates management
+		 */
+		template: {
+
+			initConfig: function() {
+				var config = $('#portal_config');
+				if (config.data('ams-allowed-change')) {
+					// Init sortables and resizables
+					$('.rows', config).addClass('sortable');
+					$('.slots', config).addClass('sortable');
+					$('.slot', config).addClass('resizable');
+					$('.portlets', config).addClass('sortable');
+					MyAMS.plugins.enabled.sortable(config);
+					MyAMS.plugins.enabled.resizable(config);
+					// Init rows toolbar drag and drop
+					$('.btn-row', '.btn-toolbar').draggable({
+						cursor: 'move',
+						helper: 'clone',
+						revert: 'invalid',
+						connectToSortable: '.rows'
+					});
+					$('.rows', config).droppable({
+						accept: '.btn-row',
+						drop: function(event, ui) {
+							if (ui.draggable.hasClass('already-dropped'))
+								return;
+							ui.draggable.addClass('already-dropped');
+							MyAMS.ajax.post('add-template-row.json', {}, function(result) {
+								var row_id = result.row_id;
+								var rows = $('.rows', '#portal_config');
+								ui.draggable.removeClassPrefix('btn')
+											.removeClassPrefix('ui-')
+											.removeClass('already-dropped')
+											.removeAttr('style')
+											.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($('<div></div>').addClass('slots')
+																	.sortable({
+																		placeholder: 'slot-highlight',
+																		connectWith: '.slots',
+																		over: PyAMS_portal.template.overSlots,
+																		stop: PyAMS_portal.template.sortSlots
+																	}))
+											.contextMenu({
+												menuSelector: '#rowMenu',
+												menuSelected: MyAMS.helpers.contextMenuHandler
+											});
+								PyAMS_portal.template.sortRows();
+								rows.sortable('refresh');
+							});
+						}
+					});
+					// Init slot toolbar drag and drop
+					$('.btn-slot', '.btn-toolbar').draggable({
+						cursor: 'move',
+						helper: 'clone',
+						revert: 'invalid',
+						connectToSortable: '.slots'
+					});
+					$('.slots', config).droppable({
+						accept: '.btn-slot',
+						drop: function(event, ui) {
+							if (ui.draggable.hasClass('already-dropped'))
+								return;
+							ui.draggable.addClass('already-dropped');
+							var row_id = ui.helper.parents('.row:first').data('ams-row-id');
+							MyAMS.dialog.open('add-template-slot.html?form.widgets.row_id=' + row_id);
+						}
+					});
+					// Init portlets toolbar drag and drop
+					$('.btn-portlet', '.btn-toolbar').draggable({
+						cursor: 'move',
+						helper: 'clone',
+						revert: 'invalid',
+						connectToSortable: '.portlets'
+					});
+					$('.portlets', config).droppable({
+						accept: '.btn-portlet',
+						hoverClass: 'portlets-hover',
+						activeClass: 'portlets-active',
+						drop: function(event, ui) {
+							if (ui.draggable.hasClass('already-dropped'))
+								return;
+							ui.draggable.addClass('already-dropped');
+							var source = ui.draggable;
+							var target = $(this);
+							var slot = target.parents('.slot:first');
+							MyAMS.ajax.post('drag-template-portlet.json', {
+								portlet_name: source.data('ams-portlet-name'),
+								slot_name: slot.data('ams-slot-name')
+							}, function(result) {
+								MyAMS.ajax.handleJSON(result);
+							});
+						}
+					});
+				}
+			},
+
+
+			/**
+			 * Display selector
+			 */
+
+			selectDisplay: function() {
+				var device = $(this).val();
+				MyAMS.ajax.post('get-slots-width.json',
+								{device: device},
+								function(result) {
+									var config = $('#portal_config');
+									config.removeClassPrefix('container-');
+									if (device) {
+										config.addClass('container-' + device);
+									}
+									$('.slot', config).removeClassPrefix('col-');
+									for (var slot_name in result) {
+										var widths = result[slot_name];
+										var slot = $('.slot[data-ams-slot-name="' + slot_name + '"]', config);
+										if (device) {
+											slot.addClass('col-' + widths[device]);
+										} else {
+											for (var display in widths) {
+												slot.addClass('col-' + display + '-' + widths[display]);
+											}
+										}
+									}
+								});
+			},
+
+			/**
+			 * Rows management
+			 */
+
+			addRow: function() {
+				return function() {
+					$(this).parents('.btn-group').removeClass('open');
+					MyAMS.ajax.post('add-template-row.json', {}, function(result) {
+						var row_id = result.row_id;
+						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($('<div></div>').addClass('slots')
+																.sortable({
+																	placeholder: 'slot-highlight',
+																	connectWith: '.slots',
+																	over: PyAMS_portal.template.overSlots,
+																	stop: PyAMS_portal.template.sortSlots
+																}))
+										.contextMenu({
+											menuSelector: '#rowMenu',
+											menuSelected: MyAMS.helpers.contextMenuHandler
+										})
+										.appendTo(rows);
+						rows.sortable('refresh');
+					});
+				};
+			},
+
+			overRows: function(event, ui) {
+				$(ui.placeholder).attr('class', $(ui.item).attr('class'))
+								 .removeClassPrefix('ui-')
+								 .addClass('row-highlight')
+								 .css('height', $(ui.item).outerHeight());
+			},
+
+			sortRows: function(event, ui) {
+				if (ui && ui.item.hasClass('already-dropped'))
+					return;
+				var config = $('#portal_config');
+				var ids = $('.row', config).listattr('data-ams-row-id');
+				MyAMS.ajax.post('set-template-row-order.json',
+								{rows: JSON.stringify(ids)},
+								function(result) {
+									if (result.status == 'success') {
+										$('.row', config).each(function (index) {
+											$(this).attr('data-ams-row-id', index);
+											$('span.row_id', $(this)).text(index);
+										})
+									}
+								});
+			},
+
+			deleteRow: function() {
+				return function(row) {
+					MyAMS.skin.bigBox({
+						title: MyAMS.i18n.WARNING,
+						content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + MyAMS.i18n.DELETE_WARNING,
+						buttons: MyAMS.i18n.BTN_OK_CANCEL
+					}, function(button) {
+						if (button == MyAMS.i18n.BTN_OK) {
+							if (!row.hasClass('row'))
+								row = row.parents('.row');
+							MyAMS.ajax.post('delete-template-row.json',
+											{row_id: row.data('ams-row-id')},
+											function(result) {
+												if (result.status == 'success') {
+													row.remove();
+													$('.row', '#portal_config').each(function (index) {
+														$(this).removeData()
+															   .attr('data-ams-row-id', index);
+														$('span.row_id', $(this)).text(index);
+													})
+												}
+											});
+						}
+					});
+				};
+			},
+
+
+			/**
+			 * Slots management
+			 */
+
+			addSlotCallback: function(result) {
+				var slots = $('.slots', '.row[data-ams-row-id="' + result.row_id + '"]');
+				var slot_name = result.slot_name;
+				var new_slot = $('<div></div>').addClass('slot context-menu col col-md-12')
+											   .attr('data-ams-slot-name', slot_name)
+											   .append($('<div></div>').addClass('header padding-x-5')
+																	   .text(slot_name))
+											   .append($('<div></div>').addClass('portlets')
+																	   .sortable({
+																			placeholder: 'portlet-highlight',
+																			connectWith: '.portlets',
+																			over: PyAMS_portal.template.overPortlets,
+																			stop: PyAMS_portal.template.sortPortlets
+																	   }))
+											   .append($('<div></div>').addClass('clearfix'))
+											   .contextMenu({
+													menuSelector: '#slotMenu',
+													menuSelected: MyAMS.helpers.contextMenuHandler
+											   });
+				var slot_button = $('.btn-slot', slots);
+				if (slot_button.exists()) {  // Slot added via drag & drop
+					slot_button.replaceWith(new_slot);
+					$('.slot', slots).each(function() {
+						$(this).removeData();
+					});
+					PyAMS_portal.template.sortSlots();
+				} else {
+					new_slot.appendTo(slots);
+				}
+				slots.sortable('refresh');
+			},
+
+			startSlotResize: function(event, ui) {
+				var slot = ui.element;
+				var row = slot.parents('.slots:first');
+				var colWidth = (row.innerWidth() - 110) / 12;
+				var slotHeight = slot.height();
+				ui.element.resizable('option', 'grid', [colWidth, slotHeight]);
+				ui.element.resizable('option', 'minWidth', colWidth);
+				ui.element.resizable('option', 'minHeight', slotHeight);
+				ui.element.resizable('option', 'maxWidth', row.innerWidth());
+				ui.element.resizable('option', 'maxHeight', slotHeight);
+			},
+
+			stopSlotResize: function(event, ui) {
+				var slot = ui.element;
+				var row = slot.parents('.slots:first');
+				var colWidth = (row.innerWidth() - 10) / 12;
+				var slotCols = Math.round($(slot).width() / colWidth);
+				var device = $('#device_selector').val();
+				if (!device) {
+					var deviceWidth = $('body').width();
+					if (deviceWidth > 1170)
+						device = 'lg';
+					else if (deviceWidth > 970)
+						device = 'md';
+					else if (deviceWidth > 750)
+						device = 'sm';
+					else
+						device = 'xs';
+				}
+				MyAMS.ajax.post('set-slot-width.json',
+								{slot_name: slot.data('ams-slot-name'),
+								 device: device,
+								 width: slotCols},
+								function(result) {
+									slot.removeClassPrefix('col-');
+									slot.removeAttr('style');
+									var slot_name = slot.data('ams-slot-name');
+									var widths = result[slot_name];
+									if (device) {
+										slot.addClass('col-' + device + '-' + widths[device]);
+									} else {
+										slot.addClass('col-' + widths[device]);
+									}
+								});
+			},
+
+			editSlot: function() {
+				return function(slot) {
+					if (!slot.hasClass('slot'))
+						slot = slot.parents('.slot');
+					MyAMS.dialog.open('slot-properties.html?form.widgets.slot_name=' + slot.data('ams-slot-name'));
+				};
+			},
+
+			editSlotCallback: function(result) {
+				var slot = $('.slot[data-ams-slot-name="' + result.slot_name + '"]');
+				slot.attr('class', 'slot context-menu col');
+				var device = $('#device_selector').val();
+				if (device)
+					slot.addClass('col-' + result.width[device]);
+				else {
+					for (device in result.width) {
+						slot.addClass('col-' + device + '-' + result.width[device]);
+					}
+				}
+			},
+
+			overSlots: function(event, ui) {
+				$(ui.placeholder).attr('class', $(ui.item).attr('class'))
+								 .removeClassPrefix('ui-')
+								 .addClass('slot-highlight')
+								 .css('height', $(ui.item).outerHeight());
+			},
+
+			sortSlots: function(event, ui) {
+				if (ui && ui.item.hasClass('already-dropped'))
+					return;
+				var config = $('#portal_config');
+				var order = {};
+				$('.row', config).each(function() {
+					var row = $(this);
+					var row_config = [];
+					$('.slot', row).each(function() {
+						row_config.push($(this).data('ams-slot-name'));
+					});
+					order[parseInt(row.attr('data-ams-row-id'))] = row_config;
+				});
+				MyAMS.ajax.post('set-template-slot-order.json',
+								{order: JSON.stringify(order)},
+								function(result) {
+									if (result.status == 'success') {}
+								});
+			},
+
+			deleteSlot: function() {
+				return function(slot) {
+					MyAMS.skin.bigBox({
+						title: MyAMS.i18n.WARNING,
+						content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + MyAMS.i18n.DELETE_WARNING,
+						buttons: MyAMS.i18n.BTN_OK_CANCEL
+					}, function(button) {
+						if (button == MyAMS.i18n.BTN_OK) {
+							if (!slot.hasClass('slot'))
+								slot = slot.parents('.slot');
+							MyAMS.ajax.post('delete-template-slot.json',
+											{slot_name: slot.data('ams-slot-name')},
+											function(result) {
+												if (result.status == 'success') {
+													slot.remove();
+													$('.slot', '#portal_config').each(function() {
+														$(this).removeData();
+													});
+												}
+											});
+						}
+					});
+				};
+			},
+
+
+			/**
+			 * Portlets management
+			 */
+
+			addPortletCallback: function(result) {
+				var portlets = $('.portlets', '.slot[data-ams-slot-name="' + result.slot_name + '"]');
+				var portlet = $('<div></div>').addClass('portlet context-menu')
+											  .attr('data-ams-portlet-name', result.portlet_name)
+											  .attr('data-ams-portlet-slot', result.slot_name)
+											  .attr('data-ams-portlet-position', result.position)
+											  .append($('<div></div>').addClass('header padding-x-5')
+																	  .text(result.label))
+											.  append($('<div></div>').addClass('preview')
+																	  .html(result.preview || ''))
+											  .contextMenu({
+													menuSelector: '#portletMenu',
+													menuSelected: MyAMS.helpers.contextMenuHandler
+											  });
+				MyAMS.initContent($('.preview', portlet));
+				var portlet_button = $('.btn-portlet', portlets);
+				if (portlet_button.exists()) {  // Portlet added via drag & drop
+					portlet_button.replaceWith(portlet);
+					$('.portlet', portlets).each(function() {
+						$(this).removeData();
+					});
+					PyAMS_portal.template.sortPortlets(null, {item: portlet});
+				} else {
+					portlet.appendTo(portlets);
+				}
+				portlets.sortable('refresh');
+			},
+
+			editPortlet: function() {
+				return function(portlet) {
+					if (!portlet.hasClass('portlet'))
+						portlet = portlet.parents('.portlet:first');
+					var slot = portlet.parents('.slot:first');
+					var row = slot.parents('.row:first');
+					MyAMS.dialog.open('portlet-properties.html?form.widgets.slot_name=' + slot.data('ams-slot-name') +
+															 '&form.widgets.position=' + portlet.data('ams-portlet-position'));
+				};
+			},
+
+			editPortletCallback: function(result) {
+				if (result.preview) {
+					var config = $('#portal_config');
+					var portlet = $('.portlet[data-ams-portlet-slot="' + result.slot_name + '"]' +
+											'[data-ams-portlet-position="' + result.position + '"]', config);
+					$('.preview', portlet).html(result.preview);
+					MyAMS.initContent($('.preview', portlet));
+				}
+			},
+
+			overPortlets: function(event, ui) {
+				$(ui.placeholder).attr('class', $(ui.item).attr('class'))
+								 .removeClassPrefix('ui-')
+								 .addClass('portlet-highlight')
+								 .css('height', $(ui.item).outerHeight());
+			},
+
+			sortPortlets: function(event, ui) {
+				if (ui.item.hasClass('already-dropped'))
+					return;
+				var portlet = ui.item;
+				var to_slot = portlet.parents('.slot');
+				var to_portlets = $('.portlet', to_slot);
+				var order = {from: {name: portlet.data('ams-portlet-name'),
+									slot: portlet.data('ams-portlet-slot'),
+									position: portlet.data('ams-portlet-position')},
+							 to: {slot: to_slot.data('ams-slot-name'),
+								  names: to_portlets.listattr('data-ams-portlet-name'),
+								  slots: to_portlets.listattr('data-ams-portlet-slot'),
+								  positions: to_portlets.listattr('data-ams-portlet-position')}};
+				MyAMS.ajax.post('set-template-portlet-order.json',
+								{order: JSON.stringify(order)},
+								function(result) {
+									if (result.status == 'success') {
+										var from_slot = $('.slot[data-ams-slot-name="' + portlet.attr('data-ams-portlet-slot') + '"]', '#portal_config');
+										$('.portlet', from_slot).each(function(index) {
+											$(this).removeData()
+												   .attr('data-ams-portlet-position', index);
+										});
+										$('.portlet', to_slot).each(function(index) {
+											$(this).removeData()
+												   .attr('data-ams-portlet-slot', to_slot.attr('data-ams-slot-name'))
+												   .attr('data-ams-portlet-position', index);
+										});
+									}
+								});
+			},
+
+			deletePortlet: function() {
+				return function(portlet) {
+					MyAMS.skin.bigBox({
+						title: MyAMS.i18n.WARNING,
+						content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + MyAMS.i18n.DELETE_WARNING,
+						buttons: MyAMS.i18n.BTN_OK_CANCEL
+					}, function(button) {
+						if (button == MyAMS.i18n.BTN_OK) {
+							if (!portlet.hasClass('portlet'))
+								portlet = portlet.parents('.portlet');
+							MyAMS.ajax.post('delete-template-portlet.json',
+											{slot_name: portlet.data('ams-portlet-slot'),
+											 position: portlet.data('ams-portlet-position')},
+											function(result) {
+												if (result.status == 'success') {
+													portlet.remove();
+													$('.portlet', '#portal_config').each(function() {
+														$(this).removeData();
+													});
+												}
+											});
+						}
+					});
+				};
+			}
+		}
+	};
+
+})(jQuery);