- Flat list of Modified Files for a user sandbox, in the expandable Modified Files area of the sandbox view
 - Filename is clickable to view the content of the modified version of the file
 - Added 'creator' column to the files list when browsing a website
. Fixed DownloadContentServlet to handle AVM noderefs with space character %20 in the encoded NodeRef url element

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3843 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2006-09-19 12:47:48 +00:00
parent e27ccc118c
commit 09fc8a5041
5 changed files with 193 additions and 22 deletions

View File

@@ -808,6 +808,8 @@ sandbox_title=Website ''{0}'' sandbox ''{1}''
sandbox_staging=Staging
website_browse_folders=Browse Folders
website_browse_files=Browse Files
creator=Creator
modified_items=Modified Items
# Website actions and dialog messages
title_import_content=Import Content into Website

View File

@@ -19,6 +19,7 @@ package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.Date;
@@ -146,7 +147,7 @@ public class DownloadContentServlet extends BaseServlet
// assume 'workspace' or other NodeRef based protocol for remaining URL elements
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
String id = t.nextToken();
String id = URLDecoder.decode(t.nextToken(), "UTF-8");
// build noderef from the appropriate URL elements
nodeRef = new NodeRef(storeRef, id);

View File

@@ -79,6 +79,7 @@ public class AVMNode implements Map<String, Object>
this.properties.put("name", this.avmRef.getName());
this.properties.put("created", this.avmRef.getCreateDate());
this.properties.put("modified", this.avmRef.getModDate());
this.properties.put("creator", this.avmRef.getCreator());
}
return this.properties;

View File

