Merge from HEAD to WCM-DEV2.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3659 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2006-09-02 18:19:00 +00:00
parent 3b1d6b89f5
commit cc6af1a45c
100 changed files with 4941 additions and 1298 deletions

View File

@@ -29,8 +29,10 @@ import org.alfresco.config.ConfigService;
import org.alfresco.web.app.servlet.ExternalAccessServlet;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.dialog.DialogManager;
import org.alfresco.web.bean.dialog.DialogState;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.wizard.WizardManager;
import org.alfresco.web.bean.wizard.WizardState;
import org.alfresco.web.config.DialogsConfigElement;
import org.alfresco.web.config.NavigationConfigElement;
import org.alfresco.web.config.NavigationElementReader;
@@ -47,9 +49,9 @@ import org.apache.commons.logging.LogFactory;
public class AlfrescoNavigationHandler extends NavigationHandler
{
public final static String OUTCOME_SEPARATOR = ":";
public final static String DIALOG_PREXIX = "dialog" + OUTCOME_SEPARATOR;
public final static String DIALOG_PREFIX = "dialog" + OUTCOME_SEPARATOR;
public final static String WIZARD_PREFIX = "wizard" + OUTCOME_SEPARATOR;
public final static String CLOSE_DIALOG_OUTCOME = DIALOG_PREXIX + "close";
public final static String CLOSE_DIALOG_OUTCOME = DIALOG_PREFIX + "close";
public final static String CLOSE_WIZARD_OUTCOME = WIZARD_PREFIX + "close";
protected final static String CONFIG_NAV_BEAN = "NavigationBean";
@@ -135,7 +137,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler
{
boolean dialog = false;
if (outcome != null && outcome.startsWith(DIALOG_PREXIX))
if (outcome != null && outcome.startsWith(DIALOG_PREFIX))
{
dialog = true;
}
@@ -589,16 +591,51 @@ public class AlfrescoNavigationHandler extends NavigationHandler
// or any overridden outcome that may be present
if (getViewStack(context).empty() == false)
{
String newViewId = (String)getViewStack(context).pop();
// is there an overidden outcome?
String overriddenOutcome = getOutcomeOverride(outcome);
if (overriddenOutcome == null)
{
// there isn't an overidden outcome so go back to the previous view
if (logger.isDebugEnabled())
logger.debug("Closing " + closingItem + ", going back to view id: " + newViewId);
logger.debug("Closing " + closingItem + ", going back to previous page");
// if the top of the stack is not a dialog or wizard just get the
// view id and navigate back to it.
// if the top of the stack is a dialog or wizard retrieve the state
// and setup the appropriate manager with that state, then get the
// appropriate container page and navigate to it.
Object topOfStack = getViewStack(context).pop();
if (logger.isDebugEnabled())
logger.debug("Popped item from the top of the view stack: " + topOfStack);
String newViewId = null;
if (topOfStack instanceof String)
{
newViewId = (String)topOfStack;
}
else if (topOfStack instanceof DialogState)
{
// restore the dialog state and get the dialog container viewId
Application.getDialogManager().restoreState((DialogState)topOfStack);
newViewId = getDialogContainer(context);
}
else if (topOfStack instanceof WizardState)
{
// restore the wizard state and get the wizard container viewId
Application.getWizardManager().restoreState((WizardState)topOfStack);
newViewId = getWizardContainer(context);
}
else
{
if (logger.isWarnEnabled())
logger.warn("Invalid object found on view stack: " + topOfStack);
}
// go to the appropraite page
goToView(context, newViewId);
}
else
@@ -656,33 +693,66 @@ public class AlfrescoNavigationHandler extends NavigationHandler
*
* @param context FacesContext
*/
@SuppressWarnings("unchecked")
protected void addCurrentViewToStack(FacesContext context)
{
// if we are opening a wizard or dialog push the current view
// id on to the stack, but only if it is different than the
// current view at the top (you can't launch a dialog from
// the same page 2 times in a row!)
// if the current viewId is either the dialog or wizard container page
// we need to save the state of the current dialog or wizard to the stack
// TODO: This wouldn't happen if we could be sure a dialog is
// ALWAYS exited properly, look into a way of ensuring
// dialogs get closed if a user navigates away from the page,
// would a PhaseListener help in any way??
// If the current view is a normal page and it is not the same as the
// view currently at the top of the stack (you can't launch a dialog from
// the same page 2 times in a row so it must mean the user navigated away
// from the first dialog) just add the viewId to the stack
// work out what to add to the stack
String viewId = context.getViewRoot().getViewId();
if (getViewStack(context).empty() ||
viewId.equals(getViewStack(context).peek()) == false)
String dialogContainer = getDialogContainer(context);
String wizardContainer = getWizardContainer(context);
Object objectForStack = null;
if (viewId.equals(dialogContainer))
{
getViewStack(context).push(viewId);
if (logger.isDebugEnabled())
logger.debug("Pushed current view to stack: " + viewId);
DialogManager dlgMgr = Application.getDialogManager();
objectForStack = dlgMgr.getState();
}
else if (viewId.equals(wizardContainer))
{
WizardManager wizMgr = Application.getWizardManager();
objectForStack = wizMgr.getState();
}
else
{
if (getViewStack(context).empty() == false && logger.isDebugEnabled())
objectForStack = viewId;
}
// if the stack is currently empty add the item
Stack stack = getViewStack(context);
if (stack.empty())
{
stack.push(objectForStack);
if (logger.isDebugEnabled())
logger.debug("Pushed item to view stack: " + objectForStack);
}
else
{
// if the item to go on to the stack and the top of
// stack are both Strings and equals to each other
// don't add anything to the stack to stop it
// growing unecessarily
Object topOfStack = stack.peek();
if (objectForStack instanceof String &&
topOfStack instanceof String &&
topOfStack.equals(objectForStack))
{
logger.debug("current view is already top the view stack!");
if (logger.isDebugEnabled())
logger.debug("current view is already top of the view stack!");
}
else
{
stack.push(objectForStack);
if (logger.isDebugEnabled())
logger.debug("Pushed item to view stack: " + objectForStack);
}
}
}
@@ -725,13 +795,13 @@ public class AlfrescoNavigationHandler extends NavigationHandler
* the users session, will never be null
*/
@SuppressWarnings("unchecked")
private Stack<String> getViewStack(FacesContext context)
private Stack getViewStack(FacesContext context)
{
Stack<String> viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK);
Stack viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK);
if (viewStack == null)
{
viewStack = new Stack<String>();
viewStack = new Stack();
context.getExternalContext().getSessionMap().put(VIEW_STACK, viewStack);
}

View File

@@ -0,0 +1,143 @@
package org.alfresco.web.app;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.jsf.DelegatingVariableResolver;
/**
* JSF VariableResolver that first delegates to the Spring JSF variable
* resolver. The sole purpose of this variable resolver is to look out
* for the <code>Container</code> variable. If this variable is encountered
* the current viewId is examined. If the current viewId matches the
* configured dialog or wizard container the appropriate manager object is
* returned i.e. DialogManager or WizardManager.
*
* <p>Configure this resolver in your <code>faces-config.xml</code> file as follows:
*
* <pre>
* &lt;application&gt;
* ...
* &lt;variable-resolver&gt;org.alfresco.web.app.AlfrescoVariableResolver&lt;/variable-resolver&gt;
* &lt;/application&gt;</pre>
*
* @see org.alfresco.web.bean.dialog.DialogManager
* @see org.alfresco.web.bean.wizard.WizardManager
* @author gavinc
*/
public class AlfrescoVariableResolver extends DelegatingVariableResolver
{
protected String dialogContainer = null;
protected String wizardContainer = null;
private static final String CONTAINER = "Container";
private static final Log logger = LogFactory.getLog(AlfrescoVariableResolver.class);
/**
* Creates a new VariableResolver.
*
* @param originalVariableResolver The original variable resolver
*/
public AlfrescoVariableResolver(VariableResolver originalVariableResolver)
{
super(originalVariableResolver);
}
/**
* Resolves the variable with the given name.
* <p>
* This implementation will first delegate to the Spring variable resolver.
* If the variable is not found by the Spring resolver and the variable name
* is <code>Container</code> the current viewId is examined.
* If the current viewId matches the configured dialog or wizard container
* the appropriate manager object is returned i.e. DialogManager or WizardManager.
*
* @param context FacesContext
* @param name The name of the variable to resolve
*/
public Object resolveVariable(FacesContext context, String name)
throws EvaluationException
{
Object variable = super.resolveVariable(context, name);
if (variable == null)
{
// if the variable was not resolved see if the name is "Container"
if (name.equals(CONTAINER))
{
// get the current view id and the configured dialog and wizard
// container pages
String viewId = context.getViewRoot().getViewId();
String dialogContainer = getDialogContainer(context);
String wizardContainer = getWizardContainer(context);
// see if we are currently in a wizard or a dialog
if (viewId.equals(dialogContainer))
{
variable = Application.getDialogManager();
}
else if (viewId.equals(wizardContainer))
{
variable = Application.getWizardManager();
}
if (variable != null && logger.isDebugEnabled())
{
logger.debug("Resolved 'Container' variable to: " + variable);
}
}
}
return variable;
}
/**
* Retrieves the configured dialog container page
*
* @param context FacesContext
* @return The container page
*/
protected String getDialogContainer(FacesContext context)
{
if (this.dialogContainer == null)
{
ConfigService configSvc = Application.getConfigService(context);
Config globalConfig = configSvc.getGlobalConfig();
if (globalConfig != null)
{
this.dialogContainer = globalConfig.getConfigElement("dialog-container").getValue();
}
}
return this.dialogContainer;
}
/**
* Retrieves the configured wizard container page
*
* @param context FacesContext
* @return The container page
*/
protected String getWizardContainer(FacesContext context)
{
if (this.wizardContainer == null)
{
ConfigService configSvc = Application.getConfigService(context);
Config globalConfig = configSvc.getGlobalConfig();
if (globalConfig != null)
{
this.wizardContainer = globalConfig.getConfigElement("wizard-container").getValue();
}
}
return this.wizardContainer;
}
}

View File

@@ -33,6 +33,7 @@ import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.UnavailableException;
import org.alfresco.config.ConfigService;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.cmr.security.AuthenticationService;
@@ -43,7 +44,9 @@ import org.alfresco.web.app.servlet.AuthenticationStatus;
import org.alfresco.web.bean.ErrorBean;
import org.alfresco.web.bean.FileUploadBean;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.ClientConfigElement;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.portlet.PortletFileUpload;
@@ -259,7 +262,18 @@ public class AlfrescoFacesPortlet extends MyFacesGenericPortlet
// perform the forward to the page processed by the Faces servlet
response.setContentType("text/html");
request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true");
nonFacesRequest(request, response, "/jsp/browse/browse.jsp");
// get the start location as configured by the web-client config
ConfigService configService = (ConfigService)ctx.getBean("webClientConfigService");
ClientConfigElement configElement = (ClientConfigElement)configService.getGlobalConfig().getConfigElement("client");
if (NavigationBean.LOCATION_MYALFRESCO.equals(configElement.getInitialLocation()))
{
nonFacesRequest(request, response, "/jsp/dashboards/container.jsp");
}
else
{
nonFacesRequest(request, response, "/jsp/browse/browse.jsp");
}
}
else
{

View File

@@ -77,7 +77,6 @@ public abstract class BaseServlet extends HttpServlet
validRedirectJSPs.add("/jsp/forums/forums.jsp");
validRedirectJSPs.add("/jsp/users/users.jsp");
validRedirectJSPs.add("/jsp/trashcan/trash-list.jsp");
validRedirectJSPs.add("/jsp/dashboards/container.jsp");
}
private static Log logger = LogFactory.getLog(BaseServlet.class);
@@ -156,10 +155,15 @@ public abstract class BaseServlet extends HttpServlet
throws IOException
{
// authentication failed - so end servlet execution and redirect to login page
// also save the full requested URL so the login page knows where to redirect too later
res.sendRedirect(req.getContextPath() + FACES_SERVLET + Application.getLoginPage(sc));
// save the full requested URL so the login page knows where to redirect too later
String uri = req.getRequestURI();
String url = uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : "");
String url = uri;
if (req.getQueryString() != null && req.getQueryString().length() != 0)
{
url += "?" + req.getQueryString();
}
if (uri.indexOf(req.getContextPath() + FACES_SERVLET) != -1)
{
// if we find a JSF servlet reference in the URI then we need to check if the rest of the

View File

@@ -40,13 +40,12 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.templating.OutputUtil;
import org.alfresco.web.templating.TemplatingService;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.apache.commons.logging.Log;
@@ -376,8 +375,8 @@ public class CheckinCheckoutBean
*/
private Node setupContentDocument(String id)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("Setup for action, setting current document to: " + id);
if (logger.isDebugEnabled())
logger.debug("Setup for action, setting current document to: " + id);
Node node = null;
@@ -427,14 +426,14 @@ public class CheckinCheckoutBean
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
tx.begin();
if (LOGGER.isDebugEnabled())
LOGGER.debug("Trying to checkout content node Id: " + node.getId());
if (logger.isDebugEnabled())
logger.debug("Trying to checkout content node Id: " + node.getId());
// checkout the node content to create a working copy
if (LOGGER.isDebugEnabled())
if (logger.isDebugEnabled())
{
LOGGER.debug("Checkout copy location: " + getCopyLocation());
LOGGER.debug("Selected Space Id: " + this.selectedSpaceId);
logger.debug("Checkout copy location: " + getCopyLocation());
logger.debug("Selected Space Id: " + this.selectedSpaceId);
}
NodeRef workingCopyRef;
if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null)
@@ -478,7 +477,7 @@ public class CheckinCheckoutBean
}
else
{
LOGGER.warn("WARNING: checkoutFile called without a current Document!");
logger.warn("WARNING: checkoutFile called without a current Document!");
}
return outcome;
@@ -494,16 +493,22 @@ public class CheckinCheckoutBean
Node node = getWorkingDocument();
if (node != null)
{
// reset the underlying node
if (this.browseBean.getDocument() != null)
{
this.browseBean.getDocument().reset();
}
// clean up and clear action context
clearUpload();
setDocument(null);
setWorkingDocument(null);
outcome = "browse";
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
else
{
LOGGER.warn("WARNING: checkoutFileOK called without a current WorkingDocument!");
logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!");
}
return outcome;
@@ -524,11 +529,11 @@ public class CheckinCheckoutBean
setDocument(null);
setWorkingDocument(null);
outcome = "browse";
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
else
{
LOGGER.warn("WARNING: editFileOK called without a current Document!");
logger.warn("WARNING: editFileOK called without a current Document!");
}
return outcome;
@@ -567,17 +572,12 @@ public class CheckinCheckoutBean
MimetypeMap.MIMETYPE_JAVASCRIPT.equals(mimetype))
{
// make content available to the editing screen
String contentString = reader.getContentString();
setDocumentContent(contentString);
setEditorOutput(contentString);
// navigate to appropriate screen
FacesContext fc = FacesContext.getCurrentInstance();
this.navigator.setupDispatchContext(node);
String s = (MimetypeMap.MIMETYPE_XML.equals(mimetype)
? "editXmlInline"
: "editTextInline");
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, s);
setEditorOutput(reader.getContentString());
// navigate to appropriate screen
FacesContext fc = FacesContext.getCurrentInstance();
this.navigator.setupDispatchContext(node);
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editTextInline");
}
else
{
@@ -588,7 +588,7 @@ public class CheckinCheckoutBean
// navigate to appropriate screen
FacesContext fc = FacesContext.getCurrentInstance();
this.navigator.setupDispatchContext(node);
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editHtmlInline");
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editHtmlInline");
}
}
}
@@ -598,7 +598,7 @@ public class CheckinCheckoutBean
// normal downloadable document
FacesContext fc = FacesContext.getCurrentInstance();
this.navigator.setupDispatchContext(node);
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editFile");
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editFile");
}
}
}
@@ -620,31 +620,23 @@ public class CheckinCheckoutBean
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
tx.begin();
if (LOGGER.isDebugEnabled())
LOGGER.debug("Trying to update content node Id: " + node.getId());
if (logger.isDebugEnabled())
logger.debug("Trying to update content node Id: " + node.getId());
// get an updating writer that we can use to modify the content on the current node
ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
writer.putContent(this.editorOutput);
// commit the transaction
tx.commit();
if (nodeService.getProperty(node.getNodeRef(),
TemplatingService.TT_QNAME) != null)
{
OutputUtil.regenerate(node.getNodeRef(),
this.contentService,
this.nodeService);
}
// clean up and clear action context
clearUpload();
setDocument(null);
setDocumentContent(null);
setEditorOutput(null);
outcome = "browse";
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
catch (Throwable err)
{
@@ -656,7 +648,7 @@ public class CheckinCheckoutBean
}
else
{
LOGGER.warn("WARNING: editInlineOK called without a current Document!");
logger.warn("WARNING: editInlineOK called without a current Document!");
}
return outcome;
@@ -679,7 +671,7 @@ public class CheckinCheckoutBean
clearUpload();
outcome = "browse";
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
catch (Throwable err)
{
@@ -689,7 +681,7 @@ public class CheckinCheckoutBean
}
else
{
LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!");
logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
}
return outcome;
@@ -726,10 +718,10 @@ public class CheckinCheckoutBean
{
throw new IllegalStateException("Node supplied for undo checkout has neither Working Copy or Locked aspect!");
}
clearUpload();
outcome = "browse";
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
catch (Throwable err)
{
@@ -738,7 +730,7 @@ public class CheckinCheckoutBean
}
else
{
LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!");
logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
}
return outcome;
@@ -763,8 +755,8 @@ public class CheckinCheckoutBean
tx = Repository.getUserTransaction(context);
tx.begin();
if (LOGGER.isDebugEnabled())
LOGGER.debug("Trying to checkin content node Id: " + node.getId());
if (logger.isDebugEnabled())
logger.debug("Trying to checkin content node Id: " + node.getId());
// we can either checkin the content from the current working copy node
// which would have been previously updated by the user
@@ -816,7 +808,8 @@ public class CheckinCheckoutBean
setDocument(null);
clearUpload();
outcome = "browse";
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
catch (Throwable err)
{
@@ -828,7 +821,7 @@ public class CheckinCheckoutBean
}
else
{
LOGGER.warn("WARNING: checkinFileOK called without a current Document!");
logger.warn("WARNING: checkinFileOK called without a current Document!");
}
return outcome;
@@ -853,8 +846,8 @@ public class CheckinCheckoutBean
tx = Repository.getUserTransaction(context);
tx.begin();
if (LOGGER.isDebugEnabled())
LOGGER.debug("Trying to update content node Id: " + node.getId());
if (logger.isDebugEnabled())
logger.debug("Trying to update content node Id: " + node.getId());
// get an updating writer that we can use to modify the content on the current node
ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
@@ -872,7 +865,7 @@ public class CheckinCheckoutBean
setDocument(null);
clearUpload();
outcome = "browse";
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
catch (Throwable err)
{
@@ -884,7 +877,7 @@ public class CheckinCheckoutBean
}
else
{
LOGGER.warn("WARNING: updateFileOK called without a current Document!");
logger.warn("WARNING: updateFileOK called without a current Document!");
}
return outcome;
@@ -898,7 +891,7 @@ public class CheckinCheckoutBean
// reset the state
clearUpload();
return "browse";
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
/**
@@ -929,7 +922,7 @@ public class CheckinCheckoutBean
// ------------------------------------------------------------------------------
// Private data
private static final Log LOGGER = LogFactory.getLog(CheckinCheckoutBean.class);
private static Log logger = LogFactory.getLog(CheckinCheckoutBean.class);
/** I18N messages */
private static final String MSG_ERROR_CHECKIN = "error_checkin";

View File

@@ -91,13 +91,21 @@ public class LoginBean
}
/**
* @param navigator The NavigationBean to set.
* @param navigator The NavigationBean to set.
*/
public void setNavigator(NavigationBean navigator)
{
this.navigator = navigator;
}
/**
* @param preferences The UserPreferencesBean to set
*/
public void setUserPreferencesBean(UserPreferencesBean preferences)
{
this.preferences = preferences;
}
/**
* @return true if the default Alfresco authentication process is being used, else false
* if an external authorisation mechanism is present.
@@ -329,7 +337,7 @@ public class LoginBean
else
{
// special case to handle jump to My Alfresco page initially
String location = Application.getClientConfig(FacesContext.getCurrentInstance()).getInitialLocation();
String location = this.preferences.getStartLocation();
if (NavigationBean.LOCATION_MYALFRESCO.equals(location))
{
return "myalfresco";
@@ -451,4 +459,7 @@ public class LoginBean
/** The NavigationBean bean reference */
protected NavigationBean navigator;
/** The user preferences bean reference */
protected UserPreferencesBean preferences;
}

View File

