diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index e0e21d9a69..733a3001e9 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -13,6 +13,7 @@ checkinfile_description=Check in your working copy for other team members to wor checkoutfilelink_description=Edit the checked out file, undo the check out or carry on working. checkoutfile_description=Enter information about the check out. documentdetails_description=View the details about the content. +linkdetails_description=View the details about the link object. previewdocument_description=Preview the content or space within a Template. spacedetails_description=View the details about the space. undocheckoutfile_description=Cancel the check out of a document and discard any changes. @@ -30,6 +31,7 @@ editdocument_description=Modify the document properties then click OK. editcategory_description=Set the category for the document then click OK. editworkflow_description=Modify the simple workflow properties then click OK. editspace_description=Modify the space properties then click OK. +editlink_description=Modify the link object properties then click OK. newspace_description=Enter information about the new space then click Create Space. space_rules_description=This view shows you all the rules to be applied to content in this space. warning_inline=This is only recommended for HTML or plain text documents. @@ -168,6 +170,8 @@ security=Security all_formats=All Formats rules_count=Number of rules applied to this Space working_copy_document=Working Copy +copy_of=Copy of +link_to=Link to # Properties username=User Name @@ -497,7 +501,9 @@ allow_versioning=Allow Versioning version_history=Version History version=Version document_properties=Document Properties +link_properties=Link Properties other_properties=Other Properties +link_destination=Link Destination no_other_properties=This document does not have any other properties to show. modify_categories_of=Modify categories of space_props=Space Properties @@ -785,6 +791,7 @@ title_file_details=Document Details title_file_preview=Preview In Template title_edit_categories=Edit Categories title_edit_doc_props=Edit Document Properties +title_edit_link_props=Edit Link Properties title_edit_file=Edit File title_edit_html_inline=Edit HTML File Inline title_edit_text_inline=Edit Text File Inline diff --git a/config/alfresco/web-client-config-actions.xml b/config/alfresco/web-client-config-actions.xml index d2e95f1ab9..5978b6e3a4 100644 --- a/config/alfresco/web-client-config-actions.xml +++ b/config/alfresco/web-client-config-actions.xml @@ -261,7 +261,7 @@ #{ClipboardBean.cutNode} #{actionContext.id} - #{NavigationBean.currentNodeId} + @@ -272,12 +272,12 @@ #{ClipboardBean.copyNode} #{actionContext.id} - #{NavigationBean.currentNodeId} + - + - + @@ -566,6 +566,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/web-client-config-forum-actions.xml b/config/alfresco/web-client-config-forum-actions.xml index 3a5449a514..b43f12eefc 100644 --- a/config/alfresco/web-client-config-forum-actions.xml +++ b/config/alfresco/web-client-config-forum-actions.xml @@ -269,6 +269,9 @@ + + + @@ -277,6 +280,7 @@ + @@ -285,6 +289,7 @@ + diff --git a/config/alfresco/web-client-config-navigation.xml b/config/alfresco/web-client-config-navigation.xml index 0222671006..c340a99c71 100644 --- a/config/alfresco/web-client-config-navigation.xml +++ b/config/alfresco/web-client-config-navigation.xml @@ -26,5 +26,23 @@ - + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/web-client-config-properties.xml b/config/alfresco/web-client-config-properties.xml index ad1adaf4c3..745f3ab583 100644 --- a/config/alfresco/web-client-config-properties.xml +++ b/config/alfresco/web-client-config-properties.xml @@ -44,6 +44,18 @@ + + + + + + + + + + + + diff --git a/source/java/org/alfresco/web/action/evaluator/CheckoutDocEvaluator.java b/source/java/org/alfresco/web/action/evaluator/CheckoutDocEvaluator.java index d03ce52cf6..adb9346b4a 100644 --- a/source/java/org/alfresco/web/action/evaluator/CheckoutDocEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/CheckoutDocEvaluator.java @@ -16,10 +16,14 @@ */ package org.alfresco.web.action.evaluator; +import javax.faces.context.FacesContext; + import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.web.action.ActionEvaluator; import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; /** * UI Action Evaluator - Checkout document. @@ -33,9 +37,13 @@ public final class CheckoutDocEvaluator implements ActionEvaluator */ public boolean evaluate(Node node) { - return (node.hasPermission(PermissionService.CHECK_OUT) && + DictionaryService dd = Repository.getServiceRegistry( + FacesContext.getCurrentInstance()).getDictionaryService(); + + return dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT) && + ((node.hasPermission(PermissionService.CHECK_OUT) && (node.isLocked() == false && - node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)); + node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))); } } /* diff --git a/source/java/org/alfresco/web/action/evaluator/EditDocCIFSEvaluator.java b/source/java/org/alfresco/web/action/evaluator/EditDocCIFSEvaluator.java index 631d89ab93..11bd2e8156 100644 --- a/source/java/org/alfresco/web/action/evaluator/EditDocCIFSEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/EditDocCIFSEvaluator.java @@ -19,9 +19,11 @@ package org.alfresco.web.action.evaluator; import javax.faces.context.FacesContext; import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.web.action.ActionEvaluator; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; /** * UI Action Evaluator - Edit document via CIFS. @@ -36,19 +38,25 @@ public final class EditDocCIFSEvaluator implements ActionEvaluator public boolean evaluate(Node node) { FacesContext fc = FacesContext.getCurrentInstance(); + DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService(); + + boolean result = false; // if the node is inline editable, the default http behaviour should always be used - if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) == false && - "webdav".equals(Application.getClientConfig(fc).getEditLinkType())) + if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT)) { - if (node.isWorkingCopyOwner() == true || - (node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)) + if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) == false && + "webdav".equals(Application.getClientConfig(fc).getEditLinkType())) { - return true; + if (node.isWorkingCopyOwner() == true || + (node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)) + { + result = true; + } } } - return false; + return result; } } /* diff --git a/source/java/org/alfresco/web/action/evaluator/EditDocHttpEvaluator.java b/source/java/org/alfresco/web/action/evaluator/EditDocHttpEvaluator.java index b751209d4e..2ded8854fa 100644 --- a/source/java/org/alfresco/web/action/evaluator/EditDocHttpEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/EditDocHttpEvaluator.java @@ -19,9 +19,11 @@ package org.alfresco.web.action.evaluator; import javax.faces.context.FacesContext; import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.web.action.ActionEvaluator; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; /** * UI Action Evaluator - Edit document via HTTP or inline edit. @@ -36,20 +38,26 @@ public final class EditDocHttpEvaluator implements ActionEvaluator public boolean evaluate(Node node) { FacesContext fc = FacesContext.getCurrentInstance(); + DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService(); + + boolean result = false; // if the node is inline editable, the default http behaviour should // always be used otherwise the configured approach is used - if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) == true || - "http".equals(Application.getClientConfig(fc).getEditLinkType())) + if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT)) { - if (node.isWorkingCopyOwner() == true || - (node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)) + if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) == true || + "http".equals(Application.getClientConfig(fc).getEditLinkType())) { - return true; + if (node.isWorkingCopyOwner() == true || + (node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)) + { + result = true; + } } } - return false; + return result; } } /* diff --git a/source/java/org/alfresco/web/action/evaluator/EditDocWebDavEvaluator.java b/source/java/org/alfresco/web/action/evaluator/EditDocWebDavEvaluator.java index bd3dc04113..0575609f19 100644 --- a/source/java/org/alfresco/web/action/evaluator/EditDocWebDavEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/EditDocWebDavEvaluator.java @@ -19,9 +19,11 @@ package org.alfresco.web.action.evaluator; import javax.faces.context.FacesContext; import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.web.action.ActionEvaluator; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; /** * UI Action Evaluator - Edit document via Webdav. @@ -36,19 +38,25 @@ public final class EditDocWebDavEvaluator implements ActionEvaluator public boolean evaluate(Node node) { FacesContext fc = FacesContext.getCurrentInstance(); + DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService(); + + boolean result = false; // if the node is inline editable, the default http behaviour should always be used - if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) == false && - "cifs".equals(Application.getClientConfig(fc).getEditLinkType())) + if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT)) { - if (node.isWorkingCopyOwner() == true || - (node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)) + if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) == false && + "cifs".equals(Application.getClientConfig(fc).getEditLinkType())) { - return true; + if (node.isWorkingCopyOwner() == true || + (node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)) + { + result = true; + } } } - return false; + return result; } } /* diff --git a/source/java/org/alfresco/web/action/evaluator/UpdateDocEvaluator.java b/source/java/org/alfresco/web/action/evaluator/UpdateDocEvaluator.java index 74de8e5265..ffb9c74885 100644 --- a/source/java/org/alfresco/web/action/evaluator/UpdateDocEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/UpdateDocEvaluator.java @@ -16,9 +16,13 @@ */ package org.alfresco.web.action.evaluator; +import javax.faces.context.FacesContext; + import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.web.action.ActionEvaluator; import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; /** * UI Action Evaluator - Update document content. @@ -32,9 +36,13 @@ public final class UpdateDocEvaluator implements ActionEvaluator */ public boolean evaluate(Node node) { - return (node.isWorkingCopyOwner() == true || + DictionaryService dd = Repository.getServiceRegistry( + FacesContext.getCurrentInstance()).getDictionaryService(); + + return dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT) && + ((node.isWorkingCopyOwner() == true || (node.isLocked() == false && - node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false)); + node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))); } } /* diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index b3ebd6b384..b116b09018 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -424,11 +424,11 @@ public class BrowseBean implements IContextListener { // special properties to be used by the value binding components on the page node.addPropertyResolver("url", this.resolverUrl); + node.addPropertyResolver("webdavUrl", this.resolverWebdavUrl); + node.addPropertyResolver("cifsPath", this.resolverCifsPath); node.addPropertyResolver("fileType16", this.resolverFileType16); node.addPropertyResolver("fileType32", this.resolverFileType32); node.addPropertyResolver("size", this.resolverSize); - node.addPropertyResolver("webdavUrl", this.resolverWebdavUrl); - node.addPropertyResolver("cifsPath", this.resolverCifsPath); } @@ -557,35 +557,59 @@ public class BrowseBean implements IContextListener if (typeDef != null) { - // look for Space or File nodes + MapNode node = null; + + // look for Space folder node if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) == true && this.dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false) { // create our Node representation - MapNode node = new MapNode(nodeRef, this.nodeService, true); + node = new MapNode(nodeRef, this.nodeService, false); node.addPropertyResolver("icon", this.resolverSpaceIcon); node.addPropertyResolver("smallIcon", this.resolverSmallIcon); - for (NodeEventListener listener : getNodeEventListeners()) - { - listener.created(node, type); - } - this.containerNodes.add(node); } + // look for File content node else if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) { // create our Node representation - MapNode node = new MapNode(nodeRef, this.nodeService, true); - + node = new MapNode(nodeRef, this.nodeService, false); setupCommonBindingProperties(node); + this.contentNodes.add(node); + } + // look for File Link object node + else if (ContentModel.TYPE_FILELINK.equals(type)) + { + // create our File Link Node representation + node = new MapNode(nodeRef, this.nodeService, false); + node.addPropertyResolver("url", this.resolverLinkUrl); + node.addPropertyResolver("webdavUrl", this.resolverLinkWebdavUrl); + node.addPropertyResolver("cifsPath", this.resolverLinkCifsPath); + node.addPropertyResolver("fileType16", this.resolverFileType16); + node.addPropertyResolver("fileType32", this.resolverFileType32); + node.addPropertyResolver("size", this.resolverSize); + + this.contentNodes.add(node); + } + else if (ContentModel.TYPE_FOLDERLINK.equals(type)) + { + // create our Folder Link Node representation + node = new MapNode(nodeRef, this.nodeService, false); + node.addPropertyResolver("icon", this.resolverSpaceIcon); + node.addPropertyResolver("smallIcon", this.resolverSmallIcon); + + this.containerNodes.add(node); + } + + // inform any listeners that a Node wrapper has been created + if (node != null) + { for (NodeEventListener listener : getNodeEventListeners()) { listener.created(node, type); } - - this.contentNodes.add(node); } } else @@ -680,41 +704,69 @@ public class BrowseBean implements IContextListener if (typeDef != null) { + MapNode node = null; + // look for Space or File nodes if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) && this.dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false) { // create our Node representation - MapNode node = new MapNode(nodeRef, this.nodeService, true); + node = new MapNode(nodeRef, this.nodeService, false); node.addPropertyResolver("path", this.resolverPath); node.addPropertyResolver("displayPath", this.resolverDisplayPath); node.addPropertyResolver("icon", this.resolverSpaceIcon); node.addPropertyResolver("smallIcon", this.resolverSmallIcon); - for (NodeEventListener listener : getNodeEventListeners()) - { - listener.created(node, type); - } - this.containerNodes.add(node); } else if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) { // create our Node representation - MapNode node = new MapNode(nodeRef, this.nodeService, true); + node = new MapNode(nodeRef, this.nodeService, false); setupCommonBindingProperties(node); node.addPropertyResolver("path", this.resolverPath); node.addPropertyResolver("displayPath", this.resolverDisplayPath); + this.contentNodes.add(node); + } + // look for File Link object node + else if (ContentModel.TYPE_FILELINK.equals(type)) + { + // create our File Link Node representation + node = new MapNode(nodeRef, this.nodeService, false); + node.addPropertyResolver("url", this.resolverLinkUrl); + node.addPropertyResolver("webdavUrl", this.resolverLinkWebdavUrl); + node.addPropertyResolver("cifsPath", this.resolverLinkCifsPath); + node.addPropertyResolver("fileType16", this.resolverFileType16); + node.addPropertyResolver("fileType32", this.resolverFileType32); + node.addPropertyResolver("size", this.resolverSize); + node.addPropertyResolver("path", this.resolverPath); + node.addPropertyResolver("displayPath", this.resolverDisplayPath); + + this.contentNodes.add(node); + } + else if (ContentModel.TYPE_FOLDERLINK.equals(type)) + { + // create our Folder Link Node representation + node = new MapNode(nodeRef, this.nodeService, false); + node.addPropertyResolver("icon", this.resolverSpaceIcon); + node.addPropertyResolver("smallIcon", this.resolverSmallIcon); + node.addPropertyResolver("path", this.resolverPath); + node.addPropertyResolver("displayPath", this.resolverDisplayPath); + + this.containerNodes.add(node); + } + + // inform any listeners that a Node wrapper has been created + if (node != null) + { for (NodeEventListener listener : getNodeEventListeners()) { listener.created(node, type); } - - this.contentNodes.add(node); } } else @@ -794,6 +846,36 @@ public class BrowseBean implements IContextListener } }; + public NodePropertyResolver resolverLinkDownload = new NodePropertyResolver() { + public Object get(Node node) { + NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); + String destName = Repository.getNameForNode(nodeService, destRef); + return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), destName); + } + }; + + public NodePropertyResolver resolverLinkUrl = new NodePropertyResolver() { + public Object get(Node node) { + NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); + String destName = Repository.getNameForNode(nodeService, destRef); + return DownloadContentServlet.generateBrowserURL(destRef, destName); + } + }; + + public NodePropertyResolver resolverLinkWebdavUrl = new NodePropertyResolver() { + public Object get(Node node) { + NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); + return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.WEBDAV); + } + }; + + public NodePropertyResolver resolverLinkCifsPath = new NodePropertyResolver() { + public Object get(Node node) { + NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); + return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.CIFS); + } + }; + public NodePropertyResolver resolverFileType16 = new NodePropertyResolver() { public Object get(Node node) { return Utils.getFileTypeImage(node.getName(), true); @@ -845,7 +927,7 @@ public class BrowseBean implements IContextListener public NodePropertyResolver resolverSize = new NodePropertyResolver() { public Object get(Node node) { ContentData content = (ContentData)node.getProperties().get(ContentModel.PROP_CONTENT); - return (content != null ? new Long(content.getSize()) : null); + return (content != null ? new Long(content.getSize()) : 0L); } }; @@ -889,6 +971,13 @@ public class BrowseBean implements IContextListener try { NodeRef ref = new NodeRef(Repository.getStoreRef(), id); + + // handle special folder link node case + if (ContentModel.TYPE_FOLDERLINK.equals(this.nodeService.getType(ref))) + { + ref = (NodeRef)this.nodeService.getProperty(ref, ContentModel.PROP_LINK_DESTINATION); + } + clickSpace(ref); } catch (InvalidNodeRefException refErr) @@ -1096,7 +1185,14 @@ public class BrowseBean implements IContextListener Node node = new Node(ref); // store the URL to for downloading the content - node.addPropertyResolver("url", this.resolverDownload); + if (ContentModel.TYPE_FILELINK.equals(node.getType())) + { + node.addPropertyResolver("url", this.resolverLinkDownload); + } + else + { + node.addPropertyResolver("url", this.resolverDownload); + } node.addPropertyResolver("fileType32", this.resolverFileType32); node.addPropertyResolver("mimetype", this.resolverMimetype); node.addPropertyResolver("size", this.resolverSize); diff --git a/source/java/org/alfresco/web/bean/DocumentDetailsBean.java b/source/java/org/alfresco/web/bean/DocumentDetailsBean.java index f4726d37e2..cd92caaa3d 100644 --- a/source/java/org/alfresco/web/bean/DocumentDetailsBean.java +++ b/source/java/org/alfresco/web/bean/DocumentDetailsBean.java @@ -156,7 +156,8 @@ public class DocumentDetailsBean */ public String getBrowserUrl() { - return Utils.generateURL(FacesContext.getCurrentInstance(), getDocument(), URLMode.HTTP_INLINE); + Node doc = getLinkResolvedDocument(); + return Utils.generateURL(FacesContext.getCurrentInstance(), doc, URLMode.HTTP_INLINE); } /** @@ -166,7 +167,8 @@ public class DocumentDetailsBean */ public String getDownloadUrl() { - return Utils.generateURL(FacesContext.getCurrentInstance(), getDocument(), URLMode.HTTP_DOWNLOAD); + Node doc = getLinkResolvedDocument(); + return Utils.generateURL(FacesContext.getCurrentInstance(), doc, URLMode.HTTP_DOWNLOAD); } /** @@ -176,7 +178,19 @@ public class DocumentDetailsBean */ public String getWebdavUrl() { - return Utils.generateURL(FacesContext.getCurrentInstance(), getDocument(), URLMode.WEBDAV); + Node doc = getLinkResolvedDocument(); + return Utils.generateURL(FacesContext.getCurrentInstance(), doc, URLMode.WEBDAV); + } + + /** + * Returns the CIFS path for the current document + * + * @return The CIFS path + */ + public String getCifsPath() + { + Node doc = getLinkResolvedDocument(); + return Utils.generateURL(FacesContext.getCurrentInstance(), doc, URLMode.CIFS); } /** @@ -190,13 +204,19 @@ public class DocumentDetailsBean } /** - * Returns the CIFS path for the current document + * Resolve the actual document Node from any Link object that may be proxying it * - * @return The CIFS path + * @return current document Node or document Node resolved from any Link object */ - public String getCifsPath() + private Node getLinkResolvedDocument() { - return Utils.generateURL(FacesContext.getCurrentInstance(), getDocument(), URLMode.CIFS); + Node document = getDocument(); + if (ContentModel.TYPE_FILELINK.equals(document.getType())) + { + NodeRef destRef = (NodeRef)document.getProperties().get(ContentModel.PROP_LINK_DESTINATION); + document = new Node(destRef); + } + return document; } /** @@ -1075,19 +1095,21 @@ public class DocumentDetailsBean */ public void takeOwnership(ActionEvent event) { + FacesContext fc = FacesContext.getCurrentInstance(); + UserTransaction tx = null; try { - tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); + tx = Repository.getUserTransaction(fc); tx.begin(); this.ownableService.takeOwnership(getDocument().getNodeRef()); - FacesContext context = FacesContext.getCurrentInstance(); - String msg = Application.getMessage(context, MSG_SUCCESS_OWNERSHIP); + String msg = Application.getMessage(fc, MSG_SUCCESS_OWNERSHIP); FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); - context.addMessage("document-details:document-props", facesMsg); + String formId = Utils.getParentForm(fc, event.getComponent()).getClientId(fc); + fc.addMessage(formId + ":document-props", facesMsg); // commit the transaction tx.commit(); @@ -1097,7 +1119,7 @@ public class DocumentDetailsBean // rollback the transaction try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} Utils.addErrorMessage(MessageFormat.format(Application.getMessage( - FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), e.getMessage()), e); + fc, Repository.ERROR_GENERIC), e.getMessage()), e); } } @@ -1125,7 +1147,7 @@ public class DocumentDetailsBean */ public Map getTemplateModel() { - HashMap model = new HashMap(3, 1.0f); + HashMap model = new HashMap(2, 1.0f); FacesContext fc = FacesContext.getCurrentInstance(); TemplateNode documentNode = new TemplateNode(getDocument().getNodeRef(), diff --git a/source/java/org/alfresco/web/bean/LinkPropertiesBean.java b/source/java/org/alfresco/web/bean/LinkPropertiesBean.java new file mode 100644 index 0000000000..6f28531414 --- /dev/null +++ b/source/java/org/alfresco/web/bean/LinkPropertiesBean.java @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * 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.alfresco.web.bean; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.Iterator; +import java.util.Map; + +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; +import javax.transaction.UserTransaction; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.Utils; + +/** + * Backing bean for the edit link properties dialog + * + * @author kevinr + */ +public class LinkPropertiesBean +{ + protected NodeService nodeService; + protected DictionaryService dictionaryService; + protected BrowseBean browseBean; + protected NavigationBean navigator; + private Node editableNode; + + /** + * Returns the node being edited + * + * @return The node being edited + */ + public Node getEditableNode() + { + return this.editableNode; + } + + /** + * Event handler called to setup the link object for property editing + * + * @param event The event + */ + public void setupFileLinkForAction(ActionEvent event) + { + this.editableNode = new Node(this.browseBean.getDocument().getNodeRef()); + } + + /** + * Event handler called to setup the link object for property editing + * + * @param event The event + */ + public void setupFolderLinkForAction(ActionEvent event) + { + this.editableNode = new Node(this.browseBean.getActionSpace().getNodeRef()); + } + + /** + * @return Human readable version of the Path to the destination object + */ + public String getDestinationPath() + { + NodeRef destRef = (NodeRef)this.editableNode.getProperties().get(ContentModel.PROP_LINK_DESTINATION); + return Repository.getNamePath( + this.nodeService, this.nodeService.getPath(destRef), null, "/", null); + } + + /** + * Event handler used to save the edited properties back to the repository + * + * @return The outcome + */ + public String save() + { + String outcome = "cancelEdit"; + + // setup the dispatch context as it is required for correct cancel/finish back to link dialog + this.navigator.setupDispatchContext(this.editableNode); + + UserTransaction tx = null; + + try + { + tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); + tx.begin(); + + NodeRef nodeRef = this.editableNode.getNodeRef(); + Map props = this.editableNode.getProperties(); + + // get the name and move the node as necessary + String name = (String)props.get(ContentModel.PROP_NAME); + //if (name != null) + //{ + // fileFolderService.rename(nodeRef, name); + //} + + Map properties = this.nodeService.getProperties(nodeRef); + // we need to put all the properties from the editable bag back into + // the format expected by the repository + + // deal with adding the "titled" aspect if required + String title = (String)props.get(ContentModel.PROP_TITLE); + String description = (String)props.get(ContentModel.PROP_DESCRIPTION); + if (title != null || description != null) + { + // add the aspect to be sure it's present + nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, null); + // other props will get added later in setProperties() + } + + // add the remaining properties + Iterator iterProps = props.keySet().iterator(); + while (iterProps.hasNext()) + { + String propName = iterProps.next(); + QName qname = QName.createQName(propName); + + // make sure the property is represented correctly + Serializable propValue = (Serializable)props.get(propName); + + // check for empty strings when using number types, set to null in this case + if ((propValue != null) && (propValue instanceof String) && + (propValue.toString().length() == 0)) + { + PropertyDefinition propDef = this.dictionaryService.getProperty(qname); + if (propDef != null) + { + if (propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) || + propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) || + propDef.getDataType().getName().equals(DataTypeDefinition.INT) || + propDef.getDataType().getName().equals(DataTypeDefinition.LONG)) + { + propValue = null; + } + } + } + + properties.put(qname, propValue); + } + + // send the properties back to the repository + this.nodeService.setProperties(nodeRef, properties); + + // commit the transaction + tx.commit(); + + // set the outcome to refresh + outcome = "finishEdit"; + + // reset any document held by the browse bean as it's just been updated + // if this is a space link then it doesn't matter anyway + this.browseBean.getDocument().reset(); + } + catch (InvalidNodeRefException err) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {this.browseBean.getDocument().getId()}) ); + + // this failure means the node no longer exists - we cannot show the doc properties screen + outcome = "browse"; + } + catch (Throwable e) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), e.getMessage()), e); + } + + return outcome; + } + + public String cancel() + { + // setup the dispatch context as it is required for correct cancel/finish back to link dialog + this.navigator.setupDispatchContext(this.editableNode); + + return "cancelEdit"; + } + + public Map getProperties() + { + return this.editableNode.getProperties(); + } + + /** + * @return Returns the nodeService. + */ + public NodeService getNodeService() + { + return this.nodeService; + } + + /** + * @param nodeService The nodeService to set. + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * Sets the DictionaryService to use when persisting metadata + * + * @param dictionaryService The DictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * @return The BrowseBean + */ + public BrowseBean getBrowseBean() + { + return this.browseBean; + } + + /** + * @param browseBean The BrowseBean to set. + */ + public void setBrowseBean(BrowseBean browseBean) + { + this.browseBean = browseBean; + } + + /** + * @param navigator The NavigationBean to set. + */ + public void setNavigator(NavigationBean navigator) + { + this.navigator = navigator; + } +} diff --git a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java index 70ead82fba..88a61b169c 100644 --- a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java +++ b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java @@ -155,7 +155,19 @@ public class SpaceDetailsBean */ public String getWebdavUrl() { - return Utils.generateURL(FacesContext.getCurrentInstance(), getSpace(), URLMode.WEBDAV); + Node space = getLinkResolvedSpace(); + return Utils.generateURL(FacesContext.getCurrentInstance(), space, URLMode.WEBDAV); + } + + /** + * Returns the CIFS path for the current space + * + * @return The CIFS path + */ + public String getCifsPath() + { + Node space = getLinkResolvedSpace(); + return Utils.generateURL(FacesContext.getCurrentInstance(), space, URLMode.CIFS); } /** @@ -169,13 +181,19 @@ public class SpaceDetailsBean } /** - * Returns the CIFS path for the current space + * Resolve the actual space Node from any Link object that may be proxying it * - * @return The CIFS path + * @return current space Node or space Node resolved from any Link object */ - public String getCifsPath() + private Node getLinkResolvedSpace() { - return Utils.generateURL(FacesContext.getCurrentInstance(), getSpace(), URLMode.CIFS); + Node space = getSpace(); + if (ContentModel.TYPE_FOLDERLINK.equals(space.getType())) + { + NodeRef destRef = (NodeRef)space.getProperties().get(ContentModel.PROP_LINK_DESTINATION); + space = new Node(destRef); + } + return space; } /** @@ -312,20 +330,22 @@ public class SpaceDetailsBean */ public void takeOwnership(ActionEvent event) { + FacesContext fc = FacesContext.getCurrentInstance(); + UserTransaction tx = null; try { - tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); + tx = Repository.getUserTransaction(fc); tx.begin(); this.ownableService.takeOwnership(getSpace().getNodeRef()); - FacesContext context = FacesContext.getCurrentInstance(); - String msg = Application.getMessage(context, MSG_SUCCESS_OWNERSHIP); + String msg = Application.getMessage(fc, MSG_SUCCESS_OWNERSHIP); FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); - context.addMessage("space-details:space-props", facesMsg); - + String formId = Utils.getParentForm(fc, event.getComponent()).getClientId(fc); + fc.addMessage(formId + ":space-props", facesMsg); + // commit the transaction tx.commit(); } @@ -334,7 +354,7 @@ public class SpaceDetailsBean // rollback the transaction try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} Utils.addErrorMessage(MessageFormat.format(Application.getMessage( - FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), e.getMessage()), e); + fc, Repository.ERROR_GENERIC), e.getMessage()), e); } } diff --git a/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java b/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java index 92d75275d0..54c505e206 100644 --- a/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java +++ b/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java @@ -16,8 +16,10 @@ */ package org.alfresco.web.bean.clipboard; +import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,13 +28,16 @@ import javax.faces.event.ActionEvent; import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.model.FileExistsException; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileNotFoundException; import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.CopyService; import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.bean.NavigationBean; @@ -67,6 +72,14 @@ public class ClipboardBean this.fileFolderService = fileFolderService; } + /** + * @param nodeOperationsService The NodeOperationsService to set. + */ + public void setNodeOperationsService(CopyService nodeOperationsService) + { + this.nodeOperationsService = nodeOperationsService; + } + /** * @param navigator The NavigationBean to set. */ @@ -218,48 +231,132 @@ public class ClipboardBean { NodeRef destRef = new NodeRef(Repository.getStoreRef(), this.navigator.getCurrentNodeId()); - // TODO: Should we use primary parent here? + DictionaryService dd = Repository.getServiceRegistry( + FacesContext.getCurrentInstance()).getDictionaryService(); + + // TODO: Should we be using primary parent here? // We are assuming that the item exists in only a single parent and that the source for // the clipboard operation (e.g. the source folder) is specifically that parent node. - // This does not allow for more than one possible parent node - or for linked objects! + // So does not allow for more than one possible parent node - or for linked objects! + // This code should be refactored to use a parent ID when appropriate. ChildAssociationRef assocRef = this.nodeService.getPrimaryParent(item.Node.getNodeRef()); - if (item.Mode == ClipboardStatus.COPY) + // initial name to attempt the copy of the item with + String name = item.Node.getName(); + + boolean operationComplete = false; + while (operationComplete == false) { - if (action == UIClipboardShelfItem.ACTION_PASTE_LINK) + try { - if (logger.isDebugEnabled()) - logger.debug("Attempting to link node ID: " + item.Node.getId() + " into node ID: " + destRef.getId()); - - // copy as link was specifically requested by the user - this.nodeService.addChild( - destRef, - item.Node.getNodeRef(), - ContentModel.ASSOC_CONTAINS, - assocRef.getQName()); - } - else - { - if (logger.isDebugEnabled()) - logger.debug("Attempting to copy node ID: " + item.Node.getId() + " into node ID: " + destRef.getId()); + if (item.Mode == ClipboardStatus.COPY) + { + if (action == UIClipboardShelfItem.ACTION_PASTE_LINK) + { + if (logger.isDebugEnabled()) + logger.debug("Attempting to link node ID: " + item.Node.getId() + " into node ID: " + destRef.getId()); + + // copy as link was specifically requested by the user + + // we create a special Link Object node that has a property to reference the original + // use FileFolderService to check if already exists as using nodeService directly here + String linkTo = Application.getMessage(FacesContext.getCurrentInstance(), MSG_LINK_TO); + + // create the node using the nodeService (can only use FileFolderService for content) + Map props = new HashMap(4, 1.0f); + String linkName = linkTo + ' ' + name; + props.put(ContentModel.PROP_NAME, linkName + ".lnk"); + props.put(ContentModel.PROP_LINK_DESTINATION, item.Node.getNodeRef()); + if (dd.isSubClass(item.Node.getType(), ContentModel.TYPE_CONTENT)) + { + // create File Link node + ChildAssociationRef childRef = this.nodeService.createNode( + destRef, + ContentModel.ASSOC_CONTAINS, + assocRef.getQName(), + ContentModel.TYPE_FILELINK, + props); - // call the node ops service to initiate the copy - this.fileFolderService.copy( - item.Node.getNodeRef(), - destRef, - null); // TODO: could add "Copy of ..." here if copy fails + // apply the titled aspect - title and description + Map titledProps = new HashMap(2, 1.0f); + titledProps.put(ContentModel.PROP_TITLE, linkName); + titledProps.put(ContentModel.PROP_DESCRIPTION, linkName); + this.nodeService.addAspect(childRef.getChildRef(), ContentModel.ASPECT_TITLED, titledProps); + } + else + { + // create Folder link node + ChildAssociationRef childRef = this.nodeService.createNode( + destRef, + ContentModel.ASSOC_CONTAINS, + assocRef.getQName(), + ContentModel.TYPE_FOLDERLINK, + props); + + // apply the uifacets aspect - icon, title and description props + Map uiFacetsProps = new HashMap(3, 1.0f); + uiFacetsProps.put(ContentModel.PROP_ICON, "space-icon-link"); + uiFacetsProps.put(ContentModel.PROP_TITLE, linkName); + uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, linkName); + this.nodeService.addAspect(childRef.getChildRef(), ContentModel.ASPECT_UIFACETS, uiFacetsProps); + } + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Attempting to copy node ID: " + item.Node.getId() + " into node ID: " + destRef.getId()); + + if (dd.isSubClass(item.Node.getType(), ContentModel.TYPE_CONTENT)) + { + // call the node ops service to initiate the copy + this.fileFolderService.copy( + item.Node.getNodeRef(), + destRef, + name); + } + else + { + this.nodeOperationsService.copy( + item.Node.getNodeRef(), + destRef, + ContentModel.ASSOC_CONTAINS, + assocRef.getQName(), + true); + } + } + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Attempting to move node ID: " + item.Node.getId() + " into node ID: " + destRef.getId()); + + if (dd.isSubClass(item.Node.getType(), ContentModel.TYPE_CONTENT)) + { + // move the node + this.fileFolderService.move( + item.Node.getNodeRef(), + destRef, + name); // TODO: could add "Copy of ..." here if move fails + } + else + { + // move the node + this.nodeService.moveNode( + item.Node.getNodeRef(), + destRef, + ContentModel.ASSOC_CONTAINS, + assocRef.getQName()); + } + } + + // if we get here without an exception, the clipboard operation was successful + operationComplete = true; + } + catch (FileExistsException fileExistsErr) + { + String copyOf = Application.getMessage(FacesContext.getCurrentInstance(), MSG_COPY_OF); + name = copyOf + ' ' + name; } - } - else - { - if (logger.isDebugEnabled()) - logger.debug("Attempting to move node ID: " + item.Node.getId() + " into node ID: " + destRef.getId()); - - // move the node - this.fileFolderService.move( - item.Node.getNodeRef(), - destRef, - null); // TODO: could add "Copy of ..." here if move fails } } @@ -308,7 +405,9 @@ public class ClipboardBean private static Log logger = LogFactory.getLog(ClipboardBean.class); /** I18N messages */ - private static final String MSG_ERROR_PASTE = "error_paste"; + private static final String MSG_ERROR_PASTE = "error_paste"; + private static final String MSG_COPY_OF = "copy_of"; + private static final String MSG_LINK_TO = "link_to"; /** The NodeService to be used by the bean */ protected NodeService nodeService; @@ -316,6 +415,9 @@ public class ClipboardBean /** The FileFolderService to be used by the bean */ protected FileFolderService fileFolderService; + /** The NodeOperationsService to be used by the bean */ + protected CopyService nodeOperationsService; + /** The NavigationBean reference */ protected NavigationBean navigator; diff --git a/source/java/org/alfresco/web/bean/repository/Repository.java b/source/java/org/alfresco/web/bean/repository/Repository.java index 357a221fb4..54d9ae2996 100644 --- a/source/java/org/alfresco/web/bean/repository/Repository.java +++ b/source/java/org/alfresco/web/bean/repository/Repository.java @@ -274,7 +274,10 @@ public final class Repository // ignore root node check if not passed in boolean foundRoot = (rootNode == null); - buf.append(prefix); + if (prefix != null) + { + buf.append(prefix); + } // skip first element as it represents repo root '/' for (int i=1; iimg tag */ - public static String buildImageTag(FacesContext context, String image, int width, int height, String alt, String onclick) + public static String buildImageTag(FacesContext context, String image, int width, int height, + String alt, String onclick) { return buildImageTag(context, image, width, height, alt, onclick, null); } @@ -684,7 +704,8 @@ public final class Utils * * @return Populated img tag */ - public static String buildImageTag(FacesContext context, String image, int width, int height, String alt, String onclick, String align) + public static String buildImageTag(FacesContext context, String image, int width, int height, + String alt, String onclick, String align) { StringBuilder buf = new StringBuilder(200); diff --git a/source/java/org/alfresco/web/ui/common/converter/DisplayPathConverter.java b/source/java/org/alfresco/web/ui/common/converter/DisplayPathConverter.java new file mode 100644 index 0000000000..3f7074b0ed --- /dev/null +++ b/source/java/org/alfresco/web/ui/common/converter/DisplayPathConverter.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * 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.alfresco.web.ui.common.converter; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.ConverterException; + +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.web.bean.repository.Repository; + +/** + * Converter class to convert a Path or NodeRef reference value (including null) into a human readable form. + * + * @author Kevin Roast + */ +public class DisplayPathConverter implements Converter +{ + /** + *

