diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index faf79f0b81..87b9078102 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -1204,28 +1204,36 @@ view_link_validation_report=View Link Validation Report link_validation_unknown_error=An unknown error occurred during the link validation check link_validation_error=An error occurred during the link validation check link_validaton_dialog_title=Link Validation Report -link_validaton_dialog_desc=This dialog shows the results of a link validation check and allows broken links to be fixed. -initial_check=Initial check -current_status=Current status -files_links_checked=The check was completed at {0}, {1} file(s) were checked and {2} link(s) were found. -files_links_checked_error=The check failed at {0} due to the error: -files_links_broken={0} broken link(s) were found in {1} file(s). -files_links_still_broken={0} link(s) still broken in {1} file(s). -broken_items_fixed={0} broken item(s) have been fixed. -files_with_broken_links=Static files with broken links -forms_with_broken_links=Generated files with broken links +link_validaton_dialog_desc=This dialog shows the results of a link validation check and allows you to fix broken links. +report_summary=Report Summary +link_check_completed_at=Broken links were checked at {0} using snapshot {1}. +link_check_not_latest=This is not the latest snapshot. +link_check_items_found={0} file(s) were checked, {1} link(s) were found. +link_check_items_broken={0} broken link(s) were found in {1} file(s). +link_check_no_broken=No broken links were found. +link_check_error=The broken links check failed at {0} due to the error: +update_status=Recount generated_files=Generated Files broken_links=Broken Links +expand_all=Expand All +collapse_all=Collapse All rerun_report=Run Report Again -update_status=Update Status -fixed_items=Items you have fixed no_items=No items to display +broken=Broken +fixed=Fixed +static_tab={0} Static Files +generated_tab={0} Generated Files +all_items_tab=All Items +inc_tab_size=Increases the size of the scrollable area by 100px +dec_tab_size=Decreases the size of the scrollable area by 100px (to a minimum of 100px) + prompt_for_web_form=Select Web Form prompt_for_web_form_info=Select the Web Form to use for editing this file prompt_for_web_form_form_not_found_error_in_web_project=Unable to find Web Form {0} associated with {1} in Web Project {2}. prompt_for_web_form_form_not_found_error=Unable to find Web Form {0} associated with {1}. prompt_for_web_form_explanation=Select the Web Form to use for {0}. prompt_for_web_form_continue_msg=To edit {0} using the selected Web Form, click ok. If {0} is not a Web Form generated asset and should be treated as regular content, click cancel. + # New User Wizard messages new_user_title=New User Wizard new_user_title_edit=Edit User Wizard diff --git a/config/alfresco/web-client-config-wcm.xml b/config/alfresco/web-client-config-wcm.xml index a50dbd8c76..59316c7340 100644 --- a/config/alfresco/web-client-config-wcm.xml +++ b/config/alfresco/web-client-config-wcm.xml @@ -13,6 +13,10 @@ wcmwf:changerequest + + 25 + + diff --git a/source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java index 42ca0fcd4e..df87a52bf8 100644 --- a/source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java @@ -27,11 +27,10 @@ package org.alfresco.web.action.evaluator; import javax.faces.context.FacesContext; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.util.Pair; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.wcm.AVMNode; import org.alfresco.web.bean.wcm.AVMUtil; /** @@ -52,14 +51,12 @@ public class WCMWorkflowDeletedEvaluator extends WCMLockEvaluator { final FacesContext facesContext = FacesContext.getCurrentInstance(); final AVMService avmService = Repository.getServiceRegistry(facesContext).getAVMService(); - final Pair p = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef()); - final int version = p.getFirst(); - final String path = p.getSecond(); + final String path = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef()).getSecond(); // evaluate to true if we are within a workflow store (i.e. list of resources in the task // dialog) or not part of an already in-progress workflow proceed = (AVMUtil.isWorkflowStore(AVMUtil.getStoreName(path)) || - avmService.hasAspect(version, path, AVMSubmittedAspect.ASPECT) == false); + !((AVMNode)node).isWorkflowInFlight()); } return proceed; } diff --git a/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java index 3ed2871a05..286b0bd94a 100644 --- a/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java @@ -27,11 +27,11 @@ package org.alfresco.web.action.evaluator; import javax.faces.context.FacesContext; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.util.Pair; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.wcm.AVMNode; import org.alfresco.web.bean.wcm.AVMUtil; /** @@ -58,8 +58,8 @@ public class WCMWorkflowEvaluator extends WCMLockEvaluator // evaluate to true if we are not deleted and within a workflow store (i.e. list of resources // in the task dialog) or not part of an already in-progress workflow proceed = ((AVMUtil.isWorkflowStore(AVMUtil.getStoreName(path)) || - avmService.hasAspect(version, path, AVMSubmittedAspect.ASPECT) == false) && - avmService.lookup(version, path) != null); + !((AVMNode)node).isWorkflowInFlight()) && + avmService.lookup(version, path) != null); } return proceed; } diff --git a/source/java/org/alfresco/web/app/servlet/FacesHelper.java b/source/java/org/alfresco/web/app/servlet/FacesHelper.java index 297525162f..a22d97a15c 100644 --- a/source/java/org/alfresco/web/app/servlet/FacesHelper.java +++ b/source/java/org/alfresco/web/app/servlet/FacesHelper.java @@ -53,7 +53,7 @@ import org.apache.commons.logging.LogFactory; public final class FacesHelper { private static Log logger = LogFactory.getLog(FacesHelper.class); - private static Pattern FACES_ID_PATTERN = Pattern.compile("[^a-z^A-Z^_]?[^a-z^A-Z^_^-]"); + private static Pattern FACES_ID_PATTERN = Pattern.compile("[^a-z^A-Z^_]?[^a-z^A-Z^0-9^_^-]"); /** * Private constructor diff --git a/source/java/org/alfresco/web/bean/ajax/MySpacesBean.java b/source/java/org/alfresco/web/bean/ajax/MySpacesBean.java index 5552f07e60..2dfb40ab6d 100644 --- a/source/java/org/alfresco/web/bean/ajax/MySpacesBean.java +++ b/source/java/org/alfresco/web/bean/ajax/MySpacesBean.java @@ -27,21 +27,19 @@ package org.alfresco.web.bean.ajax; import java.io.Serializable; import java.util.HashMap; import java.util.Map; -import java.util.StringTokenizer; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; -import org.alfresco.filesys.server.filesys.FileExistsException; import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; +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.namespace.QName; -import org.alfresco.web.app.servlet.BaseServlet; import org.alfresco.web.app.servlet.ajax.InvokeCommand; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.spaces.CreateSpaceWizard; diff --git a/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java b/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java index 2e6478556d..e8c55b02af 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java @@ -42,6 +42,8 @@ import javax.faces.event.ActionEvent; import javax.faces.model.SelectItem; import javax.transaction.UserTransaction; +import org.alfresco.config.ConfigElement; +import org.alfresco.config.ConfigService; import org.alfresco.linkvalidation.HrefValidationProgress; import org.alfresco.model.WCMAppModel; import org.alfresco.repo.avm.AVMNodeConverter; @@ -68,14 +70,15 @@ 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.repository.User; -import org.alfresco.web.bean.wizard.WizardManager; -import org.alfresco.web.forms.*; +import org.alfresco.web.forms.FormInstanceData; +import org.alfresco.web.forms.FormNotFoundException; +import org.alfresco.web.forms.FormsService; +import org.alfresco.web.forms.Rendition; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.IBreadcrumbHandler; import org.alfresco.web.ui.common.component.UIActionLink; @@ -85,9 +88,9 @@ import org.alfresco.web.ui.common.component.data.UIRichList; import org.alfresco.web.ui.wcm.WebResources; import org.alfresco.web.ui.wcm.component.UISandboxSnapshots; import org.alfresco.web.ui.wcm.component.UIUserSandboxes; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.commons.lang.StringUtils; /** * Bean backing up the AVM specific browse screens @@ -98,7 +101,7 @@ public class AVMBrowseBean implements IContextListener { public static final String BEAN_NAME = "AVMBrowseBean"; - private static final Log LOGGER = LogFactory.getLog(AVMBrowseBean.class); + private static final Log logger = LogFactory.getLog(AVMBrowseBean.class); private static final String REQUEST_BEEN_DEPLOYED_KEY = "_alfBeenDeployedEvaluated"; private static final String REQUEST_BEEN_DEPLOYED_RESULT = "_alfBeenDeployedResult"; @@ -110,9 +113,6 @@ public class AVMBrowseBean implements IContextListener private static final String MSG_CREATED_ON = "store_created_on"; private static final String MSG_CREATED_BY = "store_created_by"; 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 */ static final String COMPONENT_SANDBOXESPANEL = "sandboxes-panel"; @@ -178,6 +178,12 @@ public class AVMBrowseBean implements IContextListener /** breadcrumb location */ private List location = null; + /** The current view page sizes */ + private int pageSizeFolders; + private int pageSizeFiles; + private String pageSizeFoldersStr; + private String pageSizeFilesStr; + /** The NodeService to be used by the bean */ protected NodeService nodeService; @@ -205,6 +211,8 @@ public class AVMBrowseBean implements IContextListener public AVMBrowseBean() { UIContextService.getInstance(FacesContext.getCurrentInstance()).registerBean(this); + + initFromClientConfig(); } @@ -277,6 +285,48 @@ public class AVMBrowseBean implements IContextListener { this.formsService = formsService; } + + public int getPageSizeFiles() + { + return this.pageSizeFiles; + } + + public void setPageSizeFiles(int pageSizeContent) + { + this.pageSizeFiles = pageSizeContent; + this.pageSizeFilesStr = Integer.toString(pageSizeContent); + } + + public int getPageSizeFolders() + { + return this.pageSizeFolders; + } + + public void setPageSizeFolders(int pageSizeSpaces) + { + this.pageSizeFolders = pageSizeSpaces; + this.pageSizeFoldersStr = Integer.toString(pageSizeSpaces); + } + + public String getPageSizeFilesStr() + { + return this.pageSizeFilesStr; + } + + public void setPageSizeFilesStr(String pageSizeContentStr) + { + this.pageSizeFilesStr = pageSizeContentStr; + } + + public String getPageSizeFoldersStr() + { + return this.pageSizeFoldersStr; + } + + public void setPageSizeFoldersStr(String pageSizeSpacesStr) + { + this.pageSizeFoldersStr = pageSizeSpacesStr; + } /** * Summary text for the staging store: @@ -510,15 +560,11 @@ public class AVMBrowseBean implements IContextListener this.linkValidationState = state; } - /** - */ public List getNodesForSubmit() { return this.nodesForSubmit; } - /** - */ public void setNodesForSubmit(final List nodesForSubmit) { this.nodesForSubmit = nodesForSubmit; @@ -962,8 +1008,8 @@ public class AVMBrowseBean implements IContextListener /*package*/ void setupContentAction(final String path, final boolean refresh) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Setup content action for path: " + path); + if (logger.isDebugEnabled()) + logger.debug("Setup content action for path: " + path); if (path == null && path.length() == 0) { @@ -1030,16 +1076,16 @@ public class AVMBrowseBean implements IContextListener String avmPath = this.getAvmActionNode().getPath(); if (this.avmService.hasAspect(-1, avmPath, WCMAppModel.ASPECT_RENDITION)) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug(avmPath + " is a rendition, editing primary rendition instead"); + if (logger.isDebugEnabled()) + logger.debug(avmPath + " is a rendition, editing primary rendition instead"); try { final FormInstanceData fid = this.formsService.getRendition(-1, avmPath).getPrimaryFormInstanceData(); avmPath = fid.getPath(); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Editing primary form instance data " + avmPath); + if (logger.isDebugEnabled()) + logger.debug("Editing primary form instance data " + avmPath); this.setAvmActionNode(new AVMNode(this.avmService.lookup(-1, avmPath))); } @@ -1051,8 +1097,8 @@ public class AVMBrowseBean implements IContextListener } } - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Editing AVM node: " + avmPath); + if (logger.isDebugEnabled()) + logger.debug("Editing AVM node: " + avmPath); String outcome = null; // calculate which editor screen to display if (this.avmService.hasAspect(-1, avmPath, WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) @@ -1068,7 +1114,7 @@ public class AVMBrowseBean implements IContextListener } catch (FormNotFoundException fnfe) { - LOGGER.debug(fnfe.getMessage(), fnfe); + logger.debug(fnfe.getMessage(), fnfe); final Map params = new HashMap(2, 1.0f); params.put("finishOutcome", "wizard:editWebContent"); params.put("cancelOutcome", "dialog:editAvmFile"); @@ -1083,7 +1129,7 @@ public class AVMBrowseBean implements IContextListener outcome = "dialog:editAvmFile"; } - LOGGER.debug("outcome " + outcome + " for path " + path); + logger.debug("outcome " + outcome + " for path " + path); final FacesContext fc = FacesContext.getCurrentInstance(); fc.getApplication().getNavigationHandler().handleNavigation(fc, null, outcome); @@ -1330,6 +1376,57 @@ public class AVMBrowseBean implements IContextListener } } + /** + * Update page size based on user selection + */ + public void updateFoldersPageSize(ActionEvent event) + { + try + { + int size = Integer.parseInt(this.pageSizeFoldersStr); + if (size >= 0) + { + this.pageSizeFolders = size; + } + else + { + // reset to known value if this occurs + this.pageSizeFoldersStr = Integer.toString(this.pageSizeFolders); + } + } + catch (NumberFormatException err) + { + // reset to known value if this occurs + this.pageSizeFoldersStr = Integer.toString(this.pageSizeFolders); + } + } + + /** + * Update page size based on user selection + */ + public void updateFilesPageSize(ActionEvent event) + { + try + { + int size = Integer.parseInt(this.pageSizeFilesStr); + if (size >= 0) + { + this.pageSizeFiles = size; + } + else + { + // reset to known value if this occurs + this.pageSizeFilesStr = Integer.toString(this.pageSizeFiles); + } + } + catch (NumberFormatException err) + { + // reset to known value if this occurs + this.pageSizeFilesStr = Integer.toString(this.pageSizeFiles); + } + } + + // ------------------------------------------------------------------------------ // Private helpers @@ -1350,6 +1447,33 @@ public class AVMBrowseBean implements IContextListener return (this.currentPath == null); } + /** + * Initialise default values from client configuration + */ + private void initFromClientConfig() + { + ConfigService config = Application.getConfigService(FacesContext.getCurrentInstance()); + ConfigElement wcmConfig = config.getGlobalConfig().getConfigElement("wcm"); + if (wcmConfig != null) + { + ConfigElement viewsConfig = wcmConfig.getChild("views"); + if (viewsConfig != null) + { + ConfigElement pageConfig = viewsConfig.getChild("browse-page-size"); + if (pageConfig != null) + { + String strPageSize = pageConfig.getValue(); + if (strPageSize != null) + { + int pageSize = Integer.valueOf(strPageSize.trim()); + setPageSizeFiles(pageSize); + setPageSizeFolders(pageSize); + } + } + } + } + } + /** * Update the breadcrumb with the clicked Group location */ diff --git a/source/java/org/alfresco/web/bean/wcm/AVMNode.java b/source/java/org/alfresco/web/bean/wcm/AVMNode.java index f4a827c2f6..be27b4921b 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMNode.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMNode.java @@ -25,6 +25,7 @@ package org.alfresco.web.bean.wcm; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; import javax.faces.context.FacesContext; @@ -34,9 +35,11 @@ import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.avm.AVMNodeType; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.LayeringDescriptor; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; import org.alfresco.web.app.Application; import org.alfresco.web.bean.BrowseBean; import org.alfresco.web.bean.repository.Node; @@ -123,12 +126,13 @@ public class AVMNode extends Node implements Map } }; + private final AVMNodeDescriptor avmRef; + private LayeringDescriptor layeringDesc; + private final int version; + private final boolean deleted; + private WebProject webProject; + private Boolean workflowInFlight; - private AVMNodeDescriptor avmRef; - private int version; - private boolean deleted = false; - - /** * Constructor * @@ -193,6 +197,58 @@ public class AVMNode extends Node implements Map return this.avmRef.isFile() || this.avmRef.isDeletedFile(); } + public final boolean isModified() + { + if (this.layeringDesc == null) + { + this.layeringDesc = getServiceRegistry().getAVMService().getLayeringInfo(this.version, this.id); + } + return !this.layeringDesc.isBackground(); + } + + public final boolean isWorkflowInFlight() + { + if (this.workflowInFlight == null) + { + if (!this.isModified()) + { + this.workflowInFlight = false; + } + else + { + // optimization to avoid having to perform a workflow query and multiple lookups + // per workflow sandbox. only accurate for files, not new directories + if (!this.isDirectory()) + { + this.workflowInFlight = false; + final List> headPaths = this.getServiceRegistry().getAVMService().getHeadPaths(this.getDescriptor()); + for (final Pair headPath : headPaths) + { + if (AVMUtil.isWorkflowStore(AVMUtil.getStoreName(headPath.getSecond()))) + { + this.workflowInFlight = true; + break; + } + } + } + else + { + this.workflowInFlight = AVMWorkflowUtil.getAssociatedTasksForNode(this.getDescriptor()).size() != 0; + } + } + } + return this.workflowInFlight; + } + + public WebProject getWebProject() + { + if (this.webProject == null) + { + this.webProject = new WebProject(this.id); + } + return this.webProject; + } + /** * @return All the properties known about this node. */ diff --git a/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java b/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java index ece99433cd..ade27b49b1 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java @@ -20,7 +20,7 @@ * and Open Source Software ("FLOSS") applications as described in Alfresco's * FLOSS exception. You should have recieved a copy of the text describing * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" + * http://www.alfresco.com/legal/licensing */ package org.alfresco.web.bean.wcm; @@ -30,26 +30,21 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.StringTokenizer; +import java.util.*; import javax.faces.context.FacesContext; import org.alfresco.config.ConfigElement; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.WCMAppModel; +import org.alfresco.model.WCMWorkflowModel; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.security.authority.AuthorityDAO; import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.avm.AVMNodeDescriptor; -import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.*; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.repository.ContentReader; @@ -59,10 +54,7 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.workflow.WorkflowDefinition; -import org.alfresco.service.cmr.workflow.WorkflowException; -import org.alfresco.service.cmr.workflow.WorkflowPath; -import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.cmr.workflow.*; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; import org.alfresco.web.app.Application; @@ -79,57 +71,53 @@ import org.apache.commons.logging.LogFactory; */ public class AVMWorkflowUtil extends WorkflowUtil { - private static final Log logger = LogFactory.getLog(AVMWorkflowUtil.class); + private static final Log LOGGER = LogFactory.getLog(AVMWorkflowUtil.class); // cached configured lists private static List configuredWorkflowDefs = null; public static NodeRef createWorkflowPackage(final List srcPaths, final SandboxInfo sandboxInfo, - final WorkflowPath path, - final AVMSubmittedAspect avmSubmittedAspect, - final AVMSyncService avmSyncService, - final AVMService avmService, - final WorkflowService workflowService, - final NodeService nodeService) + final WorkflowPath path) { + final FacesContext fc = FacesContext.getCurrentInstance(); + final WorkflowService workflowService = Repository.getServiceRegistry(fc).getWorkflowService(); + final AVMService avmService = Repository.getServiceRegistry(fc).getAVMLockingAwareService(); + final AVMSyncService avmSyncService = Repository.getServiceRegistry(fc).getAVMSyncService(); // create package paths (layered to user sandbox area as target) final String workflowMainStoreName = sandboxInfo.getMainStoreName(); final String packagesPath = AVMUtil.buildStoreRootPath(workflowMainStoreName); final String stagingStoreName = AVMUtil.getStoreId(workflowMainStoreName); - final HashSet directoriesAdded = new HashSet(); final List diffs = new ArrayList(srcPaths.size()); for (final String srcPath : srcPaths) { - // add all newly created directories - String parentPath = AVMNodeConverter.SplitBase(srcPath)[0]; - while (!directoriesAdded.contains(parentPath) && - avmService.lookup(-1, AVMUtil.getCorrespondingPath(parentPath, stagingStoreName)) == null) + final AVMNodeDescriptor node = avmService.lookup(-1, srcPath, true); + if (node.isDirectory()) { - diffs.add(new AVMDifference(-1, parentPath, - -1, AVMUtil.getCorrespondingPath(parentPath, workflowMainStoreName), + diffs.add(new AVMDifference(-1, srcPath, + -1, AVMUtil.getCorrespondingPath(srcPath, workflowMainStoreName), + AVMDifference.NEWER)); + } + else + { + final HashSet directoriesAdded = new HashSet(); + // add all newly created directories + String parentPath = AVMNodeConverter.SplitBase(srcPath)[0]; + while (!directoriesAdded.contains(parentPath) && + avmService.lookup(-1, AVMUtil.getCorrespondingPath(parentPath, stagingStoreName), true) == null) + { + diffs.add(new AVMDifference(-1, parentPath, + -1, AVMUtil.getCorrespondingPath(parentPath, workflowMainStoreName), + AVMDifference.NEWER)); + directoriesAdded.add(parentPath); + parentPath = AVMNodeConverter.SplitBase(parentPath)[0]; + } + diffs.add(new AVMDifference(-1, srcPath, + -1, AVMUtil.getCorrespondingPath(srcPath, workflowMainStoreName), AVMDifference.NEWER)); - try - { - avmSubmittedAspect.markSubmitted(-1, parentPath, path.instance.id); - } - catch (final WorkflowException alreadySubmitted) - { - if (! path.instance.id.equals(avmSubmittedAspect.getWorkflowInstance(-1, parentPath))) - { - throw alreadySubmitted; - } - } - directoriesAdded.add(parentPath); - parentPath = AVMNodeConverter.SplitBase(parentPath)[0]; } - - diffs.add(new AVMDifference(-1, srcPath, - -1, AVMUtil.getCorrespondingPath(srcPath, workflowMainStoreName), - AVMDifference.NEWER)); - avmSubmittedAspect.markSubmitted(-1, srcPath, path.instance.id); } // write changes to layer so files are marked as modified @@ -139,7 +127,6 @@ public class AVMWorkflowUtil extends WorkflowUtil final AVMNodeDescriptor packageDesc = avmService.lookup(-1, packagesPath); final NodeRef packageNodeRef = workflowService.createPackage(AVMNodeConverter.ToNodeRef(-1, packageDesc.getPath())); avmService.setNodeProperty(packagesPath, WorkflowModel.PROP_IS_SYSTEM_PACKAGE, new PropertyValue(null, true)); - // nodeService.setProperty(packageNodeRef, WorkflowModel.PROP_IS_SYSTEM_PACKAGE, true); // apply global permission to workflow package // TODO: Determine appropriate permissions @@ -148,7 +135,7 @@ public class AVMWorkflowUtil extends WorkflowUtil permissionService.setPermission(packageNodeRef, PermissionService.ALL_AUTHORITIES, PermissionService.ALL_PERMISSIONS, true); return packageNodeRef; } - + /** * Serialize the workflow params to a content stream * @@ -220,10 +207,18 @@ public class AVMWorkflowUtil extends WorkflowUtil FacesContext fc = FacesContext.getCurrentInstance(); List defs = Collections.emptyList(); ConfigElement config = Application.getConfigService(fc).getGlobalConfig().getConfigElement("wcm"); - if (config != null) + if (config == null) + { + LOGGER.warn("WARNING: Unable to find 'wcm' config element definition."); + } + else { ConfigElement workflowConfig = config.getChild("workflows"); - if (workflowConfig != null) + if (workflowConfig == null) + { + LOGGER.warn("WARNING: Unable to find WCM 'workflows' config element definition."); + } + else { WorkflowService service = Repository.getServiceRegistry(fc).getWorkflowService(); StringTokenizer t = new StringTokenizer(workflowConfig.getValue().trim(), ", "); @@ -238,21 +233,64 @@ public class AVMWorkflowUtil extends WorkflowUtil } else { - logger.warn("WARNING: Cannot find WCM workflow def for configured definition name: " + wfName); + LOGGER.warn("WARNING: Cannot find WCM workflow def for configured definition name: " + wfName); } } } - else - { - logger.warn("WARNING: Unable to find WCM 'workflows' config element definition."); - } - } - else - { - logger.warn("WARNING: Unable to find 'wcm' config element definition."); } configuredWorkflowDefs = defs; } return configuredWorkflowDefs; } + + public static List getAssociatedTasksForSandbox(final String storeName) + { + final String fromPath = AVMUtil.buildStoreRootPath(storeName); + final FacesContext fc = FacesContext.getCurrentInstance(); + final WorkflowService workflowService = Repository.getServiceRegistry(fc).getWorkflowService(); + final WorkflowTaskQuery query = new WorkflowTaskQuery(); + final HashMap props = new HashMap(1, 1.0f); + props.put(WCMWorkflowModel.PROP_FROM_PATH, fromPath); + query.setProcessCustomProps(props); + final List tasks = workflowService.queryTasks(query); + LOGGER.debug("found " + tasks.size() + " tasks originating user sandbox " + fromPath); + return tasks; + } + + public static List getAssociatedTasksForNode(final AVMNodeDescriptor node) + { + final List tasks = AVMWorkflowUtil.getAssociatedTasksForSandbox(AVMUtil.getStoreName(node.getPath())); + final List result = new LinkedList(); + final FacesContext fc = FacesContext.getCurrentInstance(); + final AVMService avmService = Repository.getServiceRegistry(fc).getAVMService(); + for (final WorkflowTask task : tasks) + { + final NodeRef ref = task.path.instance.workflowPackage; + final String path = AVMUtil.getCorrespondingPath(node.getPath(), ref.getStoreRef().getIdentifier()); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("checking store " + ref.getStoreRef().getIdentifier() + + " for " + node.getPath() + " (" + path + ")"); + } + try + { + final LayeringDescriptor ld = avmService.getLayeringInfo(-1, path); + if (!ld.isBackground()) + { + LOGGER.debug(path + " is in the foreground. workflow active"); + result.add(task); + } + else + { +// LOGGER.debug(path + " is in the background"); + } + } + catch (final AVMNotFoundException avmnfe) + { + LOGGER.debug(path + " not found"); + } + } + + return result; + } } diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java index 650bb6436a..42e3091030 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java @@ -47,7 +47,6 @@ import org.alfresco.model.ContentModel; import org.alfresco.model.WCMAppModel; import org.alfresco.model.WCMWorkflowModel; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.cmr.avm.AVMExistsException; @@ -109,7 +108,6 @@ public class CreateWebContentWizard extends BaseContentWizard protected AVMService avmService; protected AVMSyncService avmSyncService; protected AVMBrowseBean avmBrowseBean; - protected AVMSubmittedAspect avmSubmittedAspect; protected FilePickerBean filePickerBean; protected FormsService formsService; @@ -129,14 +127,6 @@ public class CreateWebContentWizard extends BaseContentWizard this.avmSyncService = avmSyncService; } - /** - * @param avmSubmittedAspect The AVM Submitted Aspect to set. - */ - public void setAvmSubmittedAspect(AVMSubmittedAspect avmSubmittedAspect) - { - this.avmSubmittedAspect = avmSubmittedAspect; - } - /** * @param avmBrowseBean The AVMBrowseBean to set. */ diff --git a/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java index 801a8bc041..82653bb324 100644 --- a/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java @@ -47,7 +47,6 @@ import org.alfresco.model.ContentModel; import org.alfresco.model.WCMAppModel; import org.alfresco.model.WCMWorkflowModel; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.cmr.avm.AVMExistsException; diff --git a/source/java/org/alfresco/web/bean/wcm/LinkValidationDialog.java b/source/java/org/alfresco/web/bean/wcm/LinkValidationDialog.java index f0679960f3..f84c091c1f 100644 --- a/source/java/org/alfresco/web/bean/wcm/LinkValidationDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/LinkValidationDialog.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.Map; import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; import javax.transaction.UserTransaction; import org.alfresco.linkvalidation.HrefValidationProgress; @@ -46,6 +47,8 @@ import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.BaseDialogBean; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIActionLink; +import org.alfresco.web.ui.wcm.component.UILinkValidationReport; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -66,10 +69,12 @@ public class LinkValidationDialog extends BaseDialogBean private String store; private String webapp; private String webappPath; + private String initialTab; private NodeRef webappPathRef; private boolean runningReport = false; private boolean update = false; private boolean compareToStaging = false; + private boolean sectionsExpanded = false; private static final Log logger = LogFactory.getLog(LinkValidationDialog.class); @@ -90,6 +95,7 @@ public class LinkValidationDialog extends BaseDialogBean // setup context for dialog this.webappPath = AVMUtil.buildStoreWebappPath(this.store, this.webapp); this.webappPathRef = AVMNodeConverter.ToNodeRef(-1, this.webappPath); + this.initialTab = UILinkValidationReport.DEFAULT_INTIAL_TAB; this.runningReport = false; String modeParam = parameters.get("mode"); @@ -230,6 +236,20 @@ public class LinkValidationDialog extends BaseDialogBean return outcome; } + public void toggleSections(ActionEvent event) + { + this.sectionsExpanded = !this.sectionsExpanded; + + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String tab = params.get("tab"); + + if (tab != null) + { + this.initialTab = tab; + } + } + /** * Sets up the dialog to update the status and display the differences * @@ -287,6 +307,39 @@ public class LinkValidationDialog extends BaseDialogBean return !this.runningReport; } + /** + * @return true if the broken links and generated files section are expanded + */ + public boolean getSectionsExpanded() + { + return sectionsExpanded; + } + + /** + * @param sectionsExpanded true if the broken links and generated + * files section are expanded + */ + public void setSectionsExpanded(boolean sectionsExpanded) + { + this.sectionsExpanded = sectionsExpanded; + } + + /** + * @return The initial tab to be selected + */ + public String getInitialTab() + { + return initialTab; + } + + /** + * @param initialTab Sets the initial tab to be selected + */ + public void setInitialTab(String initialTab) + { + this.initialTab = initialTab; + } + /** * @param avmBrowseBean The AVM BrowseBean to set */ diff --git a/source/java/org/alfresco/web/bean/wcm/LinkValidationState.java b/source/java/org/alfresco/web/bean/wcm/LinkValidationState.java index 94cdb30f29..efe918bd73 100644 --- a/source/java/org/alfresco/web/bean/wcm/LinkValidationState.java +++ b/source/java/org/alfresco/web/bean/wcm/LinkValidationState.java @@ -60,7 +60,7 @@ public class LinkValidationState private String store; private String webapp; private boolean checkBeenReRun = false; - private Date initialCheckCompletedAt; + private Date checkCompletedAt; private int noFilesCheckedStart = -1; private int noFilesCheckedLast = -1; @@ -76,6 +76,12 @@ public class LinkValidationState private int noFixedItems = -1; + private int noBrokenLinksInStaticFiles = -1; + private int noBrokenLinksInForms = -1; + + private int baseSnapshotVersion = 0; + private int latestSnapshotVersion = 0; + private List brokenStaticFilesStart; private List brokenFormsStart; @@ -123,11 +129,11 @@ public class LinkValidationState } /** - * @return The date the initial check was completed + * @return The date the check was completed */ - public Date getInitialCheckCompletedAt() + public Date getCheckCompletedAt() { - return this.initialCheckCompletedAt; + return this.checkCompletedAt; } /** @@ -202,6 +208,22 @@ public class LinkValidationState return this.noBrokenLinksLast; } + /** + * @return The number of broken links in static files + */ + public int getNoBrokenLinksInStaticFiles() + { + return noBrokenLinksInStaticFiles; + } + + /** + * @return The number of broken links in forms + */ + public int getNoBrokenLinksInForms() + { + return noBrokenLinksInForms; + } + /** * @return The number of items fixed since the initial link check */ @@ -210,6 +232,22 @@ public class LinkValidationState return this.noFixedItems; } + /** + * @return The snapshot version of the staging area the link check was run against + */ + public int getBaseSnapshotVersion() + { + return baseSnapshotVersion; + } + + /** + * @return The snapshot version of the staging area at the end of the link check + */ + public int getLatestSnapshotVersion() + { + return latestSnapshotVersion; + } + /** * @return A list of paths to non-generated files that contain broken links */ @@ -302,6 +340,8 @@ public class LinkValidationState StringBuilder buffer = new StringBuilder(super.toString()); buffer.append(" (store=").append(this.store); buffer.append(" webapp=").append(this.webapp); + buffer.append(" baseSnapshot=").append(this.baseSnapshotVersion); + buffer.append(" latestSnapshot=").append(this.latestSnapshotVersion); buffer.append(" error=").append(this.cause).append(")"); return buffer.toString(); } @@ -314,11 +354,12 @@ public class LinkValidationState this.checkBeenReRun = updatedReport; this.cause = report.getError(); - // make sure there is an initial check completed date - if (this.initialCheckCompletedAt == null) - { - this.initialCheckCompletedAt = report.getCheckCompletedAt(); - } + // update the check completed date + this.checkCompletedAt = report.getCheckCompletedAt(); + + // get the snapshot versions + this.baseSnapshotVersion = report.getBaseSnapshotVersion(); + this.latestSnapshotVersion = report.getLatestSnapshotVersion(); if (this.cause == null) { @@ -365,6 +406,7 @@ public class LinkValidationState this.fixedFiles.add(file); } } + for (String file : this.brokenFormsStart) { if (this.brokenFormsLast.contains(file) == false && @@ -377,6 +419,32 @@ public class LinkValidationState // calculate the number of fixed items we have this.noFixedItems = this.fixedFiles.size() + this.fixedForms.size(); } + + // calculate the number of broken links for static files and how + // many are from generated files (forms) + this.noBrokenLinksInStaticFiles = 0; + this.noBrokenLinksInForms = 0; + + for (String file : this.brokenStaticFilesLast) + { + List links = this.getBrokenLinksForFile(file); + if (links != null) + { + this.noBrokenLinksInStaticFiles += links.size(); + } + } + + for (String form : this.brokenFormsLast) + { + for (String file: this.getBrokenFilesByForm(form)) + { + List links = this.getBrokenLinksForFile(file); + if (links != null) + { + this.noBrokenLinksInForms += links.size(); + } + } + } } } diff --git a/source/java/org/alfresco/web/bean/wcm/ManageChangeRequestTaskDialog.java b/source/java/org/alfresco/web/bean/wcm/ManageChangeRequestTaskDialog.java index 2303813323..281681948e 100644 --- a/source/java/org/alfresco/web/bean/wcm/ManageChangeRequestTaskDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/ManageChangeRequestTaskDialog.java @@ -35,7 +35,6 @@ import javax.transaction.UserTransaction; import org.alfresco.model.WCMModel; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.sandbox.SandboxConstants; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avmsync.AVMDifference; @@ -62,7 +61,6 @@ public class ManageChangeRequestTaskDialog extends ManageTaskDialog { protected boolean doResubmitNow = false; protected AVMBrowseBean avmBrowseBean; - protected AVMSubmittedAspect avmSubmittedAspect; private final static Log logger = LogFactory.getLog(ManageChangeRequestTaskDialog.class); @@ -189,15 +187,6 @@ public class ManageChangeRequestTaskDialog extends ManageTaskDialog this.avmBrowseBean = avmBrowseBean; } - /** - * Sets the avm submitted aspect service to use - * - * @param avmSubmittedAspect AVMSubmittedAspect instance - */ - public void setAvmSubmittedAspect(AVMSubmittedAspect avmSubmittedAspect) - { - this.avmSubmittedAspect = avmSubmittedAspect; - } // ------------------------------------------------------------------------------ // Helper methods diff --git a/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java b/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java index 44cc146115..9eb43dabd0 100644 --- a/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java @@ -45,7 +45,6 @@ import org.alfresco.model.WCMAppModel; import org.alfresco.model.WCMWorkflowModel; import org.alfresco.repo.avm.AVMDAOs; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; @@ -106,7 +105,6 @@ public class SubmitDialog extends BaseDialogBean private List submitItems; private List warningItems; private HashSet workflows; -// private Map formWorkflowMap; private Map expirationDates; private List workflowItems; private Map workflowParams; @@ -124,7 +122,6 @@ public class SubmitDialog extends BaseDialogBean private String virtUpdatePath; protected AVMService avmService; - protected AVMSubmittedAspect avmSubmittedAspect; protected AVMBrowseBean avmBrowseBean; protected WorkflowService workflowService; protected AVMSyncService avmSyncService; @@ -135,7 +132,7 @@ public class SubmitDialog extends BaseDialogBean /** Current workflow for dialog context */ protected WorkflowConfiguration actionWorkflow = null; - private static final Log LOGGER = LogFactory.getLog(SubmitDialog.class); + private static final Log logger = LogFactory.getLog(SubmitDialog.class); /** * @param avmService The AVM Service to set. @@ -145,14 +142,6 @@ public class SubmitDialog extends BaseDialogBean this.avmService = avmService; } - /** - * @param avmSubmittedAspect The AVM Submitted Aspect to set. - */ - public void setAvmSubmittedAspect(AVMSubmittedAspect avmSubmittedAspect) - { - this.avmSubmittedAspect = avmSubmittedAspect; - } - /** * @param avmSyncService The AVMSyncService to set. */ @@ -562,14 +551,7 @@ public class SubmitDialog extends BaseDialogBean if (startTask.state == WorkflowTaskState.IN_PROGRESS) { final NodeRef workflowPackage = - AVMWorkflowUtil.createWorkflowPackage(this.srcPaths, - sandboxInfo, - path, - this.avmSubmittedAspect, - this.avmSyncService, - this.avmService, - this.workflowService, - this.nodeService); + AVMWorkflowUtil.createWorkflowPackage(this.srcPaths, sandboxInfo, path); this.workflowParams.put(WorkflowModel.ASSOC_PACKAGE, workflowPackage); @@ -624,7 +606,7 @@ public class SubmitDialog extends BaseDialogBean catch (Throwable e) { // not much we can do now, just log the error to inform admins - LOGGER.error("Failed to cleanup workflow sandbox after workflow failure", e); + logger.error("Failed to cleanup workflow sandbox after workflow failure", e); } } @@ -938,6 +920,7 @@ public class SubmitDialog extends BaseDialogBean // if the dialog was started from a workflow the AVM browse bean should // have the list of nodes that need submitting selected = this.avmBrowseBean.getNodesForSubmit(); + this.avmBrowseBean.setNodesForSubmit(null); } // if the dialog was started from the UI determine what nodes the user selected to submit else if (this.avmBrowseBean.getAllItemsAction()) @@ -976,7 +959,7 @@ public class SubmitDialog extends BaseDialogBean this.warningItems = new ArrayList(selected.size() >> 1); for (AVMNodeDescriptor node : selected) { - if (this.avmService.hasAspect(-1, node.getPath(), AVMSubmittedAspect.ASPECT)) + if (AVMWorkflowUtil.getAssociatedTasksForNode(node).size() != 0) { this.warningItems.add(new ItemWrapper(node)); continue; @@ -1071,8 +1054,8 @@ public class SubmitDialog extends BaseDialogBean this.avmService.setNodeProperty(srcPath, WCMAppModel.PROP_EXPIRATIONDATE, new PropertyValue(DataTypeDefinition.DATETIME, expirationDate)); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Set expiration date of " + expirationDate + + if (logger.isDebugEnabled()) + logger.debug("Set expiration date of " + expirationDate + " for " + srcPath); } @@ -1081,16 +1064,15 @@ public class SubmitDialog extends BaseDialogBean */ public void setupConfigureWorkflow(ActionEvent event) { - if (this.workflowSelectedValue == null) + if (this.workflowSelectedValue != null) { - return; - } - String workflowName = this.workflowSelectedValue[0]; - for (WorkflowConfiguration wrapper : this.workflows) - { - if (wrapper.getName().equals(workflowName)) + String workflowName = this.workflowSelectedValue[0]; + for (WorkflowConfiguration wrapper : this.workflows) { - setActionWorkflow(wrapper); + if (wrapper.getName().equals(workflowName)) + { + setActionWorkflow(wrapper); + } } } } @@ -1118,8 +1100,8 @@ public class SubmitDialog extends BaseDialogBean */ public void applyDefaultExpireDateToAll(ActionEvent event) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("applying default expiration date of " + this.defaultExpireDate + " to all modified items"); + if (logger.isDebugEnabled()) + logger.debug("applying default expiration date of " + this.defaultExpireDate + " to all modified items"); List items = this.getSubmitItems(); for (ItemWrapper item : items) diff --git a/source/java/org/alfresco/web/ui/wcm/component/AbstractLinkValidationReportComponent.java b/source/java/org/alfresco/web/ui/wcm/component/AbstractLinkValidationReportComponent.java index 301ab8b15d..49825c41f3 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/AbstractLinkValidationReportComponent.java +++ b/source/java/org/alfresco/web/ui/wcm/component/AbstractLinkValidationReportComponent.java @@ -25,18 +25,12 @@ package org.alfresco.web.ui.wcm.component; import java.io.IOException; -import java.util.List; -import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; -import javax.faces.context.ResponseWriter; import javax.faces.el.ValueBinding; -import org.alfresco.config.JNDIConstants; -import org.alfresco.web.app.Application; import org.alfresco.web.bean.wcm.LinkValidationState; import org.alfresco.web.ui.common.component.SelfRenderingComponent; -import org.alfresco.web.ui.repo.component.UIActions; /** * Base class for all the link validation report JSF components. @@ -85,216 +79,6 @@ public abstract class AbstractLinkValidationReportComponent extends SelfRenderin { // the child components are rendered explicitly during the encodeBegin() } - - // ------------------------------------------------------------------------------ - // Helper methods - - /** - * Returns the name and path for the given avm path - * - * @param avmPath The path to split - * @return A String array with the name in the first position and the path in the - * second position. - */ - protected String[] getFileNameAndPath(String avmPath) - { - String fileName = avmPath; - String filePath = avmPath; - - int idx = avmPath.lastIndexOf("/"); - if (idx != -1) - { - fileName = avmPath.substring(idx+1); - - int appbaseIdx = avmPath.indexOf(JNDIConstants.DIR_DEFAULT_APPBASE); - if (appbaseIdx != -1) - { - filePath = avmPath.substring(appbaseIdx+JNDIConstants.DIR_DEFAULT_APPBASE.length(), idx); - } - else - { - filePath = avmPath.substring(0, idx); - } - } - - return new String[] {fileName, filePath}; - } - - /** - * Constructs a comma separated list of broken links for the given avm path - * - * @param avmPath The avm path to get the broken links for - * @param linkState The current link valiation state - * @return Comma separated list of broken links - */ - protected String getBrokenLinks(FacesContext context, String avmPath, LinkValidationState linkState) - { - List brokenLinks = linkState.getBrokenLinksForFile(avmPath); - StringBuilder builder = new StringBuilder(); - boolean first = true; - for (String link : brokenLinks) - { - if (first == false) - { - builder.append("
"); - } - else - { - first = false; - } - - builder.append(""); - builder.append(parseBrokenLink(link)); - } - - return builder.toString(); - } - - /** - * Removes the virtaulisation server host name from the link if appropriate - * - * @param linkUrl The URL that is broken - * @return Parsed URL - */ - protected String parseBrokenLink(String linkUrl) - { - String link = linkUrl; - - if (linkUrl.startsWith("http://") && linkUrl.indexOf("www--sandbox") != -1) - { - // remove the virtualisation server host name - int idx = linkUrl.indexOf("/", 7); - if (idx != -1) - { - link = linkUrl.substring(idx); - } - } - - // truncate the link if it is longer than 100 chars - String title = link; - if (link.length() > 60) - { - link = link.substring(0, 60) + "..."; - } - - return " " + link + ""; - } - - /** - * Renders the HTML to display a file and it's optional broken links - * - * @param out ResponseWriter instance to write to - * @param context FacesContext - * @param fileName Name of the file - * @param filePath Path to the file - * @param brokenLinks List of broken links in the file - * @throws IOException - */ - protected void renderFile(ResponseWriter out, FacesContext context, - String fileName, String filePath, String brokenLinks) throws IOException - { - out.write(""); - out.write("
"); - out.write(fileName); - out.write("
"); - out.write(filePath); - out.write("
"); - - if (brokenLinks != null && brokenLinks.length() > 0) - { - out.write("
"); - out.write(Application.getMessage(context, "broken_links")); - out.write(":
"); - out.write(brokenLinks); - out.write("
"); - } - - out.write("
"); - } - - /** - * Renders the "No items to display" message - * - * @param out ResponseWriter instance to write to - * @param context FacesContext - * @throws IOException - */ - protected void renderNoItems(ResponseWriter out, FacesContext context) - throws IOException - { - out.write("
"); - out.write(Application.getMessage(context, "no_items")); - out.write("
"); - } - - /** - * Returns the icon to use given a file name - * - * @param fileName File name to find an icon for - * @return The path to the icon to use - */ - protected String getIcon(String fileName) - { - // work out what icon to use - String icon = "/images/filetypes32/html.gif"; - String ext = ""; - int idx = fileName.indexOf("."); - if (idx != -1) - { - ext = fileName.substring(idx); - } - - if (ext.equals(".xml")) - { - icon = "/images/icons/webform_large.gif"; - } - - return icon; - } - - /** - * Aquire the UIActions component for the specified action group ID. - * Search for the component in the child list or create as needed. - * - * @param id ActionGroup id of the UIActions component - * - * @return UIActions component - */ - @SuppressWarnings("unchecked") - protected UIActions aquireUIActions(String id, String store) - { - UIActions uiActions = null; - String componentId = id + '_' + store; - - for (UIComponent component : (List)getChildren()) - { - if (componentId.equals(component.getId())) - { - uiActions = (UIActions)component; - break; - } - } - - if (uiActions == null) - { - javax.faces.application.Application facesApp = FacesContext.getCurrentInstance().getApplication(); - uiActions = (UIActions)facesApp.createComponent("org.alfresco.faces.Actions"); - uiActions.setShowLink(false); - uiActions.getAttributes().put("styleClass", "inlineAction"); - uiActions.setId(componentId); - uiActions.setParent(this); - uiActions.setValue(id); - - this.getChildren().add(uiActions); - } - - return uiActions; - } // ------------------------------------------------------------------------------ // Strongly typed component property accessors diff --git a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationBrokenFiles.java b/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationBrokenFiles.java deleted file mode 100644 index 140bfd3802..0000000000 --- a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationBrokenFiles.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing - */ -package org.alfresco.web.ui.wcm.component; - -import java.io.IOException; -import java.util.List; - -import javax.faces.context.FacesContext; -import javax.faces.context.ResponseWriter; - -import org.alfresco.service.cmr.avm.AVMNodeDescriptor; -import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.web.app.Application; -import org.alfresco.web.bean.repository.Repository; -import org.alfresco.web.bean.wcm.AVMNode; -import org.alfresco.web.bean.wcm.AVMUtil; -import org.alfresco.web.bean.wcm.LinkValidationState; -import org.alfresco.web.config.ClientConfigElement; -import org.alfresco.web.ui.common.Utils; -import org.alfresco.web.ui.repo.component.UIActions; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * JSF component that shows the broken file information for a link - * validation report. - * - * @author gavinc - */ -public class UILinkValidationBrokenFiles extends AbstractLinkValidationReportComponent -{ - private boolean oddRow = true; - - private static Log logger = LogFactory.getLog(UILinkValidationBrokenFiles.class); - - // ------------------------------------------------------------------------------ - // Component implementation - - @Override - public String getFamily() - { - return "org.alfresco.faces.LinkValidationBrokenFiles"; - } - - @SuppressWarnings("unchecked") - @Override - public void encodeBegin(FacesContext context) throws IOException - { - if (isRendered() == false) - { - return; - } - - // get the link validation state object to get the data from - ResponseWriter out = context.getResponseWriter(); - LinkValidationState linkState = getValue(); - - if (logger.isDebugEnabled()) - logger.debug("Rendering broken files from state object: " + linkState); - - // render the list of broken files and their contained links - out.write("
"); - out.write(Application.getMessage(context, "files_with_broken_links")); - out.write("
"); - - List brokenFiles = linkState.getStaticFilesWithBrokenLinks(); - if (brokenFiles == null || brokenFiles.size() == 0) - { - renderNoItems(out, context); - } - else - { - UIActions actions = aquireUIActions("broken_file_actions", getValue().getStore()); - AVMService avmService = Repository.getServiceRegistry(context).getAVMService(); - int rootPathIndex = AVMUtil.buildSandboxRootPath(linkState.getStore()).length(); - String dns = AVMUtil.lookupStoreDNS(linkState.getStore()); - ClientConfigElement config = Application.getClientConfig(context); - String wcmDomain = config.getWCMDomain(); - String wcmPort = config.getWCMPort(); - - // render each broken file - for (String file : brokenFiles) - { - renderBrokenFile(context, out, file, linkState, actions, avmService, - rootPathIndex, wcmDomain, wcmPort, dns); - } - } - - out.write("
"); - } - - // ------------------------------------------------------------------------------ - // Helpers - - private void renderBrokenFile(FacesContext context, ResponseWriter out, - String file, LinkValidationState linkState, UIActions actions, - AVMService avmService, int rootPathIndex, String wcmDomain, - String wcmPort, String dns) - throws IOException - { - // gather the data to show for the file - String[] nameAndPath = this.getFileNameAndPath(file); - String fileName = nameAndPath[0]; - String filePath = nameAndPath[1]; - - // build the list of broken links for the file - String brokenLinks = getBrokenLinks(context, file, linkState); - - // render the row with the appropriate background style - out.write(""); - renderFile(out, context, fileName, filePath, brokenLinks); - out.write("
"); - - // setup the context for the actions - AVMNodeDescriptor desc = avmService.lookup(-1, file); - AVMNode node = new AVMNode(desc); - - String assetPath = file.substring(rootPathIndex); - String previewUrl = AVMUtil.buildAssetUrl(assetPath, wcmDomain, wcmPort, dns); - node.getProperties().put("previewUrl", previewUrl); - actions.setContext(node); - - // render the actions - Utils.encodeRecursive(context, actions); - - out.write("
"); - } -} - - - - diff --git a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationBrokenForms.java b/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationBrokenForms.java deleted file mode 100644 index 4911501eb7..0000000000 --- a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationBrokenForms.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing - */ -package org.alfresco.web.ui.wcm.component; - -import java.io.IOException; -import java.util.List; - -import javax.faces.context.FacesContext; -import javax.faces.context.ResponseWriter; - -import org.alfresco.service.cmr.avm.AVMNodeDescriptor; -import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.web.app.Application; -import org.alfresco.web.bean.repository.Repository; -import org.alfresco.web.bean.wcm.AVMNode; -import org.alfresco.web.bean.wcm.LinkValidationState; -import org.alfresco.web.ui.common.Utils; -import org.alfresco.web.ui.repo.component.UIActions; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * JSF component that shows the broken form information for a link - * validation report. - * - * @author gavinc - */ -public class UILinkValidationBrokenForms extends AbstractLinkValidationReportComponent -{ - private boolean oddRow = true; - - private static Log logger = LogFactory.getLog(UILinkValidationBrokenForms.class); - - // ------------------------------------------------------------------------------ - // Component implementation - - @Override - public String getFamily() - { - return "org.alfresco.faces.LinkValidationBrokenForms"; - } - - @SuppressWarnings("unchecked") - @Override - public void encodeBegin(FacesContext context) throws IOException - { - if (isRendered() == false) - { - return; - } - - // get the link validation state object to get the data from - ResponseWriter out = context.getResponseWriter(); - LinkValidationState linkState = getValue(); - - if (logger.isDebugEnabled()) - logger.debug("Rendering broken forms from state object: " + linkState); - - out.write("\n"); - - // render the list of broken files and their contained links - out.write("
"); - out.write(Application.getMessage(context, "forms_with_broken_links")); - out.write("
"); - - List brokenForms = linkState.getFormsWithBrokenLinks(); - if (brokenForms == null || brokenForms.size() == 0) - { - renderNoItems(out, context); - } - else - { - UIActions actions = aquireUIActions("broken_form_actions", getValue().getStore()); - AVMService avmService = Repository.getServiceRegistry(context).getAVMService(); - - for (String form : brokenForms) - { - renderBrokenForm(context, out, form, linkState, actions, avmService); - } - } - - out.write("
"); - } - - // ------------------------------------------------------------------------------ - // Helpers - - private void renderBrokenForm(FacesContext context, ResponseWriter out, - String file, LinkValidationState linkState, UIActions actions, - AVMService avmService) throws IOException - { - // get the web form name and path - String[] formNamePath = this.getFileNameAndPath(file); - String formName = formNamePath[0]; - String formPath = formNamePath[1]; - - // setup the context for the actions - AVMNodeDescriptor desc = avmService.lookup(-1, file); - AVMNode node = new AVMNode(desc); - actions.setContext(node); - - // generate a unique id for this form - String formId = this.getId() + "_" + desc.getId(); - - // render the row with the appropriate background style - out.write(""); - out.write("
"); - out.write(formName); - out.write("
"); - out.write(formPath); - out.write("
"); - out.write(Application.getMessage(context, "generated_files")); - out.write(":
"); - - out.write("
"); - out.write(" "); - - - - // render the actions - Utils.encodeRecursive(context, actions); - - out.write("
"); - } -} - - - - diff --git a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationFixedFiles.java b/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationFixedFiles.java deleted file mode 100644 index 5fa2f5e8a0..0000000000 --- a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationFixedFiles.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing - */ -package org.alfresco.web.ui.wcm.component; - -import java.io.IOException; -import java.util.List; - -import javax.faces.context.FacesContext; -import javax.faces.context.ResponseWriter; - -import org.alfresco.web.app.Application; -import org.alfresco.web.bean.wcm.LinkValidationState; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * JSF component that shows the fixed files for a link validation report. - * - * @author gavinc - */ -public class UILinkValidationFixedFiles extends AbstractLinkValidationReportComponent -{ - private boolean oddRow = true; - - private static Log logger = LogFactory.getLog(UILinkValidationFixedFiles.class); - - // ------------------------------------------------------------------------------ - // Component implementation - - @Override - public String getFamily() - { - return "org.alfresco.faces.LinkValidationFixedFiles"; - } - - @SuppressWarnings("unchecked") - @Override - public void encodeBegin(FacesContext context) throws IOException - { - if (isRendered() == false) - { - return; - } - - // get the link validation state object to get the data from - ResponseWriter out = context.getResponseWriter(); - LinkValidationState linkState = getValue(); - - if (logger.isDebugEnabled()) - logger.debug("Rendering fixed files from state object: " + linkState); - - // render the list of broken files and their contained links - out.write("
"); - out.write(Application.getMessage(context, "fixed_items")); - out.write("
"); - - int fixedItems = 0; - List fixedFiles = linkState.getFixedFiles(); - List fixedForms = linkState.getFixedForms(); - if (fixedFiles != null) - { - fixedItems = fixedFiles.size(); - } - if (fixedForms != null) - { - fixedItems += fixedForms.size(); - } - - if (fixedItems == 0) - { - renderNoItems(out, context); - } - else - { - for (String file : fixedFiles) - { - renderFixedItem(context, out, file, linkState); - } - - for (String file : fixedForms) - { - renderFixedItem(context, out, file, linkState); - } - } - - out.write("
"); - } - - // ------------------------------------------------------------------------------ - // Helpers - - private void renderFixedItem(FacesContext context, ResponseWriter out, - String file, LinkValidationState linkState) throws IOException - { - // gather the data to show for the file - String[] nameAndPath = this.getFileNameAndPath(file); - String fileName = nameAndPath[0]; - String filePath = nameAndPath[1]; - - // render the row with the appropriate background style - out.write(""); - renderFile(out, context, fileName, filePath, null); - out.write(""); - } -} - - - - diff --git a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationReport.java b/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationReport.java new file mode 100644 index 0000000000..9185b9ed09 --- /dev/null +++ b/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationReport.java @@ -0,0 +1,948 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.web.ui.wcm.component; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.List; +import java.util.ResourceBundle; + +import javax.faces.component.UICommand; +import javax.faces.component.UIComponent; +import javax.faces.component.UIParameter; +import javax.faces.context.FacesContext; +import javax.faces.context.ResponseWriter; +import javax.faces.el.MethodBinding; +import javax.faces.el.ValueBinding; + +import org.alfresco.config.JNDIConstants; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.wcm.AVMNode; +import org.alfresco.web.bean.wcm.AVMUtil; +import org.alfresco.web.bean.wcm.LinkValidationState; +import org.alfresco.web.config.ClientConfigElement; +import org.alfresco.web.ui.common.ComponentConstants; +import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIActionLink; +import org.alfresco.web.ui.repo.component.UIActions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * JSF component that renders the results of a link validation report. + * + * @author gavinc + */ +public class UILinkValidationReport extends AbstractLinkValidationReportComponent +{ + public static final String DEFAULT_INTIAL_TAB = "staticTab"; + + private String initialTab; + private Boolean itemsExpanded; + private boolean oddRow = true; + + private static Log logger = LogFactory.getLog(UILinkValidationReport.class); + + // ------------------------------------------------------------------------------ + // Component implementation + + @Override + public String getFamily() + { + return "org.alfresco.faces.LinkValidationReport"; + } + + // ------------------------------------------------------------------------------ + // Component implementation + + @SuppressWarnings("unchecked") + @Override + public void restoreState(FacesContext context, Object state) + { + Object values[] = (Object[])state; + // standard component attributes are restored by the super class + super.restoreState(context, values[0]); + this.itemsExpanded = (Boolean)values[1]; + this.initialTab = (String)values[2]; + } + + @Override + public Object saveState(FacesContext context) + { + Object values[] = new Object[3]; + // standard component attributes are saved by the super class + values[0] = super.saveState(context); + values[1] = this.itemsExpanded; + values[2] = this.initialTab; + return values; + } + + @SuppressWarnings("unchecked") + @Override + public void encodeBegin(FacesContext context) throws IOException + { + if (isRendered() == false) + { + return; + } + + // get the link validation state object to get the data from + ResourceBundle bundle = Application.getBundle(context); + ResponseWriter out = context.getResponseWriter(); + LinkValidationState linkState = getValue(); + + if (logger.isDebugEnabled()) + logger.debug("Rendering report from state object: " + linkState); + + if (linkState.getError() == null && linkState.getNumberBrokenLinks() > 0) + { + // determine whether the generated files and broken links sections + // should be expanded + boolean sectionsExpanded = this.getItemsExpanded(); + + // render the required JavaScript + String selectedTab = this.getInitialTab(); + out.write("\n"); + + out.write("\n"); + + out.write("\n"); + + // gather count data for tab titles + int numStaticFiles = linkState.getStaticFilesWithBrokenLinks().size(); + int numForms = linkState.getFormsWithBrokenLinks().size(); + int numBrokenFileLinks = linkState.getNoBrokenLinksInStaticFiles(); + int numBrokenFormLinks = linkState.getNoBrokenLinksInForms(); + int numFixedItems = linkState.getNumberFixedItems(); + + String pattern = bundle.getString("static_tab"); + String staticTabTitle = MessageFormat.format(pattern, + new Object[] {numStaticFiles}); + + pattern = bundle.getString("generated_tab"); + String generatedTabTitle = MessageFormat.format(pattern, + new Object[] {numForms}); + + // render the tabs + out.write("
"); + + // reset the oddRow flag + this.oddRow = true; + + // render the list of broken files and their contained links + out.write(""); + + // reset the oddRow flag + this.oddRow = true; + + // render the list of broken forms, the files it generated and their contained links + out.write(""); + + // reset the oddRow flag + this.oddRow = true; + + // render the list of fixed items + out.write(""); + } + else + { + out.write("
 