@@ -126,6 +126,14 @@ public class NavigationBean
this.contentDiskDriver = contentDiskDriver;
}
/**
* @param preferences The UserPreferencesBean to set
*/
public void setUserPreferencesBean(UserPreferencesBean preferences)
{
this.preferences = preferences;
}
/**
* @return the User object representing the current instance for this user
*/
@@ -252,6 +260,15 @@ public class NavigationBean
}
else if (LOCATION_MYALFRESCO.equals(location))
{
// make sure we set a current node ID as some screens expect this
if (getCurrentNodeId() == null)
{
String homeSpaceId = Application.getCurrentUser(context).getHomeSpaceId();
NodeRef homeSpaceRef = new NodeRef(Repository.getStoreRef(), homeSpaceId);
setCurrentNodeId(homeSpaceRef.getId());
}
// create a breadcrumb handler for this special case location (not a node)
List<IBreadcrumbHandler> elements = new ArrayList<IBreadcrumbHandler>(1);
elements.add(new IBreadcrumbHandler()
{
@@ -507,13 +524,8 @@ public class NavigationBean
{
if (this.location == null)
{
// get the initial location from the client config
String initialLocation = clientConfig.getInitialLocation();
if (initialLocation == null || initialLocation.length() == 0)
{
initialLocation = LOCATION_HOME;
}
processToolbarLocation(initialLocation, false);
// get the initial location from the user preferences
processToolbarLocation(this.preferences.getStartLocation(), false);
}
return this.location;
@@ -798,10 +810,10 @@ public class NavigationBean
private static Logger s_logger = Logger.getLogger(NavigationBean.class);
/** constant values used by the toolbar location modelist control */
static final String LOCATION_COMPANY = "companyhome";
static final String LOCATION_HOME = "userhome";
static final String LOCATION_GUEST = "guesthome";
static final String LOCATION_MYALFRESCO = "myalfresco";
public static final String LOCATION_COMPANY = "companyhome";
public static final String LOCATION_HOME = "userhome";
public static final String LOCATION_GUEST = "guesthome";
public static final String LOCATION_MYALFRESCO = "myalfresco";
private static final String MSG_MYALFRESCO = "my_alfresco";
@@ -828,6 +840,9 @@ public class NavigationBean
/** Client configuration object */
protected ClientConfigElement clientConfig = null;
/** The user preferences bean reference */
protected UserPreferencesBean preferences;
/** Cached path to our CIFS server and top level node DIR */
private String cifsServerPath;

View File

@@ -0,0 +1,66 @@
/*
* 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.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.PreferencesService;
/**
* Simple bean backing the user preferences settings.
*
* @author Kevin Roast
*/
public class UserPreferencesBean
{
private static final String PREF_STARTLOCATION = "start-location";
private static final String MSG_MYALFRESCO = "my_alfresco";
private static final String MSG_MYHOME = "my_home";
private static final String MSG_COMPANYHOME = "company_home";
private static final String MSG_GUESTHOME = "guest_home";
public String getStartLocation()
{
String location = (String)PreferencesService.getPreferences().getValue(PREF_STARTLOCATION);
if (location == null)
{
// default to value from client config
location = Application.getClientConfig(FacesContext.getCurrentInstance()).getInitialLocation();
}
return location;
}
public void setStartLocation(String location)
{
PreferencesService.getPreferences().setValue(PREF_STARTLOCATION, location);
}
public SelectItem[] getStartLocations()
{
ResourceBundle msg = Application.getBundle(FacesContext.getCurrentInstance());
return new SelectItem[] {
new SelectItem(NavigationBean.LOCATION_MYALFRESCO, msg.getString(MSG_MYALFRESCO)),
new SelectItem(NavigationBean.LOCATION_HOME, msg.getString(MSG_MYHOME)),
new SelectItem(NavigationBean.LOCATION_COMPANY, msg.getString(MSG_COMPANYHOME)),
new SelectItem(NavigationBean.LOCATION_GUEST, msg.getString(MSG_GUESTHOME))};
}
}

View File

@@ -6,7 +6,7 @@ import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.repo.action.executer.ScriptActionExecutor;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.FacesHelper;
@@ -25,7 +25,7 @@ public class ScriptHandler extends BaseActionHandler
public String getJSPPath()
{
return getJSPPath(ScriptActionExecutor.NAME);
return getJSPPath(ScriptActionExecuter.NAME);
}
public void prepareForSave(Map<String, Serializable> actionProps,
@@ -34,13 +34,13 @@ public class ScriptHandler extends BaseActionHandler
// add the selected script noderef to the action properties
String id = (String)actionProps.get(PROP_SCRIPT);
NodeRef scriptRef = new NodeRef(Repository.getStoreRef(), id);
repoProps.put(ScriptActionExecutor.PARAM_SCRIPTREF, scriptRef);
repoProps.put(ScriptActionExecuter.PARAM_SCRIPTREF, scriptRef);
}
public void prepareForEdit(Map<String, Serializable> actionProps,
Map<String, Serializable> repoProps)
{
NodeRef scriptRef = (NodeRef)repoProps.get(ScriptActionExecutor.PARAM_SCRIPTREF);
NodeRef scriptRef = (NodeRef)repoProps.get(ScriptActionExecuter.PARAM_SCRIPTREF);
actionProps.put(PROP_SCRIPT, scriptRef.getId());
}

View File

@@ -34,8 +34,6 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
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.FileInfo;
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;
@@ -182,12 +180,8 @@ public class ClipboardBean
*/
private void performPasteItems(int index, int action)
{
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
tx.begin();
if (index == -1)
{
// paste all
@@ -219,16 +213,11 @@ public class ClipboardBean
}
}
// commit the transaction
tx.commit();
// refresh UI on success
UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
}
catch (Throwable err)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
Utils.addErrorMessage(Application.getMessage(
FacesContext.getCurrentInstance(), MSG_ERROR_PASTE) + err.getMessage(), err);
}
@@ -241,7 +230,7 @@ public class ClipboardBean
* @param action the clipboard action to perform (see UIClipboardShelfItem)
*/
private void performClipboardOperation(ClipboardItem item, int action)
throws FileExistsException, FileNotFoundException
throws Throwable
{
NodeRef destRef = new NodeRef(Repository.getStoreRef(), this.navigator.getCurrentNodeId());
@@ -267,8 +256,12 @@ public class ClipboardBean
boolean operationComplete = false;
while (operationComplete == false)
{
UserTransaction tx = null;
try
{
// attempt each copy/paste in its own transaction
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
tx.begin();
if (item.Mode == ClipboardStatus.COPY)
{
if (action == UIClipboardShelfItem.ACTION_PASTE_LINK)
@@ -399,10 +392,25 @@ public class ClipboardBean
throw fileExistsErr;
}
}
if (operationComplete == false)
catch (Throwable e)
{
String copyOf = Application.getMessage(FacesContext.getCurrentInstance(), MSG_COPY_OF);
name = copyOf + ' ' + name;
// some other type of exception occured - rollback and exit
throw e;
}
finally
{
// rollback if the operation didn't complete
if (operationComplete == false)
{
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
String copyOf = Application.getMessage(FacesContext.getCurrentInstance(), MSG_COPY_OF);
name = copyOf + ' ' + name;
}
else
{
// commit the transaction
tx.commit();
}
}
}
}

View File

@@ -1,23 +1,6 @@
/*
* 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.content;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
@@ -35,17 +18,9 @@ import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
import org.alfresco.web.templating.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.ContentWriter;
import java.io.OutputStreamWriter;
import org.alfresco.web.app.servlet.FacesHelper;
/**
* Bean implementation for the "Create Content Wizard" dialog
*
@@ -53,14 +28,12 @@ import org.alfresco.web.app.servlet.FacesHelper;
*/
public class CreateContentWizard extends BaseContentWizard
{
protected String content = null;
protected String templateTypeName;
protected List<SelectItem> createMimeTypes;
private static final Log LOGGER =
LogFactory.getLog(CreateContentWizard.class);
protected String content = null;
protected List<SelectItem> createMimeTypes;
private static Log logger = LogFactory.getLog(CreateContentWizard.class);
// ------------------------------------------------------------------------------
// Wizard implementation
@@ -68,28 +41,10 @@ public class CreateContentWizard extends BaseContentWizard
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
LOGGER.debug("saving file content to " + this.fileName);
saveContent(null, this.content);
if (this.templateTypeName != null)
{
LOGGER.debug("generating template output for " + this.templateTypeName);
this.nodeService.setProperty(this.createdNode,
TemplatingService.TT_QNAME,
this.templateTypeName);
TemplatingService ts = TemplatingService.getInstance();
TemplateType tt = this.getTemplateType();
OutputUtil.generate(this.createdNode,
ts.parseXML(this.content),
tt,
this.fileName,
this.getContainerNodeRef(),
this.fileFolderService,
this.contentService,
this.nodeService);
}
// return the default outcome
return outcome;
saveContent(null, this.content);
// return the default outcome
return outcome;
}
@Override
@@ -99,7 +54,6 @@ public class CreateContentWizard extends BaseContentWizard
this.content = null;
this.inlineEdit = true;
this.templateTypeName = null;
this.mimeType = MimetypeMap.MIMETYPE_HTML;
}
@@ -162,20 +116,6 @@ public class CreateContentWizard extends BaseContentWizard
{
this.content = content;
}
public List<SelectItem> getCreateTemplateTypes()
{
Collection<TemplateType> ttl = TemplatingService.getInstance().getTemplateTypes();
List<SelectItem> sil = new ArrayList<SelectItem>(ttl.size());
for (TemplateType tt : ttl)
{
sil.add(new SelectItem(tt.getName(), tt.getName()));
}
QuickSort sorter = new QuickSort(sil, "label", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
return sil;
}
/**
* @return Returns a list of mime types to allow the user to select from
@@ -213,37 +153,18 @@ public class CreateContentWizard extends BaseContentWizard
}
else
{
LOGGER.warn("Could not find 'create-mime-types' configuration element");
logger.warn("Could not find 'create-mime-types' configuration element");
}
}
else
{
LOGGER.warn("Could not find 'Content Wizards' configuration section");
logger.warn("Could not find 'Content Wizards' configuration section");
}
}
return this.createMimeTypes;
}
public String getTemplateTypeName()
{
return this.templateTypeName;
}
public TemplateType getTemplateType()
{
final TemplatingService ts = TemplatingService.getInstance();
return ts.getTemplateType(this.getTemplateTypeName());
}
/**
* @param templateType Sets the currently selected template type
*/
public void setTemplateTypeName(final String templateTypeName)
{
this.templateTypeName = templateTypeName;
}
/**
* @return Returns the summary data for the wizard.

View File

@@ -0,0 +1,75 @@
package org.alfresco.web.bean.content;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
/**
* Bean implementation of the "View Content Properties" dialog.
*
* @author gavinc
*/
public class ViewContentPropertiesDialog extends BaseDialogBean
{
protected static final String TEMP_PROP_MIMETYPE = "mimetype";
protected Node viewingNode;
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
// setup the editable node
this.viewingNode = new Node(this.browseBean.getDocument().getNodeRef());
// special case for Mimetype - since this is a sub-property of the ContentData object
// we must extract it so it can be edited in the client, then we check for it later
// and create a new ContentData object to wrap it and it's associated URL
ContentData content = (ContentData)this.viewingNode.getProperties().get(ContentModel.PROP_CONTENT);
if (content != null)
{
this.viewingNode.getProperties().put(TEMP_PROP_MIMETYPE, content.getMimetype());
}
// add the specially handled 'size' property
this.viewingNode.addPropertyResolver("size", this.browseBean.resolverSize);
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
// nothing to do as the finish button is not shown and the dialog is read only
return outcome;
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "close");
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* Returns the node being viewed
*
* @return The node being viewed
*/
public Node getViewingNode()
{
return this.viewingNode;
}
}

View File

@@ -125,6 +125,14 @@ public class DashboardWizard extends BaseWizardBean
// ------------------------------------------------------------------------------
// Dashboard Wizard bean getters
/**
* @return true to allow the Guest user to configure the dashboard, false otherwise
*/
public boolean getAllowGuestConfig()
{
return DashboardManager.getDashboardConfig().getAllowGuestConfig();
}
/**
* @return The currently selected layout ID - used by the Dynamic Description component
*/

View File

@@ -0,0 +1,70 @@
/*
* 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.dashboard;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.NavigationBean;
/**
* Backing bean for the Getting Started Dashlet page.
*
* @author Kevin Roast
*/
public class GettingStartedBean
{
private NavigationBean navigationBean;
/**
* @param navigationBean The navigationBean to set.
*/
public void setNavigationBean(NavigationBean navigationBean)
{
this.navigationBean = navigationBean;
}
public String browseHomeSpace()
{
this.navigationBean.setCurrentNodeId(getHomeSpaceId());
return "browse";
}
public String createSpace()
{
this.navigationBean.setCurrentNodeId(getHomeSpaceId());
return "dialog:createSpace";
}
public String createContent()
{
this.navigationBean.setCurrentNodeId(getHomeSpaceId());
return "wizard:createContent";
}
public String addContent()
{
this.navigationBean.setCurrentNodeId(getHomeSpaceId());
return "addContent";
}
private String getHomeSpaceId()
{
return Application.getCurrentUser(FacesContext.getCurrentInstance()).getHomeSpaceId();
}
}

View File

@@ -59,6 +59,11 @@ public abstract class BaseDialogBean implements IDialogBean
this.isFinished = false;
}
public void restored()
{
// do nothing by default, subclasses can override if necessary
}
public String cancel()
{
return getDefaultCancelOutcome();
@@ -126,6 +131,16 @@ public abstract class BaseDialogBean implements IDialogBean
return true;
}
public String getTitle()
{
return null;
}
public String getDescription()
{
return null;
}
/**
* @param browseBean The BrowseBean to set.
*/

View File

