diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 645c75b2d5..150b3889b2 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -647,7 +647,6 @@ create_form_form_details_desc=Enter information about the web form you want to c create_form_form_details_step1_desc=Select XML schema to use create_form_form_details_step2_desc=Specify details for new form. create_form_form_details_no_schema_selected= - create_form_configure_rendering_engine_templates_title=Step Two - Configure Rendering Engine Templates create_form_configure_rendering_engine_templates_desc=Enter information about the rendering engine templates you want to use for this form. create_form_select_default_workflow_title=Stop Three - Select default workflow @@ -656,7 +655,6 @@ create_form_summary_desc=The wizard has successfully created the content and all create_form_summary_content_details=Content Details create_form_summary_rendition_details=Rendition Details create_form_summary_submit_message=Submit {0} when wizard finishes. - selected_rendering_engines=Selected Rendering Engines create_form_configure_rendering_engines_title=Configure Rendering Engines create_form_configure_rendering_engines_step1_desc=Upload rendering engine template and specify the extension to use for its renditions. @@ -669,7 +667,6 @@ schema=Schema schema_root_element_name=Root element form=Form - # Rule and Action Wizard messages run_action_title=Run Action Wizard run_action_desc=This wizard helps you run an action @@ -884,9 +881,13 @@ store_created_by=Created By store_working_users=There are {0} user(s) working on this web project. avm_node_deleted=Deleted revert=Revert +revert_success=Successfully reverted item: {0} +revertall_success=Successfully reverted sandbox for user: {0} +revertselected_success=Successfully reverted selected items for user: {0} submit=Submit submit_success=Successfully submitted item: {0} submitall_success=Successfully submitted sandbox for user: {0} +submitselected_success=Successfully submitted selected items for user: {0} folder_preview=Preview Folder file_preview=Preview File selected=Selected diff --git a/config/alfresco/web-client-config-wcm-actions.xml b/config/alfresco/web-client-config-wcm-actions.xml index 8e3df83ab6..daad7c57d4 100644 --- a/config/alfresco/web-client-config-wcm-actions.xml +++ b/config/alfresco/web-client-config-wcm-actions.xml @@ -114,7 +114,7 @@ new - + CreateChildren diff --git a/source/java/org/alfresco/web/bean/content/BaseContentWizard.java b/source/java/org/alfresco/web/bean/content/BaseContentWizard.java index 3f2e003940..8d25ea414f 100644 --- a/source/java/org/alfresco/web/bean/content/BaseContentWizard.java +++ b/source/java/org/alfresco/web/bean/content/BaseContentWizard.java @@ -83,6 +83,7 @@ public abstract class BaseContentWizard extends BaseWizardBean this.mimeType == null); } + // ------------------------------------------------------------------------------ // Bean Getters and Setters @@ -307,10 +308,6 @@ public abstract class BaseContentWizard extends BaseWizardBean return this.objectTypes; } - // ------------------------------------------------------------------------------ - // Action event handlers - - // ------------------------------------------------------------------------------ // Service Injection @@ -323,6 +320,7 @@ public abstract class BaseContentWizard extends BaseWizardBean this.contentService = contentService; } + // ------------------------------------------------------------------------------ // Helper methods diff --git a/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java index e44d90efaf..ab614b7803 100644 --- a/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java +++ b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java @@ -1,6 +1,7 @@ package org.alfresco.web.bean.dialog; import java.text.MessageFormat; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -52,7 +53,7 @@ public abstract class BaseDialogBean implements IDialogBean if (this.parameters == null) { - this.parameters = new HashMap(); + this.parameters = Collections.emptyMap(); } // reset the isFinished flag diff --git a/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java b/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java index 48089388f6..8b3cb3f814 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java @@ -16,10 +16,12 @@ */ package org.alfresco.web.bean.wcm; +import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ResourceBundle; @@ -31,11 +33,16 @@ import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.avm.actions.AVMUndoSandboxListAction; +import org.alfresco.repo.avm.actions.SimpleAVMSubmitAction; +import org.alfresco.repo.avm.util.VersionPathStuffer; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; @@ -49,10 +56,12 @@ import org.alfresco.web.app.Application; import org.alfresco.web.app.context.IContextListener; import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.app.servlet.DownloadContentServlet; +import org.alfresco.web.app.servlet.FacesHelper; import org.alfresco.web.bean.BrowseBean; import org.alfresco.web.bean.NavigationBean; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.wizard.WizardManager; import org.alfresco.web.config.ClientConfigElement; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.IBreadcrumbHandler; @@ -73,6 +82,9 @@ public class AVMBrowseBean implements IContextListener { private static Log logger = LogFactory.getLog(AVMBrowseBean.class); + private static final String MSG_REVERT_SUCCESS = "revert_success"; + private static final String MSG_REVERTALL_SUCCESS = "revertall_success"; + private static final String MSG_REVERTSELECTED_SUCCESS = "revertselected_success"; private static final String MSG_SANDBOXTITLE = "sandbox_title"; private static final String MSG_SANDBOXSTAGING = "sandbox_staging"; private static final String MSG_CREATED_ON = "store_created_on"; @@ -80,14 +92,11 @@ public class AVMBrowseBean implements IContextListener private static final String MSG_WORKING_USERS = "store_working_users"; private static final String MSG_SUBMIT_SUCCESS = "submit_success"; private static final String MSG_SUBMITALL_SUCCESS = "submitall_success"; + private static final String MSG_SUBMITSELECTED_SUCCESS = "submitselected_success"; /** Component id the status messages are tied too */ private static final String COMPONENT_SANDBOXESPANEL = "sandboxes-panel"; - /** Action bean Id for the AVM Submit action*/ - private static final String ACTION_AVM_SUBMIT = "simple-avm-submit"; - private static final String ACTION_AVM_WORKFLOW = "start-avm-workflow"; - /** Content Manager role name */ private static final String ROLE_CONTENT_MANAGER = "ContentManager"; @@ -139,6 +148,9 @@ public class AVMBrowseBean implements IContextListener /** AVM service bean reference */ protected AVMService avmService; + /** AVM Sync service bean reference */ + protected AVMSyncService avmSyncService; + /** Action service bean reference */ protected ActionService actionService; @@ -167,6 +179,14 @@ public class AVMBrowseBean implements IContextListener this.avmService = avmService; } + /** + * @param avmSyncService The AVMSyncService to set. + */ + public void setAvmSyncService(AVMSyncService avmSyncService) + { + this.avmSyncService = avmSyncService; + } + /** * @param nodeService The NodeService to set. */ @@ -718,7 +738,7 @@ public class AVMBrowseBean implements IContextListener */ public void submitNode(ActionEvent event) { - setupContentAction(event); + String path = getPathFromEventArgs(event); UserTransaction tx = null; try @@ -727,15 +747,20 @@ public class AVMBrowseBean implements IContextListener tx = Repository.getUserTransaction(context, false); tx.begin(); - Action action = this.actionService.createAction(ACTION_AVM_SUBMIT); - this.actionService.executeAction(action, getAvmActionNode().getNodeRef()); + AVMNodeDescriptor node = this.avmService.lookup(-1, path, true); + if (node != null) + { + Action action = this.actionService.createAction(SimpleAVMSubmitAction.NAME); + this.actionService.executeAction(action, AVMNodeConverter.ToNodeRef(-1, path)); + } // commit the transaction tx.commit(); // if we get here, all was well - output friendly status message to the user + String msg = MessageFormat.format(Application.getMessage( - context, MSG_SUBMIT_SUCCESS), getAvmActionNode().getName()); + context, MSG_SUBMIT_SUCCESS), node.getName()); FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); String formId = Utils.getParentForm(context, event.getComponent()).getClientId(context); context.addMessage(formId + ':' + COMPONENT_SANDBOXESPANEL, facesMsg); @@ -769,7 +794,7 @@ public class AVMBrowseBean implements IContextListener tx = Repository.getUserTransaction(context, true); tx.begin(); - Action action = this.actionService.createAction(ACTION_AVM_SUBMIT); + Action action = this.actionService.createAction(SimpleAVMSubmitAction.NAME); this.actionService.executeAction(action, rootRef); // commit the transaction @@ -797,7 +822,6 @@ public class AVMBrowseBean implements IContextListener { UIActionLink link = (UIActionLink)event.getComponent(); Map params = link.getParameterMap(); - String store = params.get("store"); String username = params.get("username"); List selected = this.userSandboxes.getSelectedNodes(username); @@ -810,9 +834,10 @@ public class AVMBrowseBean implements IContextListener tx = Repository.getUserTransaction(context, false); tx.begin(); + // TODO: better to duplicate code in action rather than call multiple times? for (AVMNodeDescriptor node : selected) { - Action action = this.actionService.createAction(ACTION_AVM_SUBMIT); + Action action = this.actionService.createAction(SimpleAVMSubmitAction.NAME); this.actionService.executeAction(action, AVMNodeConverter.ToNodeRef(-1, node.getPath())); } @@ -822,7 +847,7 @@ public class AVMBrowseBean implements IContextListener // if we get here, all was well - output friendly status message to the user // TODO: different message once the submit screen is available String msg = MessageFormat.format(Application.getMessage( - context, MSG_SUBMITALL_SUCCESS), username); + context, MSG_SUBMITSELECTED_SUCCESS), username); FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); String formId = Utils.getParentForm(context, event.getComponent()).getClientId(context); context.addMessage(formId + ':' + COMPONENT_SANDBOXESPANEL, facesMsg); @@ -842,6 +867,42 @@ public class AVMBrowseBean implements IContextListener */ public void revertNode(ActionEvent event) { + String path = getPathFromEventArgs(event); + + UserTransaction tx = null; + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context, false); + tx.begin(); + + AVMNodeDescriptor node = this.avmService.lookup(-1, path, true); + if (node != null) + { + Map args = new HashMap(1, 1.0f); + String paths = new VersionPathStuffer().add(-1, path).toString(); + args.put(AVMUndoSandboxListAction.PARAM_NODE_LIST, paths); + Action action = this.actionService.createAction(AVMUndoSandboxListAction.NAME, args); + this.actionService.executeAction(action, null); // dummy action ref + } + + // commit the transaction + tx.commit(); + + // if we get here, all was well - output friendly status message to the user + String msg = MessageFormat.format(Application.getMessage( + context, MSG_REVERT_SUCCESS), node.getName()); + FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); + String formId = Utils.getParentForm(context, event.getComponent()).getClientId(context); + context.addMessage(formId + ':' + COMPONENT_SANDBOXESPANEL, facesMsg); + } + catch (Throwable err) + { + err.printStackTrace(System.err); + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + } } /** @@ -849,6 +910,47 @@ public class AVMBrowseBean implements IContextListener */ public void revertAll(ActionEvent event) { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String store = params.get("store"); + String username = params.get("username"); + + UserTransaction tx = null; + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context, true); + tx.begin(); + + // calcluate the list of differences between the user store and the staging area + List diffs = this.avmSyncService.compare(-1, store + ":/", -1, getStagingStore() + ":/"); + VersionPathStuffer stuffer = new VersionPathStuffer(); + for (AVMDifference diff : diffs) + { + stuffer.add(-1, diff.getSourcePath()); + } + String paths = stuffer.toString(); + Map args = new HashMap(1, 1.0f); + args.put(AVMUndoSandboxListAction.PARAM_NODE_LIST, paths); + Action action = this.actionService.createAction(AVMUndoSandboxListAction.NAME, args); + this.actionService.executeAction(action, null); // dummy action ref + + // commit the transaction + tx.commit(); + + // if we get here, all was well - output friendly status message to the user + String msg = MessageFormat.format(Application.getMessage( + context, MSG_REVERTALL_SUCCESS), username); + FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); + String formId = Utils.getParentForm(context, event.getComponent()).getClientId(context); + context.addMessage(formId + ':' + COMPONENT_SANDBOXESPANEL, facesMsg); + } + 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) {} + } } /** @@ -856,6 +958,68 @@ public class AVMBrowseBean implements IContextListener */ public void revertSelected(ActionEvent event) { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String username = params.get("username"); + + List selected = this.userSandboxes.getSelectedNodes(username); + if (selected != null) + { + UserTransaction tx = null; + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context, false); + tx.begin(); + + VersionPathStuffer stuffer = new VersionPathStuffer(); + for (AVMNodeDescriptor node : selected) + { + stuffer.add(-1, node.getPath()); + } + Map args = new HashMap(1, 1.0f); + args.put(AVMUndoSandboxListAction.PARAM_NODE_LIST, stuffer.toString()); + for (AVMNodeDescriptor node : selected) + { + Action action = this.actionService.createAction(AVMUndoSandboxListAction.NAME, args); + this.actionService.executeAction(action, AVMNodeConverter.ToNodeRef(-1, node.getPath())); + } + + // commit the transaction + tx.commit(); + + // if we get here, all was well - output friendly status message to the user + // TODO: different message once the submit screen is available + String msg = MessageFormat.format(Application.getMessage( + context, MSG_REVERTSELECTED_SUCCESS), username); + FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); + String formId = Utils.getParentForm(context, event.getComponent()).getClientId(context); + context.addMessage(formId + ':' + COMPONENT_SANDBOXESPANEL, facesMsg); + } + catch (Throwable err) + { + err.printStackTrace(System.err); + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + } + } + } + + /** + * Create web content from a specific Form via the User Sandbox 'Available Forms' panel + */ + public void createFormContent(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String id = params.get("form-id"); + + // pass form ID to the wizard - to be picked up in init() + FacesContext fc = FacesContext.getCurrentInstance(); + WizardManager manager = (WizardManager)FacesHelper.getManagedBean(fc, "WizardManager"); + manager.setupParameters(event); + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "wizard:createWebContent"); } @@ -876,6 +1040,16 @@ public class AVMBrowseBean implements IContextListener setCurrentPath(path); } + /** + * @return the path from the 'id' argument in the specified UIActionLink event + */ + private String getPathFromEventArgs(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + return params.get("id"); + } + // ------------------------------------------------------------------------------ // IContextListener implementation diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java index 01313ae0ac..02bed6fc8d 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java @@ -44,6 +44,7 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.web.app.Application; import org.alfresco.web.bean.content.BaseContentWizard; +import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.data.IDataContainer; import org.alfresco.web.data.QuickSort; import org.alfresco.web.forms.*; @@ -64,6 +65,7 @@ public class CreateWebContentWizard extends BaseContentWizard protected String createdPath = null; protected List renditions = null; protected FormInstanceData formInstanceData = null; + protected boolean formSelectDisabled = false; /** AVM service bean reference */ protected AVMService avmService; @@ -91,6 +93,30 @@ public class CreateWebContentWizard extends BaseContentWizard // ------------------------------------------------------------------------------ // Wizard implementation + @Override + public void init(Map parameters) + { + super.init(parameters); + + this.content = null; + this.inlineEdit = true; + this.formName = null; + this.mimeType = MimetypeMap.MIMETYPE_XML; + + // check for a form ID being passed in as a parameter + if (parameters.get("form-id") != null) + { + // it is used to init the dialog to a specific template + String formId = parameters.get("form-id"); + Form form = FormsService.getInstance().getForm(new NodeRef(Repository.getStoreRef(), formId)); + if (form != null) + { + this.formName = form.getName(); + this.formSelectDisabled = true; + } + } + } + @Override protected String finishImpl(FacesContext context, String outcome) throws Exception @@ -100,15 +126,34 @@ public class CreateWebContentWizard extends BaseContentWizard return outcome; } - // ------------------------------------------------------------------------------ - // Helper methods - + @Override + public boolean getNextButtonDisabled() + { + // TODO: Allow the next button state to be configured so that + // wizard implementations don't have to worry about + // checking step numbers + + boolean disabled = false; + int step = Application.getWizardManager().getCurrentStep(); + switch(step) + { + case 1: + { + disabled = (this.fileName == null || this.fileName.length() == 0); + break; + } + } + + return disabled; + } + /** * Save the specified content using the currently set wizard attributes * * @param fileContent File content to save * @param strContent String content to save */ + @Override protected void saveContent(File fileContent, String strContent) throws Exception { if (logger.isDebugEnabled()) @@ -160,38 +205,6 @@ public class CreateWebContentWizard extends BaseContentWizard } } - @Override - public void init(Map parameters) - { - super.init(parameters); - - this.content = null; - this.inlineEdit = true; - this.formName = null; - this.mimeType = MimetypeMap.MIMETYPE_XML; - } - - @Override - public boolean getNextButtonDisabled() - { - // TODO: Allow the next button state to be configured so that - // wizard implementations don't have to worry about - // checking step numbers - - boolean disabled = false; - int step = Application.getWizardManager().getCurrentStep(); - switch(step) - { - case 1: - { - disabled = (this.fileName == null || this.fileName.length() == 0); - break; - } - } - - return disabled; - } - // ------------------------------------------------------------------------------ // Bean Getters and Setters @@ -342,6 +355,16 @@ public class CreateWebContentWizard extends BaseContentWizard { return this.renditions; } + + public boolean getFormSelectDisabled() + { + return this.formSelectDisabled; + } + + public void setFormSelectDisabled(boolean formSelectDisabled) + { + this.formSelectDisabled = formSelectDisabled; + } /** * @return Returns the summary data for the wizard. diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java index 62c187aca3..7bc88fdd96 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java @@ -790,6 +790,10 @@ public class CreateWebsiteWizard extends BaseWizardBean // tag the store with the DNS name property tagStoreDNSPath(stagingStore, name, "staging"); + // snapshot the store + this.avmService.createSnapshot(stagingStore, null, null); + + // create the 'preview' store for the website String previewStore = AVMConstants.buildAVMStagingPreviewStoreName(name); this.avmService.createAVMStore(previewStore); @@ -815,6 +819,9 @@ public class CreateWebsiteWizard extends BaseWizardBean // tag the store with the DNS name property tagStoreDNSPath(previewStore, name, "preview"); + // snapshot the store + this.avmService.createSnapshot(previewStore, null, null); + // tag all related stores to indicate that they are part of a single sandbox String sandboxIdProp = AVMConstants.PROP_SANDBOXID + GUID.generate(); @@ -889,6 +896,9 @@ public class CreateWebsiteWizard extends BaseWizardBean // tag the store with the DNS name property tagStoreDNSPath(userStore, name, username); + // snapshot the store + this.avmService.createSnapshot(userStore, null, null); + // create the user 'preview' store String previewStore = AVMConstants.buildAVMUserPreviewStoreName(name, username); @@ -920,6 +930,9 @@ public class CreateWebsiteWizard extends BaseWizardBean // tag the store with the DNS name property tagStoreDNSPath(previewStore, name, username, "preview"); + // snapshot the store + this.avmService.createSnapshot(previewStore, null, null); + // tag all related stores to indicate that they are part of a single sandbox String sandboxIdProp = AVMConstants.PROP_SANDBOXID + GUID.generate(); diff --git a/source/java/org/alfresco/web/bean/wcm/ImportWebsiteDialog.java b/source/java/org/alfresco/web/bean/wcm/ImportWebsiteDialog.java index 48ee119573..841523514b 100644 --- a/source/java/org/alfresco/web/bean/wcm/ImportWebsiteDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/ImportWebsiteDialog.java @@ -25,6 +25,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.text.DateFormat; import java.text.MessageFormat; import java.util.Enumeration; import java.util.zip.ZipException; @@ -212,7 +213,7 @@ public class ImportWebsiteDialog processZipImport(this.file, importRef); // After an import it's a good idea to snapshot the staging store - // TODO Maybe a nice auto generated comment. + // TODO: Maybe a nice auto generated comment. this.avmService.createSnapshot(store, null, null); } } diff --git a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java index 1a563dfde4..84390b36aa 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java @@ -73,14 +73,23 @@ public class UIUserSandboxes extends SelfRenderingComponent { private static Log logger = LogFactory.getLog(UIUserSandboxes.class); + private static final String ACT_CREATE_FORM_CONTENT = "create_form_content"; + private static final String ACT_SANDBOX_REVERTSELECTED = "sandbox_revertselected"; + private static final String ACT_SANDBOX_SUBMITSELECTED = "sandbox_submitselected"; + private static final String ACT_SANDBOX_BROWSE = "sandbox_browse"; + private static final String ACT_SANDBOX_REVERTALL = "sandbox_revertall"; + private static final String ACT_SANDBOX_SUBMITALL = "sandbox_submitall"; + private static final String ACT_SANDBOX_PREVIEW = "sandbox_preview"; + private static final String ACT_SANDBOX_ICON = "sandbox_icon"; + private static final String ACTIONS_FILE = "avm_file_modified"; private static final String ACTIONS_FOLDER = "avm_folder_modified"; private static final String ACTIONS_DELETED = "avm_deleted_modified"; private static final String COMPONENT_ACTIONS = "org.alfresco.faces.Actions"; - private static final String ACT_MODIFIED_PANEL = "_items"; - private static final String ACT_FORMS_PANEL = "_forms"; + private static final String PANEL_MODIFIED = "_items"; + private static final String PANEL_FORMS = "_forms"; private static final String MSG_MODIFIED_ITEMS = "modified_items"; private static final String MSG_CONTENT_FORMS = "content_forms"; @@ -94,6 +103,8 @@ public class UIUserSandboxes extends SelfRenderingComponent private static final String MSG_DELETED_ITEM = "avm_node_deleted"; private static final String MSG_SELECTED = "selected"; + private static final String REQUEST_FORM_REF = "formref"; + private static final String SPACE_ICON = "/images/icons/" + BrowseBean.SPACE_SMALL_DEFAULT + ".gif"; /** website to show sandboxes for */ @@ -179,11 +190,11 @@ public class UIUserSandboxes extends SelfRenderingComponent Map valuesMap = context.getExternalContext().getRequestParameterValuesMap(); // detect if Modified Items or Available Content Forms panel has been expanded/collapsed - String fieldId = getClientId(context) + ACT_FORMS_PANEL; + String fieldId = getClientId(context) + PANEL_FORMS; String value = (String)requestMap.get(fieldId); if (value == null || value.length() == 0) { - fieldId = getClientId(context) + ACT_MODIFIED_PANEL; + fieldId = getClientId(context) + PANEL_MODIFIED; value = (String)requestMap.get(fieldId); } if (value != null && value.length() != 0) @@ -293,8 +304,8 @@ public class UIUserSandboxes extends SelfRenderingComponent // show the icon for the sandbox as a clickable browse link image // this is currently identical to the sandbox_browse action as below Utils.encodeRecursive(context, aquireAction( - context, mainStore, username, "sandbox_icon", WebResources.IMAGE_USERSANDBOX_32, - "#{AVMBrowseBean.setupSandboxAction}", "browseSandbox", null)); + context, mainStore, username, ACT_SANDBOX_ICON, WebResources.IMAGE_USERSANDBOX_32, + "#{AVMBrowseBean.setupSandboxAction}", "browseSandbox")); out.write(""); out.write(""); out.write(bundle.getString(MSG_USERNAME)); @@ -307,44 +318,38 @@ public class UIUserSandboxes extends SelfRenderingComponent // direct actions for a sandbox String sandboxUrl = AVMConstants.buildAVMStoreUrl(mainStore); Utils.encodeRecursive(context, aquireAction( - context, mainStore, username, "sandbox_preview", "/images/icons/preview_website.gif", - null, null, sandboxUrl)); - out.write(" "); - - // TODO: add this action back once we can create via configured form attached to website project - /*Utils.encodeRecursive(context, aquireAction( - context, mainStore, username, "sandbox_create", "/images/icons/new_content.gif", - "#{AVMBrowseBean.setupSandboxAction}", "wizard:createWebContent", null)); - out.write(" ");*/ - - Utils.encodeRecursive(context, aquireAction( - context, mainStore, username, "sandbox_submitall", "/images/icons/submit.gif", - "#{AVMBrowseBean.submitAll}", null, null)); + context, mainStore, username, ACT_SANDBOX_PREVIEW, "/images/icons/preview_website.gif", + null, null, sandboxUrl, null)); out.write(" "); Utils.encodeRecursive(context, aquireAction( - context, mainStore, username, "sandbox_revertall", "/images/icons/revert.gif", - "#{AVMBrowseBean.revertAll}", null, null)); + context, mainStore, username, ACT_SANDBOX_SUBMITALL, "/images/icons/submit.gif", + "#{AVMBrowseBean.submitAll}", null)); out.write(" "); Utils.encodeRecursive(context, aquireAction( - context, mainStore, username, "sandbox_browse", "/images/icons/space_small.gif", - "#{AVMBrowseBean.setupSandboxAction}", "browseSandbox", null)); + context, mainStore, username, ACT_SANDBOX_REVERTALL, "/images/icons/revert.gif", + "#{AVMBrowseBean.revertAll}", null)); + out.write(" "); + + Utils.encodeRecursive(context, aquireAction( + context, mainStore, username, ACT_SANDBOX_BROWSE, "/images/icons/space_small.gif", + "#{AVMBrowseBean.setupSandboxAction}", "browseSandbox")); out.write(""); // modified items panel out.write(""); String panelImage = WebResources.IMAGE_COLLAPSED; - if (this.expandedPanels.contains(username + ACT_MODIFIED_PANEL)) + if (this.expandedPanels.contains(username + PANEL_MODIFIED)) { panelImage = WebResources.IMAGE_EXPANDED; } out.write(Utils.buildImageTag(context, panelImage, 11, 11, "", - Utils.generateFormSubmit(context, this, getClientId(context) + ACT_MODIFIED_PANEL, username + ACT_MODIFIED_PANEL))); + Utils.generateFormSubmit(context, this, getClientId(context) + PANEL_MODIFIED, username + PANEL_MODIFIED))); out.write(" "); out.write(bundle.getString(MSG_MODIFIED_ITEMS)); out.write(""); - if (this.expandedPanels.contains(username + ACT_MODIFIED_PANEL)) + if (this.expandedPanels.contains(username + PANEL_MODIFIED)) { out.write("
"); @@ -356,16 +361,16 @@ public class UIUserSandboxes extends SelfRenderingComponent // content forms panel out.write(""); panelImage = WebResources.IMAGE_COLLAPSED; - if (this.expandedPanels.contains(username + ACT_FORMS_PANEL)) + if (this.expandedPanels.contains(username + PANEL_FORMS)) { panelImage = WebResources.IMAGE_EXPANDED; } out.write(Utils.buildImageTag(context, panelImage, 11, 11, "", - Utils.generateFormSubmit(context, this, getClientId(context) + ACT_FORMS_PANEL, username + ACT_FORMS_PANEL))); + Utils.generateFormSubmit(context, this, getClientId(context) + PANEL_FORMS, username + PANEL_FORMS))); out.write(" "); out.write(bundle.getString(MSG_CONTENT_FORMS)); out.write(""); - if (this.expandedPanels.contains(username + ACT_FORMS_PANEL)) + if (this.expandedPanels.contains(username + PANEL_FORMS)) { out.write("
"); @@ -608,12 +613,12 @@ public class UIUserSandboxes extends SelfRenderingComponent out.write(bundle.getString(MSG_SELECTED)); out.write(": "); Utils.encodeRecursive(fc, aquireAction( - fc, userStorePrefix, username, "sandbox_submitselected", "/images/icons/submit.gif", - "#{AVMBrowseBean.submitSelected}", null, null)); + fc, userStorePrefix, username, ACT_SANDBOX_SUBMITSELECTED, "/images/icons/submit.gif", + "#{AVMBrowseBean.submitSelected}", null)); out.write(" "); Utils.encodeRecursive(fc, aquireAction( - fc, userStorePrefix, username, "sandbox_revertselected", "/images/icons/revert.gif", - "#{AVMBrowseBean.revertSelected}", null, null)); + fc, userStorePrefix, username, ACT_SANDBOX_REVERTSELECTED, "/images/icons/revert.gif", + "#{AVMBrowseBean.revertSelected}", null)); out.write(""); // end table @@ -638,6 +643,7 @@ public class UIUserSandboxes extends SelfRenderingComponent throws IOException { NodeService nodeService = getNodeService(fc); + Map requestMap = fc.getExternalContext().getRequestMap(); String userStorePrefix = AVMConstants.buildAVMUserMainStoreName(storeRoot, username); // only need to collect the list of forms once per render @@ -677,10 +683,21 @@ public class UIUserSandboxes extends SelfRenderingComponent String desc = (String)nodeService.getProperty(formRef, ContentModel.PROP_DESCRIPTION); out.write(desc != null ? desc : ""); out.write(""); - // actions - Utils.encodeRecursive(fc, aquireAction( - fc, userStorePrefix, username, "create_form_content", "/images/icons/new_content.gif", - null, "wizard:createWebContent", null)); + // actions + UIActionLink action = findAction(ACT_CREATE_FORM_CONTENT, userStorePrefix); + if (action == null) + { + // create content action passes the ID of the Form to uses + Map params = new HashMap(1, 1.0f); + // setup a data-binding param for the Form ID + params.put("form-id", "#{" + REQUEST_FORM_REF + ".id}"); + action = createAction(fc, userStorePrefix, username, ACT_CREATE_FORM_CONTENT, + "/images/icons/new_content.gif", "#{AVMBrowseBean.createFormContent}", null, null, params); + } + // set the form-id into the request scope for data binding + requestMap.put(REQUEST_FORM_REF, formRef); + Utils.encodeRecursive(fc, action); + requestMap.remove(REQUEST_FORM_REF); out.write(""); } @@ -751,17 +768,37 @@ public class UIUserSandboxes extends SelfRenderingComponent * @param icon Icon to display for the action * @param actionListener Actionlistener for the action * @param outcome Navigation outcome for the action - * @param url HREF URL for the action * * @return UIActionLink component */ private UIActionLink aquireAction(FacesContext fc, String store, String username, - String name, String icon, String actionListener, String outcome, String url) + String name, String icon, String actionListener, String outcome) { - UIActionLink action = findAction(name, store, username); + return aquireAction(fc, store, username, name, icon, actionListener, outcome, null, null); + } + + /** + * Aquire a UIActionLink component for the specified action + * + * @param fc FacesContext + * @param store Root store name for the user sandbox + * @param username Username of the user for the action + * @param name Action name - will be used for I18N message lookup + * @param icon Icon to display for the action + * @param actionListener Actionlistener for the action + * @param outcome Navigation outcome for the action + * @param url HREF URL for the action + * @param params Parameters name/values for the action listener args + * + * @return UIActionLink component + */ + private UIActionLink aquireAction(FacesContext fc, String store, String username, String name, + String icon, String actionListener, String outcome, String url, Map params) + { + UIActionLink action = findAction(name, store); if (action == null) { - action = createAction(fc, store, username, name, icon, actionListener, outcome, url); + action = createAction(fc, store, username, name, icon, actionListener, outcome, null, null); } return action; } @@ -775,7 +812,7 @@ public class UIUserSandboxes extends SelfRenderingComponent * * @return UIActionLink component if found, else null if not created yet */ - private UIActionLink findAction(String name, String store, String username) + private UIActionLink findAction(String name, String store) { UIActionLink action = null; String actionId = name + '_' + store; @@ -805,11 +842,12 @@ public class UIUserSandboxes extends SelfRenderingComponent * @param actionListener Actionlistener for the action * @param outcome Navigation outcome for the action * @param url HREF URL for the action + * @param params Parameters name/values for the action listener args * * @return UIActionLink child component */ - private UIActionLink createAction(FacesContext fc, String store, String username, - String name, String icon, String actionListener, String outcome, String url) + private UIActionLink createAction(FacesContext fc, String store, String username, String name, + String icon, String actionListener, String outcome, String url, Map params) { javax.faces.application.Application facesApp = fc.getApplication(); UIActionLink control = (UIActionLink)facesApp.createComponent(UIActions.COMPONENT_ACTIONLINK); @@ -828,16 +866,42 @@ public class UIUserSandboxes extends SelfRenderingComponent control.setActionListener(facesApp.createMethodBinding( actionListener, UIActions.ACTION_CLASS_ARGS)); - UIParameter param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER); - param.setId(id + "_1"); - param.setName("store"); - param.setValue(store); - control.getChildren().add(param); - param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER); - param.setId(id + "_2"); - param.setName("username"); - param.setValue(username); - control.getChildren().add(param); + // add the store and username as default action listener parameters + if (params == null) + { + UIParameter param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER); + param.setId(id + "_1"); + param.setName("store"); + param.setValue(store); + control.getChildren().add(param); + param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER); + param.setId(id + "_2"); + param.setName("username"); + param.setValue(username); + control.getChildren().add(param); + } + else + { + // if a specific set of parameters are supplied, then add them instead + int idIndex = 1; + for (String key : params.keySet()) + { + UIParameter param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER); + param.setId(id + '_' + Integer.toString(idIndex++)); + param.setName(key); + String value = params.get(key); + if (value.startsWith("#{") == true) + { + ValueBinding vb = facesApp.createValueBinding(value); + param.setValueBinding("value", vb); + } + else + { + param.setValue(params.get(key)); + } + control.getChildren().add(param); + } + } } if (outcome != null) { diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index 1d85f6e981..fba6e74eb6 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -2243,6 +2243,10 @@ avmService #{AVMService} + + avmSyncService + #{AVMSyncService} + navigationBean #{NavigationBean} diff --git a/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp b/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp index da6f8db455..4d2d992c2a 100644 --- a/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp +++ b/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp @@ -43,7 +43,7 @@ - +