@@ -34,12 +34,18 @@ import javax.faces.el.ValueBinding;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
import org.alfresco.service.cmr.avmsync.AVMDifference;
import org.alfresco.service.cmr.avmsync.AVMSyncService;
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.servlet.DownloadContentServlet;
import org.alfresco.web.bean.BrowseBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.wcm.AVMConstants;
import org.alfresco.web.ui.common.ComponentConstants;
@@ -48,11 +54,14 @@ import org.alfresco.web.ui.common.PanelGenerator;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.SelfRenderingComponent;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.alfresco.web.ui.common.converter.ByteSizeConverter;
import org.alfresco.web.ui.common.converter.XMLDateConverter;
import org.alfresco.web.ui.repo.component.UIActions;
import org.alfresco.web.ui.wcm.WebResources;
import org.apache.myfaces.taglib.UIComponentTagUtils;
import org.springframework.web.jsf.FacesContextUtils;
import sun.security.krb5.internal.crypto.f;
import sun.swing.UIAction;
/**
@@ -60,15 +69,24 @@ import sun.swing.UIAction;
*/
public class UIUserSandboxes extends SelfRenderingComponent
{
private static final String MSG_MODIFIED_ITEMS = "modified_items";
private static final String MSG_DATETIME_PATTERN = "date_time_pattern";
private static final String MSG_SIZE = "size";
private static final String MSG_CREATED = "created_date";
private static final String MSG_USERNAME = "username";
private static final String MSG_NAME = "name";
private static final String MSG_DESCRIPTION = "description";
private static final String MSG_MODIFIED = "modified_date";
private static final String MSG_ACTIONS = "actions";
private static final String SPACE_ICON = "/images/icons/" + BrowseBean.SPACE_SMALL_DEFAULT + ".gif";
/** website to show sandboxes for */
private NodeRef value;
private ByteSizeConverter sizeConverter = null;
private XMLDateConverter dateConverter = null;
private Set<String> expandedPanels = new HashSet<String>();
@@ -230,7 +248,9 @@ public class UIUserSandboxes extends SelfRenderingComponent
}
out.write(Utils.buildImageTag(context, panelImage, 11, 11, "",
Utils.generateFormSubmit(context, this, getClientId(context), username)));
out.write("&nbsp;<b>Modified Items (3)</b>");
out.write("&nbsp;<b>");
out.write(bundle.getString(MSG_MODIFIED_ITEMS));
out.write("</b>");
if (this.expandedPanels.contains(username))
{
out.write("<div style='padding:2px'></div>");
@@ -240,26 +260,19 @@ public class UIUserSandboxes extends SelfRenderingComponent
out.write("<tr align=left><th width=16></th><th>");
out.write(bundle.getString(MSG_NAME));
out.write("</th><th>");
out.write(bundle.getString(MSG_DESCRIPTION));
out.write(bundle.getString(MSG_CREATED));
out.write("</th><th>");
out.write(bundle.getString(MSG_MODIFIED));
out.write("</th><th>");
out.write(bundle.getString(MSG_SIZE));
out.write("</th><th>");
out.write(bundle.getString(MSG_ACTIONS));
out.write("</th></tr>");
// row per modified doc item
// TODO: add modified items list for this sandbox user
out.write("<tr><td width=16>(O)</td><td>");
out.write("Some document.html");
out.write("</td><td>");
out.write("A description would go here");
out.write("</td><td>");
out.write("01-01-2006 11:58am");
out.write("</td><td>");
// TODO: add UI actions for this item
out.write("(P)&nbsp;(E)&nbsp;(T)&nbsp;(D)");
out.write("</td></tr>");
// row per modified doc item for this sandbox user
renderUserFiles(context, out, username, storeRoot);
// end table
out.write("</table>");
}
out.write("</td></tr></table>");
@@ -286,6 +299,119 @@ public class UIUserSandboxes extends SelfRenderingComponent
}
}
/**
* Render the list of user modified files/folders in the layered sandbox area.
*
* @param fc FacesContext
* @param out ResponseWriter
* @param username The username to render the modified files for
* @param storeRoot Root name of the store containing the users sandbox
*
* @throws IOException
*/
private void renderUserFiles(FacesContext fc, ResponseWriter out, String username, String storeRoot)
throws IOException
{
AVMSyncService avmSyncService = getAVMSyncService(fc);
AVMService avmService = getAVMService(fc);
// build the paths to the stores to compare
String userStore = AVMConstants.buildAVMUserMainStoreName(storeRoot, username) + ":/";
String stagingStore = AVMConstants.buildAVMStagingStoreName(storeRoot) + ":/";
// use the sync service to get the list of diffs between the stores
List<AVMDifference> diffs = avmSyncService.compare(-1, userStore, -1, stagingStore);
for (AVMDifference diff : diffs)
{
//if (diff.getDifferenceCode() == AVMDifference.NEWER)
//{
String sourcePath = diff.getSourcePath();
AVMNodeDescriptor node = avmService.lookup(-1, sourcePath);
if (node != null)
{
// icon and name of the file/folder - files are clickable to see the content
String name = node.getName();
String linkPrefix =
"<a href=\"" +
fc.getExternalContext().getRequestContextPath() +
DownloadContentServlet.generateBrowserURL(AVMNodeConverter.ToNodeRef(-1, sourcePath), name) +
"\" target='new'>";
out.write("<tr><td width=16>");
if (node.isFile())
{
out.write(linkPrefix);
out.write(Utils.buildImageTag(fc, Utils.getFileTypeImage(fc, name, true), ""));
out.write("</a></td><td>");
out.write(linkPrefix);
out.write(name);
out.write("</a>");
}
else
{
out.write(Utils.buildImageTag(fc, SPACE_ICON, 16, 16, ""));
out.write("</td><td>");
out.write(name);
}
out.write("</td><td>");
// created date
out.write(getDateConverter().getAsString(fc, this, node.getCreateDate()));
out.write("</td><td>");
// modified date
out.write(getDateConverter().getAsString(fc, this, node.getModDate()));
out.write("</td><td>");
if (node.isFile())
{
// size of files
out.write(getSizeConverter().getAsString(fc, this, node.getLength()));
}
out.write("</td><td>");
// TODO: add UI actions for this item
out.write("(P)&nbsp;(E)&nbsp;(T)&nbsp;(D)");
out.write("</td></tr>");
}
//}
}
}
/**
* @return Byte size converter
*/
private ByteSizeConverter getSizeConverter()
{
if (this.sizeConverter == null)
{
this.sizeConverter = new ByteSizeConverter();
}
return this.sizeConverter;
}
/**
* @return Date format converter
*/
private XMLDateConverter getDateConverter()
{
if (this.dateConverter == null)
{
this.dateConverter = new XMLDateConverter();
this.dateConverter.setPattern(
Application.getMessage(FacesContext.getCurrentInstance(), MSG_DATETIME_PATTERN));
}
return this.dateConverter;
}
/**
* Aquire a UIActionLink component for the specified action
*
* @param fc FacesContext
* @param store Root store name for the user sandbox
* @param username Username of the user for the action
* @param name Action name - will be used for I18N message lookup
* @param icon Icon to display for the actio n
* @param actionListener Actionlistener for the action
* @param outcome Navigation outcome for the action
*
* @return UIActionLink component
*/
private UIActionLink aquireAction(FacesContext fc, String store, String username,
String name, String icon, String actionListener, String outcome)
{
@@ -297,6 +423,13 @@ public class UIUserSandboxes extends SelfRenderingComponent
return action;
}
/**
* Locate a child UIActionLink component by name.
*
* @param name Of the action component to find
*
* @return UIActionLink component if found, else null if not created yet
*/
private UIActionLink findAction(String name)
{
UIActionLink action = null;
@@ -312,6 +445,19 @@ public class UIUserSandboxes extends SelfRenderingComponent
return action;
}
/**
* Create a UIActionLink child component.
*
* @param fc FacesContext
* @param store Root store name for the user sandbox
* @param username Username of the user for the action
* @param name Action name - will be used for I18N message lookup
* @param icon Icon to display for the actio n
* @param actionListener Actionlistener for the action
* @param outcome Navigation outcome for the action
*
* @return UIActionLink child component
*/
private UIActionLink createAction(FacesContext fc, String store, String username,
String name, String icon, String actionListener, String outcome)
{
@@ -358,6 +504,11 @@ public class UIUserSandboxes extends SelfRenderingComponent
return Repository.getServiceRegistry(fc).getNodeService();
}
private AVMSyncService getAVMSyncService(FacesContext fc)
{
return (AVMSyncService)FacesContextUtils.getRequiredWebApplicationContext(fc).getBean("AVMSyncService");
}
// ------------------------------------------------------------------------------
// Strongly typed component property accessors