@@ -20,11 +20,10 @@ import org.alfresco.web.ui.common.component.UIActionLink;
*
* @author gavinc
*/
public class DialogManager
public final class DialogManager
{
protected IDialogBean currentDialog;
protected DialogConfig currentDialogConfig;
protected Map<String, String> currentDialogParams;
private DialogState currentDialogState;
private Map<String, String> paramsToApply;
/**
* Action handler used to setup parameters for the dialog being launched
@@ -38,7 +37,7 @@ public class DialogManager
if (component instanceof UIActionLink)
{
// store the parameters
this.currentDialogParams = ((UIActionLink)component).getParameterMap();
this.paramsToApply = ((UIActionLink)component).getParameterMap();
}
}
@@ -49,22 +48,48 @@ public class DialogManager
*/
public void setCurrentDialog(DialogConfig config)
{
this.currentDialogConfig = config;
String beanName = this.currentDialogConfig.getManagedBean();
this.currentDialog = (IDialogBean)FacesHelper.getManagedBean(
String beanName = config.getManagedBean();
IDialogBean dialog = (IDialogBean)FacesHelper.getManagedBean(
FacesContext.getCurrentInstance(), beanName);
if (this.currentDialog == null)
if (dialog == null)
{
throw new AlfrescoRuntimeException("Failed to find managed bean '" + beanName + "'");
}
// initialise the managed bean
this.currentDialog.init(this.currentDialogParams);
dialog.init(this.paramsToApply);
// reset the current parameters so subsequent dialogs don't get them
this.currentDialogParams = null;
this.paramsToApply = null;
// create the DialogState object
this.currentDialogState = new DialogState(config, dialog);
}
/**
* Returns the state of the currently active dialog
*
* @return Current dialog's state
*/
public DialogState getState()
{
return this.currentDialogState;
}
/**
* Restores the dialog represented by the given DialogState object.
* NOTE: The dialog's restored() method is also called during this
* method.
*
* @param state The DialogState for the dialog to restore
*/
public void restoreState(DialogState state)
{
this.currentDialogState = state;
// retrieve the dialog and call it's restored() method
this.currentDialogState.getDialog().restored();
}
/**
@@ -74,7 +99,7 @@ public class DialogManager
*/
public DialogConfig getCurrentDialog()
{
return this.currentDialogConfig;
return this.currentDialogState.getConfig();
}
/**
@@ -84,7 +109,7 @@ public class DialogManager
*/
public IDialogBean getBean()
{
return this.currentDialog;
return this.currentDialogState.getDialog();
}
/**
@@ -94,7 +119,7 @@ public class DialogManager
*/
public String getIcon()
{
return this.currentDialogConfig.getIcon();
return this.currentDialogState.getConfig().getIcon();
}
/**
@@ -105,7 +130,7 @@ public class DialogManager
public String getErrorMessage()
{
return Application.getMessage(FacesContext.getCurrentInstance(),
this.currentDialogConfig.getErrorMessageId());
this.currentDialogState.getConfig().getErrorMessageId());
}
/**
@@ -115,15 +140,23 @@ public class DialogManager
*/
public String getTitle()
{
String title = this.currentDialogConfig.getTitleId();
// try and get the title directly from the dialog
String title = this.currentDialogState.getDialog().getTitle();
if (title != null)
if (title == null)
{
title = Application.getMessage(FacesContext.getCurrentInstance(), title);
}
else
{
title = this.currentDialogConfig.getTitle();
// try and get the title via a message bundle key
title = this.currentDialogState.getConfig().getTitleId();
if (title != null)
{
title = Application.getMessage(FacesContext.getCurrentInstance(), title);
}
else
{
// try and get the title from the configuration
title = this.currentDialogState.getConfig().getTitle();
}
}
return title;
@@ -136,15 +169,23 @@ public class DialogManager
*/
public String getDescription()
{
String desc = this.currentDialogConfig.getDescriptionId();
// try and get the description directly from the dialog
String desc = this.currentDialogState.getDialog().getDescription();
if (desc != null)
if (desc == null)
{
desc = Application.getMessage(FacesContext.getCurrentInstance(), desc);
}
else
{
desc = this.currentDialogConfig.getDescription();
// try and get the description via a message bundle key
desc = this.currentDialogState.getConfig().getDescriptionId();
if (desc != null)
{
desc = Application.getMessage(FacesContext.getCurrentInstance(), desc);
}
else
{
// try and get the description from the configuration
desc = this.currentDialogState.getConfig().getDescription();
}
}
return desc;
@@ -158,7 +199,7 @@ public class DialogManager
*/
public String getActions()
{
return this.currentDialogConfig.getActionsConfigId();
return this.currentDialogState.getConfig().getActionsConfigId();
}
/**
@@ -168,7 +209,7 @@ public class DialogManager
*/
public String getPage()
{
return this.currentDialogConfig.getPage();
return this.currentDialogState.getConfig().getPage();
}
/**
@@ -178,7 +219,7 @@ public class DialogManager
*/
public boolean isOKButtonVisible()
{
return this.currentDialogConfig.isOKButtonVisible();
return this.currentDialogState.getConfig().isOKButtonVisible();
}
/**
@@ -191,10 +232,10 @@ public class DialogManager
List<DialogButtonConfig> buttons = null;
// get a list of buttons to display from the configuration
List<DialogButtonConfig> cfgButtons = this.currentDialogConfig.getButtons();
List<DialogButtonConfig> cfgButtons = this.currentDialogState.getConfig().getButtons();
// get a list of buttons added dynamically by the dialog
List<DialogButtonConfig> dynButtons = this.currentDialog.getAdditionalButtons();
List<DialogButtonConfig> dynButtons = this.currentDialogState.getDialog().getAdditionalButtons();
if (cfgButtons != null && dynButtons != null)
{
@@ -223,7 +264,7 @@ public class DialogManager
*/
public String getCancelButtonLabel()
{
return this.currentDialog.getCancelButtonLabel();
return this.currentDialogState.getDialog().getCancelButtonLabel();
}
/**
@@ -233,7 +274,7 @@ public class DialogManager
*/
public String getFinishButtonLabel()
{
return this.currentDialog.getFinishButtonLabel();
return this.currentDialogState.getDialog().getFinishButtonLabel();
}
/**
@@ -243,7 +284,7 @@ public class DialogManager
*/
public boolean getFinishButtonDisabled()
{
return this.currentDialog.getFinishButtonDisabled();
return this.currentDialogState.getDialog().getFinishButtonDisabled();
}
/**
@@ -253,7 +294,7 @@ public class DialogManager
*/
public String finish()
{
return this.currentDialog.finish();
return this.currentDialogState.getDialog().finish();
}
/**
@@ -263,6 +304,6 @@ public class DialogManager
*/
public String cancel()
{
return this.currentDialog.cancel();
return this.currentDialogState.getDialog().cancel();
}
}

View File

@@ -0,0 +1,53 @@
package org.alfresco.web.bean.dialog;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.config.DialogsConfigElement.DialogConfig;
/**
* Object responsible for holding the current state of an active dialog.
*
* @author gavinc
*/
public final class DialogState
{
private DialogConfig config;
private IDialogBean dialog;
/**
* Default constructor
*
* @param config The configuration for the dialog
* @param dialog The dialog bean instance
*/
public DialogState(DialogConfig config, IDialogBean dialog)
{
this.config = config;
this.dialog = dialog;
}
/**
* Returns the configuration for the dialog
*
* @return The dialog configuration
*/
public DialogConfig getConfig()
{
return config;
}
/**
* Returns the bean representing the dialog instance
*
* @return The dialog bean instance
*/
public IDialogBean getDialog()
{
return dialog;
}
@Override
public String toString()
{
return AlfrescoNavigationHandler.DIALOG_PREFIX + this.config.getName();
}
}

View File

@@ -19,6 +19,11 @@ public interface IDialogBean
*/
public void init(Map<String, String> parameters);
/**
* Called when the dialog is restored after a nested dialog is closed
*/
public void restored();
/**
* Method handler called when the cancel button of the dialog is pressed
*
@@ -60,4 +65,22 @@ public interface IDialogBean
* @return true if the button should be disabled
*/
public boolean getFinishButtonDisabled();
/**
* Returns the title to be used for the dialog
* <p>If this returns null the DialogManager will
* lookup the title via the dialog configuration</p>
*
* @return The title or null if the title is to be acquired via configuration
*/
public String getTitle();
/**
* Returns the description to be used for the dialog
* <p>If this returns null the DialogManager will
* lookup the description via the dialog configuration</p>
*
* @return The title or null if the title is to be acquired via configuration
*/
public String getDescription();
}

View File

@@ -12,7 +12,6 @@ import org.alfresco.web.ui.repo.component.property.PropertySheetItem;
*/
public class HeaderSeparatorGenerator extends SeparatorGenerator
{
@Override
protected String getHtml(UIComponent component, PropertySheetItem item)
{
String html = "<div class='wizardSectionHeading mainSubTitle' style='margin-top: 6px; margin-bottom: 6px;'>&nbsp;" +

View File

@@ -0,0 +1,79 @@
package org.alfresco.web.bean.generator;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.alfresco.web.ui.repo.component.property.PropertySheetItem;
import org.alfresco.web.ui.repo.component.property.UIPropertySheet;
/**
* Generates a component to represent a separator.
* <p>The HTML to be used for the separator is configured via the
* <code>setHtml</code> method.
*
* @author gavinc
*/
public class HtmlSeparatorGenerator extends BaseComponentGenerator
{
protected String html = "<b>default</b>";
/**
* Returns the HTML configured to be used for this separator
*
* @return The HTML to display
*/
public String getHtml()
{
return html;
}
/**
* Sets the HTML to display for the separator
*
* @param html The HTML
*/
public void setHtml(String html)
{
this.html = html;
}
@SuppressWarnings("unchecked")
public UIComponent generate(FacesContext context, String id)
{
UIComponent component = this.createOutputTextComponent(context, id);
component.getAttributes().put("escape", Boolean.FALSE);
return component;
}
@Override
@SuppressWarnings("unchecked")
protected UIComponent createComponent(FacesContext context, UIPropertySheet propertySheet,
PropertySheetItem item)
{
UIComponent component = this.generate(context, item.getName());
// set the HTML to use
component.getAttributes().put("value", getResolvedHtml(component, item));
return component;
}
/**
* Returns the resolved HTML to use for the separator.
* <p>In the default case we just return the HTML set
* via setHtml however subclasses may choose to generate
* the resulting HTML using a combination of the HTML set
* via setHtml and the given PropertySheetItem.
*
* @param component The JSF component representing the separator
* @param item The separator item
* @return The resolved HTML
*/
protected String getResolvedHtml(UIComponent component, PropertySheetItem item)
{
// In the default case we just return the HTML set via setHtml
return this.html;
}
}

View File

@@ -0,0 +1,85 @@
package org.alfresco.web.bean.generator;
import javax.faces.component.UIComponent;
import org.alfresco.web.ui.repo.component.property.PropertySheetItem;
/**
* Generates a component to represent a separator that uses the
* property sheet display label configuration. The CSS class used
* for the HTML representing the label can also be configured via
* the <code>setStyleClass</code> method.
*
* @author gavinc
*/
public class LabelSeparatorGenerator extends HtmlSeparatorGenerator
{
protected String style = "margin-top: 6px; margin-bottom: 6px;";
protected String styleClass;
/**
* Returns the CSS class configured to be used for this separator
*
* @return The CSS class
*/
public String getStyleClass()
{
return styleClass;
}
/**
* Sets the CSS class to use for the separator
*
* @param styleClass The CSS class
*/
public void setStyleClass(String styleClass)
{
this.styleClass = styleClass;
}
/**
* Returns the CSS style configured to be used for this separator
*
* @return The CSS style
*/
public String getStyle()
{
return style;
}
/**
* Sets the CSS style to use for the separator
*
* @param style The CSS style
*/
public void setStyle(String style)
{
this.style = style;
}
@Override
protected String getResolvedHtml(UIComponent component, PropertySheetItem item)
{
StringBuilder htmlBuilder = new StringBuilder("<div");
if (this.styleClass != null && this.styleClass.length() > 0)
{
htmlBuilder.append(" class=\"");
htmlBuilder.append(this.styleClass);
htmlBuilder.append("\"");
}
if (this.style != null && this.style.length() > 0)
{
htmlBuilder.append(" style=\"");
htmlBuilder.append(this.style);
htmlBuilder.append("\"");
}
// add the display label and close the div
htmlBuilder.append(">&nbsp;");
htmlBuilder.append(item.getDisplayLabel());
htmlBuilder.append("</div>");
return htmlBuilder.toString();
}
}

View File

@@ -1,49 +1,16 @@
package org.alfresco.web.bean.generator;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.alfresco.web.ui.repo.component.property.PropertySheetItem;
import org.alfresco.web.ui.repo.component.property.UIPropertySheet;
/**
* Generates a component to represent a separator.
* Generates a component to represent a separator using the HTML <code>&lt;hr/&gt;</code> element.
*
* @author gavinc
*/
public class SeparatorGenerator extends BaseComponentGenerator
public class SeparatorGenerator extends HtmlSeparatorGenerator
{
@SuppressWarnings("unchecked")
public UIComponent generate(FacesContext context, String id)
public SeparatorGenerator()
{
UIComponent component = this.createOutputTextComponent(context, id);
component.getAttributes().put("escape", Boolean.FALSE);
// For the standard separator just show a <hr/> element
return component;
}
@Override
@SuppressWarnings("unchecked")
protected UIComponent createComponent(FacesContext context, UIPropertySheet propertySheet,
PropertySheetItem item)
{
UIComponent component = this.generate(context, item.getName());
// set the HTML to use
component.getAttributes().put("value", getHtml(component, item));
return component;
}
/**
* Returns the HTML to display for the separator
*
* @param component The JSF component representing the separator
* @param item The separator item
* @return The HTML
*/
protected String getHtml(UIComponent component, PropertySheetItem item)
{
return "<div style='margin-top: 6px; margin-bottom: 6px;'><hr/></div>";
this.html = "<div style='margin-top: 6px; margin-bottom: 6px;'><hr/></div>";
}
}

View File

@@ -1,7 +1,9 @@
package org.alfresco.web.bean.repository;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -10,6 +12,8 @@ import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
@@ -54,9 +58,6 @@ public class TransientNode extends Node
// initialise the node
initNode(data);
if (logger.isDebugEnabled())
logger.debug("Constructed transient node: " + this);
}
/**
@@ -93,11 +94,64 @@ public class TransientNode extends Node
{
if (assocDef.isChild())
{
this.childAssociations.put(item, data.get(item));
// TODO: handle lists of NodeRef's
NodeRef child = null;
Object obj = data.get(item);
if (obj instanceof String)
{
child = new NodeRef((String)obj);
}
else if (obj instanceof NodeRef)
{
child = (NodeRef)obj;
}
else if (obj instanceof List)
{
if (logger.isWarnEnabled())
logger.warn("0..* child associations are not supported yet");
}
if (child != null)
{
// create a child association reference, add it to a list and add the list
// to the list of child associations for this node
List<ChildAssociationRef> assocs = new ArrayList<ChildAssociationRef>(1);
ChildAssociationRef childRef = new ChildAssociationRef(assocDef.getName(), this.nodeRef,
null, child);
assocs.add(childRef);
this.childAssociations.put(item, assocs);
}
}
else
{
this.associations.put(item, data.get(item));
// TODO: handle lists of NodeRef's
NodeRef target = null;
Object obj = data.get(item);
if (obj instanceof String)
{
target = new NodeRef((String)obj);
}
else if (obj instanceof NodeRef)
{
target = (NodeRef)obj;
}
else if (obj instanceof List)
{
if (logger.isWarnEnabled())
logger.warn("0..* associations are not supported yet");
}
if (target != null)
{
// create a association reference, add it to a list and add the list
// to the list of associations for this node
List<AssociationRef> assocs = new ArrayList<AssociationRef>(1);
AssociationRef assocRef = new AssociationRef(this.nodeRef, assocDef.getName(), target);
assocs.add(assocRef);
this.associations.put(item, assocs);
}
}
}
}
@@ -140,7 +194,7 @@ public class TransientNode extends Node
// don't reset anything otherwise we'll lose our data
// with no way of getting it back!!
}
@Override
public String toString()
{

View File

@@ -130,7 +130,7 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis
Set<String> mailedAuthorities = new HashSet<String>(usersGroups.size());
// walk the list of users/groups to notify
// walk the list of users/groups to notify - handle duplicates along the way
for (Map node : usersGroups)
{
String authority = (String)node.get(PROP_USERNAME);
@@ -254,31 +254,47 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis
tx = Repository.getUserTransaction(context, true);
tx.begin();
// Return all the permissions set against the current node
// for any authentication instance (user/group).
// Then combine them into a single list for each authentication found.
// Return all the permissions set against the current node for any authentication
// instance (user/group), walking the parent space inheritance chain.
// Then combine them into a single list for each authentication found.
String currentAuthority = Application.getCurrentUser(context).getUserName();
Map<String, List<String>> permissionMap = new HashMap<String, List<String>>(8, 1.0f);
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(getSpace().getNodeRef());
for (AccessPermission permission : permissions)
NodeRef spaceRef = getSpace().getNodeRef();
while (spaceRef != null)
{
// we are only interested in Allow and not groups/owner etc.
if (permission.getAccessStatus() == AccessStatus.ALLOWED &&
(permission.getAuthorityType() == AuthorityType.USER ||
permission.getAuthorityType() == AuthorityType.GROUP ||
permission.getAuthorityType() == AuthorityType.GUEST ||
permission.getAuthorityType() == AuthorityType.EVERYONE))
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(spaceRef);
for (AccessPermission permission : permissions)
{
String authority = permission.getAuthority();
List<String> userPermissions = permissionMap.get(authority);
if (userPermissions == null)
// we are only interested in Allow and not Guest/Everyone/owner
if (permission.getAccessStatus() == AccessStatus.ALLOWED &&
(permission.getAuthorityType() == AuthorityType.USER ||
permission.getAuthorityType() == AuthorityType.GROUP))
{
// create for first time
userPermissions = new ArrayList<String>(4);
permissionMap.put(authority, userPermissions);
String authority = permission.getAuthority();
if (currentAuthority.equals(authority) == false)
{
List<String> userPermissions = permissionMap.get(authority);
if (userPermissions == null)
{
// create for first time
userPermissions = new ArrayList<String>(4);
permissionMap.put(authority, userPermissions);
}
// add the permission name for this authority
userPermissions.add(permission.getPermission());
}
}
// add the permission name for this authority
userPermissions.add(permission.getPermission());
}
// walk parent inheritance chain until root or no longer inherits
if (permissionService.getInheritParentPermissions(spaceRef))
{
spaceRef = nodeService.getPrimaryParent(spaceRef).getParentRef();
}
else
{
spaceRef = null;
}
}
@@ -316,79 +332,6 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis
}
return this.usersGroups;
}
/**
* Build a Map representing a user/group with a set of useful property values required
* by the UIUserGroupPicker UI component.
*
* @param authority User/Group authority
* @param roles Role text for the authority
*
* @return Map
*/
private Map buildAuthorityMap(String authority, String roles)
{
Map node = null;
if (AuthorityType.getAuthorityType(authority) == AuthorityType.GUEST ||
this.personService.personExists(authority))
{
NodeRef nodeRef = this.personService.getPerson(authority);
if (nodeRef != null)
{
// create our Node representation
node = new MapNode(nodeRef);
// set data binding properties
// this will also force initialisation of the props now during the UserTransaction
// it is much better for performance to do this now rather than during page bind
Map<String, Object> props = ((MapNode)node).getProperties();
props.put(PROP_FULLNAME, ((String)props.get("firstName")) + ' ' + ((String)props.get("lastName")));
props.put(PROP_ICON, WebResources.IMAGE_PERSON);
props.put(PROP_ISGROUP, false);
}
}
else if (AuthorityType.getAuthorityType(authority) == AuthorityType.GROUP)
{
// need a map (dummy node) to represent props for this Group Authority
node = new HashMap<String, Object>(8, 1.0f);
if (authority.startsWith(PermissionService.GROUP_PREFIX) == true)
{
node.put(PROP_FULLNAME, authority.substring(PermissionService.GROUP_PREFIX.length()));
}
else
{
node.put(PROP_FULLNAME, authority);
}
node.put(PROP_USERNAME, authority);
node.put(PROP_ID, authority);
node.put(PROP_ICON, WebResources.IMAGE_GROUP);
node.put(PROP_ISGROUP, true);
node.put(PROP_EXPANDED, false);
}
if (node != null)
{
// add the common properties
node.put(PROP_ROLES, roles);
node.put(PROP_PARENT, null);
if (this.userGroupLookup.get(authority) != null)
{
// this authority already exists in the list somewhere else - mark as duplicate
node.put(PROP_DUPLICATE, true);
node.put(PROP_SELECTED, false);
}
else
{
// add to table for the first time, not a duplicate
this.userGroupLookup.put(authority, node);
node.put(PROP_DUPLICATE, false);
node.put(PROP_SELECTED, true);
}
}
return node;
}
/**
* @return TemplateMailHelperBean instance for this wizard
@@ -398,6 +341,29 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis
return this.mailHelper;
}
/**
* @return true if any authorities are selected, false otherwise
*/
public boolean getFinishButtonDisabled()
{
boolean disabled = true;
if (this.usersGroups != null)
{
for (Map userGroup : this.usersGroups)
{
if (((Boolean)userGroup.get(PROP_EXPANDED)) == false &&
((Boolean)userGroup.get(PROP_SELECTED)) == true)
{
disabled = false;
break;
}
}
}
return disabled;
}
// ------------------------------------------------------------------------------
// Action Event Listeners
@@ -435,16 +401,25 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis
{
// expand the list for this group by adding the immediate child authorities
boolean selected = (Boolean)userGroup.get(PROP_SELECTED);
String currentAuthority =
Application.getCurrentUser(FacesContext.getCurrentInstance()).getUserName();
Set<String> authorities = authorityService.getContainedAuthorities(
null, pickerEvent.Authority, true);
for (String authority : authorities)
{
Map node = buildAuthorityMap(authority, (String)userGroup.get(PROP_ROLES));
if (node != null)
if (currentAuthority.equals(authority) == false)
{
node.put(PROP_PARENT, userGroup);
node.put(PROP_SELECTED, selected);
this.usersGroups.add(++index, node);
if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER ||
AuthorityType.getAuthorityType(authority) == AuthorityType.GROUP)
{
Map node = buildAuthorityMap(authority, (String)userGroup.get(PROP_ROLES));
if (node != null)
{
node.put(PROP_PARENT, userGroup);
node.put(PROP_SELECTED, selected);
this.usersGroups.add(++index, node);
}
}
}
}
}
@@ -494,4 +469,81 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis
}
}
}
// ------------------------------------------------------------------------------
// Private helpers
/**
* Build a Map representing a user/group with a set of useful property values required
* by the UIUserGroupPicker UI component.
*
* @param authority User/Group authority
* @param roles Role text for the authority
*
* @return Map
*/
private Map buildAuthorityMap(String authority, String roles)
{
Map node = null;
if (AuthorityType.getAuthorityType(authority) == AuthorityType.GUEST ||
this.personService.personExists(authority))
{
NodeRef nodeRef = this.personService.getPerson(authority);
if (nodeRef != null)
{
// create our Node representation
node = new MapNode(nodeRef);
// set data binding properties
// this will also force initialisation of the props now during the UserTransaction
// it is much better for performance to do this now rather than during page bind
Map<String, Object> props = ((MapNode)node).getProperties();
props.put(PROP_FULLNAME, ((String)props.get("firstName")) + ' ' + ((String)props.get("lastName")));
props.put(PROP_ICON, WebResources.IMAGE_PERSON);
props.put(PROP_ISGROUP, false);
}
}
else if (AuthorityType.getAuthorityType(authority) == AuthorityType.GROUP)
{
// need a map (dummy node) to represent props for this Group Authority
node = new HashMap<String, Object>(8, 1.0f);
if (authority.startsWith(PermissionService.GROUP_PREFIX) == true)
{
node.put(PROP_FULLNAME, authority.substring(PermissionService.GROUP_PREFIX.length()));
}
else
{
node.put(PROP_FULLNAME, authority);
}
node.put(PROP_USERNAME, authority);
node.put(PROP_ID, authority);
node.put(PROP_ICON, WebResources.IMAGE_GROUP);
node.put(PROP_ISGROUP, true);
}
if (node != null)
{
// add the common properties
node.put(PROP_ROLES, roles);
node.put(PROP_PARENT, null);
node.put(PROP_EXPANDED, false);
if (this.userGroupLookup.get(authority) != null)
{
// this authority already exists in the list somewhere else - mark as duplicate
node.put(PROP_DUPLICATE, true);
node.put(PROP_SELECTED, false);
}
else
{
// add to table for the first time, not a duplicate
this.userGroupLookup.put(authority, node);
node.put(PROP_DUPLICATE, false);
node.put(PROP_SELECTED, true);
}
}
return node;
}
}

View File