"); + } + } + + // ------------------------------------------------------------------------------ + // Strongly typed component property accessors + + /** + * @return true if broken links and generated files should be expanded + */ + public boolean getItemsExpanded() + { + ValueBinding vb = getValueBinding("itemsExpanded"); + if (vb != null) + { + this.itemsExpanded = (Boolean)vb.getValue(getFacesContext()); + } + + if (this.itemsExpanded == null) + { + this.itemsExpanded = Boolean.FALSE; + } + + return this.itemsExpanded.booleanValue(); + } + + /** + * @param value true if broken links and generated files should be expanded + */ + public void setItemsExpanded(boolean value) + { + this.itemsExpanded = value; + } + + /** + * @return The tab that will be initially selected + */ + public String getInitialTab() + { + ValueBinding vb = getValueBinding("initialTab"); + if (vb != null) + { + this.initialTab = (String)vb.getValue(getFacesContext()); + } + + if (this.initialTab == null) + { + this.initialTab = DEFAULT_INTIAL_TAB; + } + + return this.initialTab; + } + + /** + * @param tab The initial tab to be selected + */ + public void setItemsExpanded(String tab) + { + this.initialTab = tab; + } + + // ------------------------------------------------------------------------------ + // Helpers + + protected void renderBrokenFile(FacesContext context, ResponseWriter out, + String file, LinkValidationState linkState, UIActions actions, + AVMService avmService, int rootPathIndex, String wcmDomain, + String wcmPort, String dns, boolean brokenLinksExpanded) + throws IOException + { + // gather the data to show for the file + String[] nameAndPath = this.getFileNameAndPath(file); + String fileName = nameAndPath[0]; + String filePath = nameAndPath[1]; + + // render the row with the appropriate background style + out.write("
"); + + // setup the context for the actions + AVMNodeDescriptor desc = avmService.lookup(-1, file); + AVMNode node = new AVMNode(desc); + + String assetPath = file.substring(rootPathIndex); + String previewUrl = AVMUtil.buildAssetUrl(assetPath, wcmDomain, wcmPort, dns); + node.getProperties().put("previewUrl", previewUrl); + actions.setContext(node); + + // render the actions + Utils.encodeRecursive(context, actions); + + out.write("
"); + + // render the file details + String brokenLinks = getBrokenLinks(context, file, linkState); + int numBrokenLinks = linkState.getBrokenLinksForFile(file).size(); + renderFileDetails(out, context, fileName, filePath, brokenLinks, + numBrokenLinks, brokenLinksExpanded); + + out.write("
"); + } + + protected void renderBrokenForm(FacesContext context, ResponseWriter out, + String file, LinkValidationState linkState, UIActions actions, + AVMService avmService, boolean generatedFilesExpanded) throws IOException + { + // get the web form name and path + String[] formNamePath = this.getFileNameAndPath(file); + String formName = formNamePath[0]; + String formPath = formNamePath[1]; + + // setup the context for the actions + AVMNodeDescriptor desc = avmService.lookup(-1, file); + AVMNode node = new AVMNode(desc); + actions.setContext(node); + + // generate a unique id for this form + String formId = this.getId() + "_" + desc.getId(); + + // render the row with the appropriate background style + out.write("
"); + + // render the actions + Utils.encodeRecursive(context, actions); + + out.write("
"); + + // render the generated files + List brokenFiles = linkState.getBrokenFilesByForm(file); + + out.write("
"); + out.write(formName); + out.write("
"); + out.write(formPath); + out.write("
"); + out.write(Application.getMessage(context, "generated_files")); + out.write(" ("); + out.write(Integer.toString(brokenFiles.size())); + out.write(")
"); + } + + protected void renderFixedItem(FacesContext context, ResponseWriter out, + String file, LinkValidationState linkState) throws IOException + { + // gather the data to show for the file + String[] nameAndPath = this.getFileNameAndPath(file); + String fileName = nameAndPath[0]; + String filePath = nameAndPath[1]; + + // render the row with the appropriate background style + out.write("
"); + + // render the file details + renderFileDetails(out, context, fileName, filePath, null, 0, false); + out.write("
"); + } + + /** + * Returns the name and path for the given avm path + * + * @param avmPath The path to split + * @return A String array with the name in the first position and the path in the + * second position. + */ + protected String[] getFileNameAndPath(String avmPath) + { + String fileName = avmPath; + String filePath = avmPath; + + int idx = avmPath.lastIndexOf("/"); + if (idx != -1) + { + fileName = avmPath.substring(idx+1); + + int appbaseIdx = avmPath.indexOf(JNDIConstants.DIR_DEFAULT_APPBASE); + if (appbaseIdx != -1) + { + filePath = avmPath.substring(appbaseIdx+JNDIConstants.DIR_DEFAULT_APPBASE.length(), idx); + } + else + { + filePath = avmPath.substring(0, idx); + } + } + + return new String[] {fileName, filePath}; + } + + /** + * Constructs a comma separated list of broken links for the given avm path + * + * @param avmPath The avm path to get the broken links for + * @param linkState The current link valiation state + * @return Comma separated list of broken links + */ + protected String getBrokenLinks(FacesContext context, String avmPath, LinkValidationState linkState) + { + List brokenLinks = linkState.getBrokenLinksForFile(avmPath); + StringBuilder builder = new StringBuilder(); + boolean first = true; + for (String link : brokenLinks) + { + if (first == false) + { + builder.append("
"); + } + else + { + first = false; + } + + builder.append(""); + builder.append(parseBrokenLink(link)); + } + + return builder.toString(); + } + + /** + * Removes the virtaulisation server host name from the link if appropriate + * + * @param linkUrl The URL that is broken + * @return Parsed URL + */ + protected String parseBrokenLink(String linkUrl) + { + String link = linkUrl; + + if (linkUrl.startsWith("http://") && linkUrl.indexOf("www--sandbox") != -1) + { + // remove the virtualisation server host name + int idx = linkUrl.indexOf("/", 7); + if (idx != -1) + { + link = linkUrl.substring(idx); + } + } + + // truncate the link if it is longer than 60 chars + String title = link; + if (link.length() > 65) + { + link = link.substring(0, 30) + " ... " + + link.substring(link.length()-30); + } + + return " " + link + ""; + } + + protected void renderTabHeader(ResponseWriter out, FacesContext context, + String tabId, boolean showExpandCollapseControls) throws IOException + { + out.write("
"); + out.write("
"); + + if (showExpandCollapseControls) + { + if (this.getItemsExpanded()) + { + UICommand collapseAllAction = aquireCollapseAllAction(context, tabId); + Utils.encodeRecursive(context, collapseAllAction); + } + else + { + UICommand expandAllAction = aquireExpandAllAction(context, tabId); + Utils.encodeRecursive(context, expandAllAction); + } + } + else + { + out.write(" "); + } + + out.write("
 