View File

@@ -124,7 +124,7 @@
</a:actionLink>
</a:column>
<%-- Description column for all view modes --%>
<%-- Description column --%>
<a:column id="col4" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col4-sort" label="#{msg.description}" value="description" styleClass="header"/>
@@ -132,7 +132,15 @@
<h:outputText id="col4-txt" value="#{r.description}" />
</a:column>
<%-- Created Date column for details view mode --%>
<%-- Creator column --%>
<a:column id="col5" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col5-sort" label="#{msg.creator}" value="creator" styleClass="header"/>
</f:facet>
<h:outputText id="col5-txt" value="#{r.creator}" />
</a:column>
<%-- Created Date column --%>
<a:column id="col6" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col6-sort" label="#{msg.created}" value="created" styleClass="header"/>
@@ -142,7 +150,7 @@
</h:outputText>
</a:column>
<%-- Modified Date column for details/icons view modes --%>
<%-- Modified Date column --%>
<a:column id="col7" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col7-sort" label="#{msg.modified}" value="modified" styleClass="header"/>
@@ -195,7 +203,7 @@
<r:lockIcon id="col10-lock" value="#{r.nodeRef}" align="absmiddle" />
</a:column>
<%-- Description column for all view modes --%>
<%-- Description column --%>
<a:column id="col13" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col13-sort" label="#{msg.description}" value="description" styleClass="header"/>
@@ -203,7 +211,7 @@
<h:outputText id="col13-txt" value="#{r.description}" />
</a:column>
<%-- Size for details/icons view modes --%>
<%-- Size column --%>
<a:column id="col15" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col15-sort" label="#{msg.size}" value="size" styleClass="header"/>
@@ -213,7 +221,15 @@
</h:outputText>
</a:column>
<%-- Created Date column for details view mode --%>
<%-- Creator column --%>
<a:column id="col15a" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col15a-sort" label="#{msg.creator}" value="creator" styleClass="header"/>
</f:facet>
<h:outputText id="col15a-txt" value="#{r.creator}" />
</a:column>
<%-- Created Date column --%>
<a:column id="col16" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col16-sort" label="#{msg.created}" value="created" styleClass="header"/>
@@ -223,7 +239,7 @@
</h:outputText>
</a:column>
<%-- Modified Date column for details/icons view modes --%>
<%-- Modified Date column --%>
<a:column id="col17" style="text-align:left">
<f:facet name="header">
<a:sortLink id="col17-sort" label="#{msg.modified}" value="modified" styleClass="header"/>