@@ -26,16 +26,12 @@ import org.apache.commons.logging.LogFactory;
*
* @author gavinc
*/
public class WizardManager
public final class WizardManager
{
private static Log logger = LogFactory.getLog(WizardManager.class);
protected int currentStep = 1;
protected PageConfig currentPageCfg;
protected WizardConfig currentWizardConfig;
protected IWizardBean currentWizard;
protected List<StepConfig> steps;
protected Map<String, String> currentWizardParams;
private WizardState currentWizardState;
private Map<String, String> paramsToApply;
/**
* Action handler used to setup parameters for the wizard being launched
@@ -49,7 +45,7 @@ public class WizardManager
if (component instanceof UIActionLink)
{
// store the parameters
this.currentWizardParams = ((UIActionLink)component).getParameterMap();
this.paramsToApply = ((UIActionLink)component).getParameterMap();
}
}
@@ -60,31 +56,53 @@ public class WizardManager
*/
public void setCurrentWizard(WizardConfig config)
{
this.currentStep = 1;
this.currentWizardConfig = config;
String beanName = this.currentWizardConfig.getManagedBean();
this.currentWizard = (IWizardBean)FacesHelper.getManagedBean(
String beanName = config.getManagedBean();
IWizardBean wizard = (IWizardBean)FacesHelper.getManagedBean(
FacesContext.getCurrentInstance(), beanName);
if (this.currentWizard == null)
if (wizard == null)
{
throw new AlfrescoRuntimeException("Failed to find managed bean '" + beanName + "'");
}
// initialise the managed bean
this.currentWizard.init(this.currentWizardParams);
wizard.init(this.paramsToApply);
// reset the current parameters so subsequent wizards don't get them
this.currentWizardParams = null;
this.paramsToApply = null;
// get the steps for the wizard
this.steps = this.currentWizardConfig.getStepsAsList();
// create the WizardState object
this.currentWizardState = new WizardState(config, wizard);
// setup the first step
determineCurrentPage();
}
/**
* Returns the state of the currently active wizard
*
* @return Current wizard's state
*/
public WizardState getState()
{
return this.currentWizardState;
}
/**
* Restores the wizard represented by the given WizardState object.
* NOTE: The wizard's restored() method is also called during this
* method.
*
* @param state The WizardState for the wizard to restore
*/
public void restoreState(WizardState state)
{
this.currentWizardState = state;
// retrieve the wizard and call it's restored() method
this.currentWizardState.getWizard().restored();
}
/**
* Returns the config for the current wizard
*
@@ -92,7 +110,7 @@ public class WizardManager
*/
public WizardConfig getCurrentWizard()
{
return this.currentWizardConfig;
return this.currentWizardState.getConfig();
}
/**
@@ -102,7 +120,7 @@ public class WizardManager
*/
public IWizardBean getBean()
{
return this.currentWizard;
return this.currentWizardState.getWizard();
}
/**
@@ -112,7 +130,7 @@ public class WizardManager
*/
public String getIcon()
{
return this.currentWizardConfig.getIcon();
return this.currentWizardState.getConfig().getIcon();
}
/**
@@ -123,7 +141,7 @@ public class WizardManager
public String getErrorMessage()
{
return Application.getMessage(FacesContext.getCurrentInstance(),
this.currentWizardConfig.getErrorMessageId());
this.currentWizardState.getConfig().getErrorMessageId());
}
/**
@@ -133,15 +151,23 @@ public class WizardManager
*/
public String getTitle()
{
String title = this.currentWizardConfig.getTitleId();
// try and get the title directly from the wizard
String title = this.currentWizardState.getWizard().getTitle();
if (title != null)
if (title == null)
{
title = Application.getMessage(FacesContext.getCurrentInstance(), title);
}
else
{
title = this.currentWizardConfig.getTitle();
// try and get the title via a message bundle key
title = this.currentWizardState.getConfig().getTitleId();
if (title != null)
{
title = Application.getMessage(FacesContext.getCurrentInstance(), title);
}
else
{
// try and get the title from the configuration
title = this.currentWizardState.getConfig().getTitle();
}
}
return title;
@@ -154,15 +180,23 @@ public class WizardManager
*/
public String getDescription()
{
String desc = this.currentWizardConfig.getDescriptionId();
// try and get the description directly from the dialog
String desc = this.currentWizardState.getWizard().getDescription();
if (desc != null)
if (desc == null)
{
desc = Application.getMessage(FacesContext.getCurrentInstance(), desc);
}
else
{
desc = this.currentWizardConfig.getDescription();
// try and get the description via a message bundle key
desc = this.currentWizardState.getConfig().getDescriptionId();
if (desc != null)
{
desc = Application.getMessage(FacesContext.getCurrentInstance(), desc);
}
else
{
// try and get the description from the configuration
desc = this.currentWizardState.getConfig().getDescription();
}
}
return desc;
@@ -175,7 +209,7 @@ public class WizardManager
*/
public int getCurrentStep()
{
return this.currentStep;
return this.currentWizardState.getCurrentStep();
}
/**
@@ -185,7 +219,7 @@ public class WizardManager
*/
public String getCurrentStepAsString()
{
return Integer.toString(this.currentStep);
return Integer.toString(this.currentWizardState.getCurrentStep());
}
/**
@@ -197,7 +231,8 @@ public class WizardManager
*/
public String getCurrentStepName()
{
return ((StepConfig)this.steps.get(this.currentStep-1)).getName();
return ((StepConfig)this.currentWizardState.getSteps().get(
this.currentWizardState.getCurrentStep()-1)).getName();
}
/**
@@ -207,12 +242,12 @@ public class WizardManager
*/
public List<UIListItem> getStepItems()
{
List<UIListItem> items = new ArrayList<UIListItem>(this.steps.size());
List<UIListItem> items = new ArrayList<UIListItem>(this.currentWizardState.getSteps().size());
for (int x = 0; x < this.steps.size(); x++)
for (int x = 0; x < this.currentWizardState.getSteps().size(); x++)
{
String uiStepNumber = Integer.toString(x + 1);
StepConfig stepCfg = this.steps.get(x);
StepConfig stepCfg = this.currentWizardState.getSteps().get(x);
UIListItem item = new UIListItem();
item.setValue(uiStepNumber);
@@ -255,7 +290,7 @@ public class WizardManager
*/
public String getPage()
{
return this.currentPageCfg.getPath();
return this.currentWizardState.getCurrentPageCfg().getPath();
}
/**
@@ -265,7 +300,7 @@ public class WizardManager
*/
public String getStepTitle()
{
String title = this.currentPageCfg.getTitleId();
String title = this.currentWizardState.getCurrentPageCfg().getTitleId();
if (title != null)
{
@@ -273,7 +308,7 @@ public class WizardManager
}
else
{
title = this.currentPageCfg.getTitle();
title = this.currentWizardState.getCurrentPageCfg().getTitle();
}
return title;
@@ -286,7 +321,7 @@ public class WizardManager
*/
public String getStepDescription()
{
String desc = this.currentPageCfg.getDescriptionId();
String desc = this.currentWizardState.getCurrentPageCfg().getDescriptionId();
if (desc != null)
{
@@ -294,7 +329,7 @@ public class WizardManager
}
else
{
desc = this.currentPageCfg.getDescription();
desc = this.currentWizardState.getCurrentPageCfg().getDescription();
}
return desc;
@@ -307,7 +342,7 @@ public class WizardManager
*/
public String getStepInstructions()
{
String instruction = this.currentPageCfg.getInstructionId();
String instruction = this.currentWizardState.getCurrentPageCfg().getInstructionId();
if (instruction != null)
{
@@ -315,7 +350,7 @@ public class WizardManager
}
else
{
instruction = this.currentPageCfg.getInstruction();
instruction = this.currentWizardState.getCurrentPageCfg().getInstruction();
}
return instruction;
@@ -328,7 +363,7 @@ public class WizardManager
*/
public String getNextButtonLabel()
{
return this.currentWizard.getNextButtonLabel();
return this.currentWizardState.getWizard().getNextButtonLabel();
}
/**
@@ -338,13 +373,13 @@ public class WizardManager
*/
public boolean getNextButtonDisabled()
{
if (this.currentStep == this.steps.size())
if (this.currentWizardState.getCurrentStep() == this.currentWizardState.getSteps().size())
{
return true;
}
else
{
return this.currentWizard.getNextButtonDisabled();
return this.currentWizardState.getWizard().getNextButtonDisabled();
}
}
@@ -355,7 +390,7 @@ public class WizardManager
*/
public String getBackButtonLabel()
{
return this.currentWizard.getBackButtonLabel();
return this.currentWizardState.getWizard().getBackButtonLabel();
}
/**
@@ -365,7 +400,7 @@ public class WizardManager
*/
public boolean getBackButtonDisabled()
{
if (this.currentStep == 1)
if (this.currentWizardState.getCurrentStep() == 1)
{
return true;
}
@@ -382,7 +417,7 @@ public class WizardManager
*/
public String getCancelButtonLabel()
{
return this.currentWizard.getCancelButtonLabel();
return this.currentWizardState.getWizard().getCancelButtonLabel();
}
/**
@@ -392,7 +427,7 @@ public class WizardManager
*/
public String getFinishButtonLabel()
{
return this.currentWizard.getFinishButtonLabel();
return this.currentWizardState.getWizard().getFinishButtonLabel();
}
/**
@@ -402,13 +437,13 @@ public class WizardManager
*/
public boolean getFinishButtonDisabled()
{
if (this.currentStep == this.steps.size())
if (this.currentWizardState.getCurrentStep() == this.currentWizardState.getSteps().size())
{
return false;
}
else
{
return this.currentWizard.getFinishButtonDisabled();
return this.currentWizardState.getWizard().getFinishButtonDisabled();
}
}
@@ -419,13 +454,16 @@ public class WizardManager
*/
public void next()
{
this.currentStep++;
// calculate next step number and update wizard state
int currentStep = this.currentWizardState.getCurrentStep();
currentStep++;
this.currentWizardState.setCurrentStep(currentStep);
if (logger.isDebugEnabled())
logger.debug("next called, current step is now: " + this.currentStep);
logger.debug("next called, current step is now: " + this.currentWizardState.getCurrentStep());
// tell the wizard the next button has been pressed
this.currentWizard.next();
this.currentWizardState.getWizard().next();
determineCurrentPage();
}
@@ -437,13 +475,16 @@ public class WizardManager
*/
public void back()
{
this.currentStep--;
// calculate next step number and update wizard state
int currentStep = this.currentWizardState.getCurrentStep();
currentStep--;
this.currentWizardState.setCurrentStep(currentStep);
if (logger.isDebugEnabled())
logger.debug("back called, current step is now: " + this.currentStep);
logger.debug("back called, current step is now: " + this.currentWizardState.getCurrentStep());
// tell the wizard the back button has been pressed
this.currentWizard.back();
this.currentWizardState.getWizard().back();
determineCurrentPage();
}
@@ -455,7 +496,7 @@ public class WizardManager
*/
public String finish()
{
return this.currentWizard.finish();
return this.currentWizardState.getWizard().finish();
}
/**
@@ -465,7 +506,7 @@ public class WizardManager
*/
public String cancel()
{
return this.currentWizard.cancel();
return this.currentWizardState.getWizard().cancel();
}
/**
@@ -473,10 +514,14 @@ public class WizardManager
*/
protected void determineCurrentPage()
{
this.currentPageCfg = null;
// reset the current page config in the state object
this.currentWizardState.setCurrentPageCfg(null);
PageConfig currentPageCfg = null;
// get the config for the current step position
StepConfig stepCfg = this.steps.get(this.currentStep-1);
StepConfig stepCfg = this.currentWizardState.getSteps().get(
this.currentWizardState.getCurrentStep()-1);
// is the step conditional?
if (stepCfg.hasConditionalPages())
@@ -497,25 +542,28 @@ public class WizardManager
Object obj = vb.getValue(context);
if (obj instanceof Boolean && ((Boolean)obj).booleanValue())
{
this.currentPageCfg = pageCfg;
currentPageCfg = pageCfg;
break;
}
}
}
// if none of the conditions passed use the default page
if (this.currentPageCfg == null)
if (currentPageCfg == null)
{
this.currentPageCfg = stepCfg.getDefaultPage();
currentPageCfg = stepCfg.getDefaultPage();
}
if (this.currentPageCfg == null)
if (currentPageCfg == null)
{
throw new AlfrescoRuntimeException("Failed to determine page for step '" + stepCfg.getName() +
"'. Make sure a default page is configured.");
}
// save the current page config in the state object
this.currentWizardState.setCurrentPageCfg(currentPageCfg);
if (logger.isDebugEnabled())
logger.debug("Config for current page: " + this.currentPageCfg);
logger.debug("Config for current page: " + this.currentWizardState.getCurrentPageCfg());
}
}

View File

@@ -0,0 +1,113 @@
package org.alfresco.web.bean.wizard;
import java.util.List;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.config.WizardsConfigElement.PageConfig;
import org.alfresco.web.config.WizardsConfigElement.StepConfig;
import org.alfresco.web.config.WizardsConfigElement.WizardConfig;
/**
* Object responsible for holding the current state of an active wizard.
*
* @author gavinc
*/
public final class WizardState
{
private int currentStep = 1;
private PageConfig currentPageCfg;
private WizardConfig config;
private IWizardBean wizard;
private List<StepConfig> steps;
/**
* Default constructor
*
* @param config The configuration for the wizard
* @param wizard The wizard bean instance
*/
public WizardState(WizardConfig config, IWizardBean wizard)
{
this.config = config;
this.wizard = wizard;
this.steps = this.config.getStepsAsList();
}
/**
* Sets the configuration for the current page of the wizard
*
* @param currentPageCfg The configuration
*/
public void setCurrentPageCfg(PageConfig currentPageCfg)
{
this.currentPageCfg = currentPageCfg;
}
/**
* Sets the current step the wizard is on
*
* @param currentStep The current step number
*/
public void setCurrentStep(int currentStep)
{
this.currentStep = currentStep;
}
/**
* Returns the wizard bean instance
*
* @return The wizard bean instance
*/
public IWizardBean getWizard()
{
return this.wizard;
}
/**
* Returns the configuration for the current wizard
*
* @return The wizard configuration
*/
public WizardConfig getConfig()
{
return this.config;
}
/**
* Returns the configuration for the current page of the wizard
*
* @return The current page configuration
*/
public PageConfig getCurrentPageCfg()
{
return currentPageCfg;
}
/**
* The current step the wizard is on
*
* @return The current wizard step
*/
public int getCurrentStep()
{
return currentStep;
}
/**
* Returns the list of steps the wizard has
*
* @return List of wizard steps
*/
public List<StepConfig> getSteps()
{
return steps;
}
@Override
public String toString()
{
return AlfrescoNavigationHandler.WIZARD_PREFIX + this.config.getName() +
"[" + this.currentStep + "]";
}
}

View File

@@ -0,0 +1,667 @@
package org.alfresco.web.bean.workflow;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
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.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.cmr.workflow.WorkflowTransition;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.MapNode;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.NodePropertyResolver;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.TransientNode;
import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean implementation for the "Manage Task" dialog.
*
* @author gavinc
*/
public class ManageTaskDialog extends BaseDialogBean
{
protected WorkflowService workflowService;
protected Node taskNode;
protected WorkflowTask task;
protected WorkflowInstance workflowInstance;
protected WorkflowTransition[] transitions;
protected NodeRef workflowPackage;
protected List<Node> resources;
protected TaskCompleteResolver completeResolver = new TaskCompleteResolver();
protected UIRichList packageItemsRichList;
protected List<String> packageItemsToAdd;
protected List<String> packageItemsToRemove;
protected String[] itemsToAdd;
protected boolean isItemBeingAdded = false;
protected final Log logger = LogFactory.getLog(getClass());
protected static final String ID_PREFIX = "transition_";
protected static final String CLIENT_ID_PREFIX = AlfrescoNavigationHandler.DIALOG_PREFIX + ID_PREFIX;
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
// reset variables
this.task = null;
this.taskNode = null;
this.workflowInstance = null;
this.transitions = null;
this.workflowPackage = null;
this.resources = null;
this.itemsToAdd = null;
this.packageItemsToAdd = null;
this.packageItemsToRemove = null;
this.isItemBeingAdded = false;
if (this.packageItemsRichList != null)
{
this.packageItemsRichList.setValue(null);
this.packageItemsRichList = null;
}
// get the task details
String taskId = this.parameters.get("id");
this.task = this.workflowService.getTaskById(taskId);
if (this.task != null)
{
// setup a transient node to represent the task we're managing
WorkflowTaskDefinition taskDef = this.task.definition;
this.taskNode = new TransientNode(taskDef.metadata.getName(),
"task_" + System.currentTimeMillis(), this.task.properties);
// get access to the workflow instance for the task
this.workflowInstance = this.task.path.instance;
// setup the workflow package for the task
Serializable obj = this.task.properties.get(WorkflowModel.ASSOC_PACKAGE);
// TODO: remove this workaroud where JBPM may return a String and not the NodeRef
if (obj instanceof NodeRef)
{
this.workflowPackage = (NodeRef)obj;
}
else if (obj instanceof String)
{
this.workflowPackage = new NodeRef((String)obj);
}
if (logger.isDebugEnabled())
{
logger.debug("Task: " + this.task);
logger.debug("Trasient node: " + this.taskNode);
logger.debug("Workflow package: " + this.workflowPackage );
}
}
}
@Override
public void restored()
{
// reset the workflow package rich list so everything gets re-evaluated
if (this.packageItemsRichList != null)
{
this.packageItemsRichList.setValue(null);
this.packageItemsRichList = null;
}
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
if (logger.isDebugEnabled())
logger.debug("Saving task: " + this.task.id);
// prepare the edited parameters for saving
Map<QName, Serializable> params = WorkflowBean.prepareTaskParams(this.taskNode);
if (logger.isDebugEnabled())
logger.debug("Saving task with parameters: " + params);
// remove any items the user selected to remove
if (this.workflowPackage != null && this.packageItemsToRemove != null &&
this.packageItemsToRemove.size() > 0)
{
for (String removedItem : this.packageItemsToRemove)
{
this.nodeService.removeChild(this.workflowPackage, new NodeRef(removedItem));
}
}
// add any items the user selected to add
if (this.workflowPackage != null && this.packageItemsToAdd != null &&
this.packageItemsToAdd.size() > 0)
{
for (String addedItem : this.packageItemsToAdd)
{
NodeRef addedNodeRef = new NodeRef(addedItem);
this.nodeService.addChild(this.workflowPackage, addedNodeRef,
ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
QName.createValidLocalName((String)this.nodeService.getProperty(
addedNodeRef, ContentModel.PROP_NAME))));
}
}
// update the task with the updated parameters
this.workflowService.updateTask(this.task.id, params, null, null);
return outcome;
}
@Override
public List<DialogButtonConfig> getAdditionalButtons()
{
List<DialogButtonConfig> buttons = null;
if (this.task != null)
{
// get the transitions available from this task and
// show them in the dialog as additional buttons
this.transitions = this.task.path.node.transitions;
if (this.transitions != null)
{
buttons = new ArrayList<DialogButtonConfig>(this.transitions.length);
for (WorkflowTransition trans : this.transitions)
{
buttons.add(new DialogButtonConfig(ID_PREFIX + trans.title, trans.title, null,
"#{DialogManager.bean.transition}", "false", null));
}
}
}
return buttons;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "save");
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getTitle()
{
String titleStart = Application.getMessage(FacesContext.getCurrentInstance(), "manage_task_title");
return titleStart + ": " + this.task.title;
}
@Override
public String getDescription()
{
return this.task.description;
}
// ------------------------------------------------------------------------------
// Event handlers
@SuppressWarnings("unused")
public String transition()
{
String outcome = getDefaultFinishOutcome();
if (logger.isDebugEnabled())
logger.debug("Transitioning task: " + this.task.id);
// to find out which transition button was pressed we need
// to look for the button's id in the request parameters,
// the first non-null result is the button that was pressed.
FacesContext context = FacesContext.getCurrentInstance();
Map reqParams = context.getExternalContext().getRequestParameterMap();
String selectedTransition = null;
for (WorkflowTransition trans : this.transitions)
{
Object result = reqParams.get(CLIENT_ID_PREFIX + trans.title);
if (result != null)
{
// this was the button that was pressed
selectedTransition = trans.id;
break;
}
}
if (selectedTransition != null)
{
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context);
tx.begin();
// prepare the edited parameters for saving
Map<QName, Serializable> params = WorkflowBean.prepareTaskParams(this.taskNode);
if (logger.isDebugEnabled())
logger.debug("Transitioning task with parameters: " + params);
// update the task with the updated parameters
this.workflowService.updateTask(this.task.id, params, null, null);
// signal the selected transition to the workflow task
this.workflowService.endTask(this.task.id, selectedTransition);
// commit the changes
tx.commit();
if (logger.isDebugEnabled())
logger.debug("Ended task with transition: " + selectedTransition);
}
catch (Throwable e)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage(formatErrorMessage(e), e);
outcome = this.getErrorOutcome(e);
}
}
return outcome;
}
/**
* Prepares the dialog to allow the user to add an item to the workflow package
*
* @param event The event
*/
public void prepareForAdd(ActionEvent event)
{
this.isItemBeingAdded = true;
}
/**
* Cancels the adding of an item to the workflow package
*
* @param event The event
*/
public void cancelAddPackageItems(ActionEvent event)
{
this.isItemBeingAdded = false;
}
/**
* Adds an item to the workflow package
*
* @param event The event
*/
public void addPackageItems(ActionEvent event)
{
if (this.itemsToAdd != null)
{
if (this.packageItemsToAdd == null)
{
// create the list of items to add if necessary
this.packageItemsToAdd = new ArrayList<String>(this.itemsToAdd.length);
}
for (String item : this.itemsToAdd)
{
// if this item is in the remove list it means it was there originally
// and has now been re-added, as a result we don't need to do anything
// to the original workflow package, therefore remove from the remove list
if (this.packageItemsToRemove != null && this.packageItemsToRemove.contains(item))
{
this.packageItemsToRemove.remove(item);
if (logger.isDebugEnabled())
logger.debug("Removed item from the removed list: " + item);
}
else
{
this.packageItemsToAdd.add(item);
if (logger.isDebugEnabled())
logger.debug("Added item to the added list: " + item);
}
}
// reset the rich list so it re-renders
this.packageItemsRichList.setValue(null);
}
this.isItemBeingAdded = false;
this.itemsToAdd = null;
}
/**
* Removes an item from the workflow package
*
* @param event The event containing a reference to the item to remove
*/
public void removePackageItem(ActionEvent event)
{
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String nodeRef = new NodeRef(Repository.getStoreRef(), params.get("id")).toString();
if (this.packageItemsToAdd != null && this.packageItemsToAdd.contains(nodeRef))
{
// remove the item from the added list if it was added in this dialog session
this.packageItemsToAdd.remove(nodeRef);
if (logger.isDebugEnabled())
logger.debug("Removed item from the added list: " + nodeRef);
}
else
{
// add the node to the list of items to remove
if (this.packageItemsToRemove == null)
{
this.packageItemsToRemove = new ArrayList<String>(1);
}
this.packageItemsToRemove.add(nodeRef);
if (logger.isDebugEnabled())
logger.debug("Added item to the removed list: " + nodeRef);
}
// reset the rich list so it re-renders
this.packageItemsRichList.setValue(null);
}
/**
* Toggles the complete flag for a workflow package item
*
* @param event The event containing a reference to the item to toggle the status for
*/
public void togglePackageItemComplete(ActionEvent event)
{
// TODO: implement this!
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* Returns a String array of NodeRef's that are being added to the workflow package
*
* @return String array of NodeRef's
*/
public String[] getItemsToAdd()
{
return this.itemsToAdd;
}
/**
* Sets the NodeRef's to add as items to the workflow package
*
* @param itemsToAdd NodeRef's to add to the workflow package
*/
public void setItemsToAdd(String[] itemsToAdd)
{
this.itemsToAdd = itemsToAdd;
}
/**
* Determines whether an item is currently being added to the workflow package
*
* @return true if an item is being added
*/
public boolean isItemBeingAdded()
{
return this.isItemBeingAdded;
}
/**
* Sets the rich list being used for the workflow package items
*
* @param richList The rich list instance
*/
public void setPackageItemsRichList(UIRichList richList)
{
this.packageItemsRichList = richList;
}
/**
* Returns the rich list being used for the workflow package items
*
* @return The rich list instance
*/
public UIRichList getPackageItemsRichList()
{
return this.packageItemsRichList;
}
/**
* Returns the Node representing the task
*
* @return The node
*/
public Node getTaskNode()
{
return this.taskNode;
}
/**
* Returns the WorkflowInstance that the current task belongs to
*
* @return The workflow instance
*/
public WorkflowInstance getWorkflowInstance()
{
return this.workflowInstance;
}
/**
* Returns the action group the current task uses for the workflow package
*
* @return action group id
*/
public String getPackageActionGroup()
{
return (String)this.task.properties.get(
WorkflowModel.PROP_PACKAGE_ACTION_GROUP);
}
/**
* Returns the action group the current task uses for each workflow package item
*
* @return action group id
*/
public String getPackageItemActionGroup()
{
return (String)this.task.properties.get(
WorkflowModel.PROP_PACKAGE_ITEM_ACTION_GROUP);
}
/**
* Returns a list of resources associated with this task
* i.e. the children of the workflow package
*
* @return The list of nodes
*/
public List<Node> getResources()
{
this.resources = new ArrayList<Node>(4);
if (this.workflowPackage != null)
{
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context, true);
tx.begin();
// get existing workflow package items
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(
this.workflowPackage, ContentModel.ASSOC_CONTAINS,
RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef ref: childRefs)
{
// create our Node representation from the NodeRef
NodeRef nodeRef = ref.getChildRef();
if (this.nodeService.exists(nodeRef))
{
// find it's type so we can see if it's a node we are interested in
QName type = this.nodeService.getType(nodeRef);
// make sure the type is defined in the data dictionary
TypeDefinition typeDef = this.dictionaryService.getType(type);
if (typeDef != null)
{
// look for content nodes or links to content
// NOTE: folders within workflow packages are ignored for now
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) ||
ContentModel.TYPE_FILELINK.equals(type))
{
// if the node is not in the removed list then add create the
// client side representation and add to the list
if (this.packageItemsToRemove == null ||
this.packageItemsToRemove.contains(nodeRef.toString()) == false)
{
createAndAddNode(nodeRef);
}
}
}
else
{
if (logger.isWarnEnabled())
logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
}
}
else
{
if (logger.isDebugEnabled())
logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository");
}
}
// now iterate through the items to add list and add them to the list of resources
if (this.packageItemsToAdd != null)
{
for (String newItem : this.packageItemsToAdd)
{
NodeRef nodeRef = new NodeRef(newItem);
if (this.nodeService.exists(nodeRef))
{
// we know the type is correct as this was added as a result of a query
// for all content items so just add the item to the resources list
createAndAddNode(nodeRef);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository");
}
}
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
this.resources = Collections.<Node>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
}
else if (logger.isDebugEnabled())
{
logger.debug("Failed to find workflow package for task: " + this.task.id);
}
return this.resources;
}
/**
* Sets the workflow service to use
*
* @param workflowService
* WorkflowService instance
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
// ------------------------------------------------------------------------------
// Helper methods
protected void createAndAddNode(NodeRef nodeRef)
{
// create our Node representation
MapNode node = new MapNode(nodeRef, this.nodeService, true);
this.browseBean.setupCommonBindingProperties(node);
// add property resolvers to show path information
node.addPropertyResolver("path", this.browseBean.resolverPath);
node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath);
// add a property resolver to indicate whether the item has been completed or not
// node.addPropertyResolver("completed", this.completeResolver);
this.resources.add(node);
}
// ------------------------------------------------------------------------------
// Inner classes
/**
* Property resolver to determine if the given node has been flagged as complete
*/
protected class TaskCompleteResolver implements NodePropertyResolver
{
public Object get(Node node)
{
String result = Application.getMessage(FacesContext.getCurrentInstance(), "no");
List<NodeRef> completedItems = (List<NodeRef>)task.properties.get(
WorkflowModel.PROP_COMPLETED_ITEMS);
if (completedItems != null && completedItems.size() > 0 &&
completedItems.contains(node.getNodeRef()))
{
result = Application.getMessage(FacesContext.getCurrentInstance(), "yes");
}
return result;
}
}
}

View File

@@ -1,476 +0,0 @@
package org.alfresco.web.bean.workflow;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
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.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.cmr.workflow.WorkflowTransition;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.MapNode;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.NodePropertyResolver;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.TransientNode;
import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean implementation for the "Manage WorkItem" dialog.
*
* @author gavinc
*/
public class ManageWorkItemDialog extends BaseDialogBean
{
protected WorkflowService workflowService;
protected Node workItemNode;
protected WorkflowTask workItem;
protected WorkflowTransition[] transitions;
protected List<Node> resources;
protected WorkItemCompleteResolver completeResolver = new WorkItemCompleteResolver();
protected UIRichList packageItemsRichList;
protected static final String ID_PREFIX = "transition_";
protected static final String CLIENT_ID_PREFIX = "dialog:" + ID_PREFIX;
private static final Log logger = LogFactory.getLog(ManageWorkItemDialog.class);
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
String taskId = this.parameters.get("id");
this.workItem = this.workflowService.getTaskById(taskId);
if (this.workItem != null)
{
// setup a transient node to represent the work item we're managing
WorkflowTaskDefinition taskDef = this.workItem.definition;
this.workItemNode = new TransientNode(taskDef.metadata.getName(),
"task_" + System.currentTimeMillis(), this.workItem.properties);
}
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
if (logger.isDebugEnabled())
logger.debug("Saving work item: " + this.workItemNode.getId());
// prepare the edited parameters for saving
Map<QName, Serializable> params = WorkflowBean.prepareWorkItemParams(this.workItemNode);
// update the task with the updated parameters
this.workflowService.updateTask(this.workItem.id, params, null, null);
return outcome;
}
@Override
public List<DialogButtonConfig> getAdditionalButtons()
{
List<DialogButtonConfig> buttons = null;
if (this.workItem != null)
{
// get the transitions available from this work item and
// show them in the dialog as additional buttons
this.transitions = this.workItem.path.node.transitions;
if (this.transitions != null)
{
buttons = new ArrayList<DialogButtonConfig>(this.transitions.length);
for (WorkflowTransition trans : this.transitions)
{
buttons.add(new DialogButtonConfig(ID_PREFIX + trans.title, trans.title, null,
"#{DialogManager.bean.transition}", "false", null));
}
}
}
return buttons;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "save");
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
// ------------------------------------------------------------------------------
// Event handlers
@SuppressWarnings("unused")
public String transition()
{
String outcome = getDefaultFinishOutcome();
if (logger.isDebugEnabled())
logger.debug("Transitioning work item: " + this.workItemNode.getId());
// to find out which transition button was pressed we need
// to look for the button's id in the request parameters,
// the first non-null result is the button that was pressed.
FacesContext context = FacesContext.getCurrentInstance();
Map reqParams = context.getExternalContext().getRequestParameterMap();
String selectedTransition = null;
for (WorkflowTransition trans : this.transitions)
{
Object result = reqParams.get(CLIENT_ID_PREFIX + trans.title);
if (result != null)
{
// this was the button that was pressed
selectedTransition = trans.id;
break;
}
}
if (selectedTransition != null)
{
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context);
tx.begin();
// prepare the edited parameters for saving
Map<QName, Serializable> params = WorkflowBean.prepareWorkItemParams(this.workItemNode);
// update the task with the updated parameters
this.workflowService.updateTask(this.workItem.id, params, null, null);
// signal the selected transition to the workflow task
this.workflowService.endTask(this.workItem.id, selectedTransition);
// commit the changes
tx.commit();
if (logger.isDebugEnabled())
logger.debug("Ended work item with transition: " + selectedTransition);
}
catch (Throwable e)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage(formatErrorMessage(e), e);
outcome = this.getErrorOutcome(e);
}
}
return outcome;
}
/**
* Removes an item from the workflow package
*
* @param event The event containing a reference to the item to remove
*/
public void removePackageItem(ActionEvent event)
{
logger.info("remove package item: " + event);
}
/**
* Toggles the complete flag for a workflow package item
*
* @param event The event containing a reference to the item to toggle the status for
*/
public void togglePackageItemComplete(ActionEvent event)
{
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
// create the node ref for the item we are toggling
NodeRef nodeRef = new NodeRef(Repository.getStoreRef(),
(String)params.get("id"));
// get the existing list of completed items
List<NodeRef> completedItems = (List<NodeRef>)this.workItem.properties.get(
WorkflowModel.PROP_COMPLETED_ITEMS);
if (completedItems == null)
{
// if it doesn't exist yet create the list and add the noderef
completedItems = new ArrayList<NodeRef>(1);
completedItems.add(nodeRef);
this.workItem.properties.put(WorkflowModel.PROP_COMPLETED_ITEMS,
(Serializable)completedItems);
}
else
{
if (completedItems.contains(nodeRef))
{
// the item is already in the list remove it
completedItems.remove(nodeRef);
// NOTE: There is a bug somwehere which causes the list to be
// returned as a byte array instead of a list if an empty
// list is persisted, therefore if the list is now empty
// set the completed items back to null
if (completedItems.size() == 0)
{
this.workItem.properties.put(WorkflowModel.PROP_COMPLETED_ITEMS, null);
}
}
else
{
// the noderef is not in the list yet so just add it
completedItems.add(nodeRef);
}
}
// update the task with the updated parameters
this.workflowService.updateTask(this.workItem.id, this.workItem.properties,
null, null);
// commit the transaction
tx.commit();
// reset the rich list if the change was successful
this.packageItemsRichList.setValue(null);
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
this.resources = Collections.<Node>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* Sets the rich list being used for the workflow package items
*
* @param richList The rich list instance
*/
public void setPackageItemsRichList(UIRichList richList)
{
this.packageItemsRichList = richList;
}
/**
* Returns the rich list being used for the workflow package items
*
* @return The rich list instance
*/
public UIRichList getPackageItemsRichList()
{
return this.packageItemsRichList;
}
/**
* Returns the Node representing the work item
*
* @return The node
*/
public Node getWorkItemNode()
{
return this.workItemNode;
}
/**
* Returns the action group the current task uses for the workflow package
*
* @return action group id
*/
public String getPackageActionGroup()
{
return (String)this.workItem.properties.get(
WorkflowModel.PROP_PACKAGE_ACTION_GROUP);
}
/**
* Returns the action group the current task uses for each workflow package item
*
* @return action group id
*/
public String getPackageItemActionGroup()
{
return (String)this.workItem.properties.get(
WorkflowModel.PROP_PACKAGE_ITEM_ACTION_GROUP);
}
/**
* Returns a list of resources associated with this work item
* i.e. the children of the workflow package
*
* @return The list of nodes
*/
public List<Node> getResources()
{
NodeRef workflowPackage = null;
Serializable obj = this.workItem.properties.get(WorkflowModel.ASSOC_PACKAGE);
// TODO: remove this workaroud where JBPM may return a String and not the NodeRef
if (obj instanceof NodeRef)
{
workflowPackage = (NodeRef)obj;
}
else if (obj instanceof String)
{
workflowPackage = new NodeRef((String)obj);
}
this.resources = new ArrayList<Node>(4);
if (workflowPackage != null)
{
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context, true);
tx.begin();
if (logger.isDebugEnabled())
logger.debug("Found workflow package for work item '" +
this.workItem.id + "': " + workflowPackage );
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(workflowPackage,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef ref: childRefs)
{
// create our Node representation from the NodeRef
NodeRef nodeRef = ref.getChildRef();
if (this.nodeService.exists(nodeRef))
{
// find it's type so we can see if it's a node we are interested in
QName type = this.nodeService.getType(nodeRef);
// make sure the type is defined in the data dictionary
TypeDefinition typeDef = this.dictionaryService.getType(type);
if (typeDef != null)
{
// look for content nodes or links to content
// NOTE: folders within workflow packages are ignored for now
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) ||
ContentModel.TYPE_FILELINK.equals(type))
{
// create our Node representation
MapNode node = new MapNode(nodeRef, this.nodeService, true);
this.browseBean.setupCommonBindingProperties(node);
// add property resolvers to show path information
node.addPropertyResolver("path", this.browseBean.resolverPath);
node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath);
// add a property resolver to indicate whether the item has been completed or not
node.addPropertyResolver("completed", this.completeResolver);
this.resources.add(node);
}
}
else
{
if (logger.isWarnEnabled())
logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
}
}
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
this.resources = Collections.<Node>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
}
else if (logger.isDebugEnabled())
{
logger.debug("Failed to find workflow package for work item: " + this.workItem.id);
}
return this.resources;
}
/**
* Sets the workflow service to use
*
* @param workflowService
* WorkflowService instance
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
// ------------------------------------------------------------------------------
// Helper methods
// ------------------------------------------------------------------------------
// Inner classes
/**
* Property resolver to determine if the given node has been flagged as complete
*/
protected class WorkItemCompleteResolver implements NodePropertyResolver
{
public Object get(Node node)
{
String result = Application.getMessage(FacesContext.getCurrentInstance(), "no");
List<NodeRef> completedItems = (List<NodeRef>)workItem.properties.get(
WorkflowModel.PROP_COMPLETED_ITEMS);
if (completedItems != null && completedItems.size() > 0 &&
completedItems.contains(node.getNodeRef()))
{
result = Application.getMessage(FacesContext.getCurrentInstance(), "yes");
}
return result;
}
}
}

