Index: ivy.xml =================================================================== --- ivy.xml (revision 6976) +++ ivy.xml (working copy) @@ -52,6 +52,7 @@ + Index: main/workspace-web/src/org/ametys/web/repository/PageGenerator.java =================================================================== --- main/workspace-web/src/org/ametys/web/repository/PageGenerator.java (revision 6976) +++ main/workspace-web/src/org/ametys/web/repository/PageGenerator.java (working copy) @@ -43,6 +43,7 @@ import org.ametys.plugins.repository.metadata.CompositeMetadata; import org.ametys.plugins.repository.metadata.MetadataSaxer; import org.ametys.runtime.util.IgnoreRootHandler; +import org.ametys.web.repository.page.ModifiablePage; import org.ametys.web.repository.page.Page; import org.ametys.web.repository.page.PagesContainer; import org.ametys.web.repository.page.Zone; @@ -105,6 +106,7 @@ AttributesImpl attrs = new AttributesImpl(); attrs.addCDATAAttribute("title", title); attrs.addCDATAAttribute("long-title", page.getLongTitle()); + attrs.addCDATAAttribute("id", page.getId()); XMLUtils.startElement(contentHandler, "page", attrs); try @@ -141,7 +143,9 @@ throw new ProcessingException("Unable to SAX page metadata", e); } - XMLUtils.startElement(contentHandler, "pageContents"); + AttributesImpl pcattrs = new AttributesImpl(); + pcattrs.addCDATAAttribute("modifiable", Boolean.toString(page instanceof ModifiablePage)); + XMLUtils.startElement(contentHandler, "pageContents", pcattrs); try { Index: main/workspace-web/stylesheets/page.xsl =================================================================== --- main/workspace-web/stylesheets/page.xsl (revision 6976) +++ main/workspace-web/stylesheets/page.xsl (working copy) @@ -106,6 +106,8 @@ { parent.org.ametys.web.skin.UIZone.register( window, + "", + "", "", "", "", @@ -189,6 +191,8 @@ { parent.org.ametys.web.skin.UIZoneItem.register( window, + "", + "", "", "", "", Index: main/workspace-web/stylesheets/wrapper.xsl =================================================================== --- main/workspace-web/stylesheets/wrapper.xsl (revision 6976) +++ main/workspace-web/stylesheets/wrapper.xsl (working copy) @@ -99,6 +99,11 @@ } + + + + + Index: main/plugin-web/resources/css/inframe-page.css =================================================================== --- main/plugin-web/resources/css/inframe-page.css (revision 6976) +++ main/plugin-web/resources/css/inframe-page.css (working copy) @@ -20,6 +20,50 @@ padding: 6px; } +div.ametys-cms-zone-droptarget +{ + border-color: #BCE8F3; + background-color: #BCE8F3 !important; +} +div.ametys-cms-zone-droptarget div.ametys-cms-zoneitem-droptarget +{ + border: 1px solid #27b1d3; + background-color: #53c4df; + height: 30px !important; + margin-top: 2px; +} + +div.ametys-cms-zone-dragtarget +{ + border: 1px dotted black !important; + background-color: #ffffff !important; + padding: 5px !important; + height: 20px !important; + overflow: hidden; +} +div.ametys-cms-zone-dragtarget img +{ + width: 16px; + height: 16px; + margin: 2px; + margin-top: 4px; + margin-right: 4px; + float: left; +} +div.ametys-cms-zone-dragtarget div +{ + font-size: 11px !important; + font-variant: none !important; + font-weight: bold !important; + font-family: "Tahoma","Helvetica","Arial",sans-serif !important; + color: #023A69 !important; + position: static !important; + border-style: none !important; + background-image: none !important; + line-height: 24px !important; + vertical-align: middle !important; +} + div.ametys-cms-zone-published { border: 1px dashed #8bdb5a; Index: main/plugin-web/resources/js/org/ametys/web/zone/MoveZoneItemAction.i18n.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/zone/MoveZoneItemAction.i18n.js (revision 0) +++ main/plugin-web/resources/js/org/ametys/web/zone/MoveZoneItemAction.i18n.js (revision 0) @@ -0,0 +1,61 @@ +/* + * Copyright 2010 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.namespace('org.ametys.web.content'); + +org.ametys.web.content.MoveZoneItemAction = function (up) +{ + var currentTargets = org.ametys.ribbon.RibbonManager.getInstance().getCurrentSelectionTargets(); + var target = org.ametys.messagebus.message.MessageTargetHelper.findFirst(currentTargets, function(target) {return target.getType() == 'page'}); + + if (target == null || target.getParameters()["zoneitem-id"] == null) + { + new org.ametys.msg.ErrorDialog("", "", "", "org.ametys.web.content.MoveZoneItemAction"); + return; + } + + var pageId = target.getParameters()["id"]; + var zoneItemId = target.getParameters()["zoneitem-id"]; + + var params = {'zoneItemId': zoneItemId}; + var serverMessage = new org.ametys.servercomm.ServerMessage('web', 'zoneitem/move' + (up ? 'Up' : 'Down'), params, org.ametys.servercomm.ServerComm.PRIORITY_MAJOR, org.ametys.web.content.MoveZoneItemAction._callback , this, [pageId, zoneItemId], "xml"); + org.ametys.servercomm.ServerComm.getInstance().send(serverMessage); +} + +org.ametys.web.content.MoveUpZoneItemAction = function (controlId, controlConfiguration, controlPluginName) +{ + org.ametys.web.content.MoveZoneItemAction(true); +} + +org.ametys.web.content.MoveDownZoneItemAction = function (controlId, controlConfiguration, controlPluginName) +{ + org.ametys.web.content.MoveZoneItemAction(false); +} + +org.ametys.web.content.MoveZoneItemAction._callback = function(response, args) +{ + if (org.ametys.servercomm.ServerComm.handleBadResponse("", response, "org.ametys.web.buttons.zoneitem.MoveAction")) + { + return; + } + + var pageId = args[0]; + var zoneItemId = args[1]; + + var targets = [org.ametys.messagebus.bus.MessageBuilder.getInstance().createTarget("page", {'id': pageId, 'zoneitem-id': zoneItemId})]; + var events = [org.ametys.messagebus.bus.MessageBuilder.getInstance().createMessage("zoningChanged", null, targets)]; + org.ametys.messagebus.MessageBus.getInstance().fireMessages(events); +} Index: main/plugin-web/resources/js/org/ametys/web/skin/UIZoneItem.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/skin/UIZoneItem.js (revision 6976) +++ main/plugin-web/resources/js/org/ametys/web/skin/UIZoneItem.js (working copy) @@ -19,6 +19,8 @@ /** * Register the html element zoneName in the document doc as a zone. If empty do some additional graphic. * @param {HTMLWindow} win The window where to work in + * @param {String} pageId The page identifier + * @param {boolean} modifiable Is the zone modifiable ? * @param {String} zoneName The id of the html element surrounding the zone * @param {String} zoneItemHTMLId The id of the html element surrounding the zone * @param {String} zoneItemId The id of the repository zone item @@ -29,7 +31,7 @@ * @param {String} mediumIcon The path to the medium icon * @param {String} largeIcon The path to the large icon */ -org.ametys.web.skin.UIZoneItem.register = function(win, zoneName, zoneItemHTMLId, zoneItemId, contentName, label, description, smallIcon, mediumIcon, largeIcon) +org.ametys.web.skin.UIZoneItem.register = function(win, pageId, modifiable, zoneName, zoneItemHTMLId, zoneItemId, contentName, label, description, smallIcon, mediumIcon, largeIcon) { var doc = win.document; if (doc.zoneItems == null){ doc.zoneItems = []; } @@ -61,6 +63,20 @@ } div.insertBefore(img, div.firstChild); + + if (modifiable) + { + org.ametys.web.skin.UIZoneItem.makesDraggable(win, pageId, div, img, label, contentName, zoneItemId); + } +} + +if (!org.ametys.web.skin.UIZoneItem.makesDraggable) +{ + org.ametys.web.skin.UIZoneItem.makesDraggable = function(win, pageId, div, img, label, contentName, zoneItemId) + { + // Default behavior : Nothing to do + // Has to be overriden + } } /** Index: main/plugin-web/resources/js/org/ametys/web/skin/DDZoneItem.i18n.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/skin/DDZoneItem.i18n.js (revision 0) +++ main/plugin-web/resources/js/org/ametys/web/skin/DDZoneItem.i18n.js (revision 0) @@ -0,0 +1,142 @@ +/* + * Copyright 2010 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Ext.namespace('org.ametys.web.skin.UIZone'); +Ext.namespace('org.ametys.web.skin.UIZoneItem'); +Ext.namespace('org.ametys.web.skin.DDZoneItem'); + +org.ametys.web.skin.UIZoneItem.makesDraggable = function(win, pageId, div, img, label, contentName, zoneItemId) +{ + win.$(div).draggable({ + cursorAt: {left: 10, top: 10}, + iframeFix: true, + revert: "invalid", + appendTo: 'body', + helper: function() + { + // Create the floating element + var i = win.$(img); + + var css = " width: " + i.parent().width() + "px;"; + if (i.parent().hasClass("ametys-cms-zone-item-selected")) + { + css += " border-width: 2px;"; + } + + var imgCloned = i.clone().wrap("<div zonteclass='ametys-cms-zone-dragtarget' style='"+ css + "'/>").after("<div>" + label + (contentName != "" ? (" (" + contentName + ")") : "") + "</div>"); + imgCloned.parent().attr("zoneitemid", zoneItemId); + return imgCloned.parent(); + }, + scope: 'ametys-zones', + zIndex: 99999, + handle: img, + refreshPositions: true, + distance: 6, + start: function() { img.oldonclick = img.onclick; img.onclick = null; win.$(img).parent().slideUp(); }, + stop: function() + { + img.onclick = img.oldonclick; + img.oldonclick = null; + win.$(img).parent().slideDown(); + + win.$("body").find(".ametys-cms-zone-empty").each(function (index, zone) + { + zone = win.$(zone); + + if (zone.children(".ametys-cms-zone-item").size() == 0) + { + zone.children(".ametys-cms-zone-empty-desc").show(); + } + else + { + zone.children(".ametys-cms-zone-empty-desc").hide(); + } + } + ); + } + }); +} + +org.ametys.web.skin.UIZone.makesDroppable = function(win, pageId, div, zoneName) +{ + win.$(div).droppable({ + scope: 'ametys-zones', + hoverClass: 'ametys-cms-zone-droptarget', + tolerance: 'pointer', + greedy: true, + over: function(event, ui) + { + // Draw a drop zone + if (ui.helper.dropzone) + { + ui.helper.dropzone.detach(); + ui.helper.dropzone = null; + } + + var zone = win.$(this); + + var id = Ext.id(); + var css = "width: " + (zone.width() - 2) + "px"; + zone.append("<div id='" + id + "' class='ametys-cms-zoneitem-droptarget' style='" + css + "'></div>"); + + ui.helper.dropzone = win.$("#" + id); + }, + out: function(event, ui) + { + // Remove the drop zone display + if (ui.helper.dropzone && ui.helper.dropzone.parent() == win.$(this)) + { + ui.helper.dropzone.detach(); + ui.helper.dropzone = null; + } + }, + drop: function(event, ui) + { + if (ui.helper.dropzone) + { + ui.helper.dropzone.after(ui.draggable) + + ui.helper.dropzone.detach(); + ui.helper.dropzone = null; + } + else + { + // this should never happens + win.$(this).append(ui.draggable); + } + + // there is a modification + var params = { + 'zoneItemId': ui.helper.attr("zoneitemid"), + 'zoneName': zoneName, + 'pageId': pageId}; + var serverMessage = new org.ametys.servercomm.ServerMessage('web', 'zoneitem/moveTo', params, org.ametys.servercomm.ServerComm.PRIORITY_MAJOR, org.ametys.web.skin.DDZoneItem._dropDone, this, params, "xml"); + org.ametys.servercomm.ServerComm.getInstance().send(serverMessage); + } + }); +} + +org.ametys.web.skin.DDZoneItem._dropDone = function(response, params) +{ + if (org.ametys.servercomm.ServerComm.handleBadResponse("", response, "org.ametys.web.skin.DDZoneItem")) + { + return; + } + + var targets = [org.ametys.messagebus.bus.MessageBuilder.getInstance().createTarget("page", {'id': params.pageId})]; + var events = [org.ametys.messagebus.bus.MessageBuilder.getInstance().createMessage("zoningChanged", null, targets)]; + org.ametys.messagebus.MessageBus.getInstance().fireMessages(events); +} Index: main/plugin-web/resources/js/org/ametys/web/skin/UIZone.i18n.js =================================================================== --- main/plugin-web/resources/js/org/ametys/web/skin/UIZone.i18n.js (revision 6976) +++ main/plugin-web/resources/js/org/ametys/web/skin/UIZone.i18n.js (working copy) @@ -19,6 +19,8 @@ /** * Register the html element zoneName in the document doc as a zone. If empty do some additional graphic. * @param {HTMLWindow} win The document where to work in + * @param {String} pageId The page identifier + * @param {boolean} modifiable Is the zone modifiable ? * @param {String} zoneName The id of the html element surrounding the zone * @param {String} zoneTitle The title of the zone * @param {String} zoneDesc The description of the zone @@ -27,7 +29,7 @@ * @param {String} largeImg The path for the small image * @param {boolean/String} emptyZone Optional boolean to indicate if zone is empty. false is the default value. Or can be a string (when not really empty - to indicate the page id that the zone items are inherited from) */ -org.ametys.web.skin.UIZone.register = function(win, zoneName, zoneTitle, zoneDesc, smallImg, mediumImg, largeImg, emptyZone) +org.ametys.web.skin.UIZone.register = function(win, pageId, modifiable, zoneName, zoneTitle, zoneDesc, smallImg, mediumImg, largeImg, emptyZone) { var doc = win.document; @@ -101,6 +103,20 @@ div.insertBefore(img, div.firstChild); img.src = context.contextPath + smallImg; } + + if (modifiable) + { + org.ametys.web.skin.UIZone.makesDroppable(win, pageId, div, zoneName); + } +} + +if (!org.ametys.web.skin.UIZone.makesDroppable) +{ + org.ametys.web.skin.UIZone.makesDroppable = function(win, pageId, div, zoneName) + { + // Default behavior : Nothing to do + // Has to be overridden + } } /** Index: main/plugin-web/plugin.xml =================================================================== --- main/plugin-web/plugin.xml (revision 6976) +++ main/plugin-web/plugin.xml (working copy) @@ -579,6 +579,15 @@ + + + PLUGINS_WEB_RIGHTS_PAGE_ORGANIZE_ZONEITEM_DESCRIPTION + PLUGINS_CMS_RIGHTS_PAGE_CATEGORY + + + + @@ -750,6 +759,66 @@ + + + + + + js/org/ametys/web/skin/DDZoneItem.i18n.js + + Web_Rights_Page_OrganizeZoneItem + + + + + org.ametys.web.content.MoveUpZoneItemAction + + PLUGINS_WEB_CONTENT_MOVEZONEITEM_UP_LABEL + PLUGINS_WEB_CONTENT_MOVEZONEITEM_UP_DESCRIPTION + PLUGINS_WEB_CONTENT_MOVEZONEITEM_UP_NOSELECTION_DESCRIPTION + PLUGINS_WEB_CONTENT_MOVEZONEITEM_UP_NORIGHT_DESCRIPTION + PLUGINS_WEB_CONTENT_MOVEZONEITEM_UP_NOMODIFIABLE_DESCRIPTION + img/skin/zoneitem_moveup_16.png + img/skin/zoneitem_moveup_32.png + img/skin/zoneitem_moveup_48.png + + + js/org/ametys/web/zone/MoveZoneItemAction.i18n.js + js/org/ametys/ribbon/control/button/ZoneItemActionButton.js + js/org/ametys/ribbon/control/button/ModifiableZoneItemActionButton.js + + Web_Rights_Page_OrganizeZoneItem + + + + + org.ametys.web.content.MoveDownZoneItemAction + + PLUGINS_WEB_CONTENT_MOVEZONEITEM_DOWN_LABEL + PLUGINS_WEB_CONTENT_MOVEZONEITEM_DOWN_DESCRIPTION + PLUGINS_WEB_CONTENT_MOVEZONEITEM_DOWN_NOSELECTION_DESCRIPTION + PLUGINS_WEB_CONTENT_MOVEZONEITEM_DOWN_NORIGHT_DESCRIPTION + PLUGINS_WEB_CONTENT_MOVEZONEITEM_DOWN_NOMODIFIABLE_DESCRIPTION + img/skin/zoneitem_movedown_16.png + img/skin/zoneitem_movedown_32.png + img/skin/zoneitem_movedown_48.png + + + js/org/ametys/web/zone/MoveZoneItemAction.i18n.js + js/org/ametys/ribbon/control/button/ZoneItemActionButton.js + js/org/ametys/ribbon/control/button/ModifiableZoneItemActionButton.js + + Web_Rights_Page_OrganizeZoneItem + + + + Index: main/plugin-web/src/org/ametys/web/live/SynchronizePageChangeObserver.java =================================================================== --- main/plugin-web/src/org/ametys/web/live/SynchronizePageChangeObserver.java (revision 6976) +++ main/plugin-web/src/org/ametys/web/live/SynchronizePageChangeObserver.java (working copy) @@ -34,7 +34,7 @@ { String id = event.getId(); return id.equals(ObservationConstants.PAGE_ADDED) || id.equals(ObservationConstants.PAGE_CHANGED) - || id.equals(ObservationConstants.ZONEITEM_ADDED) || id.equals(ObservationConstants.ZONEITEM_DELETED); + || id.equals(ObservationConstants.ZONEITEM_ADDED) || id.equals(ObservationConstants.ZONEITEM_MOVED) || id.equals(ObservationConstants.ZONEITEM_DELETED); } @Override Index: main/plugin-web/src/org/ametys/web/observation/ObservationConstants.java =================================================================== --- main/plugin-web/src/org/ametys/web/observation/ObservationConstants.java (revision 6976) +++ main/plugin-web/src/org/ametys/web/observation/ObservationConstants.java (working copy) @@ -47,6 +47,8 @@ /** Event id when a zone item is added. */ public static final String ZONEITEM_ADDED = "zoneitem.added"; + /** Event id when a zone item is moved. */ + public static final String ZONEITEM_MOVED = "zoneitem.moved"; /** Event id when a zone item is deleted. */ public static final String ZONEITEM_DELETED = "zoneitem.deleted"; Index: main/plugin-web/src/org/ametys/web/lucene/LucenePageChangePart1Observer.java =================================================================== --- main/plugin-web/src/org/ametys/web/lucene/LucenePageChangePart1Observer.java (revision 6976) +++ main/plugin-web/src/org/ametys/web/lucene/LucenePageChangePart1Observer.java (working copy) @@ -54,7 +54,7 @@ { String id = event.getId(); return id.equals(ObservationConstants.PAGE_ADDED) || id.equals(ObservationConstants.PAGE_CHANGED) - || id.equals(ObservationConstants.ZONEITEM_ADDED) || id.equals(ObservationConstants.ZONEITEM_DELETED); + || id.equals(ObservationConstants.ZONEITEM_ADDED) || id.equals(ObservationConstants.ZONEITEM_MOVED) || id.equals(ObservationConstants.ZONEITEM_DELETED); } @Override Index: main/plugin-web/src/org/ametys/web/lucene/LucenePageChangePart2Observer.java =================================================================== --- main/plugin-web/src/org/ametys/web/lucene/LucenePageChangePart2Observer.java (revision 6976) +++ main/plugin-web/src/org/ametys/web/lucene/LucenePageChangePart2Observer.java (working copy) @@ -55,7 +55,7 @@ { String id = event.getId(); return id.equals(ObservationConstants.PAGE_ADDED) || id.equals(ObservationConstants.PAGE_CHANGED) - || id.equals(ObservationConstants.ZONEITEM_ADDED) || id.equals(ObservationConstants.ZONEITEM_DELETED); + || id.equals(ObservationConstants.ZONEITEM_ADDED) || id.equals(ObservationConstants.ZONEITEM_MOVED) || id.equals(ObservationConstants.ZONEITEM_DELETED); } @Override Index: main/plugin-web/src/org/ametys/web/repository/page/jcr/DefaultZoneItem.java =================================================================== --- main/plugin-web/src/org/ametys/web/repository/page/jcr/DefaultZoneItem.java (revision 6976) +++ main/plugin-web/src/org/ametys/web/repository/page/jcr/DefaultZoneItem.java (working copy) @@ -155,7 +155,6 @@ throw new AmetysRepositoryException("Can not move a zone item " + getId() + " of type DefaultZoneItem to something that is not a DefaultZone " + newParent.getId()); } - Node node = getNode(); try @@ -163,14 +162,14 @@ if (getParent().equals(newParent)) { // Just order current node to the end - node.getParent().orderBefore(node.getName(), null); + node.getParent().orderBefore(node.getName() + "[" + node.getIndex() + "]", null); } else { DefaultZone newParentZone = (DefaultZone) newParent; // Move node - node.getSession().move(node.getPath(), newParentZone.getNode().getPath() + "/" + node.getName()); + node.getSession().move(node.getPath(), newParentZone.getNode().getPath() + "/" + DefaultZone.ZONEITEMS_NODE_NAME + "/" + node.getName()); } } catch (RepositoryException e) @@ -180,18 +179,23 @@ } @Override - public void orderBefore(AmetysObject siblingNode) throws AmetysRepositoryException + public void orderBefore(AmetysObject siblingObject) throws AmetysRepositoryException { + if (siblingObject != null && !(siblingObject instanceof JCRAmetysObject)) + { + throw new AmetysRepositoryException(String.format("Unable to order zone item '%s' before sibling '%s' (sibling is not a JCRAmetysObject)", this.getId(), siblingObject.getId())); + } + Node node = getNode(); - String name = ""; + Node siblingNode = siblingObject != null ? ((JCRAmetysObject) siblingObject).getNode() : null; + try { - name = siblingNode.getName(); - node.getParent().orderBefore(node.getName(), name); + node.getParent().orderBefore(node.getName() + "[" + node.getIndex() + "]", siblingNode != null ? siblingNode.getName() + "[" + siblingNode.getIndex() + "]" : null); } catch (RepositoryException e) { - throw new AmetysRepositoryException(String.format("Unable to order zone item '%s' before sibling '%s'", this, name), e); + throw new AmetysRepositoryException(String.format("Unable to order zone item '%s' before sibling '%s'", this.getId(), siblingObject != null ? siblingObject.getId() : ""), e); } } Index: main/plugin-web/src/org/ametys/web/repository/page/actions/MoveIntoZoneItemAction.java =================================================================== --- main/plugin-web/src/org/ametys/web/repository/page/actions/MoveIntoZoneItemAction.java (revision 0) +++ main/plugin-web/src/org/ametys/web/repository/page/actions/MoveIntoZoneItemAction.java (revision 0) @@ -0,0 +1,131 @@ +/* + * Copyright 2010 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.web.repository.page.actions; + +import java.util.Map; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.SourceResolver; + +import org.ametys.plugins.repository.AmetysObjectIterable; +import org.ametys.runtime.right.RightsManager; +import org.ametys.runtime.right.RightsManager.RightResult; +import org.ametys.web.observation.AbstractNotifierAction; +import org.ametys.web.observation.Event; +import org.ametys.web.observation.ObservationConstants; +import org.ametys.web.repository.page.ModifiableZone; +import org.ametys.web.repository.page.ModifiableZoneItem; +import org.ametys.web.repository.page.Page; +import org.ametys.web.repository.page.Zone; +import org.ametys.web.repository.page.ZoneItem; + +/** + * This action removes a {@link ZoneItem} + */ +public class MoveIntoZoneItemAction extends AbstractNotifierAction +{ + /** The rights manager */ + protected RightsManager _rightsManager; + + @Override + public void service(ServiceManager serviceManager) throws ServiceException + { + super.service(serviceManager); + + _rightsManager = (RightsManager) manager.lookup(RightsManager.ROLE); + } + + @SuppressWarnings("unchecked") + @Override + public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception + { + Map jsParameters = (Map) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); + + String zoneItemId = (String) jsParameters.get("zoneItemId"); + + boolean up = "up".equalsIgnoreCase(parameters.getParameter("direction", "up")); + + String userName; + if (_isSuperUser()) + { + userName = ""; + } + else + { + userName = _getCurrentUser(); + } + + + ZoneItem zoneItem = _resolver.resolveById(zoneItemId); + Zone zone = zoneItem.getZone(); + Page page = zone.getPage(); + + if (!_isSuperUser() && _rightsManager.hasRight(userName, "Web_Rights_Page_OrganizeZoneItem", "/pages/" + page.getSitemapName() + "/" + page.getPathInSitemap()) != RightResult.RIGHT_OK) + { + throw new IllegalArgumentException("User '" + userName + "' tryed without convinient privileges to move zone item '" + zoneItemId + "' to the zone '" + zone.getName() + "' of the page '" + page.getId() + "' !"); + } + else if (zoneItem == null) + { + throw new IllegalArgumentException("User '" + userName + "' tryed to move unexisting zone item '" + zoneItemId + "' to the zone '" + zone.getName() + "' of the page '" + page.getId() + "' !"); + } + else if (!(zone instanceof ModifiableZone)) + { + throw new IllegalArgumentException("User '" + userName + "' tryed to move zone item '" + zoneItemId + "' to the zone '" + zone.getName() + "' of the page '" + page.getId() + "' but this zone is not modifiable !"); + } + else if (!(zoneItem instanceof ModifiableZoneItem)) + { + throw new IllegalArgumentException("User '" + userName + "' tryed to move zone item '" + zoneItemId + "' to the zone '" + zone.getName() + "' of the page '" + page.getId() + "' but this zone item is not modifiable !"); + } + + ZoneItem preceding = null; + + AmetysObjectIterable ziI = zone.getZoneItems(); + while (ziI.hasNext()) + { + ZoneItem zi = ziI.next(); + if (zi.getId().equals(zoneItemId)) + { + if (up && preceding != null) + { + ((ModifiableZoneItem) zoneItem).orderBefore(preceding); + break; + } + else if (!up && ziI.hasNext()) + { + ziI.next(); + ((ModifiableZoneItem) zoneItem).orderBefore(ziI.hasNext() ? ziI.next() : null); + break; + } + } + + preceding = zi; + } + + if (page.getSitemap().needsSave()) + { + page.getSitemap().saveChanges(); + } + + _observationManager.notify(new Event(_getCurrentUser(), ObservationConstants.ZONEITEM_MOVED, page, new String[]{zoneItemId})); + + return EMPTY_MAP; + } + +} Index: main/plugin-web/src/org/ametys/web/repository/page/actions/MoveZoneItemAction.java =================================================================== --- main/plugin-web/src/org/ametys/web/repository/page/actions/MoveZoneItemAction.java (revision 0) +++ main/plugin-web/src/org/ametys/web/repository/page/actions/MoveZoneItemAction.java (revision 0) @@ -0,0 +1,113 @@ +/* + * Copyright 2010 Anyware Services + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ametys.web.repository.page.actions; + +import java.util.Map; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.SourceResolver; + +import org.ametys.runtime.right.RightsManager; +import org.ametys.runtime.right.RightsManager.RightResult; +import org.ametys.web.observation.AbstractNotifierAction; +import org.ametys.web.observation.Event; +import org.ametys.web.observation.ObservationConstants; +import org.ametys.web.repository.page.ModifiableZone; +import org.ametys.web.repository.page.ModifiableZoneItem; +import org.ametys.web.repository.page.Page; +import org.ametys.web.repository.page.Zone; +import org.ametys.web.repository.page.ZoneItem; +import org.ametys.web.repository.sitemap.Sitemap; + +/** + * This action removes a {@link ZoneItem} + */ +public class MoveZoneItemAction extends AbstractNotifierAction +{ + /** The rights manager */ + protected RightsManager _rightsManager; + + @Override + public void service(ServiceManager serviceManager) throws ServiceException + { + super.service(serviceManager); + + _rightsManager = (RightsManager) manager.lookup(RightsManager.ROLE); + } + + @SuppressWarnings("unchecked") + @Override + public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception + { + Map jsParameters = (Map) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); + + String zoneItemId = (String) jsParameters.get("zoneItemId"); + String zoneName = (String) jsParameters.get("zoneName"); + String pageId = (String) jsParameters.get("pageId"); + + String userName; + if (_isSuperUser()) + { + userName = ""; + } + else + { + userName = _getCurrentUser(); + } + + + Page page = _resolver.resolveById(pageId); + Zone zone = page.getZone(zoneName); + ZoneItem zoneItem = _resolver.resolveById(zoneItemId); + + if (!_isSuperUser() && _rightsManager.hasRight(userName, "Web_Rights_Page_OrganizeZoneItem", "/pages/" + page.getSitemapName() + "/" + page.getPathInSitemap()) != RightResult.RIGHT_OK) + { + throw new IllegalArgumentException("User '" + userName + "' tryed without convinient privileges to move zone item '" + zoneItemId + "' to the zone '" + zoneName + "' of the page '" + pageId + "' !"); + } + else if (zoneItem == null) + { + throw new IllegalArgumentException("User '" + userName + "' tryed to move unexisting zone item '" + zoneItemId + "' to the zone '" + zoneName + "' of the page '" + pageId + "' !"); + } + else if (zone == null) + { + throw new IllegalArgumentException("User '" + userName + "' tryed to move zone item '" + zoneItemId + "' to an unexisting zone '" + zoneName + "' of the page '" + pageId + "' !"); + } + else if (!(zone instanceof ModifiableZone)) + { + throw new IllegalArgumentException("User '" + userName + "' tryed to move zone item '" + zoneItemId + "' to the zone '" + zoneName + "' of the page '" + pageId + "' but this zone is not modifiable !"); + } + else if (!(zoneItem instanceof ModifiableZoneItem)) + { + throw new IllegalArgumentException("User '" + userName + "' tryed to move zone item '" + zoneItemId + "' to the zone '" + zoneName + "' of the page '" + pageId + "' but this zone item is not modifiable !"); + } + + ((ModifiableZoneItem) zoneItem).moveTo(zone, false); + Sitemap sitemap = zoneItem.getZone().getPage().getSitemap(); + if (sitemap.needsSave()) + { + sitemap.saveChanges(); + } + + _observationManager.notify(new Event(_getCurrentUser(), ObservationConstants.ZONEITEM_MOVED, page, new String[]{zoneItemId})); + + return EMPTY_MAP; + } + +} Index: main/plugin-web/src/org/ametys/web/repository/page/actions/ServiceAffectAction.java =================================================================== --- main/plugin-web/src/org/ametys/web/repository/page/actions/ServiceAffectAction.java (revision 6976) +++ main/plugin-web/src/org/ametys/web/repository/page/actions/ServiceAffectAction.java (working copy) @@ -124,7 +124,7 @@ ((JCRAmetysObject) page).getNode().save(); - _observationManager.notify(new Event(_getCurrentUser(), ObservationConstants.ZONEITEM_ADDED, page)); + _observationManager.notify(new Event(_getCurrentUser(), ObservationConstants.ZONEITEM_MOVED, page)); } catch (UnknownAmetysObjectException e) { Index: main/plugin-web/src/org/ametys/web/cache/InvalidateCacheOnPageContentChangeObserver.java =================================================================== --- main/plugin-web/src/org/ametys/web/cache/InvalidateCacheOnPageContentChangeObserver.java (revision 6976) +++ main/plugin-web/src/org/ametys/web/cache/InvalidateCacheOnPageContentChangeObserver.java (working copy) @@ -33,7 +33,8 @@ @Override public boolean supports(Event event) { - return event.getId().equals(ObservationConstants.ZONEITEM_ADDED) + return event.getId().equals(ObservationConstants.ZONEITEM_ADDED) + || event.getId().equals(ObservationConstants.ZONEITEM_MOVED) || event.getId().equals(ObservationConstants.ZONEITEM_DELETED); } Index: main/plugin-web/i18n/messages_en.xml =================================================================== --- main/plugin-web/i18n/messages_en.xml (revision 6976) +++ main/plugin-web/i18n/messages_en.xml (working copy) @@ -47,6 +47,8 @@ Create and add service to a zone in pages Service configuration Update the configuration of an existing service + Re-organize items in page areas + Re-organize contents or services in the page (moving in the same area or in another area) Delete an item in page areas Delete a content or a service previously added to an area Blank page @@ -651,8 +653,21 @@ Insert an existing content ... Unable to insert content. + Move up item + This action move up the selected content or service + This button is disabled because any content or service is selected. + This button is disabled because your rights are insufficient. + This button is disabled because the properties of the selected content or service do not allow to move it + Move down item + This action move down the selected content or service + This button is disabled because any content or service is selected. + This button is disabled because your rights are insufficient. + This button is disabled because the properties of the selected content or service do not allow to move it + Unable to move the content or the service. Please reload the page before proceding. + Incorrect selection + Selection should be a content or a service. Delete item - Using this action delete selected content or service + Use this action to delete the selected content or service This button is disabled because any content or service is selected. This button is disabled because your rights are insufficient. This button is disabled because the properties of the selected content or service do not allow to delete it Index: main/plugin-web/i18n/messages_fr.xml =================================================================== --- main/plugin-web/i18n/messages_fr.xml (revision 6976) +++ main/plugin-web/i18n/messages_fr.xml (working copy) @@ -47,6 +47,8 @@ >Autorise à ajouter un service à une zone d'une page Paramétrer un service Autorise la modification des paramètres d'un service + Réorganiser les élements des zones + Autorise à réorganiser les contenus ou les services dans la page (déplacement dans la zone ou d'une zone à l'autre) Supprimer un élement d'une zone Autorise à supprimer un contenu ou un service Page vierge @@ -650,6 +652,19 @@ Insérer un contenu existant ... L'insertion du contenu a échoué. + Déplacer vers le haut + Ce bouton permet de déplacer vers le haut le contenu ou service sélectionné + Ce bouton est désactivé car aucun contenu ou service n'est sélectionné. + Ce bouton est désactivé car vos droits sont insuffisants. + Ce bouton est désactivé car les propriétés du contenu ou service sélectionné ne permettent pas de le déplacer. + Déplacer vers le bas + Ce bouton permet de déplacer vers le bas le contenu ou service sélectionné + Ce bouton est désactivé car aucun contenu ou service n'est sélectionné. + Ce bouton est désactivé car vos droits sont insuffisants. + Ce bouton est désactivé car les propriétés du contenu ou service sélectionné ne permettent pas de le déplacer. + Le déplacement du contenu / service a échoué. Veuillez recharger la page avant de continuer. + Selection courante incorrecte + La sélection courante doit être la zone de contenu ou de service. Supprimer l'élément Ce bouton permet de supprimer le contenu ou service sélectionné Ce bouton est désactivé car aucun contenu ou service n'est sélectionné. @@ -657,7 +672,7 @@ Ce bouton est désactivé car les propriétés du contenu ou service sélectionné ne permettent pas de le supprimer. Etes-vous sûr de vouloir supprimer ce contenu ou service ?<br/>Cette action ne pourra être annulée. La suppression du contenu /service a échoué. - Selection courrant incorrecte + Selection courante incorrecte La sélection courante doit être la zone de contenu ou de service. Index: main/plugin-web/sitemap.xmap =================================================================== --- main/plugin-web/sitemap.xmap (revision 6976) +++ main/plugin-web/sitemap.xmap (working copy) @@ -125,6 +125,8 @@ + + @@ -591,6 +593,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +