diff --git a/config/alfresco/web-client-application-context.xml b/config/alfresco/web-client-application-context.xml index a8c050501c..4a95f9cbea 100644 --- a/config/alfresco/web-client-application-context.xml +++ b/config/alfresco/web-client-application-context.xml @@ -7,6 +7,8 @@ classpath:alfresco/web-client-config.xml + classpath:alfresco/web-client-config-dialogs.xml + classpath:alfresco/web-client-config-wizards.xml classpath:alfresco/web-client-config-properties.xml classpath:alfresco/web-client-config-navigation.xml classpath:alfresco/web-client-config-actions.xml diff --git a/config/alfresco/web-client-config-actions.xml b/config/alfresco/web-client-config-actions.xml index 4f3dae4037..d2e95f1ab9 100644 --- a/config/alfresco/web-client-config-actions.xml +++ b/config/alfresco/web-client-config-actions.xml @@ -329,8 +329,8 @@ new_space /images/icons/create_space.gif - createSpace - #{NewSpaceDialog.startWizard} + dialog:createSpace + diff --git a/config/alfresco/web-client-config-dialogs.xml b/config/alfresco/web-client-config-dialogs.xml new file mode 100644 index 0000000000..93203abaf9 --- /dev/null +++ b/config/alfresco/web-client-config-dialogs.xml @@ -0,0 +1,13 @@ + + + + /jsp/dialog/container.jsp + + + + + + + diff --git a/config/alfresco/web-client-config-wizards.xml b/config/alfresco/web-client-config-wizards.xml new file mode 100644 index 0000000000..5ee8beb913 --- /dev/null +++ b/config/alfresco/web-client-config-wizards.xml @@ -0,0 +1,10 @@ + + + + /jsp/dialog/container.jsp + + + + + + diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 27d219fe8c..1f8cd1492d 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -13,6 +13,8 @@ + + diff --git a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java index 8a70b08890..5547798e0a 100644 --- a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java +++ b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java @@ -26,23 +26,37 @@ import javax.faces.context.FacesContext; import org.alfresco.config.Config; import org.alfresco.config.ConfigService; +import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.bean.NavigationBean; +import org.alfresco.web.bean.dialog.DialogManager; import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.wizard.WizardManager; +import org.alfresco.web.config.DialogsConfigElement; import org.alfresco.web.config.NavigationConfigElement; import org.alfresco.web.config.NavigationElementReader; import org.alfresco.web.config.NavigationResult; +import org.alfresco.web.config.DialogsConfigElement.DialogConfig; +import org.alfresco.web.config.WizardsConfigElement.WizardConfig; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.web.jsf.FacesContextUtils; /** * @author gavinc */ public class AlfrescoNavigationHandler extends NavigationHandler { - public final static String DIALOG_SEPARATOR = ":"; - public final static String DIALOG_PREXIX = "dialog" + DIALOG_SEPARATOR; + public final static String OUTCOME_SEPARATOR = ":"; + public final static String DIALOG_PREXIX = "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_WIZARD_OUTCOME = WIZARD_PREFIX + "close"; + + protected final static String CONFIG_NAV_BEAN = "NavigationBean"; + protected final static String CONFIG_DIALOGS = "Dialogs"; + protected final static String CONFIG_WIZARDS = "Wizards"; + + protected String dialogContainer = null; + protected String wizardContainer = null; private final static Log logger = LogFactory.getLog(AlfrescoNavigationHandler.class); private final static String VIEW_STACK = "_alfViewStack"; @@ -69,186 +83,530 @@ public class AlfrescoNavigationHandler extends NavigationHandler public void handleNavigation(FacesContext context, String fromAction, String outcome) { if (logger.isDebugEnabled()) + { logger.debug("handleNavigation (fromAction=" + fromAction + ", outcome=" + outcome + ")"); + logger.debug("Current view id: " + context.getViewRoot().getViewId()); + } + + boolean isDialog = isDialog(outcome); + if (isDialog || isWizard(outcome)) + { + boolean dialogWizardClosing = isDialogOrWizardClosing(outcome); + outcome = stripPrefix(outcome); + + if (dialogWizardClosing) + { + handleDialogOrWizardClose(context, fromAction, outcome); + } + else + { + if (isDialog) + { + handleDialogOpen(context, fromAction, outcome); + } + else + { + handleWizardOpen(context, fromAction, outcome); + } + + if (logger.isDebugEnabled()) + logger.debug("view stack: " + getViewStack(context)); + } + } + else + { + handleDispatch(context, fromAction, outcome); + } + } + + /** + * Determines whether the given outcome is dialog related + * + * @param outcome The outcome to test + * @return true if outcome is dialog related i.e. starts with dialog: + */ + protected boolean isDialog(String outcome) + { + boolean dialog = false; - boolean useOriginalNavHandler = true; - boolean closingDialog = false; - String viewId = context.getViewRoot().getViewId(); - - if (logger.isDebugEnabled()) - logger.debug("Current view id: " + viewId); - - // determine if we are dealing with a dialog if (outcome != null && outcome.startsWith(DIALOG_PREXIX)) { - // determine whether it's being closed or opened - closingDialog = outcome.startsWith(CLOSE_DIALOG_OUTCOME); - - // remove the dialog prefix - outcome = outcome.substring(DIALOG_PREXIX.length()); - - if (closingDialog) + dialog = true; + } + + return dialog; + } + + /** + * Determines whether the given outcome is wizard related + * + * @param outcome The outcome to test + * @return true if outcome is wizard related + * i.e. starts with create-wizard: or edit-wizard: + */ + protected boolean isWizard(String outcome) + { + boolean wizard = false; + + if (outcome != null && outcome.startsWith(WIZARD_PREFIX)) + { + wizard = true; + } + + return wizard; + } + + /** + * Determines whether the given outcome represents a dialog or wizard closing + * + * @param outcome The outcome to test + * @return true if the outcome represents a closing dialog or wizard + */ + protected boolean isDialogOrWizardClosing(String outcome) + { + boolean closing = false; + + if (outcome != null && + (outcome.startsWith(CLOSE_DIALOG_OUTCOME) || + outcome.startsWith(CLOSE_WIZARD_OUTCOME))) + { + closing = true; + } + + return closing; + } + + /** + * Removes the dialog or wizard prefix from the given outcome + * + * @param outcome The outcome to remove the prefix from + * @return The remaining outcome + */ + protected String stripPrefix(String outcome) + { + String newOutcome = outcome; + + if (outcome != null) + { + int idx = outcome.indexOf(OUTCOME_SEPARATOR); + if (idx != -1) { - // if we are closing the dialog take the view off the - // top of the stack then decide whether to use the view - // or any overridden outcome that may be present - if (getViewStack(context).empty() == false) + newOutcome = outcome.substring(idx+1); + } + } + + return newOutcome; + } + + /** + * Returns the overridden outcome. + * Used by dialogs and wizards to go to a particular page after it closes + * rather than back to the page it was launched from. + * + * @param outcome The current outcome + * @return The overridden outcome or null if there isn't an override + */ + protected String getOutcomeOverride(String outcome) + { + String override = null; + + if (outcome != null) + { + int idx = outcome.indexOf(OUTCOME_SEPARATOR); + if (idx != -1) + { + override = outcome.substring(idx+1); + } + } + + return override; + } + + /** + * Returns the dialog configuration object for the given dialog name. + * If there is a node in the dispatch context a lookup is performed using + * the node. If this doesn't return any config or there is no dispatch + * context node a 'global' dialog lookup is performed. + * + * + * @param name The name of dialog being launched + * @param dispatchContext The node being acted upon + * @return The DialogConfig for the dialog or null if no config could be found + */ + protected DialogConfig getDialogConfig(FacesContext context, String name, Node dispatchContext) + { + DialogConfig dialogConfig = null; + ConfigService configSvc = Application.getConfigService(context); + + if (dispatchContext != null) + { + Config config = configSvc.getConfig(dispatchContext); + if (config != null) + { + DialogsConfigElement dialogsCfg = (DialogsConfigElement)config.getConfigElement( + DialogsConfigElement.CONFIG_ELEMENT_ID); + if (dialogsCfg != null) { - String newViewId = (String)getViewStack(context).pop(); + dialogConfig = dialogsCfg.getDialog(name); + } + } + } + + // if we didn't find a dialog via the dispatch look it up in the 'global' dialogs config + if (dialogConfig == null) + { + Config config = configSvc.getConfig(CONFIG_DIALOGS); + if (config != null) + { + DialogsConfigElement dialogsCfg = (DialogsConfigElement)config.getConfigElement( + DialogsConfigElement.CONFIG_ELEMENT_ID); + if (dialogsCfg != null) + { + dialogConfig = dialogsCfg.getDialog(name); + } + } + } + + return dialogConfig; + } + + /** + * Returns the wizard configuration object for the given wizard name. + * If there is a node in the dispatch context a lookup is performed using + * the node otherwise a 'global' wizard lookup is performed. + * + * @param name The name of wizard being launched + * @param dispatchContext The node being acted upon + * @return The WizardConfig for the wizard or null if no config could be found + */ + protected WizardConfig getWizardConfig(FacesContext context, String name, Node dispatchContext) + { + return null; + } + + /** + * 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 dialogsConfig = configSvc.getConfig(CONFIG_DIALOGS); + + if (dialogsConfig != null) + { + this.dialogContainer = dialogsConfig.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 wizardsConfig = configSvc.getConfig(CONFIG_WIZARDS); + + if (wizardsConfig != null) + { + this.wizardContainer = wizardsConfig.getConfigElement("wizard-container").getValue(); + } + } + + return this.wizardContainer; + } + + /** + * Returns the node currently in the dispatch context + * + * @return The node currently in the dispatch context or null if + * the dispatch context is empty + */ + protected Node getDispatchContextNode(FacesContext context) + { + Node dispatchNode = null; + + NavigationBean navBean = (NavigationBean)context.getExternalContext(). + getSessionMap().get(CONFIG_NAV_BEAN); + + if (navBean != null) + { + dispatchNode = navBean.getDispatchContextNode(); + } + + return dispatchNode; + } + + /** + * Processes any dispatching that may need to occur + * + * @param node The node in the current dispatch context + * @param viewId The current view id + * @param outcome The outcome + */ + protected void handleDispatch(FacesContext context, String fromAction, String outcome) + { + Node dispatchNode = getDispatchContextNode(context); + + if (dispatchNode != null) + { + if (logger.isDebugEnabled()) + logger.debug("Found node with type '" + dispatchNode.getType().toString() + + "' in dispatch context"); + + // get the current view id + String viewId = context.getViewRoot().getViewId(); - // is there an overiddent outcome? - int idx = outcome.indexOf(DIALOG_SEPARATOR); - if (idx == -1) - { - // there isn't an overidden outcome so go back to the previous view - if (logger.isDebugEnabled()) - logger.debug("Closing dialog, going back to view id: " + newViewId); + // see if there is any navigation config for the node type + ConfigService configSvc = Application.getConfigService(context); + Config nodeConfig = configSvc.getConfig(dispatchNode); + NavigationConfigElement navigationCfg = (NavigationConfigElement)nodeConfig. + getConfigElement(NavigationElementReader.ELEMENT_NAVIGATION); + + if (navigationCfg != null) + { + // see if there is config for the current view state + NavigationResult navResult = navigationCfg.getOverride(viewId, outcome); + + if (navResult != null) + { + if (logger.isDebugEnabled()) + logger.debug("Found navigation config: " + navResult); - goToView(context, newViewId); + if (navResult.isOutcome()) + { + navigate(context, fromAction, navResult.getResult()); } else { - // there is an overidden outcome so extract it - outcome = outcome.substring(idx+1, outcome.length()); + String newViewId = navResult.getResult(); - // we also need to empty the dialog stack if we have been given - // an overidden outcome as we could be going anywhere in the app - getViewStack(context).clear(); + if (newViewId.equals(viewId) == false) + { + if (logger.isDebugEnabled()) + logger.debug("Dispatching to new view id: " + newViewId); - if (logger.isDebugEnabled()) - logger.debug("Closing dialog with an overridden outcome of '" + outcome + "'"); - - this.origHandler.handleNavigation(context, fromAction, outcome); + goToView(context, newViewId); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("New view id is the same as the current one so setting outcome to null"); + + navigate(context, fromAction, null); + } } } else { - // we are trying to close a dialog when one hasn't been opened! - // log a warning and return a null outcome to stay on the same page - if (logger.isWarnEnabled()) - { - logger.warn("Attempting to close a dialog with an empty view stack, returning null outcome"); - } + if (logger.isDebugEnabled()) + logger.debug("No override configuration found for current view or outcome"); - this.origHandler.handleNavigation(context, fromAction, null); + navigate(context, fromAction, outcome); } } else { - // if we are opening a 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!) - - // 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 (getViewStack(context).empty() || - viewId.equals(getViewStack(context).peek()) == false) - { - getViewStack(context).push(viewId); - - if (logger.isDebugEnabled()) - logger.debug("Pushed current view to stack: " + viewId); - } - else - { - if (getViewStack(context).empty() == false && logger.isDebugEnabled()) - { - logger.debug("current view is already top the view stack!"); - } - } - } - - if (logger.isDebugEnabled()) - logger.debug("view stack: " + getViewStack(context)); - } - - if (closingDialog == false) - { - NavigationBean navBean = (NavigationBean)context.getExternalContext(). - getSessionMap().get("NavigationBean"); - - // only continue if we have some dispatching context - if (navBean != null && navBean.getDispatchContextNode() != null) - { - Node node = navBean.getDispatchContextNode(); - if (logger.isDebugEnabled()) - logger.debug("Found node with type '" + node.getType().toString() + - "' in dispatch context"); - - // see if there is any navigation config for the node type - ConfigService configSvc = Application.getConfigService(context); - Config nodeConfig = configSvc.getConfig(node); - NavigationConfigElement navigationCfg = (NavigationConfigElement)nodeConfig. - getConfigElement(NavigationElementReader.ELEMENT_NAVIGATION); - - if (navigationCfg != null) - { - // see if there is config for the current view state - NavigationResult navResult = navigationCfg.getOverride(viewId, outcome); - - if (navResult != null) - { - if (logger.isDebugEnabled()) - logger.debug("Found navigation config: " + navResult); - - if (navResult.isOutcome()) - { - outcome = navResult.getResult(); - } - else - { - String newViewId = navResult.getResult(); - - if (newViewId.equals(viewId) == false) - { - useOriginalNavHandler = false; - - if (logger.isDebugEnabled()) - logger.debug("Dispatching to new view id: " + newViewId); - - goToView(context, newViewId); - } - else - { - if (logger.isDebugEnabled()) - logger.debug("New view id is the same as the current one so setting outcome to null"); - - outcome = null; - } - } - } - else if (logger.isDebugEnabled()) - { - logger.debug("No override configuration found for current view or outcome"); - } - } - else if (logger.isDebugEnabled()) - { logger.debug("No navigation configuration found for node"); - } - // reset the dispatch context - navBean.resetDispatchContext(); - } - else if (logger.isDebugEnabled()) - { - logger.debug("No dispatch context found"); + navigate(context, fromAction, outcome); } - // do the appropriate navigation handling - if (useOriginalNavHandler) - { - if (logger.isDebugEnabled()) - logger.debug("Passing outcome '" + outcome + "' to original navigation handler"); + // reset the dispatch context + ((NavigationBean)context.getExternalContext().getSessionMap(). + get(CONFIG_NAV_BEAN)).resetDispatchContext(); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("No dispatch context found"); - this.origHandler.handleNavigation(context, fromAction, outcome); + // pass off to the original handler + navigate(context, fromAction, outcome); + } + } + + /** + * Opens a dialog + * + * @param context FacesContext + * @param fromAction The fromAction + * @param name The name of the dialog to open + */ + protected void handleDialogOpen(FacesContext context, String fromAction, String name) + { + if (logger.isDebugEnabled()) + logger.debug("Opening dialog '" + name + "'"); + + // firstly add the current view to the stack so we know where to go back to + addCurrentViewToStack(context); + + DialogConfig config = getDialogConfig(context, name, getDispatchContextNode(context)); + if (config != null) + { + if (logger.isDebugEnabled()) + logger.debug("Found config for dialog '" + name + "': " + config); + + // set the dialog manager up with the retrieved config + DialogManager dialogManager = Application.getDialogManager(); + dialogManager.setCurrentDialog(config); + + // retrieve the container page and navigate to it + goToView(context, getDialogContainer(context)); + } + else + { + // send the dialog name as the outcome to the original handler + handleDispatch(context, fromAction, name); + } + } + + /** + * Opens a wizard + * + * @param context FacesContext + * @param fromAction The fromAction + * @param name The name of the wizard to open + */ + protected void handleWizardOpen(FacesContext context, String fromAction, String name) + { + if (logger.isDebugEnabled()) + logger.debug("Opening wizard '" + name + "'"); + + // firstly add the current view to the stack so we know where to go back to + addCurrentViewToStack(context); + + WizardConfig wizard = getWizardConfig(context, name, getDispatchContextNode(context)); + if (wizard != null) + { + if (logger.isDebugEnabled()) + logger.debug("Found config for wizard '" + name + "': " + wizard); + + // set the wizard manager up with the retrieved config + WizardManager wizardManager = Application.getWizardManager(); + wizardManager.setCurrentWizard(wizard); + + // retrieve the container page and navigate to it + goToView(context, getWizardContainer(context)); + } + else + { + // send the dialog name as the outcome to the original handler + handleDispatch(context, fromAction, name); + } + } + + /** + * Closes the current dialog or wizard + */ + protected void handleDialogOrWizardClose(FacesContext context, String fromAction, String outcome) + { + // if we are closing the dialog take the view off the + // top of the stack then decide whether to use the view + // 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 dialog, going back to view id: " + newViewId); + + goToView(context, newViewId); + } + else + { + // we also need to empty the dialog stack if we have been given + // an overidden outcome as we could be going anywhere in the app + getViewStack(context).clear(); + + if (logger.isDebugEnabled()) + logger.debug("Closing dialog with an overridden outcome of '" + overriddenOutcome + "'"); + + navigate(context, fromAction, overriddenOutcome); } } + else + { + // we are trying to close a dialog when one hasn't been opened! + // log a warning and return a null outcome to stay on the same page + if (logger.isWarnEnabled()) + { + logger.warn("Attempting to close a dialog with an empty view stack, returning null outcome"); + } + + navigate(context, fromAction, null); + } + } + + /** + * Adds the current view to the stack (if required). + * If the current view is already the top of the stack it is not added again + * to stop the stack from growing and growing. + * + * @param context FacesContext + */ + protected void addCurrentViewToStack(FacesContext context) + { + // if we are opening a 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!) + + // 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?? + + String viewId = context.getViewRoot().getViewId(); + + if (getViewStack(context).empty() || + viewId.equals(getViewStack(context).peek()) == false) + { + getViewStack(context).push(viewId); + + if (logger.isDebugEnabled()) + logger.debug("Pushed current view to stack: " + viewId); + } + else + { + if (getViewStack(context).empty() == false && logger.isDebugEnabled()) + { + logger.debug("current view is already top the view stack!"); + } + } + } + + /** + * Navigates to the appropriate page using the original navigation handler + * + * @param context FacesContext + * @param fromAction The fromAction + * @param outcome The outcome + */ + private void navigate(FacesContext context, String fromAction, String outcome) + { + if (logger.isDebugEnabled()) + logger.debug("Passing outcome '" + outcome + "' to original navigation handler"); + + this.origHandler.handleNavigation(context, fromAction, outcome); } /** @@ -274,13 +632,13 @@ public class AlfrescoNavigationHandler extends NavigationHandler * the users session, will never be null */ @SuppressWarnings("unchecked") - private Stack getViewStack(FacesContext context) + private Stack getViewStack(FacesContext context) { - Stack viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK); + Stack viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK); if (viewStack == null) { - viewStack = new Stack(); + viewStack = new Stack(); context.getExternalContext().getSessionMap().put(VIEW_STACK, viewStack); } diff --git a/source/java/org/alfresco/web/app/Application.java b/source/java/org/alfresco/web/app/Application.java index cd443e61f1..90736d6ae7 100644 --- a/source/java/org/alfresco/web/app/Application.java +++ b/source/java/org/alfresco/web/app/Application.java @@ -36,8 +36,11 @@ import org.alfresco.config.ConfigService; import org.alfresco.repo.importer.ImporterBootstrap; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.web.app.servlet.AuthenticationHelper; +import org.alfresco.web.app.servlet.FacesHelper; import org.alfresco.web.bean.ErrorBean; +import org.alfresco.web.bean.dialog.DialogManager; import org.alfresco.web.bean.repository.User; +import org.alfresco.web.bean.wizard.WizardManager; import org.alfresco.web.config.ClientConfigElement; import org.apache.commons.logging.Log; import org.springframework.web.context.WebApplicationContext; @@ -164,6 +167,26 @@ public class Application } } + /** + * Retrieves the DialogManager managed bean + * + * @return DialogManager bean + */ + public static DialogManager getDialogManager() + { + return (DialogManager)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "DialogManager"); + } + + /** + * Retrieves the WizardManager managed bean + * + * @return WizardManager bean + */ + public static WizardManager getWizardManager() + { + return (WizardManager)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "WizardManager"); + } + /** * Retrieves the configured error page for the application * diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index 7bb49867e6..b3ebd6b384 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -1197,7 +1197,7 @@ public class BrowseBean implements IContextListener // setting the outcome will show the browse view again outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + - AlfrescoNavigationHandler.DIALOG_SEPARATOR + "browse"; + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; } catch (Throwable err) { @@ -1237,7 +1237,7 @@ public class BrowseBean implements IContextListener // setting the outcome will show the browse view again outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + - AlfrescoNavigationHandler.DIALOG_SEPARATOR + "browse"; + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; } catch (Throwable err) { diff --git a/source/java/org/alfresco/web/bean/ForumsBean.java b/source/java/org/alfresco/web/bean/ForumsBean.java index fa1507655a..fcd420c5eb 100644 --- a/source/java/org/alfresco/web/bean/ForumsBean.java +++ b/source/java/org/alfresco/web/bean/ForumsBean.java @@ -737,7 +737,7 @@ public class ForumsBean implements IContextListener { // return an overidden outcome which closes the dialog with an outcome outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + - AlfrescoNavigationHandler.DIALOG_SEPARATOR + outcomeOverride; + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + outcomeOverride; } return outcome; @@ -788,7 +788,7 @@ public class ForumsBean implements IContextListener { // return an overidden outcome which closes the dialog with an outcome outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + - AlfrescoNavigationHandler.DIALOG_SEPARATOR + outcomeOverride; + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + outcomeOverride; } return outcome; @@ -823,7 +823,7 @@ public class ForumsBean implements IContextListener if (outcome != null) { outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + - AlfrescoNavigationHandler.DIALOG_SEPARATOR + outcomeOverride; + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + outcomeOverride; } return outcome; diff --git a/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java new file mode 100644 index 0000000000..03b0be2c7c --- /dev/null +++ b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java @@ -0,0 +1,39 @@ +package org.alfresco.web.bean.dialog; + +import javax.faces.context.FacesContext; + +import org.alfresco.web.app.Application; +import org.alfresco.web.app.context.UIContextService; + +/** + * Base class for all dialog beans providing common functionality + * + * @author gavinc + */ +public abstract class BaseDialogBean implements IDialogBean +{ + protected static final String DIALOG_CLOSE = "dialog:close"; + + public abstract String finish(); + + public void init() + { + // tell any beans to update themselves so the UI gets refreshed + UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans(); + } + + public String cancel() + { + return DIALOG_CLOSE; + } + + public boolean getFinishButtonDisabled() + { + return true; + } + + public String getFinishButtonLabel() + { + return Application.getMessage(FacesContext.getCurrentInstance(), "ok"); + } +} diff --git a/source/java/org/alfresco/web/bean/dialog/DialogManager.java b/source/java/org/alfresco/web/bean/dialog/DialogManager.java new file mode 100644 index 0000000000..ae7b856f45 --- /dev/null +++ b/source/java/org/alfresco/web/bean/dialog/DialogManager.java @@ -0,0 +1,153 @@ +package org.alfresco.web.bean.dialog; + +import javax.faces.context.FacesContext; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.web.app.Application; +import org.alfresco.web.app.servlet.FacesHelper; +import org.alfresco.web.config.DialogsConfigElement.DialogConfig; + +/** + * Bean that manages the dialog framework + * + * @author gavinc + */ +public class DialogManager +{ + protected DialogConfig currentDialogConfig; + protected IDialogBean currentDialog; + + /** + * Sets the current dialog + * + * @param config The configuration for the dialog to set + */ + public void setCurrentDialog(DialogConfig config) + { + this.currentDialogConfig = config; + + String beanName = this.currentDialogConfig.getManagedBean(); + this.currentDialog = (IDialogBean)FacesHelper.getManagedBean( + FacesContext.getCurrentInstance(), beanName); + + if (this.currentDialog == null) + { + throw new AlfrescoRuntimeException("Failed to find managed bean '" + beanName + "'"); + } + + // initialise the managed bean + this.currentDialog.init(); + } + + /** + * Returns the current dialog bean being managed + * + * @return The current managed bean + */ + public IDialogBean getBean() + { + return this.currentDialog; + } + + /** + * Returns the icon to use for the current dialog + * + * @return The icon + */ + public String getIcon() + { + return this.currentDialogConfig.getIcon(); + } + + /** + * Returns the resolved title to use for the dialog + * + * @return The title + */ + public String getTitle() + { + String title = this.currentDialogConfig.getTitleId(); + + if (title != null) + { + title = Application.getMessage(FacesContext.getCurrentInstance(), title); + } + else + { + title = this.currentDialogConfig.getTitle(); + } + + return title; + } + + /** + * Returns the resolved description to use for the dialog + * + * @return The description + */ + public String getDescription() + { + String desc = this.currentDialogConfig.getDescriptionId(); + + if (desc != null) + { + desc = Application.getMessage(FacesContext.getCurrentInstance(), desc); + } + else + { + desc = this.currentDialogConfig.getDescription(); + } + + return desc; + } + + /** + * Returns the page the dialog will use + * + * @return The page + */ + public String getPage() + { + return this.currentDialogConfig.getPage(); + } + + /** + * Returns the label to use for the finish button + * + * @return The finish button label + */ + public String getFinishButtonLabel() + { + return this.currentDialog.getFinishButtonLabel(); + } + + /** + * Determines whether the finish button on the dialog should be disabled + * + * @return true if the button should be disabled + */ + public boolean getFinishButtonDisabled() + { + return this.currentDialog.getFinishButtonDisabled(); + } + + /** + * Method handler called when the finish button of the dialog is pressed + * + * @return The outcome + */ + public String finish() + { + return this.currentDialog.finish(); + } + + /** + * Method handler called when the cancel button of the dialog is pressed + * + * @return The outcome + */ + public String cancel() + { + return this.currentDialog.cancel(); + } +} diff --git a/source/java/org/alfresco/web/bean/dialog/IDialogBean.java b/source/java/org/alfresco/web/bean/dialog/IDialogBean.java new file mode 100644 index 0000000000..c0eeabbf44 --- /dev/null +++ b/source/java/org/alfresco/web/bean/dialog/IDialogBean.java @@ -0,0 +1,42 @@ +package org.alfresco.web.bean.dialog; + +/** + * Interface that defines the contract for a dialog backing bean + * + * @author gavinc + */ +public interface IDialogBean +{ + /** + * Initialises the dialog bean + */ + public void init(); + + /** + * Method handler called when the finish button of the dialog is pressed + * + * @return The outcome to return (normally dialog:close) + */ + public String finish(); + + /** + * Method handler called when the cancel button of the dialog is pressed + * + * @return The outcome to return (normally dialog:close) + */ + public String cancel(); + + /** + * Returns the label to use for the finish button + * + * @return The finish button label + */ + public String getFinishButtonLabel(); + + /** + * Determines whether the finish button on the dialog should be disabled + * + * @return true if the button should be disabled + */ + public boolean getFinishButtonDisabled(); +} diff --git a/source/java/org/alfresco/web/bean/dialog/SpaceDialog.java b/source/java/org/alfresco/web/bean/dialog/SpaceDialog.java new file mode 100644 index 0000000000..d702a33558 --- /dev/null +++ b/source/java/org/alfresco/web/bean/dialog/SpaceDialog.java @@ -0,0 +1,328 @@ +package org.alfresco.web.bean.dialog; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.faces.context.FacesContext; +import javax.transaction.UserTransaction; + +import org.alfresco.config.Config; +import org.alfresco.config.ConfigElement; +import org.alfresco.model.ContentModel; +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.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +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.BrowseBean; +import org.alfresco.web.bean.NavigationBean; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIListItem; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Dialog bean to create a space + * + * @author gavinc + */ +public class SpaceDialog extends BaseDialogBean +{ + protected static final String ERROR = "error_space"; + private static final String SPACE_ICON_DEFAULT = "space-icon-default"; +// private static final String DEFAULT_SPACE_TYPE_ICON = "/images/icons/space.gif"; + private static final String ICONS_LOOKUP_KEY = " icons"; + + protected NodeService nodeService; + protected FileFolderService fileFolderService; + protected NamespaceService namespaceService; + protected SearchService searchService; + protected NavigationBean navigator; + protected BrowseBean browseBean; + + protected String spaceType; + protected String icon; + protected String name; + protected String description; + + + private static Log logger = LogFactory.getLog(SpaceDialog.class); + + /** + * @param nodeService The nodeService to set. + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @param fileFolderService used to manipulate folder/folder model nodes + */ + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + /** + * @param searchService the service used to find nodes + */ + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + /** + * @param namespaceService The NamespaceService + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * @param navigator The NavigationBean to set. + */ + public void setNavigator(NavigationBean navigator) + { + this.navigator = navigator; + } + + /** + * @param browseBean The BrowseBean to set. + */ + public void setBrowseBean(BrowseBean browseBean) + { + this.browseBean = browseBean; + } + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + + /** + * @param description The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return Returns the icon. + */ + public String getIcon() + { + return icon; + } + + /** + * @param icon The icon to set. + */ + public void setIcon(String icon) + { + this.icon = icon; + } + + /** + * @return Returns the name. + */ + public String getName() + { + return name; + } + + /** + * @param name The name to set. + */ + public void setName(String name) + { + this.name = name; + } + + /** + * @return Returns the spaceType. + */ + public String getSpaceType() + { + return spaceType; + } + + /** + * @param spaceType The spaceType to set. + */ + public void setSpaceType(String spaceType) + { + this.spaceType = spaceType; + } + + /** + * Returns a list of icons to allow the user to select from. + * The list can change according to the type of space being created. + * + * @return A list of icons + */ + @SuppressWarnings("unchecked") + public List getIcons() + { + // NOTE: we can't cache this list as it depends on the space type + // which the user can change during the advanced space wizard + + List icons = null; + + QName type = QName.createQName(this.spaceType); + String typePrefixForm = type.toPrefixString(this.namespaceService); + + Config config = Application.getConfigService(FacesContext.getCurrentInstance()). + getConfig(typePrefixForm + ICONS_LOOKUP_KEY); + if (config != null) + { + ConfigElement iconsCfg = config.getConfigElement("icons"); + if (iconsCfg != null) + { + boolean first = true; + for (ConfigElement icon : iconsCfg.getChildren()) + { + String iconName = icon.getAttribute("name"); + String iconPath = icon.getAttribute("path"); + + if (iconName != null && iconPath != null) + { + if (first) + { + // if this is the first icon create the list and make + // the first icon in the list the default + + icons = new ArrayList(iconsCfg.getChildCount()); + if (this.icon == null) + { + // set the default if it is not already + this.icon = iconName; + } + first = false; + } + + UIListItem item = new UIListItem(); + item.setValue(iconName); + item.getAttributes().put("image", iconPath); + icons.add(item); + } + } + } + } + + // if we didn't find any icons display one default choice + if (icons == null) + { + icons = new ArrayList(1); + this.icon = SPACE_ICON_DEFAULT; + + UIListItem item = new UIListItem(); + item.setValue("space-icon-default"); + item.getAttributes().put("image", "/images/icons/space-icon-default.gif"); + icons.add(item); + } + + return icons; + } + + /** + * Initialises the wizard + */ + public void init() + { + super.init(); + + // reset all variables + this.spaceType = ContentModel.TYPE_FOLDER.toString(); + this.icon = null; + this.name = null; + this.description = ""; + } + + @Override + public String finish() + { + String outcome = DIALOG_CLOSE; + + UserTransaction tx = null; + + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context); + tx.begin(); + + // create the space (just create a folder for now) + NodeRef parentNodeRef; + String nodeId = this.navigator.getCurrentNodeId(); + if (nodeId == null) + { + parentNodeRef = this.nodeService.getRootNode(Repository.getStoreRef()); + } + else + { + parentNodeRef = new NodeRef(Repository.getStoreRef(), nodeId); + } + + FileInfo fileInfo = fileFolderService.create( + parentNodeRef, + this.name, + Repository.resolveToQName(this.spaceType)); + NodeRef nodeRef = fileInfo.getNodeRef(); + + if (logger.isDebugEnabled()) + logger.debug("Created folder node with name: " + this.name); + + // apply the uifacets aspect - icon, title and description props + Map uiFacetsProps = new HashMap(5); + uiFacetsProps.put(ContentModel.PROP_ICON, this.icon); + uiFacetsProps.put(ContentModel.PROP_TITLE, this.name); + uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, this.description); + this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_UIFACETS, uiFacetsProps); + + if (logger.isDebugEnabled()) + logger.debug("Added uifacets aspect with properties: " + uiFacetsProps); + + // commit the transaction + tx.commit(); + } + catch (FileExistsException e) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + // print status message + String statusMsg = MessageFormat.format( + Application.getMessage( + FacesContext.getCurrentInstance(), "error_exists"), + e.getExisting().getName()); + Utils.addErrorMessage(statusMsg); + // no outcome + outcome = null; + } + catch (Throwable e) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), ERROR), e.getMessage()), e); + outcome = null; + } + + return outcome; + } +} diff --git a/source/java/org/alfresco/web/bean/wizard/BaseWizardBean.java b/source/java/org/alfresco/web/bean/wizard/BaseWizardBean.java new file mode 100644 index 0000000000..df27aedf06 --- /dev/null +++ b/source/java/org/alfresco/web/bean/wizard/BaseWizardBean.java @@ -0,0 +1,60 @@ +package org.alfresco.web.bean.wizard; + +import javax.faces.context.FacesContext; + +import org.alfresco.web.app.Application; +import org.alfresco.web.app.context.UIContextService; + + +/** + * Base class for all wizard beans providing common functionality + * + * @author gavinc + */ +public abstract class BaseWizardBean implements IWizardBean +{ + protected static final String WIZARD_CLOSE = "wizard:close"; + + public abstract String finish(); + + public void init() + { + // tell any beans to update themselves so the UI gets refreshed + UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans(); + } + + public boolean getNextButtonDisabled() + { + return true; + } + + public boolean getBackButtonDisabled() + { + return true; + } + + public boolean getFinishButtonDisabled() + { + return true; + } + + public String getNextButtonLabel() + { + return Application.getMessage(FacesContext.getCurrentInstance(), "next_button"); + } + + public String getBackButtonLabel() + { + return Application.getMessage(FacesContext.getCurrentInstance(), "back_button"); + } + + public String getFinishButtonLabel() + { + return Application.getMessage(FacesContext.getCurrentInstance(), "finish_button"); + } + + public String cancel() + { + return WIZARD_CLOSE; + } +} diff --git a/source/java/org/alfresco/web/bean/wizard/IWizardBean.java b/source/java/org/alfresco/web/bean/wizard/IWizardBean.java new file mode 100644 index 0000000000..9617fd2714 --- /dev/null +++ b/source/java/org/alfresco/web/bean/wizard/IWizardBean.java @@ -0,0 +1,53 @@ +package org.alfresco.web.bean.wizard; + +import org.alfresco.web.bean.dialog.IDialogBean; + +/** + * Interface that defines the contract for a wizard backing bean + * + * @author gavinc + */ +public interface IWizardBean extends IDialogBean +{ + /** + * Method handler called when the next button of the wizard is pressed + * + * @return The outcome to return + */ +// public String next(); + + /** + * Method handler called when the back button of the wizard is pressed + * + * @return The outcome to return + */ +// public String back(); + + /** + * Determines whether the next button on the wizard should be disabled + * + * @return true if the button should be disabled + */ + public boolean getNextButtonDisabled(); + + /** + * Determines whether the back button on the wizard should be disabled + * + * @return true if the button should be disabled + */ + public boolean getBackButtonDisabled(); + + /** + * Returns the label to use for the next button + * + * @return The next button label + */ + public String getNextButtonLabel(); + + /** + * Returns the label to use for the back button + * + * @return The back button label + */ + public String getBackButtonLabel(); +} diff --git a/source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java b/source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java index 0743de425d..a318a8843a 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java @@ -173,7 +173,7 @@ public class NewDiscussionWizard extends NewTopicWizard // to the browse screen, this also makes sure we don't end up in the forum that // just got deleted! return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + - AlfrescoNavigationHandler.DIALOG_SEPARATOR + "browse"; + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; } diff --git a/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java b/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java index f2e5e8f9ad..478485c472 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java @@ -154,7 +154,7 @@ public class NewTopicWizard extends NewSpaceWizard // outcome of 'showTopic' this.browseBean.clickSpace(this.createdNode); - outcome = outcome + AlfrescoNavigationHandler.DIALOG_SEPARATOR + "showTopic"; + outcome = outcome + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "showTopic"; } } diff --git a/source/java/org/alfresco/web/bean/wizard/WizardManager.java b/source/java/org/alfresco/web/bean/wizard/WizardManager.java new file mode 100644 index 0000000000..821c182d73 --- /dev/null +++ b/source/java/org/alfresco/web/bean/wizard/WizardManager.java @@ -0,0 +1,50 @@ +package org.alfresco.web.bean.wizard; + +import javax.faces.context.FacesContext; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.web.app.servlet.FacesHelper; +import org.alfresco.web.config.WizardsConfigElement.WizardConfig; + +/** + * Bean that manages the wizard framework + * + * @author gavinc + */ +public class WizardManager +{ + protected WizardConfig currentWizardConfig; + protected IWizardBean currentWizard; + + /** + * Sets the current wizard + * + * @param config The configuration for the wizard to set + */ + public void setCurrentWizard(WizardConfig config) + { + this.currentWizardConfig = config; + + String beanName = this.currentWizardConfig.getManagedBean(); + this.currentWizard = (IWizardBean)FacesHelper.getManagedBean( + FacesContext.getCurrentInstance(), beanName); + + if (this.currentWizard == null) + { + throw new AlfrescoRuntimeException("Failed to find managed bean '" + beanName + "'"); + } + + // initialise the managed bean + this.currentWizard.init(); + } + + /** + * Returns the current wizard bean being managed + * + * @return The current managed bean + */ + public IWizardBean getBean() + { + return this.currentWizard; + } +} diff --git a/source/java/org/alfresco/web/config/DialogsConfigElement.java b/source/java/org/alfresco/web/config/DialogsConfigElement.java index d680de604d..77ece779bb 100644 --- a/source/java/org/alfresco/web/config/DialogsConfigElement.java +++ b/source/java/org/alfresco/web/config/DialogsConfigElement.java @@ -124,13 +124,14 @@ public class DialogsConfigElement extends ConfigElementAdapter protected String name; protected String page; protected String managedBean; + protected String icon; protected String title; protected String titleId; protected String description; protected String descriptionId; public DialogConfig(String name, String page, String bean, - String title, String titleId, + String icon, String title, String titleId, String description, String descriptionId) { // check the mandatory parameters are present @@ -141,6 +142,7 @@ public class DialogsConfigElement extends ConfigElementAdapter this.name = name; this.page = page; this.managedBean = bean; + this.icon = icon; this.title = title; this.titleId = titleId; this.description = description; @@ -172,6 +174,11 @@ public class DialogsConfigElement extends ConfigElementAdapter return this.page; } + public String getIcon() + { + return this.icon; + } + public String getTitle() { return this.title; @@ -192,6 +199,7 @@ public class DialogsConfigElement extends ConfigElementAdapter buffer.append(" (name=").append(this.name); buffer.append(" page=").append(this.page); buffer.append(" managed-bean=").append(this.managedBean); + buffer.append(" icon=").append(this.icon); buffer.append(" title=").append(this.title); buffer.append(" titleId=").append(this.titleId); buffer.append(" description=").append(this.description); diff --git a/source/java/org/alfresco/web/config/DialogsElementReader.java b/source/java/org/alfresco/web/config/DialogsElementReader.java index 1c44471121..04d0a5b935 100644 --- a/source/java/org/alfresco/web/config/DialogsElementReader.java +++ b/source/java/org/alfresco/web/config/DialogsElementReader.java @@ -35,6 +35,7 @@ public class DialogsElementReader implements ConfigElementReader public static final String ATTR_NAME = "name"; public static final String ATTR_PAGE = "page"; public static final String ATTR_MANAGED_BEAN = "managed-bean"; + public static final String ATTR_ICON = "icon"; public static final String ATTR_TITLE = "title"; public static final String ATTR_TITLE_ID = "title-id"; public static final String ATTR_DESCRIPTION = "description"; @@ -68,13 +69,14 @@ public class DialogsElementReader implements ConfigElementReader String name = item.attributeValue(ATTR_NAME); String page = item.attributeValue(ATTR_PAGE); String bean = item.attributeValue(ATTR_MANAGED_BEAN); + String icon = item.attributeValue(ATTR_ICON); String title = item.attributeValue(ATTR_TITLE); String titleId = item.attributeValue(ATTR_TITLE_ID); String description = item.attributeValue(ATTR_DESCRIPTION); String descriptionId = item.attributeValue(ATTR_DESCRIPTION_ID); DialogsConfigElement.DialogConfig cfg = new DialogsConfigElement.DialogConfig( - name, page, bean, title, titleId, description, descriptionId); + name, page, bean, icon, title, titleId, description, descriptionId); configElement.addDialog(cfg); } diff --git a/source/java/org/alfresco/web/config/WizardsConfigElement.java b/source/java/org/alfresco/web/config/WizardsConfigElement.java index 7e642572a2..a09b5ca6a6 100644 --- a/source/java/org/alfresco/web/config/WizardsConfigElement.java +++ b/source/java/org/alfresco/web/config/WizardsConfigElement.java @@ -158,9 +158,10 @@ public class WizardsConfigElement extends ConfigElementAdapter { protected String name; protected String managedBean; + protected String icon; protected Map steps = new LinkedHashMap(4); - public WizardConfig(String name, String bean, + public WizardConfig(String name, String bean, String icon, String title, String titleId, String description, String descriptionId) { @@ -171,6 +172,7 @@ public class WizardsConfigElement extends ConfigElementAdapter this.name = name; this.managedBean = bean; + this.icon = icon; } public String getName() @@ -183,6 +185,11 @@ public class WizardsConfigElement extends ConfigElementAdapter return this.managedBean; } + public String getIcon() + { + return this.icon; + } + public void addStep(StepConfig step) { this.steps.put(step.getName(), step); @@ -224,6 +231,7 @@ public class WizardsConfigElement extends ConfigElementAdapter StringBuilder buffer = new StringBuilder(super.toString()); buffer.append(" (name=").append(this.name); buffer.append(" managed-bean=").append(this.managedBean); + buffer.append(" icon=").append(this.icon); buffer.append(" title=").append(this.title); buffer.append(" titleId=").append(this.titleId); buffer.append(" description=").append(this.description); diff --git a/source/java/org/alfresco/web/config/WizardsElementReader.java b/source/java/org/alfresco/web/config/WizardsElementReader.java index 48316f2dfa..0ab4935d00 100644 --- a/source/java/org/alfresco/web/config/WizardsElementReader.java +++ b/source/java/org/alfresco/web/config/WizardsElementReader.java @@ -41,6 +41,7 @@ public class WizardsElementReader implements ConfigElementReader public static final String ATTR_NAME = "name"; public static final String ATTR_MANAGED_BEAN = "managed-bean"; + public static final String ATTR_ICON = "icon"; public static final String ATTR_TITLE = "title"; public static final String ATTR_TITLE_ID = "title-id"; public static final String ATTR_DESCRIPTION = "description"; @@ -77,6 +78,7 @@ public class WizardsElementReader implements ConfigElementReader String name = wizard.attributeValue(ATTR_NAME); String bean = wizard.attributeValue(ATTR_MANAGED_BEAN); + String icon = wizard.attributeValue(ATTR_ICON); String title = wizard.attributeValue(ATTR_TITLE); String titleId = wizard.attributeValue(ATTR_TITLE_ID); String description = wizard.attributeValue(ATTR_DESCRIPTION); @@ -84,7 +86,7 @@ public class WizardsElementReader implements ConfigElementReader // create the wizard config object WizardsConfigElement.WizardConfig wizardCfg = new WizardsConfigElement.WizardConfig( - name, bean, title, titleId, description, descriptionId); + name, bean, icon, title, titleId, description, descriptionId); Iterator steps = wizard.elementIterator(ELEMENT_STEP); while (steps.hasNext()) diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index 0396b275c9..8e48c1e589 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -95,6 +95,53 @@ + + Bean that manages the dialog framework + DialogManager + org.alfresco.web.bean.dialog.DialogManager + session + + + + Bean that manages the wizard framework + WizardManager + org.alfresco.web.bean.wizard.WizardManager + session + + + + + The bean that backs up the Create Space Dialog + + CreateSpaceDialog + org.alfresco.web.bean.dialog.SpaceDialog + session + + nodeService + #{NodeService} + + + fileFolderService + #{FileFolderService} + + + searchService + #{SearchService} + + + navigator + #{NavigationBean} + + + browseBean + #{BrowseBean} + + + namespaceService + #{NamespaceService} + + + The bean that holds a users Clipboard state. diff --git a/source/web/jsp/dialog/container.jsp b/source/web/jsp/dialog/container.jsp new file mode 100644 index 0000000000..647c8d7367 --- /dev/null +++ b/source/web/jsp/dialog/container.jsp @@ -0,0 +1,149 @@ +<%-- + 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" %> + +<%-- ***************************************************************************** --%> +<%-- TODO: Find a way to dynamically drive the container title for automated tests --%> +<%-- ***************************************************************************** --%> + + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + <%-- Main outer table --%> + + + <%-- Title bar --%> + + + + + <%-- Main area --%> + + <%-- Shelf --%> + + + <%-- Work Area --%> + + +
+ <%@ include file="../parts/titlebar.jsp" %> +
+ <%@ include file="../parts/shelf.jsp" %> + + + <%-- Breadcrumb --%> + <%@ include file="../parts/breadcrumb.jsp" %> + + <%-- Status and Actions --%> + + + + + + + <%-- separator row with gradient shadow --%> + + + + + + + <%-- Details --%> + + + + + + + <%-- separator row with bottom panel graphics --%> + + + + + + +
+ + <%-- Status and Actions inner contents table --%> + <%-- Generally this consists of an icon, textual summary and actions for the current object --%> + + + + + +
+ +
+
+
+ +
+ + + + + + +
+ + + + + <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %> + + + + + + + +
+ +
+ +
+ <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %> +
+
+
+ +
+ +
+ +
\ No newline at end of file diff --git a/source/web/jsp/spaces/create-space-details.jsp b/source/web/jsp/spaces/create-space-details.jsp new file mode 100644 index 0000000000..460d2806d6 --- /dev/null +++ b/source/web/jsp/spaces/create-space-details.jsp @@ -0,0 +1,110 @@ +<%-- + 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 import="org.alfresco.web.app.Application" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + +<%-- Create Space Dialog Fragment --%> + + + + +<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "white", "white"); %> + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +  * +
+ + + +
+   + +
+ + +
+ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %> + + + + + + <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %> +
+
+ +
+<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %>
+