View File

@@ -0,0 +1,199 @@
package org.alfresco.web.bean.workflow;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.SortableSelectItem;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIGenericPicker;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean implementation for the "Reassign Task" dialog
*
* @author gavinc
*/
public class ReassignTaskDialog extends BaseDialogBean
{
protected String taskId;
protected WorkflowService workflowService;
protected PersonService personService;
private static final Log logger = LogFactory.getLog(ReassignTaskDialog.class);
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
this.taskId = this.parameters.get("task-id");
if (this.taskId == null || this.taskId.length() == 0)
{
throw new IllegalArgumentException("Reassign task dialog called without task id");
}
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
if (logger.isDebugEnabled())
logger.debug("Reassigning task with id: " + this.taskId);
UIComponent picker = context.getViewRoot().findComponent("dialog:dialog-body:user-picker");
if (picker != null && picker instanceof UIGenericPicker)
{
UIGenericPicker userPicker = (UIGenericPicker)picker;
String[] user = userPicker.getSelectedResults();
if (user != null && user.length > 0)
{
// create a map to hold the new owner property then update the task
String userName = user[0];
Map<QName, Serializable> params = new HashMap<QName, Serializable>(1);
params.put(ContentModel.PROP_OWNER, userName);
this.workflowService.updateTask(this.taskId, params, null, null);
}
else
{
if (logger.isWarnEnabled())
logger.warn("Failed to find selected user, reassign was unsuccessful");
}
}
else
{
if (logger.isWarnEnabled())
logger.warn("Failed to find user-picker component, reassign was unsuccessful");
}
if (logger.isDebugEnabled())
logger.debug("Reassigning task with id: " + this.taskId);
return outcome;
}
@Override
protected String getErrorMessageId()
{
return "error_reassign_task";
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* Property accessed by the Generic Picker component.
*
* @return the array of filter options to show in the users/groups picker
*/
public SelectItem[] getFilters()
{
ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance());
return new SelectItem[] {new SelectItem("0", bundle.getString("users"))};
}
/**
* Query callback method executed by the Generic Picker component.
* This method is part of the contract to the Generic Picker, it is up to the backing bean
* to execute whatever query is appropriate and return the results.
*
* @param filterIndex Index of the filter drop-down selection
* @param contains Text from the contains textbox
*
* @return An array of SelectItem objects containing the results to display in the picker.
*/
public SelectItem[] pickerCallback(int filterIndex, String contains)
{
FacesContext context = FacesContext.getCurrentInstance();
SelectItem[] items;
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context, true);
tx.begin();
// build xpath to match available User/Person objects
NodeRef peopleRef = personService.getPeopleContainer();
// NOTE: see SearcherComponentTest
String xpath = "*[like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "firstName, '%" + contains + "%', false)" +
" or " + "like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "lastName, '%" + contains + "%', false)]";
List<NodeRef> nodes = searchService.selectNodes(
peopleRef,
xpath,
null,
this.namespaceService,
false);
items = new SelectItem[nodes.size()];
for (int index=0; index<nodes.size(); index++)
{
NodeRef personRef = nodes.get(index);
String firstName = (String)this.nodeService.getProperty(personRef, ContentModel.PROP_FIRSTNAME);
String lastName = (String)this.nodeService.getProperty(personRef, ContentModel.PROP_LASTNAME);
String username = (String)this.nodeService.getProperty(personRef, ContentModel.PROP_USERNAME);
SelectItem item = new SortableSelectItem(username, firstName + " " + lastName, lastName);
items[index] = item;
}
Arrays.sort(items);
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
items = new SelectItem[0];
}
return items;
}
/**
* Sets the workflow service to use
*
* @param workflowService The WorkflowService instance
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
/**
* @param permissionService The PermissionService to set.
*/
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
}

View File

@@ -1,14 +1,18 @@
package org.alfresco.web.bean.workflow;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.workflow.WorkflowModel;
@@ -23,10 +27,14 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.MapNode;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.TransientNode;
import org.alfresco.web.bean.wizard.BaseWizardBean;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -42,6 +50,11 @@ public class StartWorkflowWizard extends BaseWizardBean
protected Map<String, WorkflowDefinition> workflows;
protected WorkflowService workflowService;
protected Node startTaskNode;
protected List<Node> resources;
protected List<String> packageItemsToAdd;
protected UIRichList packageItemsRichList;
protected String[] itemsToAdd;
protected boolean isItemBeingAdded = false;
protected boolean nextButtonDisabled = false;
private static final Log logger = LogFactory.getLog(StartWorkflowWizard.class);
@@ -65,6 +78,43 @@ public class StartWorkflowWizard extends BaseWizardBean
}
this.startTaskNode = null;
this.resources = null;
this.itemsToAdd = null;
this.packageItemsToAdd = new ArrayList<String>();
this.isItemBeingAdded = false;
if (this.packageItemsRichList != null)
{
this.packageItemsRichList.setValue(null);
this.packageItemsRichList = null;
}
// TODO: Does this need to be in a read-only transaction??
// add the item the workflow wizard was started on to the list of resources
String itemToWorkflowId = this.parameters.get("item-to-workflow");
if (itemToWorkflowId != null && itemToWorkflowId.length() > 0)
{
// create the node ref for the item and determine its type
NodeRef itemToWorkflow = new NodeRef(Repository.getStoreRef(), itemToWorkflowId);
QName type = this.nodeService.getType(itemToWorkflow);
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) ||
this.dictionaryService.isSubClass(type, ContentModel.TYPE_FILELINK))
{
this.packageItemsToAdd.add(itemToWorkflow.toString());
}
}
}
@Override
public void restored()
{
// reset the workflow package rich list so everything gets re-evaluated
if (this.packageItemsRichList != null)
{
this.packageItemsRichList.setValue(null);
this.packageItemsRichList = null;
}
}
@Override
@@ -77,26 +127,23 @@ public class StartWorkflowWizard extends BaseWizardBean
logger.debug("Starting workflow: " + this.selectedWorkflow);
// prepare the parameters from the current state of the property sheet
Map<QName, Serializable> params = WorkflowBean.prepareWorkItemParams(this.startTaskNode);
Map<QName, Serializable> params = WorkflowBean.prepareTaskParams(this.startTaskNode);
if (logger.isDebugEnabled())
logger.debug("Starting workflow with parameters: " + params);
// create a workflow package for the attached items and add them
String itemToWorkflowId = this.parameters.get("item-to-workflow");
if (itemToWorkflowId != null && itemToWorkflowId.length() > 0)
if (this.packageItemsToAdd.size() > 0)
{
// create the node ref for the item and determine its type
NodeRef itemToWorkflow = new NodeRef(Repository.getStoreRef(), itemToWorkflowId);
QName type = this.nodeService.getType(itemToWorkflow);
NodeRef workflowPackage = this.workflowService.createPackage(null);
NodeRef workflowPackage = null;
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) ||
this.dictionaryService.isSubClass(type, ContentModel.TYPE_FILELINK))
for (String addedItem : this.packageItemsToAdd)
{
// create a workflow package and add the given item to workflow as a child
workflowPackage = this.workflowService.createPackage(null);
this.nodeService.addChild(workflowPackage, itemToWorkflow,
NodeRef addedNodeRef = new NodeRef(addedItem);
this.nodeService.addChild(workflowPackage, addedNodeRef,
ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
QName.createValidLocalName((String)this.nodeService.getProperty(
itemToWorkflow, ContentModel.PROP_NAME))));
addedNodeRef, ContentModel.PROP_NAME))));
}
// add the workflow package to the parameter map
@@ -175,9 +222,131 @@ public class StartWorkflowWizard extends BaseWizardBean
return this.nextButtonDisabled;
}
// ------------------------------------------------------------------------------
// Event Handlers
/**
* Prepares the dialog to allow the user to add an item to the workflow package
*
* @param event The event
*/
public void prepareForAdd(ActionEvent event)
{
this.isItemBeingAdded = true;
}
/**
* Cancels the adding of an item to the workflow package
*
* @param event The event
*/
public void cancelAddPackageItems(ActionEvent event)
{
this.isItemBeingAdded = false;
}
/**
* Adds items to the workflow package
*
* @param event The event
*/
public void addPackageItems(ActionEvent event)
{
if (this.itemsToAdd != null)
{
for (String item : this.itemsToAdd)
{
this.packageItemsToAdd.add(item);
if (logger.isDebugEnabled())
logger.debug("Added item to the added list: " + item);
}
// reset the rich list so it re-renders
this.packageItemsRichList.setValue(null);
}
this.isItemBeingAdded = false;
this.itemsToAdd = null;
}
/**
* Removes an item from the workflow package
*
* @param event The event containing a reference to the item to remove
*/
public void removePackageItem(ActionEvent event)
{
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String nodeRef = new NodeRef(Repository.getStoreRef(), params.get("id")).toString();
if (this.packageItemsToAdd.contains(nodeRef))
{
// remove the item from the added list if it was added in this dialog session
this.packageItemsToAdd.remove(nodeRef);
if (logger.isDebugEnabled())
logger.debug("Removed item from the added list: " + nodeRef);
}
// reset the rich list so it re-renders
this.packageItemsRichList.setValue(null);
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* Returns a String array of NodeRef's that are being added to the workflow package
*
* @return String array of NodeRef's
*/
public String[] getItemsToAdd()
{
return this.itemsToAdd;
}
/**
* Sets the NodeRef's to add as items to the workflow package
*
* @param itemsToAdd NodeRef's to add to the workflow package
*/
public void setItemsToAdd(String[] itemsToAdd)
{
this.itemsToAdd = itemsToAdd;
}
/**
* Determines whether an item is currently being added to the workflow package
*
* @return true if an item is being added
*/
public boolean isItemBeingAdded()
{
return this.isItemBeingAdded;
}
/**
* Sets the rich list being used for the workflow package items
*
* @param richList The rich list instance
*/
public void setPackageItemsRichList(UIRichList richList)
{
this.packageItemsRichList = richList;
}
/**
* Returns the rich list being used for the workflow package items
*
* @return The rich list instance
*/
public UIRichList getPackageItemsRichList()
{
return this.packageItemsRichList;
}
/**
* Returns the workflow selected by the user
*
@@ -317,6 +486,59 @@ public class StartWorkflowWizard extends BaseWizardBean
return availableWorkflows;
}
/**
* Returns a list of resources associated with this task
* i.e. the children of the workflow package
*
* @return The list of nodes
*/
public List<Node> getResources()
{
this.resources = new ArrayList<Node>(4);
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context, true);
tx.begin();
for (String newItem : this.packageItemsToAdd)
{
NodeRef nodeRef = new NodeRef(newItem);
if (this.nodeService.exists(nodeRef))
{
// create our Node representation
MapNode node = new MapNode(nodeRef, this.nodeService, true);
this.browseBean.setupCommonBindingProperties(node);
// add property resolvers to show path information
node.addPropertyResolver("path", this.browseBean.resolverPath);
node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath);
this.resources.add(node);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository");
}
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
this.resources = Collections.<Node>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
return this.resources;
}
/**
* Sets the workflow service to use
*

View File

@@ -0,0 +1,48 @@
package org.alfresco.web.bean.workflow;
import java.util.List;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig;
/**
* Bean implementation for the "View Completed Task" dialog.
*
* @author gavinc
*/
public class ViewCompletedTaskDialog extends ManageTaskDialog
{
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
// nothing to do as the finish button is not shown and the dialog is read only
return outcome;
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "close");
}
@Override
public List<DialogButtonConfig> getAdditionalButtons()
{
return null;
}
@Override
public String getTitle()
{
String titleStart = Application.getMessage(FacesContext.getCurrentInstance(), "view_completed_task_title");
return titleStart + ": " + this.task.title;
}
}