"); + } + + protected void renderFileDetails(ResponseWriter out, FacesContext context, + String fileName, String filePath, String brokenLinks, + int numBrokenLinks, boolean brokenLinksExpanded) throws IOException + { + // generate a unique id for the file + String fileId = "file" + Integer.toString((filePath + fileName).hashCode()); + + out.write("
"); + out.write(fileName); + out.write("
"); + out.write(filePath); + out.write("
"); + + if (brokenLinks != null && brokenLinks.length() > 0) + { + out.write("
"); + out.write(Application.getMessage(context, "broken_links")); + out.write(" ("); + out.write(Integer.toString(numBrokenLinks)); + out.write(")
"); + + out.write(""); + } + + out.write("
"); + } + + /** + * Renders the "No items to display" message + * + * @param out ResponseWriter instance to write to + * @param context FacesContext + * @throws IOException + */ + protected void renderNoItems(ResponseWriter out, FacesContext context) + throws IOException + { + out.write("
"); + out.write(Application.getMessage(context, "no_items")); + out.write("
"); + } + + /** + * Returns the icon to use given a file name + * + * @param fileName File name to find an icon for + * @return The path to the icon to use + */ + protected String getIcon(String fileName) + { + // work out what icon to use + String icon = "/images/filetypes32/html.gif"; + String ext = ""; + int idx = fileName.indexOf("."); + if (idx != -1) + { + ext = fileName.substring(idx); + } + + if (ext.equals(".xml")) + { + icon = "/images/icons/webform_large.gif"; + } + + return icon; + } + + /** + * Aquire the UIActions component for the specified action group ID. + * Search for the component in the child list or create as needed. + * + * @param id ActionGroup id of the UIActions component + * + * @return UIActions component + */ + @SuppressWarnings("unchecked") + protected UIActions aquireFileActions(String id, String store) + { + UIActions uiActions = null; + String componentId = id + '_' + store; + + for (UIComponent component : (List)getChildren()) + { + if (componentId.equals(component.getId())) + { + uiActions = (UIActions)component; + break; + } + } + + if (uiActions == null) + { + javax.faces.application.Application facesApp = FacesContext.getCurrentInstance().getApplication(); + uiActions = (UIActions)facesApp.createComponent("org.alfresco.faces.Actions"); + uiActions.setShowLink(false); + uiActions.getAttributes().put("styleClass", "inlineAction"); + uiActions.setId(componentId); + uiActions.setParent(this); + uiActions.setValue(id); + + this.getChildren().add(uiActions); + } + + return uiActions; + } + + @SuppressWarnings("unchecked") + protected UICommand aquireUpdateStatusAction(FacesContext context, String actionId) + { + UICommand action = null; + + // try find the action as a child of this component + for (UIComponent component : (List)getChildren()) + { + if (actionId.equals(component.getId())) + { + action = (UICommand)component; + break; + } + } + + if (action == null) + { + // create the action and add as a child component + javax.faces.application.Application facesApp = context.getApplication(); + action = (UICommand)facesApp.createComponent(UICommand.COMPONENT_TYPE); + action.setId(actionId); + action.setValue(Application.getMessage(context, "update_status")); + MethodBinding binding = facesApp.createMethodBinding("#{DialogManager.bean.updateStatus}", + new Class[] {}); + action.setAction(binding); + this.getChildren().add(action); + } + + return action; + } + + @SuppressWarnings("unchecked") + protected UIActionLink aquireExpandAllAction(FacesContext context, String tabId) + { + UIActionLink action = null; + String actionId = "expand_" + tabId; + + // try find the action as a child of this component + for (UIComponent component : (List)getChildren()) + { + if (actionId.equals(component.getId())) + { + action = (UIActionLink)component; + break; + } + } + + if (action == null) + { + // create the action and add as a child component + javax.faces.application.Application facesApp = context.getApplication(); + action = (UIActionLink)facesApp.createComponent(UIActions.COMPONENT_ACTIONLINK); + action.setId(actionId); + action.setValue(Application.getMessage(context, "expand_all")); + MethodBinding binding = facesApp.createMethodBinding("#{DialogManager.bean.toggleSections}", + new Class[] {javax.faces.event.ActionEvent.class}); + action.setActionListener(binding); + + // add a parameter to indicate what tab is being expanded + UIParameter param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER); + param.setId(actionId + "_param"); + param.setName("tab"); + param.setValue(tabId); + action.getChildren().add(param); + + this.getChildren().add(action); + } + + return action; + } + + @SuppressWarnings("unchecked") + protected UIActionLink aquireCollapseAllAction(FacesContext context, String tabId) + { + UIActionLink action = null; + String actionId = "collapse_" + tabId; + + // try find the action as a child of this component + for (UIComponent component : (List)getChildren()) + { + if (actionId.equals(component.getId())) + { + action = (UIActionLink)component; + break; + } + } + + if (action == null) + { + // create the action and add as a child component + javax.faces.application.Application facesApp = context.getApplication(); + action = (UIActionLink)facesApp.createComponent(UIActions.COMPONENT_ACTIONLINK); + action.setId(actionId); + action.setValue(Application.getMessage(context, "collapse_all")); + MethodBinding binding = facesApp.createMethodBinding("#{DialogManager.bean.toggleSections}", + new Class[] {javax.faces.event.ActionEvent.class}); + action.setActionListener(binding); + + // add a parameter to indicate what tab is being expanded + UIParameter param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER); + param.setId(actionId + "_param"); + param.setName("tab"); + param.setValue(tabId); + action.getChildren().add(param); + + this.getChildren().add(action); + } + + return action; + } +} + + + + diff --git a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationSummary.java b/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationSummary.java index 5249816069..d280488412 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationSummary.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UILinkValidationSummary.java @@ -27,20 +27,15 @@ package org.alfresco.web.ui.wcm.component; import java.io.IOException; import java.text.MessageFormat; import java.util.Date; -import java.util.List; import java.util.ResourceBundle; -import javax.faces.component.UICommand; -import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; -import javax.faces.el.MethodBinding; import org.alfresco.web.app.Application; import org.alfresco.web.bean.wcm.LinkValidationState; import org.alfresco.web.ui.common.PanelGenerator; import org.alfresco.web.ui.common.Utils; -import org.alfresco.web.ui.common.component.UIActionLink; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -80,73 +75,108 @@ public class UILinkValidationSummary extends AbstractLinkValidationReportCompone if (logger.isDebugEnabled()) logger.debug("Rendering summary from state object: " + linkState); + // determine what to display i.e. surrounding panel and title + boolean showPanel = true; + boolean showTitle = true; + + Object showPanelObj = this.getAttributes().get("showPanel"); + if (showPanelObj instanceof Boolean) + { + showPanel = ((Boolean)showPanelObj).booleanValue(); + } + + Object showTitleObj = this.getAttributes().get("showTitle"); + if (showTitleObj instanceof Boolean) + { + showTitle = ((Boolean)showTitleObj).booleanValue(); + } + + if (showPanel) + { + // render the summary area with a surrounding panel + PanelGenerator.generatePanelStart(out, context.getExternalContext().getRequestContextPath(), + "innerwhite", "white"); + } + + String styleClass = (String)this.getAttributes().get("styleClass"); + if (styleClass == null || styleClass.length() == 0) + { + styleClass = "linkValidationSummaryPanel"; + } + + out.write("
"); + + if (showTitle) + { + out.write("
"); + out.write(bundle.getString("report_summary")); + out.write("
"); + } + if (linkState.getError() == null) { - Object initialCheckOnly = this.getAttributes().get("initialCheckOnly"); - if (initialCheckOnly instanceof Boolean && - ((Boolean)initialCheckOnly).booleanValue()) + // render the main summary info + + int latestVersion = linkState.getLatestSnapshotVersion(); + int baseVersion = linkState.getBaseSnapshotVersion(); + + String pattern = bundle.getString("link_check_completed_at"); + Date checkAt = linkState.getCheckCompletedAt(); + String checkTime = Utils.getDateTimeFormat(context).format(checkAt); + String checkTimeSummary = MessageFormat.format(pattern, + new Object[] {checkTime, baseVersion}); + + out.write("
"); + out.write(checkTimeSummary); + + // NOTE: Whenever latestVersion > baseVersion, link validation is "behind". + if (latestVersion > baseVersion) { - out.write("
"); - renderInitialCheckSummary(context, out, linkState, bundle); - out.write("
"); + out.write(" ( "); + out.write(bundle.getString("link_check_not_latest")); + out.write(")"); + } + + pattern = bundle.getString("link_check_items_found"); + String checkedSummary = MessageFormat.format(pattern, + new Object[] {linkState.getNumberFilesChecked(), + linkState.getNumberLinksChecked()}); + + pattern = bundle.getString("link_check_items_broken"); + String brokenSummary = MessageFormat.format(pattern, + new Object[] {linkState.getNumberBrokenLinks(), + linkState.getNumberBrokenFiles()}); + + out.write("
"); + out.write(checkedSummary); + out.write("  "); + out.write(bundle.getString("link_check_no_broken")); } else { - String pattern = bundle.getString("files_links_still_broken"); - String stillBroken = MessageFormat.format(pattern, - new Object[] {linkState.getNumberBrokenLinks(), linkState.getNumberBrokenFiles()}); - pattern = bundle.getString("broken_items_fixed"); - String linksFixed = MessageFormat.format(pattern, - new Object[] {linkState.getNumberFixedItems()}); - - // get the action to update the current status - UICommand updateStatusAction = aquireAction(context, "update_status_" + linkState.getStore()); - - - out.write("
"); - - // render the summary area with a surrounding panel - PanelGenerator.generatePanelStart(out, context.getExternalContext().getRequestContextPath(), - "innerwhite", "white"); - - out.write("
"); - out.write(bundle.getString("summary")); - out.write("
"); - out.write(""); - out.write("
"); - out.write(bundle.getString("initial_check")); - out.write(":"); - renderInitialCheckSummary(context, out, linkState, bundle); - out.write("
"); - out.write(bundle.getString("current_status")); - out.write(":
 "); - out.write(stillBroken); - out.write("   "); - out.write(linksFixed); - out.write("  "); - Utils.encodeRecursive(context, updateStatusAction); - out.write("