The standard converter id for this converter.

+ */ + public static final String CONVERTER_ID = "org.alfresco.faces.DisplayPathConverter"; + + /** + * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String) + */ + public Object getAsObject(FacesContext context, UIComponent component, String value) + throws ConverterException + { + return null; + } + + /** + * @see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object) + */ + public String getAsString(FacesContext context, UIComponent component, Object value) + throws ConverterException + { + String result = ""; + + if (value != null) + { + try + { + NodeService nodeService = Repository.getServiceRegistry(context).getNodeService(); + Path path = null; + if (value instanceof NodeRef) + { + path = nodeService.getPath((NodeRef)value); + } + else if (value instanceof Path) + { + path = (Path)value; + } + if (path != null) + { + result = Repository.getNamePath(nodeService, path, null, "/", null); + } + } + catch (AccessDeniedException accessErr) + { + // use default if this occurs + } + catch (InvalidNodeRefException nodeErr) + { + // use default if this occurs + } + } + + return result; + } +} diff --git a/source/java/org/alfresco/web/ui/repo/WebResources.java b/source/java/org/alfresco/web/ui/repo/WebResources.java index 322783c08e..5f2ad468ce 100644 --- a/source/java/org/alfresco/web/ui/repo/WebResources.java +++ b/source/java/org/alfresco/web/ui/repo/WebResources.java @@ -30,6 +30,7 @@ public class WebResources extends org.alfresco.web.ui.common.WebResources public static final String IMAGE_COPY = "/images/icons/copy.gif"; public static final String IMAGE_CUT = "/images/icons/cut.gif"; public static final String IMAGE_PASTE = "/images/icons/paste.gif"; + public static final String IMAGE_PASTE_LINK = "/images/icons/paste_link.gif"; public static final String IMAGE_LOCK = "/images/icons/locked.gif"; public static final String IMAGE_LOCK_OWNER = "/images/icons/locked_owner.gif"; public static final String IMAGE_PERSON = "/images/icons/person.gif"; diff --git a/source/java/org/alfresco/web/ui/repo/component/shelf/UIClipboardShelfItem.java b/source/java/org/alfresco/web/ui/repo/component/shelf/UIClipboardShelfItem.java index a278162063..cd82ec0969 100644 --- a/source/java/org/alfresco/web/ui/repo/component/shelf/UIClipboardShelfItem.java +++ b/source/java/org/alfresco/web/ui/repo/component/shelf/UIClipboardShelfItem.java @@ -184,7 +184,7 @@ public class UIClipboardShelfItem extends UIShelfItem } out.write(Utils.buildImageTag(context, icon, 16, 16, null, null, "absmiddle")); } - else if (dd.isSubClass(item.Node.getType(), ContentModel.TYPE_CONTENT)) + else { String image = Utils.getFileTypeImage(item.Node.getName(), true); out.write(Utils.buildImageTag(context, image, null, "absmiddle")); @@ -200,11 +200,11 @@ public class UIClipboardShelfItem extends UIShelfItem out.write(buildActionLink(ACTION_REMOVE_ITEM, i, bundle.getString(MSG_REMOVE_ITEM), WebResources.IMAGE_REMOVE)); out.write(" "); out.write(buildActionLink(ACTION_PASTE_ITEM, i, bundle.getString(MSG_PASTE_ITEM), WebResources.IMAGE_PASTE)); - //if (item.Mode == ClipboardStatus.COPY) - //{ - // out.write(" "); - // out.write(buildActionLink(ACTION_PASTE_LINK, i, bundle.getString(MSG_PASTE_LINK), WebResources.IMAGE_PASTE_LINK)); - //} + if (item.Mode == ClipboardStatus.COPY) + { + out.write(" "); + out.write(buildActionLink(ACTION_PASTE_LINK, i, bundle.getString(MSG_PASTE_LINK), WebResources.IMAGE_PASTE_LINK)); + } // end actions cell and end row out.write(""); diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index 8e48c1e589..2f69f31c4e 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -161,6 +161,10 @@ fileFolderService #{FileFolderService} + + nodeOperationsService + #{CopyService} + @@ -474,6 +478,31 @@ + + + The bean that backs up the Link Properties Dialog + + LinkPropertiesBean + org.alfresco.web.bean.LinkPropertiesBean + session + + nodeService + #{NodeService} + + + dictionaryService + #{DictionaryService} + + + browseBean + #{BrowseBean} + + + navigator + #{NavigationBean} + + + The bean that backs up the New Rule Wizard diff --git a/source/web/WEB-INF/faces-config-common.xml b/source/web/WEB-INF/faces-config-common.xml index a624e22c86..72020acd8b 100644 --- a/source/web/WEB-INF/faces-config-common.xml +++ b/source/web/WEB-INF/faces-config-common.xml @@ -161,6 +161,11 @@ org.alfresco.web.ui.common.converter.ByteSizeConverter + + org.alfresco.faces.DisplayPathConverter + org.alfresco.web.ui.common.converter.DisplayPathConverter + + diff --git a/source/web/WEB-INF/faces-config-navigation.xml b/source/web/WEB-INF/faces-config-navigation.xml index 491311aaf8..9853afe0b8 100644 --- a/source/web/WEB-INF/faces-config-navigation.xml +++ b/source/web/WEB-INF/faces-config-navigation.xml @@ -263,14 +263,6 @@ deleteSpace /jsp/dialog/delete-space.jsp - - nextItem - /jsp/dialog/space-details.jsp - - - previousItem - /jsp/dialog/space-details.jsp - import /jsp/dialog/import.jsp @@ -355,14 +347,6 @@ createAction /jsp/wizard/create-action/action.jsp - - nextItem - /jsp/dialog/document-details.jsp - - - previousItem - /jsp/dialog/document-details.jsp - previewContent /jsp/dialog/preview-file.jsp @@ -445,6 +429,53 @@ + + + /jsp/dialog/filelink-details.jsp + + editLinkProperties + /jsp/dialog/edit-link-properties.jsp + + + manageContentUsers + /jsp/roles/manage-content-users.jsp + + + deleteFile + /jsp/dialog/delete-file.jsp + + + + + + /jsp/dialog/spacelink-details.jsp + + editLinkProperties + /jsp/dialog/edit-link-properties.jsp + + + manageContentUsers + /jsp/roles/manage-content-users.jsp + + + deleteFile + /jsp/dialog/delete-file.jsp + + + + + + /jsp/dialog/edit-link-properties.jsp + + cancelEdit + /jsp/dialog/filelink-details.jsp + + + finishEdit + /jsp/dialog/filelink-details.jsp + + + /jsp/roles/manage-invited-users.jsp @@ -1115,42 +1146,6 @@ - - /jsp/forums/forums-details.jsp - - nextItem - /jsp/forums/forums-details.jsp - - - previousItem - /jsp/forums/forums-details.jsp - - - - - /jsp/forums/forum-details.jsp - - nextItem - /jsp/forums/forum-details.jsp - - - previousItem - /jsp/forums/forum-details.jsp - - - - - /jsp/forums/topic-details.jsp - - nextItem - /jsp/forums/topic-details.jsp - - - previousItem - /jsp/forums/topic-details.jsp - - - /jsp/forums/delete-forums.jsp diff --git a/source/web/css/main.css b/source/web/css/main.css index 55149a4e5a..c7b7b280ce 100644 --- a/source/web/css/main.css +++ b/source/web/css/main.css @@ -272,11 +272,13 @@ a.headbarLink .recordSetRow { background-color: #FFFFFF; + vertical-align: top; } .recordSetRowAlt { background-color: #DEE5EC; + vertical-align: top; } .recordSetHeader diff --git a/source/web/images/filetypes/lnk.gif b/source/web/images/filetypes/lnk.gif new file mode 100644 index 0000000000..5f92a961dc Binary files /dev/null and b/source/web/images/filetypes/lnk.gif differ diff --git a/source/web/images/filetypes/psd.gif b/source/web/images/filetypes/psd.gif new file mode 100644 index 0000000000..f5c02c3437 Binary files /dev/null and b/source/web/images/filetypes/psd.gif differ diff --git a/source/web/images/filetypes32/lnk.gif b/source/web/images/filetypes32/lnk.gif new file mode 100644 index 0000000000..1bbc6a476b Binary files /dev/null and b/source/web/images/filetypes32/lnk.gif differ diff --git a/source/web/images/filetypes32/psd.gif b/source/web/images/filetypes32/psd.gif new file mode 100644 index 0000000000..769a9164b2 Binary files /dev/null and b/source/web/images/filetypes32/psd.gif differ diff --git a/source/web/images/icons/paste_link.gif b/source/web/images/icons/paste_link.gif new file mode 100644 index 0000000000..5f92a961dc Binary files /dev/null and b/source/web/images/icons/paste_link.gif differ diff --git a/source/web/images/icons/space-icon-link-16.gif b/source/web/images/icons/space-icon-link-16.gif new file mode 100644 index 0000000000..acb4beac34 Binary files /dev/null and b/source/web/images/icons/space-icon-link-16.gif differ diff --git a/source/web/images/icons/space-icon-link.gif b/source/web/images/icons/space-icon-link.gif new file mode 100644 index 0000000000..60dfc1d99a Binary files /dev/null and b/source/web/images/icons/space-icon-link.gif differ diff --git a/source/web/jsp/dialog/document-details.jsp b/source/web/jsp/dialog/document-details.jsp index 3f94080497..3bf479f87c 100644 --- a/source/web/jsp/dialog/document-details.jsp +++ b/source/web/jsp/dialog/document-details.jsp @@ -88,11 +88,11 @@ <%-- Navigation --%> - + - + @@ -218,8 +218,7 @@ + columns="1" mode="view" labelStyleClass="propertiesLabel" externalConfig="true" /> @@ -240,8 +239,7 @@ - + - + +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + <%-- Main outer table --%> + + + <%-- Title bar --%> + + + + + <%-- Main area --%> + + <%-- Shelf --%> + + + <%-- Work Area --%> + + +
+ <%@ include file="../parts/titlebar.jsp" %> +
+ <%@ include file="../parts/shelf.jsp" %> + + + <%-- Breadcrumb --%> + <%@ include file="../parts/breadcrumb.jsp" %> + + <%-- Status and Actions --%> + + + + + + + <%-- separator row with gradient shadow --%> + + + + + + + <%-- Details --%> + + + + + + + <%-- Error Messages --%> + + + + + + + <%-- separator row with bottom panel graphics --%> + + + + + + +
+ + <%-- Status and Actions inner contents table --%> + <%-- Generally this consists of an icon, textual summary and actions for the current object --%> + + + + + +
+ +
''
+
+
+ +
+ + + + + + +
+ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "white", "white"); %> + + + + + + + + + + + + + + + + + + + + + +
: +  * +
: + +
: + +
: + +
+ <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %> +
+ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %> + + + + + + + +
+ +
+ +
+ <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %> +
+
+ <%-- messages tag to show messages not handled by other specific message tags --%> + +
+
+ +
+ +
+ +
\ No newline at end of file diff --git a/source/web/jsp/dialog/filelink-details.jsp b/source/web/jsp/dialog/filelink-details.jsp new file mode 100644 index 0000000000..c9e5fc630f --- /dev/null +++ b/source/web/jsp/dialog/filelink-details.jsp @@ -0,0 +1,227 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + 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. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="64kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + <%-- Main outer table --%> + + + <%-- Title bar --%> + + + + + <%-- Main area --%> + + <%-- Shelf --%> + + + <%-- Work Area --%> + + +
+ <%@ include file="../parts/titlebar.jsp" %> +
+ <%@ include file="../parts/shelf.jsp" %> + + + <%-- Breadcrumb --%> + <%@ include file="../parts/breadcrumb.jsp" %> + + <%-- Status and Actions --%> + + + + + + + <%-- separator row with gradient shadow --%> + + + + + + + <%-- Details --%> + + + + + + + <%-- separator row with bottom panel graphics --%> + + + + + + +
+ + <%-- Status and Actions inner contents table --%> + <%-- Generally this consists of an icon, textual summary and actions for the current object --%> + + + + + + <%-- Navigation --%> + + +
+ + +
+ '' +
+
+ : +
+
+
+ + + + + + + +
+
+ + + + + + +
+ + + + + + + + + + + + +
+ + + + + +
+ + + + + +
+
+ +
+ + + + + + + + + + + + + + +
+ <%-- icon image for the doc --%> + + + + + + + + +
+
+ +
+
+
+ <%-- properties for the doc link --%> + + + +
+
+ +
+ + <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %> + + + + +
+ +
+ <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %> + +
+ + <%-- Document Actions --%> + + + +
+
+
+ +
+ +
+ +
\ No newline at end of file diff --git a/source/web/jsp/dialog/preview-file.jsp b/source/web/jsp/dialog/preview-file.jsp index 4fb60d7e98..442b321eb3 100644 --- a/source/web/jsp/dialog/preview-file.jsp +++ b/source/web/jsp/dialog/preview-file.jsp @@ -88,11 +88,11 @@ <%-- Navigation --%> - + - + diff --git a/source/web/jsp/dialog/preview-space.jsp b/source/web/jsp/dialog/preview-space.jsp index 4a1c0c30d6..805549bea3 100644 --- a/source/web/jsp/dialog/preview-space.jsp +++ b/source/web/jsp/dialog/preview-space.jsp @@ -88,11 +88,11 @@ <%-- Navigation --%> - + - + diff --git a/source/web/jsp/dialog/space-details.jsp b/source/web/jsp/dialog/space-details.jsp index c70e563bc2..1ed6a727a9 100644 --- a/source/web/jsp/dialog/space-details.jsp +++ b/source/web/jsp/dialog/space-details.jsp @@ -76,11 +76,11 @@ <%-- Navigation --%> - + - + diff --git a/source/web/jsp/dialog/spacelink-details.jsp b/source/web/jsp/dialog/spacelink-details.jsp new file mode 100644 index 0000000000..5aa9709fd2 --- /dev/null +++ b/source/web/jsp/dialog/spacelink-details.jsp @@ -0,0 +1,212 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + 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. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="64kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + <%-- Main outer table --%> + + + <%-- Title bar --%> + + + + + <%-- Main area --%> + + <%-- Shelf --%> + + + <%-- Work Area --%> + + +
+ <%@ include file="../parts/titlebar.jsp" %> +
+ <%@ include file="../parts/shelf.jsp" %> + + + <%-- Breadcrumb --%> + <%@ include file="../parts/breadcrumb.jsp" %> + + <%-- Status and Actions --%> + + + + + + + <%-- separator row with gradient shadow --%> + + + + + + + <%-- Details --%> + + + + + + + <%-- separator row with bottom panel graphics --%> + + + + + + +
+ + <%-- Status and Actions inner contents table --%> + <%-- Generally this consists of an icon, textual summary and actions for the current object --%> + + + + + + <%-- Navigation --%> + + +
+ + +
''
+
:
+
+
+ + + + + + + +
+
+ + + + + + +
+ + <%-- wrapper comment used by the panel to add additional component facets --%> + + + + + + + + + + + + + +
+ <%-- icon image for the space --%> + + + + + + + + +
+
+
+
+
+ <%-- properties for the space link --%> + + + +
+
+ +
+ + + + + + + + +
+ + + + + + + +
+
+ +
+ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %> + + + + +
+ +
+ <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %> + +
+ + <%-- Space Actions --%> + + + +
+
+
+ +
+ +
+ +
\ No newline at end of file diff --git a/source/web/jsp/forums/forum-details.jsp b/source/web/jsp/forums/forum-details.jsp index ea774fa2cd..4e24b500c2 100644 --- a/source/web/jsp/forums/forum-details.jsp +++ b/source/web/jsp/forums/forum-details.jsp @@ -76,11 +76,11 @@ <%-- Navigation --%> - + - + diff --git a/source/web/jsp/forums/forums-details.jsp b/source/web/jsp/forums/forums-details.jsp index dfe6a59141..f2a64f3325 100644 --- a/source/web/jsp/forums/forums-details.jsp +++ b/source/web/jsp/forums/forums-details.jsp @@ -76,11 +76,11 @@ <%-- Navigation --%> - + - + diff --git a/source/web/jsp/forums/topic-details.jsp b/source/web/jsp/forums/topic-details.jsp index 2e5f592eb3..58de0f95be 100644 --- a/source/web/jsp/forums/topic-details.jsp +++ b/source/web/jsp/forums/topic-details.jsp @@ -77,11 +77,11 @@ <%-- Navigation --%> - + - +