View File

@@ -39,8 +39,8 @@ public class WorkflowBean
{
protected NodeService nodeService;
protected WorkflowService workflowService;
protected List<Node> workItems;
protected List<Node> completedWorkItems;
protected List<Node> tasks;
protected List<Node> completedTasks;
private static final Log logger = LogFactory.getLog(WorkflowBean.class);
@@ -48,12 +48,12 @@ public class WorkflowBean
// Bean Getters and Setters
/**
* Returns a list of nodes representing the to do work items the
* Returns a list of nodes representing the to do tasks the
* current user has.
*
* @return List of to do work items
* @return List of to do tasks
*/
public List<Node> getWorkItemsToDo()
public List<Node> getTasksToDo()
{
// get the current username
FacesContext context = FacesContext.getCurrentInstance();
@@ -71,14 +71,14 @@ public class WorkflowBean
userName, WorkflowTaskState.IN_PROGRESS);
// create a list of transient nodes to represent
this.workItems = new ArrayList<Node>(tasks.size());
this.tasks = new ArrayList<Node>(tasks.size());
for (WorkflowTask task : tasks)
{
Node node = createWorkItem(task);
this.workItems.add(node);
Node node = createTask(task);
this.tasks.add(node);
if (logger.isDebugEnabled())
logger.debug("Added to do work item: " + node);
logger.debug("Added to do task: " + node);
}
// commit the changes
@@ -88,19 +88,19 @@ public class WorkflowBean
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage("Failed to get to do work items: " + e.toString(), e);
Utils.addErrorMessage("Failed to get to do tasks: " + e.toString(), e);
}
return this.workItems;
return this.tasks;
}
/**
* Returns a list of nodes representing the completed work items the
* Returns a list of nodes representing the completed tasks the
* current user has.
*
* @return List of completed work items
* @return List of completed tasks
*/
public List<Node> getWorkItemsCompleted()
public List<Node> getTasksCompleted()
{
// get the current username
FacesContext context = FacesContext.getCurrentInstance();
@@ -118,14 +118,14 @@ public class WorkflowBean
userName, WorkflowTaskState.COMPLETED);
// create a list of transient nodes to represent
this.completedWorkItems = new ArrayList<Node>(tasks.size());
this.completedTasks = new ArrayList<Node>(tasks.size());
for (WorkflowTask task : tasks)
{
Node node = createWorkItem(task);
this.completedWorkItems.add(node);
Node node = createTask(task);
this.completedTasks.add(node);
if (logger.isDebugEnabled())
logger.debug("Added completed work item: " + node);
logger.debug("Added completed task: " + node);
}
// commit the changes
@@ -135,10 +135,10 @@ public class WorkflowBean
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage("Failed to get completed work items: " + e.toString(), e);
Utils.addErrorMessage("Failed to get completed tasks: " + e.toString(), e);
}
return this.completedWorkItems;
return this.completedTasks;
}
/**
@@ -164,7 +164,7 @@ public class WorkflowBean
// ------------------------------------------------------------------------------
// Helper methods
public static Map<QName, Serializable> prepareWorkItemParams(Node node)
public static Map<QName, Serializable> prepareTaskParams(Node node)
{
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
@@ -199,9 +199,6 @@ public class WorkflowBean
params.put(assocQName, (Serializable)targets);
}
if (logger.isDebugEnabled())
logger.debug("Prepared parameters: " + params);
return params;
}
@@ -211,7 +208,7 @@ public class WorkflowBean
*
* @param task The task to create a representation of
*/
protected TransientMapNode createWorkItem(WorkflowTask task)
protected TransientMapNode createTask(WorkflowTask task)
{
// get the type of the task
WorkflowTaskDefinition taskDef = task.definition;

View File

@@ -40,7 +40,7 @@ public class ClientConfigElement extends ConfigElementAdapter
private String editLinkType = "http";
private String homeSpacePermission = null;
private boolean ajaxEnabled = false;
private String initialLocation = null;
private String initialLocation = "myalfresco";
/**
* Default Constructor

View File

@@ -37,6 +37,7 @@ public class DashboardsConfigElement extends ConfigElementAdapter
private Map<String, LayoutDefinition> layoutDefs = new LinkedHashMap<String, LayoutDefinition>(4, 1.0f);
private Map<String, DashletDefinition> dashletDefs = new LinkedHashMap<String, DashletDefinition>(8, 1.0f);
private boolean allowGuestConfig = false;
/**
* Default constructor
@@ -77,9 +78,24 @@ public class DashboardsConfigElement extends ConfigElementAdapter
combinedElement.layoutDefs.putAll(this.layoutDefs);
combinedElement.layoutDefs.putAll(newElement.layoutDefs);
if (newElement.allowGuestConfig != combinedElement.allowGuestConfig)
{
combinedElement.allowGuestConfig = newElement.allowGuestConfig;
}
return combinedElement;
}
/*package*/ void setAllowGuestConfig(boolean allow)
{
this.allowGuestConfig = allow;
}
public boolean getAllowGuestConfig()
{
return this.allowGuestConfig;
}
/*package*/ void addLayoutDefinition(LayoutDefinition def)
{
this.layoutDefs.put(def.Id, def);

View File

@@ -37,6 +37,7 @@ public class DashboardsElementReader implements ConfigElementReader
public static final String ELEMENT_LAYOUT = "layout";
public static final String ELEMENT_DASHLETS = "dashlets";
public static final String ELEMENT_DASHLET = "dashlet";
public static final String ELEMENT_GUESTCONFIG = "allow-guest-config";
public static final String ATTR_ID = "id";
public static final String ATTR_COLUMNS = "columns";
public static final String ATTR_COLUMNLENGTH = "column-length";
@@ -85,6 +86,13 @@ public class DashboardsElementReader implements ConfigElementReader
configElement.addDashletDefinition(dashletDef);
}
}
Element guestConfigElement = element.element(ELEMENT_GUESTCONFIG);
if (guestConfigElement != null)
{
boolean allow = Boolean.parseBoolean(guestConfigElement.getTextTrim());
configElement.setAllowGuestConfig(allow);
}
}
return configElement;

View File

@@ -0,0 +1,401 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the GNU Lesser General Public License as
* published by the Free Software Foundation; either version
* 2.1 of the License, or (at your option) any later version.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/lgpl.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.repo.component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Component for selecting content from the repository
*
* @author gavinc
*/
public class UIContentSelector extends UIInput
{
private final static Log logger = LogFactory.getLog(UIContentSelector.class);
private final static String ACTION_SEPARATOR = ";";
private final static String ACTION_SEARCH = "0";
private final static String FIELD_CONTAINS = "_contains";
private final static String FIELD_AVAILABLE = "_available";
private final static String MSG_SEARCH = "search";
protected String availableOptionsSize;
protected Boolean disabled;
private Boolean multiSelect;
/** List containing the currently available options */
protected List<NodeRef> availableOptions;
// ------------------------------------------------------------------------------
// Component implementation
/**
* @see javax.faces.component.UIComponent#getFamily()
*/
public String getFamily()
{
return "org.alfresco.faces.ContentSelector";
}
/**
* Default constructor
*/
public UIContentSelector()
{
setRendererType(null);
}
/**
* @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
*/
@SuppressWarnings("unchecked")
public void restoreState(FacesContext context, Object state)
{
Object values[] = (Object[])state;
// standard component attributes are restored by the super class
super.restoreState(context, values[0]);
this.availableOptions = (List<NodeRef>)values[1];
this.availableOptionsSize = (String)values[2];
this.disabled = (Boolean)values[3];
this.multiSelect = (Boolean)values[4];
}
/**
* @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
*/
public Object saveState(FacesContext context)
{
Object values[] = new Object[10];
// standard component attributes are saved by the super class
values[0] = super.saveState(context);
values[1] = this.availableOptions;
values[2] = this.availableOptionsSize;
values[3] = this.disabled;
values[4] = this.multiSelect;
return (values);
}
/**
* @see javax.faces.component.UIComponent#decode(javax.faces.context.FacesContext)
*/
public void decode(FacesContext context)
{
Map requestMap = context.getExternalContext().getRequestParameterMap();
Map valuesMap = context.getExternalContext().getRequestParameterValuesMap();
String fieldId = getHiddenFieldName();
String value = (String)requestMap.get(fieldId);
if (value != null && value.equals(ACTION_SEARCH))
{
// user has issued a search action, fill the list with options
String contains = (String)requestMap.get(fieldId + FIELD_CONTAINS);
this.availableOptions = new ArrayList<NodeRef>();
getAvailableOptions(FacesContext.getCurrentInstance(), contains);
}
else
{
// set the submitted value (if there is one)
String[] addedItems = (String[])valuesMap.get(fieldId + FIELD_AVAILABLE);
this.setSubmittedValue(addedItems);
}
}
/**
* @see javax.faces.component.UIComponent#encodeBegin(javax.faces.context.FacesContext)
*/
public void encodeBegin(FacesContext context) throws IOException
{
if (isRendered() == false)
{
return;
}
ResponseWriter out = context.getResponseWriter();
// get the child associations currently on the node and any that have been added
NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
if (isDisabled())
{
// TODO: if the component is disabled just show the current value as text
}
else
{
// start outer table
out.write("<table border='0' cellspacing='4' cellpadding='0' class='");
if (this.getAttributes().get("styleClass") != null)
{
out.write((String)this.getAttributes().get("styleClass"));
}
else
{
out.write("selector");
}
out.write("'");
if (this.getAttributes().get("style") != null)
{
out.write(" style='");
out.write((String)this.getAttributes().get("style"));
out.write("'");
}
out.write(">");
// show the search field
out.write("<tr><td colspan='2'><input type='text' maxlength='1024' size='32' name='");
out.write(getClientId(context) + FIELD_CONTAINS);
out.write("'/>&nbsp;&nbsp;<input type='submit' value='");
out.write(Application.getMessage(context, MSG_SEARCH));
out.write("' onclick=\"");
out.write(generateFormSubmit(context, ACTION_SEARCH));
out.write("\"/></td></tr>");
// show available options i.e. all content in repository
renderAvailableOptions(context, out, nodeService);
// close table
out.write("</table>");
}
}
/**
* Determines whether the component should be rendered in a disabled state
*
* @return Returns whether the component is disabled
*/
public boolean isDisabled()
{
if (this.disabled == null)
{
ValueBinding vb = getValueBinding("disabled");
if (vb != null)
{
this.disabled = (Boolean)vb.getValue(getFacesContext());
}
}
if (this.disabled == null)
{
this.disabled = Boolean.FALSE;
}
return this.disabled;
}
/**
* Determines whether the component should be rendered in a disabled state
*
* @param disabled true to disable the component
*/
public void setDisabled(boolean disabled)
{
this.disabled = disabled;
}
/**
* Returns the size of the select control when multiple items
* can be selected
*
* @return The size of the select control
*/
public String getAvailableOptionsSize()
{
if (this.availableOptionsSize == null)
{
this.availableOptionsSize = "6";
}
return this.availableOptionsSize;
}
/**
* Sets the size of the select control used when multiple items can
* be selected
*
* @param availableOptionsSize The size
*/
public void setAvailableOptionsSize(String availableOptionsSize)
{
this.availableOptionsSize = availableOptionsSize;
}
/**
* @return true if multi select should be enabled.
*/
public boolean getMultiSelect()
{
ValueBinding vb = getValueBinding("multiSelect");
if (vb != null)
{
this.multiSelect = (Boolean)vb.getValue(getFacesContext());
}
return multiSelect != null ? multiSelect.booleanValue() : true;
}
/**
* @param multiSelect Flag to determine whether multi select is enabled
*/
public void setMultiSelect(boolean multiSelect)
{
this.multiSelect = Boolean.valueOf(multiSelect);
}
/**
* Renders the list of available options
*
* @param context FacesContext
* @param out Writer to write output to
* @param nodeService The NodeService
* @throws IOException
*/
protected void renderAvailableOptions(FacesContext context, ResponseWriter out, NodeService nodeService)
throws IOException
{
boolean itemsPresent = (this.availableOptions != null && this.availableOptions.size() > 0);
out.write("<tr><td colspan='2'><select ");
if (itemsPresent == false)
{
// rather than having a very slim select box set the width if there are no results
out.write("style='width:240px;' ");
}
out.write("name='");
out.write(getClientId(context) + FIELD_AVAILABLE);
out.write("' size='");
if (getMultiSelect())
{
out.write(getAvailableOptionsSize());
out.write("' multiple");
}
else
{
out.write("1'");
}
out.write(">");
if (itemsPresent)
{
for (NodeRef item : this.availableOptions)
{
out.write("<option value='");
out.write(item.toString());
out.write("'>");
out.write(Repository.getDisplayPath(nodeService.getPath(item)));
out.write("/");
out.write(Repository.getNameForNode(nodeService, item));
out.write("</option>");
}
}
out.write("</select></td></tr>");
}
/**
* Retrieves the available options for the current association
*
* @param context Faces Context
* @param contains The contains part of the query
*/
protected void getAvailableOptions(FacesContext context, String contains)
{
// query for all content in the current repository
StringBuilder query = new StringBuilder("+TYPE:\"");
query.append(ContentModel.TYPE_CONTENT);
query.append("\"");
if (contains != null && contains.length() > 0)
{
String safeContains = Utils.remove(contains.trim(), "\"");
query.append(" AND +@");
String nameAttr = Repository.escapeQName(QName.createQName(
NamespaceService.CONTENT_MODEL_1_0_URI, "name"));
query.append(nameAttr);
query.append(":*" + safeContains + "*");
}
if (logger.isDebugEnabled())
logger.debug("Query: " + query.toString());
ResultSet results = null;
try
{
results = Repository.getServiceRegistry(context).getSearchService().query(
Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString());
this.availableOptions = results.getNodeRefs();
}
finally
{
if (results != null)
{
results.close();
}
}
if (logger.isDebugEnabled())
logger.debug("Found " + this.availableOptions.size() + " available options");
}
/**
* We use a hidden field per picker instance on the page.
*
* @return hidden field name
*/
private String getHiddenFieldName()
{
return getClientId(getFacesContext());
}
/**
* Generate FORM submit JavaScript for the specified action
*
* @param context FacesContext
* @param action Action string
*
* @return FORM submit JavaScript
*/
private String generateFormSubmit(FacesContext context, String action)
{
return Utils.generateFormSubmit(context, this, getHiddenFieldName(), action);
}
}

View File

@@ -0,0 +1,163 @@
package org.alfresco.web.ui.repo.component;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.component.SelfRenderingComponent;
/**
* JSF component that displays summary information about a workflow.
*
* @author gavinc
*/
public class UIWorkflowSummary extends SelfRenderingComponent
{
protected WorkflowInstance value = null;
// ------------------------------------------------------------------------------
// Component Impl
@Override
public String getFamily()
{
return "org.alfresco.faces.WorkflowSummary";
}
@Override
public void restoreState(FacesContext context, Object state)
{
Object values[] = (Object[])state;
// standard component attributes are restored by the super class
super.restoreState(context, values[0]);
this.value = (WorkflowInstance)values[1];
}
@Override
public Object saveState(FacesContext context)
{
Object values[] = new Object[8];
// standard component attributes are saved by the super class
values[0] = super.saveState(context);
values[1] = this.value;
return values;
}
@Override
@SuppressWarnings("unchecked")
public void encodeBegin(FacesContext context) throws IOException
{
if (!isRendered()) return;
WorkflowInstance wi = getValue();
if (wi != null)
{
ResponseWriter out = context.getResponseWriter();
ResourceBundle bundle = Application.getBundle(context);
SimpleDateFormat format = new SimpleDateFormat(bundle.getString("date_pattern"));
// output surrounding table and style if necessary
out.write("<table");
if (this.getAttributes().get("style") != null)
{
out.write(" style=\"");
out.write((String)this.getAttributes().get("style"));
out.write("\"");
}
if (this.getAttributes().get("styleClass") != null)
{
out.write(" class=\"");
out.write((String)this.getAttributes().get("styleClass"));
out.write("\"");
}
out.write(">");
// output the title and description
out.write("<tr><td>");
out.write(bundle.getString("title"));
out.write(":</td><td>");
out.write(wi.definition.title);
out.write("</td></tr><tr><td>");
out.write(bundle.getString("description"));
out.write(":</td><td>");
out.write(wi.definition.description);
out.write("</td></tr><tr><td>");
out.write(bundle.getString("initiated_by"));
out.write(":</td><td>");
if (wi.initiator != null)
{
NodeService nodeService = Repository.getServiceRegistry(
context).getNodeService();
String userName = (String)nodeService.getProperty(
wi.initiator, ContentModel.PROP_USERNAME);
out.write(userName);
}
out.write("</td></tr><tr><td>");
out.write(bundle.getString("start_date"));
out.write(":</td><td>");
if (wi.startDate != null)
{
out.write(format.format(wi.startDate));
}
out.write("</td></tr><tr><td>");
out.write(bundle.getString("due_date"));
out.write(":</td><td>");
if (wi.endDate != null)
{
out.write(format.format(wi.endDate));
}
out.write("</td></tr></table>");
}
}
@Override
public void encodeEnd(FacesContext context) throws IOException
{
if (!isRendered()) return;
}
@Override
public boolean getRendersChildren()
{
return false;
}
// ------------------------------------------------------------------------------
// Strongly typed component property accessors
/**
* Returns the workflow instance this component is showing information on
*
* @return The workflow instance
*/
public WorkflowInstance getValue()
{
ValueBinding vb = getValueBinding("value");
if (vb != null)
{
this.value = (WorkflowInstance)vb.getValue(getFacesContext());
}
return this.value;
}
/**
* Sets the workflow instance to show the summary for
*
* @param value The workflow instance
*/
public void setValue(WorkflowInstance value)
{
this.value = value;
}
}

View File

@@ -0,0 +1,113 @@
/*
* 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.repo.tag;
import javax.faces.component.UIComponent;
import org.alfresco.web.ui.common.tag.HtmlComponentTag;
/**
* Tag class to allow the content selector component to be added to a JSP page
*
* @author gavinc
*/
public class ContentSelectorTag extends HtmlComponentTag
{
private String availableOptionsSize;
private String disabled;
private String value;
private String multiSelect;
/**
* @see javax.faces.webapp.UIComponentTag#getComponentType()
*/
public String getComponentType()
{
return "org.alfresco.faces.ContentSelector";
}
/**
* @see javax.faces.webapp.UIComponentTag#getRendererType()
*/
public String getRendererType()
{
return null;
}
/**
* @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent)
*/
protected void setProperties(UIComponent component)
{
super.setProperties(component);
setStringStaticProperty(component, "availableOptionsSize", this.availableOptionsSize);
setStringProperty(component, "value", this.value);
setBooleanProperty(component, "disabled", this.disabled);
setBooleanProperty(component, "multiSelect", this.multiSelect);
}
/**
* @param value The value to set.
*/
public void setValue(String value)
{
this.value = value;
}
/**
* @param availableOptionsSize Sets the size of the available options size when
* multiple items can be selected
*/
public void setAvailableOptionsSize(String availableOptionsSize)
{
this.availableOptionsSize = availableOptionsSize;
}
/**
* Set the multiSelect
*
* @param mutliSelect the multiSelect
*/
public void setMultiSelect(String multiSelect)
{
this.multiSelect = multiSelect;
}
/**
* Sets whether the component should be rendered in a disabled state
*
* @param disabled true to render the component in a disabled state
*/
public void setDisabled(String disabled)
{
this.disabled = disabled;
}
/**
* @see javax.faces.webapp.UIComponentTag#release()
*/
public void release()
{
this.availableOptionsSize = null;
this.disabled = null;
this.value = null;
this.multiSelect = null;
super.release();
}
}

View File

@@ -0,0 +1,77 @@
/*
* 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.repo.tag;
import javax.faces.component.UIComponent;
import org.alfresco.web.ui.common.tag.HtmlComponentTag;
/**
* Tag that allows the workflow summary component to be placed on a JSP page
*
* @author gavinc
*/
public class WorkflowSummaryTag extends HtmlComponentTag
{
/**
* @see javax.faces.webapp.UIComponentTag#getComponentType()
*/
public String getComponentType()
{
return "org.alfresco.faces.WorkflowSummary";
}
/**
* @see javax.faces.webapp.UIComponentTag#getRendererType()
*/
public String getRendererType()
{
return null;
}
/**
* @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent)
*/
protected void setProperties(UIComponent component)
{
super.setProperties(component);
setStringProperty(component, "value", this.value);
}
/**
* @see org.alfresco.web.ui.common.tag.HtmlComponentTag#release()
*/
public void release()
{
super.release();
this.value = null;
}
/**
* Set the value (binding to the list of user/group data)
*
* @param value the value
*/
public void setValue(String value)
{
this.value = value;
}
/** the value (binding to the workflow instance) */
private String value;
}