"); - - // finish the surrounding panel - PanelGenerator.generatePanelEnd(out, context.getExternalContext().getRequestContextPath(), - "innerwhite"); - - out.write("
"); + out.write("/images/icons/warning.gif' /> "); + out.write(brokenSummary); } + out.write("
"); } else { - String pattern = bundle.getString("files_links_checked_error"); - Date initialCheck = linkState.getInitialCheckCompletedAt(); + // render the error that occurred + String pattern = bundle.getString("link_check_error"); + Date initialCheck = linkState.getCheckCompletedAt(); String initialCheckTime = Utils.getDateTimeFormat(context).format(initialCheck); String initialCheckSummary = MessageFormat.format(pattern, new Object[] {initialCheckTime}); - out.write("
"); out.write(initialCheckSummary); out.write(" "); String err = linkState.getError().getMessage(); @@ -158,61 +188,16 @@ public class UILinkValidationSummary extends AbstractLinkValidationReportCompone { out.write(err); } - out.write("
"); + out.write(""); } - } - - protected void renderInitialCheckSummary(FacesContext context, - ResponseWriter out, LinkValidationState linkState, - ResourceBundle bundle) throws IOException - { - String pattern = bundle.getString("files_links_checked"); - Date initialCheck = linkState.getInitialCheckCompletedAt(); - String initialCheckTime = Utils.getDateTimeFormat(context).format(initialCheck); - String initialCheckSummary = MessageFormat.format(pattern, - new Object[] {initialCheckTime, linkState.getInitialNumberFilesChecked(), - linkState.getInitialNumberLinksChecked()}); - pattern = bundle.getString("files_links_broken"); - String initialBrokenSummary = MessageFormat.format(pattern, - new Object[] {linkState.getInitialNumberBrokenLinks(), linkState.getInitialNumberBrokenFiles()}); - out.write("
"); - out.write(initialCheckSummary); - out.write("
 "); - out.write(initialBrokenSummary); out.write("