View File

@@ -34,6 +34,7 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag
private String selectedItemsMsg;
private String noSelectedItemsMsg;
private String disabled;
private String value;
/**
* @see javax.faces.webapp.UIComponentTag#getRendererType()
@@ -56,9 +57,18 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag
setStringProperty(component, "selectItemsMsg", this.selectItemsMsg);
setStringProperty(component, "selectedItemsMsg", this.selectedItemsMsg);
setStringProperty(component, "noSelectedItemsMsg", this.noSelectedItemsMsg);
setStringProperty(component, "value", this.value);
setBooleanProperty(component, "disabled", this.disabled);
}
/**
* @param value The value to set.
*/
public void setValue(String value)
{
this.value = value;
}
/**
* Sets the association name
*
@@ -140,6 +150,7 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag
this.selectedItemsMsg = null;
this.noSelectedItemsMsg = null;
this.disabled = null;
this.value = null;
super.release();
}

View File

@@ -6,7 +6,7 @@
<!-- ==================== APPLICATION ==================== -->
<application>
<navigation-handler>org.alfresco.web.app.AlfrescoNavigationHandler</navigation-handler>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
<variable-resolver>org.alfresco.web.app.AlfrescoVariableResolver</variable-resolver>
<locale-config>
<default-locale>en</default-locale>
</locale-config>

View File

@@ -31,6 +31,10 @@
<property-name>browseBean</property-name>
<value>#{BrowseBean}</value>
</managed-property>
<managed-property>
<property-name>userPreferencesBean</property-name>
<value>#{UserPreferencesBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
@@ -60,6 +64,10 @@
<property-name>ruleService</property-name>
<value>#{RuleService}</value>
</managed-property>
<managed-property>
<property-name>userPreferencesBean</property-name>
<value>#{UserPreferencesBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
@@ -583,6 +591,56 @@
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that backs up the View Content Properties Dialog
</description>
<managed-bean-name>ViewContentPropertiesDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.content.ViewContentPropertiesDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
<managed-property>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
</managed-property>
<managed-property>
<property-name>browseBean</property-name>
<value>#{BrowseBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that backs up the Set Content Properties Dialog
</description>
<managed-bean-name>SetContentPropertiesDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.content.SetContentPropertiesDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
<managed-property>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
</managed-property>
<managed-property>
<property-name>browseBean</property-name>
<value>#{BrowseBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that backs up the Edit Content Properties Dialog
@@ -1386,10 +1444,6 @@
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
<managed-property>
<property-name>searchService</property-name>
<value>#{SearchService}</value>
</managed-property>
<managed-property>
<property-name>navigator</property-name>
<value>#{NavigationBean}</value>
@@ -1551,8 +1605,8 @@
<value>#{ContentService}</value>
</managed-property>
<managed-property>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
<property-name>namespaceService</property-name>
<value>#{NamespaceService}</value>
</managed-property>
</managed-bean>
@@ -1657,10 +1711,47 @@
<property-name>browseBean</property-name>
<value>#{BrowseBean}</value>
</managed-property>
<managed-property>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
</managed-property>
<managed-property>
<property-name>namespaceService</property-name>
<value>#{NamespaceService}</value>
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that backs up the Delete Post Dialog
</description>
<managed-bean-name>DeletePostDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.forums.DeletePostDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
<managed-property>
<property-name>searchService</property-name>
<value>#{SearchService}</value>
</managed-property>
<managed-property>
<property-name>navigator</property-name>
<value>#{NavigationBean}</value>
</managed-property>
<managed-property>
<property-name>browseBean</property-name>
<value>#{BrowseBean}</value>
</managed-property>
<managed-property>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
</managed-property>
<managed-property>
<property-name>namespaceService</property-name>
<value>#{NamespaceService}</value>
@@ -1765,10 +1856,51 @@
<managed-bean>
<description>
The bean that backs up the Manage WorkItem Dialog
The bean that backs up the Manage Task Dialog
</description>
<managed-bean-name>ManageWorkItemDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.workflow.ManageWorkItemDialog</managed-bean-class>
<managed-bean-name>ManageTaskDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.workflow.ManageTaskDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
<managed-property>
<property-name>searchService</property-name>
<value>#{SearchService}</value>
</managed-property>
<managed-property>
<property-name>navigator</property-name>
<value>#{NavigationBean}</value>
</managed-property>
<managed-property>
<property-name>browseBean</property-name>
<value>#{BrowseBean}</value>
</managed-property>
<managed-property>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
</managed-property>
<managed-property>
<property-name>namespaceService</property-name>
<value>#{NamespaceService}</value>
</managed-property>
<managed-property>
<property-name>workflowService</property-name>
<value>#{WorkflowService}</value>
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that backs up the View Completed Task Dialog
</description>
<managed-bean-name>ViewCompletedTaskDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.workflow.ViewCompletedTaskDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
@@ -1829,8 +1961,8 @@
<value>#{BrowseBean}</value>
</managed-property>
<managed-property>
<property-name>namespaceService</property-name>
<value>#{NamespaceService}</value>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
</managed-property>
<managed-property>
<property-name>namespaceService</property-name>
@@ -1885,10 +2017,10 @@
<managed-bean>
<description>
The bean that backs up the Reassign Work Item Dialog
The bean that backs up the Reassign Task Dialog
</description>
<managed-bean-name>ReassignWorkItemDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.workflow.ReassignWorkItemDialog</managed-bean-class>
<managed-bean-name>ReassignTaskDialog</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.workflow.ReassignTaskDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
@@ -1976,29 +2108,27 @@
</managed-bean>
<managed-bean>
<description>Bean that manages the Dashboard framework</description>
<managed-bean-name>DashboardManager</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.dashboard.DashboardManager</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>
The bean that backs up the Dashboard Config Wizard
The bean that backs up the Getting Started Dashlet page
</description>
<managed-bean-name>DashboardWizard</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.dashboard.DashboardWizard</managed-bean-class>
<managed-bean-name>GettingStartedBean</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.dashboard.GettingStartedBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>dashboardManager</property-name>
<value>#{DashboardManager}</value>
<property-name>navigationBean</property-name>
<value>#{NavigationBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that backs up the User Preferences page
</description>
<managed-bean-name>UserPreferencesBean</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.UserPreferencesBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<!-- ==================== COMPONENT GENERATOR BEANS ==================== -->
<managed-bean>
@@ -2143,18 +2273,45 @@
<managed-bean-name>SeparatorGenerator</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.generator.SeparatorGenerator</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>
Bean that generates a header separator component
</description>
<managed-bean-name>HeaderSeparatorGenerator</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.generator.HeaderSeparatorGenerator</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>
Bean that generates a label separator component
</description>
<managed-bean-name>LabelSeparatorGenerator</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.generator.LabelSeparatorGenerator</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>
Bean that generates a label separator component rendered as a heading
</description>
<managed-bean-name>HeaderSeparatorGenerator</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.generator.LabelSeparatorGenerator</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>styleClass</property-name>
<value>wizardSectionHeading mainSubTitle</value>
</managed-property>
</managed-bean>
<!--
<managed-bean>
<description>
Bean that generates a HTML separator component
</description>
<managed-bean-name>MyCustomSeparatorGenerator</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.generator.HtmlSeparatorGenerator</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>html</property-name>
<value><![CDATA[This is <i>my</i> custom header]]></value>
</managed-property>
</managed-bean>
-->
<!-- ==================== AJAX BEANS ==================== -->
<managed-bean>
@@ -2174,32 +2331,4 @@
</managed-property>
</managed-bean>
<!-- ==================== AJAX BEANS ==================== -->
<managed-bean>
<description>
Bean that returns information on a node
</description>
<managed-bean-name>NodeInfoBean</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.ajax.NodeInfoBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>contentService</property-name>
<value>#{ContentService}</value>
</managed-property>
</managed-bean>
<managed-bean>
<description>
Bean that returns information on a node
</description>
<managed-bean-name>XFormsBean</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.ajax.XFormsBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>

View File

@@ -57,6 +57,10 @@
<from-outcome>dashboard</from-outcome>
<to-view-id>/jsp/browse/dashboard.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>addContent</from-outcome>
<to-view-id>/jsp/content/add-content-dialog.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- rule to get to the Advanced Search page from anywhere -->
@@ -878,9 +882,10 @@
</navigation-case>
</navigation-rule>
<!-- Overridden dialog:close rules -->
<navigation-rule>
<from-view-id>/jsp/dialog/container.jsp</from-view-id>
<!-- Overridden dialog:close navigation rules for forums -->
<navigation-case>
<from-outcome>forumsDeleted</from-outcome>
<to-view-id>/jsp/forums/forums.jsp</to-view-id>
@@ -893,6 +898,45 @@
<from-outcome>topicDeleted</from-outcome>
<to-view-id>/jsp/forums/forum.jsp</to-view-id>
</navigation-case>
<!-- Workflow navigation rules for actions on workflow package items -->
<navigation-case>
<from-outcome>checkoutFile</from-outcome>
<to-view-id>/jsp/dialog/checkout-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>checkinFile</from-outcome>
<to-view-id>/jsp/dialog/checkin-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>undoCheckoutFile</from-outcome>
<to-view-id>/jsp/dialog/undocheckout-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>updateFile</from-outcome>
<to-view-id>/jsp/dialog/update-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editFile</from-outcome>
<to-view-id>/jsp/dialog/edit-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editHtmlInline</from-outcome>
<to-view-id>/jsp/dialog/edit-html-inline.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editTextInline</from-outcome>
<to-view-id>/jsp/dialog/edit-text-inline.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>itemDetails</from-outcome>
<to-view-id>/jsp/trashcan/item-details.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>recoveryReport</from-outcome>
<to-view-id>/jsp/trashcan/recovery-report.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>

View File

@@ -54,6 +54,11 @@
<component-class>org.alfresco.web.ui.repo.component.UISpaceSelector</component-class>
</component>
<component>
<component-type>org.alfresco.faces.ContentSelector</component-type>
<component-class>org.alfresco.web.ui.repo.component.UIContentSelector</component-class>
</component>
<component>
<component-type>org.alfresco.faces.CategorySelector</component-type>
<component-class>org.alfresco.web.ui.repo.component.UICategorySelector</component-class>
@@ -144,6 +149,10 @@
<component-class>org.alfresco.web.ui.repo.component.UIUserGroupPicker</component-class>
</component>
<component>
<component-type>org.alfresco.faces.WorkflowSummary</component-type>
<component-class>org.alfresco.web.ui.repo.component.UIWorkflowSummary</component-class>
</component>
<!-- ==================== CONVERTERS ==================== -->
<component>

View File

@@ -209,11 +209,17 @@
<tag>
<name>associationEditor</name>
<tag-class>org.alfresco.web.ui.repo.tag.AssociationEditorTag</tag-class>
<tag-class>org.alfresco.web.ui.repo.tag.property.AssociationEditorTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>assocationName</name>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>associationName</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
@@ -329,11 +335,17 @@
<tag>
<name>childAssociationEditor</name>
<tag-class>org.alfresco.web.ui.repo.tag.ChildAssociationEditorTag</tag-class>
<tag-class>org.alfresco.web.ui.repo.tag.property.ChildAssociationEditorTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>assocationName</name>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>associationName</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
@@ -721,6 +733,60 @@
</attribute>
</tag>
<tag>
<name>contentSelector</name>
<tag-class>org.alfresco.web.ui.repo.tag.ContentSelectorTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>availableOptionsSize</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>multiSelect</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>binding</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>rendered</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>style</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>styleClass</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>categorySelector</name>
<tag-class>org.alfresco.web.ui.repo.tag.CategorySelectorTag</tag-class>
@@ -1614,4 +1680,50 @@
</attribute>
</tag>
<tag>
<name>workflowSummary</name>
<tag-class>org.alfresco.web.ui.repo.tag.WorkflowSummaryTag</tag-class>
<body-content>JSP</body-content>
<description>
Shows summary information of a workflow instance.
</description>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>binding</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>rendered</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>style</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>styleClass</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>

View File

@@ -94,24 +94,14 @@
<!-- -->
<!-- JBPM START -->
<!-- Used by the JPBM console for monitoring in-flight workflows -->
<!-- TODO: Remove this block - just a temporary placement for testing -->
<!-- -->
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>org.jbpm.webapp.filter.LogFilter</filter-class>
</filter>
<filter>
<filter-name>JbpmContextFilter</filter-name>
<filter-class>org.jbpm.webapp.filter.JbpmContextFilter</filter-class>
<!-- <filter-class>org.jbpm.webapp.filter.JbpmContextFilter</filter-class> -->
</filter>
<!--
<filter>
<filter-name>JbpmAuthenticationFilter</filter-name>
<filter-class>org.jbpm.webapp.filter.AuthenticationFilter</filter-class>
</filter>
-->
<!-- -->
<!-- JBPM END -->
@@ -138,31 +128,14 @@
<!-- -->
<!-- JBPM START -->
<!-- Used by the JPBM console for monitoring in-flight workflows -->
<!-- TODO: Remove this block - just a temporary placement for testing -->
<!-- -->
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/faces/jbpm/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>JbpmContextFilter</filter-name>
<url-pattern>/faces/jbpm/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>JbpmContextFilter</filter-name>
<url-pattern>/processimage</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>JbpmContextFilter</filter-name>
<url-pattern>/faces/jsp/dashboards/*</url-pattern>
</filter-mapping>
<!--
<filter-mapping>
<filter-name>JbpmAuthenticationFilter</filter-name>
<url-pattern>/faces/jbpm/*</url-pattern>
</filter-mapping>
-->
<!-- -->
<!-- JBPM END -->
@@ -241,30 +214,6 @@
<servlet-name>JBPMDeployProcessServlet</servlet-name>
<servlet-class>org.alfresco.web.app.servlet.JBPMDeployProcessServlet</servlet-class>
</servlet>
<!-- -->
<!-- JBPM START -->
<!-- TODO: Remove this block - just a temporary placement for testing -->
<!-- -->
<!--
<servlet>
<servlet-name>JbpmThreadsServlet</servlet-name>
<servlet-class>org.jbpm.web.JbpmThreadsServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
-->
<!-- jBPM FileServlet -->
<servlet>
<servlet-name>ProcessImageServlet</servlet-name>
<servlet-class>org.jbpm.webapp.servlet.ProcessImageServlet</servlet-class>
</servlet>
<!-- -->
<!-- JBPM END -->
<!-- -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
@@ -316,28 +265,6 @@
<url-pattern>/jbpm/deployprocess</url-pattern>
</servlet-mapping>
<!-- -->
<!-- JBPM START -->
<!-- TODO: Remove this block - just a temporary placement for testing -->
<!-- -->
<!--
<servlet-mapping>
<servlet-name>JbpmThreadsServlet</servlet-name>
<url-pattern>/threads</url-pattern>
</servlet-mapping>
-->
<!-- jBPM FileServlet -->
<servlet-mapping>
<servlet-name>ProcessImageServlet</servlet-name>
<url-pattern>/processimage</url-pattern>
</servlet-mapping>
<!-- -->
<!-- JBPM END -->
<!-- -->
<session-config>
<session-timeout>60</session-timeout>
</session-config>

View File

@@ -528,3 +528,14 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl
border-style: solid;
border-color: #AAAAAA;
}
.workflowSummary
{
margin-left: 6px;
}
.workflowSummary td
{
padding-right: 9px;
padding-top: 4px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,21 +1,51 @@
<%--
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.
--%>
<%-- redirect to the web application's start page --%>
<%
response.sendRedirect(request.getContextPath() + "/faces/jsp/browse/browse.jsp");
%>
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.
--%>
<%@ page import="org.springframework.web.context.support.WebApplicationContextUtils" %>
<%@ page import="org.alfresco.config.ConfigService" %>
<%@ page import="org.alfresco.web.app.servlet.AuthenticationHelper" %>
<%@ page import="org.alfresco.web.bean.NavigationBean" %>
<%@ page import="org.alfresco.web.bean.repository.User" %>
<%@ page import="org.alfresco.web.bean.repository.PreferencesService" %>
<%@ page import="org.alfresco.web.config.ClientConfigElement" %>
<%-- redirect to the web application's appropriate start page --%>
<%
// get the start location as configured by the web-client config
ConfigService configService = (ConfigService)WebApplicationContextUtils.getRequiredWebApplicationContext(session.getServletContext()).getBean("webClientConfigService");
ClientConfigElement configElement = (ClientConfigElement)configService.getGlobalConfig().getConfigElement("client");
String location = configElement.getInitialLocation();
// override with the users preference if they have one
User user = (User)session.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
if (user != null)
{
String preference = (String)PreferencesService.getPreferences(user).getValue("start-location");
if (preference != null)
{
location = preference;
}
}
if (NavigationBean.LOCATION_MYALFRESCO.equals(location))
{
response.sendRedirect(request.getContextPath() + "/faces/jsp/dashboards/container.jsp");
}
else
{
response.sendRedirect(request.getContextPath() + "/faces/jsp/browse/browse.jsp");
}
%>

View File

@@ -126,6 +126,12 @@
<tr>
<td><a:actionLink value="#{msg.node_browser}" image="/images/icons/node_browser.gif" action="dialog:showNodeBrowser" styleClass="title" /></td>
</tr>
<tr>
<td>
<img src="<%=request.getContextPath()%>/images/icons/workflow.gif" align="absmiddle" />
<h:outputLink value="/alfresco/faces/jbpm/home.jsp" styleClass="title"><h:outputText value="jBPM Console" /></h:outputLink>
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "ballongrey"); %>

View File

@@ -0,0 +1,24 @@
<%--
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="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<r:propertySheetGrid id="content-props" value="#{DialogManager.bean.viewingNode}"
var="viewContentProps" columns="1" externalConfig="true"
mode="view" labelStyleClass="propertiesLabel" />

View File

@@ -0,0 +1,54 @@
<%--
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="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ page import="org.alfresco.web.app.Application" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<r:page titleId="title_my_alfresco">
<f:view>
<%-- load a bundle of properties with I18N strings --%>
<f:loadBundle basename="alfresco.messages.webclient" var="msg"/>
<h:form acceptCharset="UTF-8" id="dashboard">
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td width="100%" valign="top">
<f:subview id="dash-body">
<jsp:include page="<%=Application.getDashboardManager().getLayoutPage()%>" />
</f:subview>
</td>
</tr>
<tr>
<td style="padding-left:8px"><a:actionLink value="#{msg.configure}" image="/images/icons/configure_dashboard.gif" padding="2" action="wizard:configureDashboard" /></td>
</tr>
</table>
</h:form>
</f:view>
</r:page>

View File

@@ -74,7 +74,7 @@
<div class="mainSubText"><h:outputText value="#{msg.dashboard_description}" /></div>
</td>
<td align="right">
<a:actionLink value="#{msg.configure}" image="/images/icons/configure_dashboard.gif" padding="2" action="wizard:configureDashboard" />
<a:actionLink value="#{msg.configure}" image="/images/icons/configure_dashboard.gif" padding="2" action="wizard:configureDashboard" rendered="#{NavigationBean.isGuest == false || DashboardWizard.allowGuestConfig}" />
</td>
</tr>
</table>

View File

@@ -0,0 +1,20 @@
<%--
Copyright (C) 2006 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="/WEB-INF/repo.tld" prefix="r" %>
<%-- Note that this template is loaded from the classpath --%>
<r:template template="/alfresco/templates/checkedout_docs.ftl" />

View File

@@ -24,33 +24,93 @@
<f:verbatim>
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellow", "#ffffcc"); %>
</f:verbatim>
<h:panelGrid columns="3" cellpadding="2" cellspacing="2" border="0" width="100%" style="background-colour:##ffffcc">
<h:outputText style="font-size: 11px; font-weight:bold; color:#4272B4" value="Alfresco" />
<h:outputText style="font-size: 11px; font-weight:bold; color:#4272B4" value="Common Tasks" />
<h:outputText style="font-size: 11px; font-weight:bold; color:#4272B4" value="Working with Alfresco" />
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0" width="100%" style="background-colour:##ffffcc" rowClasses="alignTop">
<h:panelGrid columns="1" cellpadding="2" cellspacing="2" border="0">
<h:outputText style="font-size: 11px; font-weight:bold; color:#4272B4" value="#{msg.product_name}" />
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/logo/AlfrescoLogo32.gif" width="32" height="32" />
<h:panelGroup>
<h:outputText style="font-weight:bold" value="Feature Tour" />
<f:verbatim><br></f:verbatim>
<h:outputText value="Lorem ipsum dolor sit amet, consectetuer adipiscing elit." />
</h:panelGroup>
</h:panelGrid>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/gettingstarted_demonstration.gif" width="32" height="32" />
<h:panelGroup>
<a:actionLink href="http://www.alfresco.com/products/ecm/demonstrations/" target="new" style="font-weight:bold" value="#{msg.gettingstarted_demonstration}" />
<f:verbatim><br></f:verbatim>
<h:outputText value="#{msg.gettingstarted_demonstration_desc}" />
</h:panelGroup>
</h:panelGrid>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/Details.gif" width="32" height="32" />
<h:panelGroup>
<h:outputText style="font-weight:bold" value="Browse items in your home space" />
<f:verbatim><br></f:verbatim>
<h:outputText value="Lorem ipsum dolor sit amet, consectetuer adipiscing elit." />
</h:panelGroup>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/gettingstarted_featuretour.gif" width="32" height="32" />
<h:panelGroup>
<a:actionLink href="http://www.alfresco.com/products/ecm/tour/" target="new" style="font-weight:bold" value="#{msg.gettingstarted_featuretour}" />
<f:verbatim><br></f:verbatim>
<h:outputText value="#{msg.gettingstarted_featuretour_desc}" />
</h:panelGroup>
</h:panelGrid>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/gettingstarted_onlinehelp.gif" width="32" height="32" />
<h:panelGroup>
<a:actionLink href="#{NavigationBean.helpUrl}" target="help" style="font-weight:bold" value="#{msg.gettingstarted_onlinehelp}" />
<f:verbatim><br></f:verbatim>
<h:outputText value="#{msg.gettingstarted_onlinehelp_desc}" />
</h:panelGroup>
</h:panelGrid>
</h:panelGrid>
<h:panelGrid columns="1" cellpadding="2" cellspacing="2" border="0">
<h:outputText style="font-weight:bold" value="Inviting users to a space" />
<h:outputText value="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Lorem ipsum dolor sit amet, consectetuer adipiscing elit." />
<h:outputText style="font-size: 11px; font-weight:bold; color:#4272B4" value="#{msg.gettingstarted_commontasks}" />
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/gettingstarted_browse.gif" width="32" height="32" />
<h:panelGroup>
<a:actionLink style="font-weight:bold" value="#{msg.gettingstarted_browse}" action="#{GettingStartedBean.browseHomeSpace}" />
<f:verbatim><br></f:verbatim>
<h:outputText value="#{msg.gettingstarted_browse_desc}" />
</h:panelGroup>
</h:panelGrid>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/create_space_large.gif" width="32" height="32" />
<h:panelGroup>
<a:booleanEvaluator value="#{NavigationBean.isGuest == false}">
<a:actionLink style="font-weight:bold" value="#{msg.gettingstarted_createspace}" action="#{GettingStartedBean.createSpace}" />
</a:booleanEvaluator>
<a:booleanEvaluator value="#{NavigationBean.isGuest == true}">
<h:outputText style="font-weight:bold" value="#{msg.gettingstarted_createspace}" />
</a:booleanEvaluator>
<f:verbatim><br></f:verbatim>
<h:outputText value="#{msg.gettingstarted_createspace_desc}" />
</h:panelGroup>
</h:panelGrid>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/add_content_large.gif" width="32" height="32" />
<h:panelGroup>
<a:booleanEvaluator value="#{NavigationBean.isGuest == false}">
<a:actionLink style="font-weight:bold" value="#{msg.gettingstarted_addcontent}" action="#{GettingStartedBean.addContent}" actionListener="#{AddContentDialog.start}" />
</a:booleanEvaluator>
<a:booleanEvaluator value="#{NavigationBean.isGuest == true}">
<h:outputText style="font-weight:bold" value="#{msg.gettingstarted_addcontent}" />
</a:booleanEvaluator>
<f:verbatim><br></f:verbatim>
<h:outputText value="#{msg.gettingstarted_addcontent_desc}" />
</h:panelGroup>
</h:panelGrid>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2" border="0">
<h:graphicImage value="/images/icons/new_content_large.gif" width="32" height="32" />
<h:panelGroup>
<a:booleanEvaluator value="#{NavigationBean.isGuest == false}">
<a:actionLink style="font-weight:bold" value="#{msg.gettingstarted_createcontent}" action="#{GettingStartedBean.createContent}" />
</a:booleanEvaluator>
<a:booleanEvaluator value="#{NavigationBean.isGuest == true}">
<h:outputText style="font-weight:bold" value="#{msg.gettingstarted_createcontent}" />
</a:booleanEvaluator>
<f:verbatim><br></f:verbatim>
<h:outputText value="#{msg.gettingstarted_createcontent_desc}" />
</h:panelGroup>
</h:panelGrid>
</h:panelGrid>
</h:panelGrid>
<f:verbatim>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "yellow"); %>

View File

@@ -14,9 +14,7 @@
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="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<%-- Note that this template is loaded from the classpath --%>
<r:template template="/alfresco/templates/my_docs.ftl" />

View File

@@ -0,0 +1,20 @@
<%--
Copyright (C) 2006 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="/WEB-INF/repo.tld" prefix="r" %>
<%-- Note that this template is loaded from the classpath --%>
<r:template template="/alfresco/templates/my_images.ftl" />

View File

@@ -100,9 +100,9 @@
<img src="<%=request.getContextPath()%>/images/logo/alfresco3d.jpg" width=520 height=168>
</div>
<div style="padding:4px">
<a href="http://www.alfresco.org/" class="title" target="new">http://www.alfresco.org</a>
<a href="http://www.alfresco.com/" class="title" target="new">http://www.alfresco.com</a>
<p>
Alfresco Software Inc. &#169; 2005-2006 All rights reserved. <a href="http://www.alfresco.org/legalandlicense.html" target="new">Legal and License</a>
Alfresco Software Inc. &#169; 2005-2006 All rights reserved. <a href="http://www.alfresco.com/legal/" target="new">Legal and License</a>
</div>
<div style="padding:4px" class="mainSubTitle">

View File

@@ -121,7 +121,7 @@
<tr><td class="dialogButtonSpacing"></td></tr>
<tr>
<td align="center">
<h:commandButton value="#{msg.cancel}" action="browse" styleClass="dialogControls" />
<h:commandButton value="#{msg.cancel}" action="dialog:close" styleClass="dialogControls" />
</td>
</tr>
</table>

View File

@@ -153,7 +153,7 @@
<tr><td class="dialogButtonSpacing"></td></tr>
<tr>
<td align="center">
<h:commandButton value="#{msg.cancel}" action="browse" styleClass="dialogControls" />
<h:commandButton value="#{msg.cancel}" action="dialog:close" styleClass="dialogControls" />
</td>
</tr>
</table>

View File

@@ -126,7 +126,7 @@
<tr><td class="dialogButtonSpacing"></td></tr>
<tr>
<td align="center">
<h:commandButton value="#{msg.cancel}" action="browse" styleClass="dialogControls" />
<h:commandButton value="#{msg.cancel}" action="dialog:close" styleClass="dialogControls" />
</td>
</tr>
</table>

View File

@@ -115,7 +115,7 @@
<tr><td class="dialogButtonSpacing"></td></tr>
<tr>
<td align="center">
<h:commandButton value="#{msg.cancel}" action="browse" styleClass="dialogControls" />
<h:commandButton value="#{msg.cancel}" action="dialog:close" styleClass="dialogControls" />
</td>
</tr>
</table>

View File

@@ -24,22 +24,27 @@
<script type="text/javascript">
window.onload = pageLoaded;
var okEnabled;
function pageLoaded()
{
document.getElementById("dialog:dialog-body:subject").focus();
okEnabled = !document.getElementById("dialog:finish-button").disabled;
checkButtonState();
}
function checkButtonState()
{
if (document.getElementById("dialog:dialog-body:subject").value.length == 0)
if (okEnabled)
{
document.getElementById("dialog:finish-button").disabled = true;
}
else
{
document.getElementById("dialog:finish-button").disabled = false;
if (document.getElementById("dialog:dialog-body:subject").value.length == 0)
{
document.getElementById("dialog:finish-button").disabled = true;
}
else
{
document.getElementById("dialog:finish-button").disabled = false;
}
}
}
</script>

View File

@@ -134,14 +134,25 @@
</a:panel>
<div style="padding:4px"></div>
<h:panelGroup id="pref-panel-facets">
<%--<h:panelGroup id="pref-panel-facets">
<f:facet name="title">
<a:actionLink value="#{msg.modify}" action="" showLink="false" image="/images/icons/Change_details.gif" rendered="#{NavigationBean.isGuest == false}" />
</f:facet>
</h:panelGroup>
<a:panel label="#{msg.general_pref}" id="pref-panel" facetsId="pref-panel-facets"
</h:panelGroup>--%>
<a:panel label="#{msg.general_pref}" id="pref-panel" rendered="#{NavigationBean.isGuest == false}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE">
<table width=100% cellspacing=2 cellpadding=2 border=0>
<table cellspacing=2 cellpadding=2 border=0>
<tr>
<td>
<h:outputText value="#{msg.start_location}" />:&nbsp;
</td>
<td>
<%-- Start Location drop-down selector --%>
<h:selectOneMenu id="start-location" value="#{UserPreferencesBean.startLocation}" onchange="document.forms['user-console'].submit(); return true;">
<f:selectItems value="#{UserPreferencesBean.startLocations}" />
</h:selectOneMenu>
</td>
</tr>
</table>
</a:panel>
</td>

View File

@@ -0,0 +1,132 @@
<%--
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="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<a:panel id="props-panel" label="#{msg.task_properties}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle">
<r:propertySheetGrid id="task-props" value="#{DialogManager.bean.taskNode}"
var="taskProps" columns="1" externalConfig="true" />
</a:panel>
<h:outputText styleClass="paddingRow" value="&nbsp;" escape="false" />
<a:panel id="resources-panel" label="#{msg.resources}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle">
<a:richList id="resources-list" viewMode="details" value="#{DialogManager.bean.resources}" var="r"
binding="#{DialogManager.bean.packageItemsRichList}"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow"
altRowStyleClass="recordSetRowAlt" width="100%" pageSize="10"
initialSortColumn="name" initialSortDescending="true">
<%-- Name column --%>
<a:column primary="true" width="200" style="padding:2px; text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.name}" value="name" mode="case-insensitive" styleClass="header"/>
</f:facet>
<f:facet name="small-icon">
<a:actionLink value="#{r.name}" href="#{r.url}" target="new" image="#{r.fileType16}"
showLink="false" styleClass="inlineAction" />
</f:facet>
<a:actionLink value="#{r.name}" href="#{r.url}" target="new" />
<r:lockIcon value="#{r.nodeRef}" align="absmiddle" />
</a:column>
<%-- Description column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.description}" value="description" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.description}" />
</a:column>
<%-- Path column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.path}" value="path" styleClass="header"/>
</f:facet>
<r:nodePath value="#{r.path}" />
</a:column>
<%-- Created Date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.created}" value="created" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.created}">
<a:convertXMLDate type="both" pattern="#{msg.date_time_pattern}" />
</h:outputText>
</a:column>
<%-- Modified Date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.modified}" value="modified" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.modified}">
<a:convertXMLDate type="both" pattern="#{msg.date_time_pattern}" />
</h:outputText>
</a:column>
<%-- Actions column --%>
<a:column actions="true" style="text-align:left">
<f:facet name="header">
<h:outputText value="#{msg.actions}"/>
</f:facet>
<r:actions value="#{DialogManager.bean.packageItemActionGroup}"
context="#{r}" showLink="false" styleClass="inlineAction" />
</a:column>
<%-- Completed column --%>
<%--
<a:column style="text-align:left">
<f:facet name="header">
<h:outputText value="#{msg.completed}" />
</f:facet>
<a:actionLink value="#{r.completed}" actionListener="#{DialogManager.bean.togglePackageItemComplete}">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</a:column>
--%>
</a:richList>
<h:panelGrid columns="1" styleClass="paddingRow">
<r:actions context="#{DialogManager.bean.taskNode}" value="#{DialogManager.bean.packageActionGroup}" />
</h:panelGrid>
<h:panelGrid columns="1" rendered="#{DialogManager.bean.itemBeingAdded}" styleClass="selector" style="margin-top: 6px;">
<r:contentSelector value="#{DialogManager.bean.itemsToAdd}" styleClass="" />
<h:panelGrid columns="2">
<h:commandButton value="#{msg.add_to_list_button}" actionListener="#{DialogManager.bean.addPackageItems}" />
<h:commandButton value="#{msg.cancel}" actionListener="#{DialogManager.bean.cancelAddPackageItems}" />
</h:panelGrid>
</h:panelGrid>
</a:panel>
<h:outputText styleClass="paddingRow" value="&nbsp;" escape="false" />
<a:panel id="workflow-summary-panel" label="#{msg.part_of_workflow}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle">
<r:workflowSummary value="#{DialogManager.bean.workflowInstance}" styleClass="workflowSummary" />
</a:panel>

View File

@@ -0,0 +1,40 @@
<%--
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="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<h:outputText value="#{msg.reassign_select_user}<br/><br/>" escape="false" />
<a:genericPicker id="user-picker" showAddButton="false" filters="#{DialogManager.bean.filters}"
queryCallback="#{DialogManager.bean.pickerCallback}" multiSelect="false" />
<script type="text/javascript">
document.getElementById("dialog:dialog-body:user-picker_results").onchange = checkButtonState;
function checkButtonState()
{
var button = document.getElementById("dialog:finish-button");
var list = document.getElementById("dialog:dialog-body:user-picker_results");
button.disabled = (list.selectedIndex == -1);
}
</script>

View File

@@ -44,7 +44,91 @@
<r:propertySheetGrid id="task-props" value="#{WizardManager.bean.taskMetadataNode}"
var="taskProps" columns="1" externalConfig="true" />
</a:panel>
<h:outputText styleClass="paddingRow" value="&nbsp;" escape="false" />
<a:panel id="resources-panel" label="#{msg.resources}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle">
<a:richList id="resources-list" viewMode="details" value="#{WizardManager.bean.resources}" var="r"
binding="#{WizardManager.bean.packageItemsRichList}"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow"
altRowStyleClass="recordSetRowAlt" width="100%" pageSize="10"
initialSortColumn="name" initialSortDescending="true">
<%-- Name column --%>
<a:column primary="true" width="200" style="padding:2px; text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.name}" value="name" mode="case-insensitive" styleClass="header"/>
</f:facet>
<f:facet name="small-icon">
<a:actionLink value="#{r.name}" href="#{r.url}" target="new" image="#{r.fileType16}"
showLink="false" styleClass="inlineAction" />
</f:facet>
<a:actionLink value="#{r.name}" href="#{r.url}" target="new" />
</a:column>
<%-- Description column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.description}" value="description" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.description}" />
</a:column>
<%-- Path column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.path}" value="path" styleClass="header"/>
</f:facet>
<r:nodePath value="#{r.path}" />
</a:column>
<%-- Created Date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.created}" value="created" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.created}">
<a:convertXMLDate type="both" pattern="#{msg.date_time_pattern}" />
</h:outputText>
</a:column>
<%-- Modified Date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.modified}" value="modified" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.modified}">
<a:convertXMLDate type="both" pattern="#{msg.date_time_pattern}" />
</h:outputText>
</a:column>
<%-- Actions column --%>
<a:column actions="true" style="text-align:left">
<f:facet name="header">
<h:outputText value="#{msg.actions}"/>
</f:facet>
<r:actions id="actions-col-actions" value="#{WizardManager.bean.packageItemActionGroup}"
context="#{r}" showLink="false" styleClass="inlineAction" />
</a:column>
</a:richList>
<h:panelGrid columns="1" styleClass="paddingRow">
<r:actions context="#{WizardManager.bean.taskMetadataNode}" value="#{WizardManager.bean.packageActionGroup}" />
</h:panelGrid>
<h:panelGrid columns="1" rendered="#{WizardManager.bean.itemBeingAdded}" styleClass="selector" style="margin-top: 6px;">
<r:contentSelector value="#{WizardManager.bean.itemsToAdd}" styleClass="" />
<h:panelGrid columns="2">
<h:commandButton value="#{msg.add_to_list_button}" actionListener="#{WizardManager.bean.addPackageItems}" />
<h:commandButton value="#{msg.cancel}" actionListener="#{WizardManager.bean.cancelAddPackageItems}" />
</h:panelGrid>
</h:panelGrid>
</a:panel>
</h:panelGroup>

View File

@@ -0,0 +1,72 @@
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<a:richList id="tasks-completed-list" viewMode="details" value="#{WorkflowBean.tasksCompleted}" var="r"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow"
altRowStyleClass="recordSetRowAlt" width="100%" pageSize="10"
initialSortColumn="name" initialSortDescending="true">
<%-- Primary column for details view mode --%>
<a:column primary="true" width="200" style="padding:2px;text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.title}" value="name" mode="case-insensitive" styleClass="header"/>
</f:facet>
<f:facet name="small-icon">
<a:actionLink value="#{r.name}" image="/images/icons/completed_workflow_task.gif" showLink="false"
actionListener="#{DialogManager.setupParameters}" action="dialog:viewCompletedTask">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</f:facet>
<a:actionLink value="#{r.name}" actionListener="#{DialogManager.setupParameters}"
action="dialog:viewCompletedTask">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</a:column>
<%-- Task id column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.id}" value="bpm:taskId" styleClass="header"/>
</f:facet>
<h:outputText value="#{r['bpm:taskId']}" />
</a:column>
<%-- Source column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.source}" value="sourceSpaceName" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.sourceSpaceName}" />
</a:column>
<%-- Completed date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.completed_on}" value="bpm:completionDate" styleClass="header"/>
</f:facet>
<h:outputText value="#{r['bpm:completionDate']}">
<a:convertXMLDate type="both" pattern="#{msg.date_pattern}" />
</h:outputText>
</a:column>
<%-- Outcome column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.outcome}" value="outcome" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.outcome}" />
</a:column>
<%-- Actions column --%>
<a:column actions="true" style="text-align:left">
<f:facet name="header">
<h:outputText value="#{msg.actions}"/>
</f:facet>
<r:actions value="dashlet_completed_actions" context="#{r}" showLink="false"
styleClass="inlineAction" />
</a:column>
<a:dataPager styleClass="pager" />
</a:richList>

View File

@@ -0,0 +1,80 @@
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<a:richList id="tasks-todo-list" viewMode="details" value="#{WorkflowBean.tasksToDo}" var="r"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow"
altRowStyleClass="recordSetRowAlt" width="100%" pageSize="10"
initialSortColumn="name" initialSortDescending="true">
<%-- Primary column for details view mode --%>
<a:column primary="true" width="200" style="padding:2px;text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.title}" value="name" mode="case-insensitive" styleClass="header"/>
</f:facet>
<f:facet name="small-icon">
<a:actionLink value="#{r.name}" image="/images/icons/workflow_task.gif" showLink="false"
actionListener="#{DialogManager.setupParameters}" action="dialog:manageTask">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</f:facet>
<a:actionLink value="#{r.name}" actionListener="#{DialogManager.setupParameters}"
action="dialog:manageTask">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</a:column>
<%-- Task id column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.id}" value="bpm:taskId" styleClass="header"/>
</f:facet>
<h:outputText value="#{r['bpm:taskId']}" />
</a:column>
<%-- Source column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.source}" value="sourceSpaceName" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.sourceSpaceName}" />
</a:column>
<%-- Due date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.due_date}" value="bpm:startDate" styleClass="header"/>
</f:facet>
<h:outputText value="#{r['bpm:dueDate']}">
<a:convertXMLDate type="both" pattern="#{msg.date_pattern}" />
</h:outputText>
</a:column>
<%-- Status column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.status}" value="bpm:status" styleClass="header"/>
</f:facet>
<h:outputText value="#{r['bpm:status']}" />
</a:column>
<%-- Priority column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.priority}" value="bpm:priority" styleClass="header"/>
</f:facet>
<h:outputText value="#{r['bpm:priority']}" />
</a:column>
<%-- Actions column --%>
<a:column actions="true" style="text-align:left">
<f:facet name="header">
<h:outputText value="#{msg.actions}"/>
</f:facet>
<r:actions value="dashlet_todo_actions" context="#{r}" showLink="false"
styleClass="inlineAction" />
</a:column>
<a:dataPager styleClass="pager" />
</a:richList>

View File

@@ -0,0 +1,98 @@
<%--
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="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<a:panel id="props-panel" label="#{msg.task_properties}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle">
<r:propertySheetGrid id="task-props" value="#{DialogManager.bean.taskNode}"
var="taskProps" columns="1" externalConfig="true" mode="view" />
</a:panel>
<h:outputText styleClass="paddingRow" value="&nbsp;" escape="false" />
<a:panel id="resources-panel" label="#{msg.resources}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle">
<a:richList id="resources-list" viewMode="details" value="#{DialogManager.bean.resources}" var="r"
binding="#{DialogManager.bean.packageItemsRichList}"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow"
altRowStyleClass="recordSetRowAlt" width="100%" pageSize="10"
initialSortColumn="name" initialSortDescending="true">
<%-- Name column --%>
<a:column primary="true" width="200" style="padding:2px; text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.name}" value="name" mode="case-insensitive" styleClass="header"/>
</f:facet>
<f:facet name="small-icon">
<a:actionLink value="#{r.name}" href="#{r.url}" target="new" image="#{r.fileType16}"
showLink="false" styleClass="inlineAction" />
</f:facet>
<a:actionLink value="#{r.name}" href="#{r.url}" target="new" />
<r:lockIcon value="#{r.nodeRef}" align="absmiddle" />
</a:column>
<%-- Description column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.description}" value="description" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.description}" />
</a:column>
<%-- Path column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.path}" value="path" styleClass="header"/>
</f:facet>
<r:nodePath value="#{r.path}" />
</a:column>
<%-- Created Date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.created}" value="created" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.created}">
<a:convertXMLDate type="both" pattern="#{msg.date_time_pattern}" />
</h:outputText>
</a:column>
<%-- Modified Date column --%>
<a:column style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.modified}" value="modified" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.modified}">
<a:convertXMLDate type="both" pattern="#{msg.date_time_pattern}" />
</h:outputText>
</a:column>
</a:richList>
</a:panel>
<h:outputText styleClass="paddingRow" value="&nbsp;" escape="false" />
<a:panel id="workflow-summary-panel" label="#{msg.part_of_workflow}"
border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle">
<r:workflowSummary value="#{DialogManager.bean.workflowInstance}" styleClass="workflowSummary" />
</a:panel>