"); - } - - @SuppressWarnings("unchecked") - private UICommand aquireAction(FacesContext context, String actionId) - { - UICommand action = null; - // try find the action as a child of this component - for (UIComponent component : (List)getChildren()) + if (showPanel) { - if (actionId.equals(component.getId())) - { - action = (UICommand)component; - break; - } + // finish the surrounding panel + PanelGenerator.generatePanelEnd(out, context.getExternalContext().getRequestContextPath(), + "innerwhite"); } - - if (action == null) - { - // create the action and add as a child component - javax.faces.application.Application facesApp = context.getApplication(); - action = (UICommand)facesApp.createComponent(UICommand.COMPONENT_TYPE); - action.setId(actionId); - action.setValue(Application.getMessage(context, "update_status")); - MethodBinding binding = facesApp.createMethodBinding("#{DialogManager.bean.updateStatus}", - new Class[] {}); - action.setAction(binding); - this.getChildren().add(action); - } - - return action; } } 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 ca99e60385..1e0ffb77a3 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java @@ -375,7 +375,7 @@ public class UIUserSandboxes extends SelfRenderingComponent out.write(")"); // Direct actions for a sandbox... - Map params = new HashMap(3); + Map params = new HashMap(6); params.put("store", mainStore); params.put("username", username); params.put("webapp", this.getWebapp()); diff --git a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationBrokenFilesTag.java b/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationBrokenFilesTag.java deleted file mode 100644 index d223a1657e..0000000000 --- a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationBrokenFilesTag.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.web.ui.wcm.tag; - -import javax.faces.component.UIComponent; - -import org.alfresco.web.ui.common.tag.HtmlComponentTag; - -/** - * Tag class for adding the UILinkValidationBrokenFiles component to a JSP page. - * - * @author gavinc - */ -public class LinkValidationBrokenFilesTag extends HtmlComponentTag -{ - private String value; - - /** - * @see javax.faces.webapp.UIComponentTag#getComponentType() - */ - public String getComponentType() - { - return "org.alfresco.faces.LinkValidationBrokenFiles"; - } - - /** - * @see javax.faces.webapp.UIComponentTag#getRendererType() - */ - public String getRendererType() - { - return null; - } - - /** - * @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent) - */ - protected void setProperties(UIComponent component) - { - super.setProperties(component); - - setStringProperty(component, "value", this.value); - } - - /** - * @see org.alfresco.web.ui.common.tag.HtmlComponentTag#release() - */ - public void release() - { - super.release(); - this.value = null; - } - - /** - * @param value the value (the list of servers to deploy to) - */ - public void setValue(String value) - { - this.value = value; - } -} diff --git a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationFixedFilesTag.java b/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationFixedFilesTag.java deleted file mode 100644 index 094efeca57..0000000000 --- a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationFixedFilesTag.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.web.ui.wcm.tag; - -import javax.faces.component.UIComponent; - -import org.alfresco.web.ui.common.tag.HtmlComponentTag; - -/** - * Tag class for adding the UILinkValidationFixedFiles component to a JSP page. - * - * @author gavinc - */ -public class LinkValidationFixedFilesTag extends HtmlComponentTag -{ - private String value; - - /** - * @see javax.faces.webapp.UIComponentTag#getComponentType() - */ - public String getComponentType() - { - return "org.alfresco.faces.LinkValidationFixedFiles"; - } - - /** - * @see javax.faces.webapp.UIComponentTag#getRendererType() - */ - public String getRendererType() - { - return null; - } - - /** - * @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent) - */ - protected void setProperties(UIComponent component) - { - super.setProperties(component); - - setStringProperty(component, "value", this.value); - } - - /** - * @see org.alfresco.web.ui.common.tag.HtmlComponentTag#release() - */ - public void release() - { - super.release(); - this.value = null; - } - - /** - * @param value the value (the list of servers to deploy to) - */ - public void setValue(String value) - { - this.value = value; - } -} diff --git a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationBrokenFormsTag.java b/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationReportTag.java similarity index 72% rename from source/java/org/alfresco/web/ui/wcm/tag/LinkValidationBrokenFormsTag.java rename to source/java/org/alfresco/web/ui/wcm/tag/LinkValidationReportTag.java index 85a6d59038..564018e294 100644 --- a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationBrokenFormsTag.java +++ b/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationReportTag.java @@ -29,20 +29,22 @@ import javax.faces.component.UIComponent; import org.alfresco.web.ui.common.tag.HtmlComponentTag; /** - * Tag class for adding the UILinkValidationBrokenForms component to a JSP page. + * Tag class for adding the UILinkValidationReport component to a JSP page. * * @author gavinc */ -public class LinkValidationBrokenFormsTag extends HtmlComponentTag +public class LinkValidationReportTag extends HtmlComponentTag { private String value; + private String itemsExpanded; + private String initialTab; /** * @see javax.faces.webapp.UIComponentTag#getComponentType() */ public String getComponentType() { - return "org.alfresco.faces.LinkValidationBrokenForms"; + return "org.alfresco.faces.LinkValidationReport"; } /** @@ -61,6 +63,8 @@ public class LinkValidationBrokenFormsTag extends HtmlComponentTag super.setProperties(component); setStringProperty(component, "value", this.value); + setStringProperty(component, "initialTab", this.initialTab); + setBooleanProperty(component, "itemsExpanded", this.itemsExpanded); } /** @@ -70,6 +74,8 @@ public class LinkValidationBrokenFormsTag extends HtmlComponentTag { super.release(); this.value = null; + this.itemsExpanded = null; + this.initialTab = null; } /** @@ -79,4 +85,21 @@ public class LinkValidationBrokenFormsTag extends HtmlComponentTag { this.value = value; } + + /** + * @param value true to render the report with all broken links and + * generated files expanded + */ + public void setItemsExpanded(String value) + { + this.itemsExpanded = value; + } + + /** + * @param initialTab The initial tab to be selected + */ + public void setInitialTab(String initialTab) + { + this.initialTab = initialTab; + } } diff --git a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationSummaryTag.java b/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationSummaryTag.java index da8ab72849..a2337594ad 100644 --- a/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationSummaryTag.java +++ b/source/java/org/alfresco/web/ui/wcm/tag/LinkValidationSummaryTag.java @@ -36,7 +36,8 @@ import org.alfresco.web.ui.common.tag.HtmlComponentTag; public class LinkValidationSummaryTag extends HtmlComponentTag { private String value; - private String initialCheckOnly; + private String showPanel; + private String showTitle; /** * @see javax.faces.webapp.UIComponentTag#getComponentType() @@ -62,7 +63,8 @@ public class LinkValidationSummaryTag extends HtmlComponentTag super.setProperties(component); setStringProperty(component, "value", this.value); - setBooleanProperty(component, "initialCheckOnly", this.initialCheckOnly); + setBooleanProperty(component, "showPanel", this.showPanel); + setBooleanProperty(component, "showTitle", this.showTitle); } /** @@ -72,7 +74,8 @@ public class LinkValidationSummaryTag extends HtmlComponentTag { super.release(); this.value = null; - this.initialCheckOnly = null; + this.showPanel = null; + this.showTitle = null; } /** @@ -84,10 +87,18 @@ public class LinkValidationSummaryTag extends HtmlComponentTag } /** - * @param initialCheckOnly true will make the component only show the initial check summary info + * @param showPanel false to hide the surrounding panel */ - public void setInitialCheckOnly(String initialCheckOnly) + public void setShowPanel(String showPanel) { - this.initialCheckOnly = initialCheckOnly; + this.showPanel = showPanel; + } + + /** + * @param showTitle false to hide the title within the panel + */ + public void setShowTitle(String showTitle) + { + this.showTitle = showTitle; } } diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index fe4f0b5b08..c79accbeb1 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -2035,10 +2035,6 @@ avmSyncService #{AVMSyncService} - - avmSubmittedAspect - #{AVMSubmittedAspect} - avmBrowseBean #{AVMBrowseBean} @@ -2639,10 +2635,6 @@ avmSyncService #{AVMSyncService} - - avmSubmittedAspect - #{AVMSubmittedAspect} - avmBrowseBean #{AVMBrowseBean} @@ -2700,10 +2692,6 @@ avmSyncService #{AVMSyncService} - - avmSubmittedAspect - #{AVMSubmittedAspect} - avmBrowseBean #{AVMBrowseBean} @@ -3433,10 +3421,6 @@ avmBrowseBean #{AVMBrowseBean} - - avmSubmittedAspect - #{AVMSubmittedAspect} - workflowService #{WorkflowService} diff --git a/source/web/WEB-INF/faces-config-wcm.xml b/source/web/WEB-INF/faces-config-wcm.xml index 589d14f801..f385d9be5f 100644 --- a/source/web/WEB-INF/faces-config-wcm.xml +++ b/source/web/WEB-INF/faces-config-wcm.xml @@ -50,18 +50,8 @@ - org.alfresco.faces.LinkValidationBrokenFiles - org.alfresco.web.ui.wcm.component.UILinkValidationBrokenFiles - - - - org.alfresco.faces.LinkValidationBrokenForms - org.alfresco.web.ui.wcm.component.UILinkValidationBrokenForms - - - - org.alfresco.faces.LinkValidationFixedFiles - org.alfresco.web.ui.wcm.component.UILinkValidationFixedFiles + org.alfresco.faces.LinkValidationReport + org.alfresco.web.ui.wcm.component.UILinkValidationReport diff --git a/source/web/WEB-INF/wcm.tld b/source/web/WEB-INF/wcm.tld index 64354ccb27..6e873af69e 100644 --- a/source/web/WEB-INF/wcm.tld +++ b/source/web/WEB-INF/wcm.tld @@ -303,10 +303,17 @@ - initialCheckOnly + showPanel false true - Only shows the initial check summary if set to true, false by default + Hides the surrounding panel if set to false, true by default + + + + showTitle + false + true + Hides the summary report title if set to false, true by default @@ -322,14 +329,21 @@ true Flag to determine whether component should be rendered + + + styleClass + false + true + CSS class to apply to the summary panel (applies to outer div element) + - linkValidationBrokenFiles - org.alfresco.web.ui.wcm.tag.LinkValidationBrokenFilesTag + linkValidationReport + org.alfresco.web.ui.wcm.tag.LinkValidationReportTag JSP - Link Validation Broken Files - Displays broken file information for a link validation report + Link Validation Report + Displays the results of a link validation report value @@ -351,63 +365,22 @@ true Flag to determine whether component should be rendered - - - - linkValidationBrokenForms - org.alfresco.web.ui.wcm.tag.LinkValidationBrokenFormsTag - JSP - Link Validation Broken Forms - Displays broken form information for a link validation report - value - true + itemsExpanded + false true - The link validation state object holding the report data + + Flag to determine whether component should render the broken + links and generated files sections expanded + - id + initialTab false true - The component identifier for this component - - - - rendered - false - true - Flag to determine whether component should be rendered - - - - - linkValidationFixedFiles - org.alfresco.web.ui.wcm.tag.LinkValidationFixedFilesTag - JSP - Link Validation Fixed Files - Displays the list of files fixed since the initial run of a link validation report - - - value - true - true - The link validation state object holding the report data - - - - id - false - true - The component identifier for this component - - - - rendered - false - true - Flag to determine whether component should be rendered + The tab to be initially selected diff --git a/source/web/css/main.css b/source/web/css/main.css index ddf6af6393..ef0a624a8c 100644 --- a/source/web/css/main.css +++ b/source/web/css/main.css @@ -719,6 +719,90 @@ a.sidebarButtonLink, a.sidebarButtonLink:link, a.sidebarButtonLink:visited white-space: nowrap; } +.tabs +{ + width: 100%; + line-height: 1.5em; +} + +.tabs ul +{ + margin: 0px; + padding: 10px 10px 0px 0px; + list-style: none; +} + +.tabs li +{ + display: inline; + margin: 0px; + padding: 0px; +} + +.tabs a +{ + float: left; + background: url("../images/parts/tab_left.gif") no-repeat left top; + margin: 0px; + padding: 0px 0px 0px 4px; + text-decoration: none; + cursor: pointer; +} + +.tabs a:hover +{ + text-decoration: none; +} + +.tabs a span +{ + float: left; + display: block; + background: url("../images/parts/tab_right.gif") no-repeat right top; + padding: 5px 10px 4px 4px; + margin-right: 2px; + color: #627EB7; +} + +.tabs .selectedTab a +{ + background:url("../images/parts/tab_left_selected.gif") no-repeat left top; +} + +.tabs .selectedTab a span +{ + background:url("../images/parts/tab_right_selected.gif") no-repeat right top; + color: white; +} + +.tabs span.tabLabel +{ + font-weight: bold; + float:left; + display: block; + color: #627EB7; + padding: 4px 6px 0px 6px; +} + +.tabs span.tabButton +{ + float:left; + display: block; + color: #627EB7; + padding: 3px 0px 0px 15px; +} + +.expandCollapseControls +{ + float: left; + padding-top: 3px; +} + +.incDecControls +{ + text-align: right; +} + .linkValidationProgressPanel { width: 100%; @@ -736,68 +820,176 @@ a.sidebarButtonLink, a.sidebarButtonLink:link, a.sidebarButtonLink:visited font-size: 11px; } -.linkValidationReportTitle -{ - color: #004488; - font-size: 14px; - font-weight: bold; - padding-bottom: 8px; -} - -.linkValidationReportSubTitle -{ - color: #004488; - font-weight: bold; - font-size: 11px; - padding-right: 8px; -} - .linkValidationSummaryPanel { - margin: 6px; - margin-top: 3px; - padding: 8px; - background-color: white; + text-align: center; +} + +.linkValidationSummaryPanel img +{ + vertical-align: -4px; +} + +.linkValidationSummaryTitle +{ + font-weight: bold; + font-size: 12px; + padding-bottom: 7px; +} + +.linkValSummaryText +{ + padding-bottom: 4px; +} + +.linkValidationSummaryPanelTask +{ + text-align: left; + margin-bottom: 10px; + margin-left: 4px; +} + +.linkValidationSummaryPanelTask img +{ + vertical-align: -4px; +} - _width: 100%; +.linkValTabContentHeader +{ + border-bottom: 1px dotted #BCD2E6; + padding: 8px 15px 8px 10px; } -.linkValidationBrokenFilesPanel +.linkValTabContentHeader img { - margin: 6px; - padding: 8px; - background-color: white; + cursor: pointer; } -.linkValidationBrokenFormsPanel -{ - margin: 6px; - padding: 8px; - background-color: white; -} - -.linkValidationFixedFilesPanel -{ - margin: 6px; - padding: 8px; - background-color: white; -} - -.linkValidationList +.linkValTabContentBody { + height: 300px; + width: 100%; overflow: auto; - height: 132px; - border: 1px solid #aaa; } -.linkValidationListOddRow +.linkValRow { - background-color: white; + padding: 10px 0px 10px 10px; } -.linkValidationListEvenRow +.linkValRowEven { - background-color: #f9f9f9; + background-color: #f9f9f9 !important; +} + +.linkValRowOdd +{ + background-color: #fff !important; +} + +.linkValNoItems +{ + padding: 10px; +} + +.linkValIcon +{ + float: left; + width: 40px; +} + +.linkValActions +{ + float: right; + width: 70px; + text-align: right; + padding-right: 10px; +} + +.linkValItemDetails +{ + margin: 0px 80px 0px 40px; +} + +.linkValFileName +{ + font-weight: bold; +} + +.linkValFilePath +{ + padding-top: 2px; +} + +.linkValFormName +{ + font-weight: bold; +} + +.linkValFormPath +{ + padding-top: 2px; +} + +.linkValToggle +{ + color: #505E6B; + padding-bottom: 3px; +} + +.linkValToggleExpanded +{ + vertical-align: -6px; +} + +.linkValToggleCollapsed +{ + vertical-align: -6px; +} + +.linkValBrokenLinks +{ + margin-left: 2px; +} + +.linkValBrokenLinks img +{ + vertical-align: -4px; +} + +.tabTitleBrokenLinkIcon +{ + border: none; + vertical-align: -4px; + margin-right: 2px; + margin-left: 2px; +} + +#staticTabContent +{ + -moz-border-radius: 9px; + border: 1px solid #BCD2E6; + clear: both; + padding-bottom: 5px; + margin-bottom: 5px; +} + +#generatedTabContent +{ + -moz-border-radius: 9px; + border: 1px solid #BCD2E6; + clear: both; + padding-bottom: 5px; + margin-bottom: 5px; +} + +#fixedTabContent +{ + -moz-border-radius: 9px; + border: 1px solid #BCD2E6; + clear: both; + padding-bottom: 5px; + margin-bottom: 5px; } diff --git a/source/web/images/icons/dec_tab_size.gif b/source/web/images/icons/dec_tab_size.gif new file mode 100644 index 0000000000..95b55159b3 Binary files /dev/null and b/source/web/images/icons/dec_tab_size.gif differ diff --git a/source/web/images/icons/green_tick.gif b/source/web/images/icons/green_tick.gif new file mode 100644 index 0000000000..c715e56be0 Binary files /dev/null and b/source/web/images/icons/green_tick.gif differ diff --git a/source/web/images/icons/inc_tab_size.gif b/source/web/images/icons/inc_tab_size.gif new file mode 100644 index 0000000000..c7ebf42bc5 Binary files /dev/null and b/source/web/images/icons/inc_tab_size.gif differ diff --git a/source/web/images/parts/tab_left.gif b/source/web/images/parts/tab_left.gif new file mode 100644 index 0000000000..4639494056 Binary files /dev/null and b/source/web/images/parts/tab_left.gif differ diff --git a/source/web/images/parts/tab_left_selected.gif b/source/web/images/parts/tab_left_selected.gif new file mode 100644 index 0000000000..ae92213103 Binary files /dev/null and b/source/web/images/parts/tab_left_selected.gif differ diff --git a/source/web/images/parts/tab_right.gif b/source/web/images/parts/tab_right.gif new file mode 100644 index 0000000000..8ec115c11b Binary files /dev/null and b/source/web/images/parts/tab_right.gif differ diff --git a/source/web/images/parts/tab_right_selected.gif b/source/web/images/parts/tab_right_selected.gif new file mode 100644 index 0000000000..6b20c2e80f Binary files /dev/null and b/source/web/images/parts/tab_right_selected.gif differ diff --git a/source/web/jsp/wcm/browse-sandbox.jsp b/source/web/jsp/wcm/browse-sandbox.jsp index 16a7f5b438..0deeeeef50 100644 --- a/source/web/jsp/wcm/browse-sandbox.jsp +++ b/source/web/jsp/wcm/browse-sandbox.jsp @@ -35,6 +35,32 @@ + + <%-- load a bundle of properties with I18N strings --%> @@ -137,10 +163,19 @@ + + + + + +
+
+
+
+ facetsId="folder-panel-facets" label="#{msg.website_browse_folders}"> - @@ -160,14 +195,6 @@ - <%-- Description column - - - - - - --%> - <%-- Creator column --%> @@ -228,10 +255,19 @@ + + + + + +
+
+
+
+ facetsId="files-panel-facets" label="#{msg.website_browse_files}"> - @@ -247,14 +283,6 @@
- <%-- Description column - - - - - - --%> - <%-- Size column --%> diff --git a/source/web/jsp/wcm/link-validation.jsp b/source/web/jsp/wcm/link-validation.jsp index 558bc1e3fa..1a50aad56b 100644 --- a/source/web/jsp/wcm/link-validation.jsp +++ b/source/web/jsp/wcm/link-validation.jsp @@ -36,11 +36,11 @@ <%-- Display the reporting components if showing a report --%> - + - - - + diff --git a/source/web/jsp/wcm/manage-broken-links-task-dialog.jsp b/source/web/jsp/wcm/manage-broken-links-task-dialog.jsp index 3f51349b7b..9fdffafbf4 100644 --- a/source/web/jsp/wcm/manage-broken-links-task-dialog.jsp +++ b/source/web/jsp/wcm/manage-broken-links-task-dialog.jsp @@ -52,10 +52,11 @@ - + + style='margin-left: 4px;'/> diff --git a/source/web/scripts/ajax/link-validation-report.js b/source/web/scripts/ajax/link-validation-report.js index fc7babf0bf..4981e064e9 100644 --- a/source/web/scripts/ajax/link-validation-report.js +++ b/source/web/scripts/ajax/link-validation-report.js @@ -1,12 +1,69 @@ +Alfresco.tabSelected = function(tab) +{ + var tabElem = document.getElementById(_alfCurrentTab); + if (tabElem != null) + { + tabElem.className = ""; + } + + var tabContentElem = document.getElementById(_alfCurrentTab + "Content"); + if (tabContentElem != null) + { + tabContentElem.style.display = "none"; + } + + tabElem = document.getElementById(tab + "Tab"); + if (tabElem != null) + { + tabElem.className = "selectedTab"; + _alfCurrentTab = tab + "Tab"; + } + + tabContentElem = document.getElementById(tab + "TabContent"); + if (tabContentElem != null) + { + tabContentElem.style.display = "block"; + } +} + +Alfresco.toggleBrokenLinks = function(icon, brokenLinksId) +{ + var currentState = icon.className; + var brokenLinksDiv = document.getElementById(brokenLinksId); + + if (currentState == "linkValToggleCollapsed") + { + icon.src = getContextPath() + "/images/icons/arrow_open.gif"; + icon.className = "linkValToggleExpanded"; + + // show the div holding the broken links + if (brokenLinksDiv != null) + { + brokenLinksDiv.style.display = "block"; + } + } + else + { + icon.src = getContextPath() + "/images/icons/arrow_closed.gif"; + icon.className = "linkValToggleCollapsed"; + + // hide the div holding the broken links + if (brokenLinksDiv != null) + { + brokenLinksDiv.style.display = "none"; + } + } +} + Alfresco.toggleGeneratedFiles = function(icon, genFilesId) { var currentState = icon.className; var genFilesDiv = document.getElementById(genFilesId); - if (currentState == "collapsed") + if (currentState == "linkValToggleCollapsed") { icon.src = getContextPath() + "/images/icons/arrow_open.gif"; - icon.className = "expanded"; + icon.className = "linkValToggleExpanded"; // show the div holding the generated files if (genFilesDiv != null) @@ -17,7 +74,7 @@ Alfresco.toggleGeneratedFiles = function(icon, genFilesId) else { icon.src = getContextPath() + "/images/icons/arrow_closed.gif"; - icon.className = "collapsed"; + icon.className = "linkValToggleCollapsed"; // hide the div holding the generated files if (genFilesDiv != null) @@ -25,4 +82,36 @@ Alfresco.toggleGeneratedFiles = function(icon, genFilesId) genFilesDiv.style.display = "none"; } } -} \ No newline at end of file +} + +Alfresco.increaseTabSize = function(tabBodyId) +{ + var tabElem = document.getElementById(tabBodyId); + + if (tabElem != null) + { + var currentHeight = YAHOO.util.Dom.getStyle(tabElem, "height"); + var size = currentHeight.substring(0, currentHeight.length-2); + var newSize = Number(size) + 100; + + YAHOO.util.Dom.setStyle(tabElem, "height", newSize + "px"); + } +} + +Alfresco.decreaseTabSize = function(tabBodyId) +{ + var tabElem = document.getElementById(tabBodyId); + + if (tabElem != null) + { + var currentHeight = YAHOO.util.Dom.getStyle(tabElem, "height"); + var size = currentHeight.substring(0, currentHeight.length-2); + var newSize = Number(size) - 100; + if (newSize < 100) + { + newSize = 100; + } + + YAHOO.util.Dom.setStyle(tabElem, "height", newSize + "px"); + } +}