From a4564a1a49021f033e1f714d030bbaa0e44edee6 Mon Sep 17 00:00:00 2001 From: Gavin Cornwell Date: Thu, 22 Dec 2005 11:57:43 +0000 Subject: [PATCH] Next phase of forums functionality Simple dialog framework implementation git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2056 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 4 + config/alfresco/web-client-config-icons.xml | 2 + config/alfresco/web-client-config.xml | 4 +- .../web/app/AlfrescoNavigationHandler.java | 253 ++++++++--- .../org/alfresco/web/bean/BrowseBean.java | 33 +- .../org/alfresco/web/bean/ExportBean.java | 2 +- .../org/alfresco/web/bean/ForumsBean.java | 424 ++++++++++++++---- .../org/alfresco/web/bean/ImportBean.java | 2 +- .../alfresco/web/bean/SpaceDetailsBean.java | 4 +- .../web/bean/wizard/NewDiscussionWizard.java | 132 ++++++ .../web/bean/wizard/NewForumWizard.java | 50 +-- .../web/bean/wizard/NewForumsWizard.java | 28 +- .../web/bean/wizard/NewPostWizard.java | 44 +- .../web/bean/wizard/NewReplyWizard.java | 16 +- .../web/bean/wizard/NewSpaceWizard.java | 10 +- .../web/bean/wizard/NewTopicWizard.java | 101 ++--- .../ui/repo/component/UISpaceSelector.java | 4 +- .../renderer/NodeDescendantsLinkRenderer.java | 4 +- .../web/WEB-INF/faces-config-navigation.xml | 200 +++------ source/web/WEB-INF/faces-config.xml | 45 ++ source/web/images/icons/create_forum.gif | Bin 1044 -> 585 bytes .../web/images/icons/create_forum_large.gif | Bin 1598 -> 1452 bytes source/web/images/icons/create_forums.gif | Bin 649 -> 631 bytes .../web/images/icons/create_forums_large.gif | Bin 0 -> 1586 bytes source/web/images/icons/create_post.gif | Bin 1052 -> 1018 bytes source/web/images/icons/create_post_large.gif | Bin 0 -> 1491 bytes source/web/images/icons/create_topic.gif | Bin 1052 -> 579 bytes .../web/images/icons/create_topic_large.gif | Bin 1574 -> 1331 bytes source/web/images/icons/edit_post.gif | Bin 0 -> 519 bytes source/web/images/icons/edit_post_large.gif | Bin 0 -> 1195 bytes source/web/images/icons/forum.gif | Bin 1026 -> 1009 bytes source/web/images/icons/forum_large.gif | Bin 1594 -> 1511 bytes source/web/images/icons/forums.gif | Bin 637 -> 648 bytes source/web/images/icons/forums_large.gif | Bin 1586 -> 1613 bytes source/web/images/icons/post_reply.gif | Bin 949 -> 553 bytes source/web/images/icons/post_reply_large.gif | Bin 0 -> 1304 bytes source/web/images/icons/topic.gif | Bin 1027 -> 581 bytes source/web/images/icons/topic_exclamation.gif | Bin 0 -> 591 bytes .../images/icons/topic_exclamation_large.gif | Bin 0 -> 1428 bytes source/web/images/icons/topic_large.gif | Bin 1572 -> 1400 bytes source/web/images/icons/topic_question.gif | Bin 0 -> 594 bytes .../web/images/icons/topic_question_large.gif | Bin 0 -> 1435 bytes source/web/jsp/admin/admin-console.jsp | 4 +- source/web/jsp/browse/browse.jsp | 31 +- source/web/jsp/dialog/space-details.jsp | 4 +- source/web/jsp/forums/create-discussion.jsp | 202 +++++++++ source/web/jsp/forums/create-forums.jsp | 2 +- source/web/jsp/forums/create-post.jsp | 2 +- source/web/jsp/forums/create-reply.jsp | 2 +- source/web/jsp/forums/create-topic.jsp | 2 +- source/web/jsp/forums/delete-forum.jsp | 4 +- source/web/jsp/forums/delete-forums.jsp | 4 +- source/web/jsp/forums/delete-post.jsp | 4 +- source/web/jsp/forums/delete-topic.jsp | 4 +- source/web/jsp/forums/edit-forum.jsp | 2 +- source/web/jsp/forums/edit-forums.jsp | 2 +- source/web/jsp/forums/edit-post.jsp | 2 +- source/web/jsp/forums/edit-topic.jsp | 2 +- source/web/jsp/forums/forum-details.jsp | 24 +- source/web/jsp/forums/forum.jsp | 20 +- source/web/jsp/forums/forums-details.jsp | 24 +- source/web/jsp/forums/forums.jsp | 30 +- source/web/jsp/forums/topic-details.jsp | 24 +- source/web/jsp/forums/topic.jsp | 16 +- source/web/jsp/roles/manage-invited-users.jsp | 2 +- 65 files changed, 1215 insertions(+), 560 deletions(-) create mode 100644 source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java create mode 100644 source/web/images/icons/create_forums_large.gif create mode 100644 source/web/images/icons/create_post_large.gif create mode 100644 source/web/images/icons/edit_post.gif create mode 100644 source/web/images/icons/edit_post_large.gif create mode 100644 source/web/images/icons/post_reply_large.gif create mode 100644 source/web/images/icons/topic_exclamation.gif create mode 100644 source/web/images/icons/topic_exclamation_large.gif create mode 100644 source/web/images/icons/topic_question.gif create mode 100644 source/web/images/icons/topic_question_large.gif create mode 100644 source/web/jsp/forums/create-discussion.jsp diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 191c20d171..934e9f28f3 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -319,6 +319,9 @@ edit_forum_description=Modify the forum properties then click OK. edit_topic_description=Modify the topic properties then click OK. edit_post_description=Modify the message then click OK. edit_post_finish=To save the message click Post. +start_discussion=Start Discussion +discuss=Discuss +discussion_for={0} discussion # Common Wizard messages steps=Steps @@ -828,6 +831,7 @@ title_create_forum=Create Forum title_forums_details=Forum Space Details title_forum_details=Forum Details title_create_topic=Create Topic +title_create_discussion=Create Discussion title_topic_details=Topic Details title_create_post=Post Message title_create_reply=Create Reply diff --git a/config/alfresco/web-client-config-icons.xml b/config/alfresco/web-client-config-icons.xml index 98da12e776..88e4f13ae5 100644 --- a/config/alfresco/web-client-config-icons.xml +++ b/config/alfresco/web-client-config-icons.xml @@ -33,6 +33,8 @@ + + diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 7cffe13ad9..8d20c3aa13 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -153,7 +153,6 @@ - @@ -167,7 +166,6 @@ - @@ -325,7 +323,7 @@ - + diff --git a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java index 26d1b6e81e..84fe5144f4 100644 --- a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java +++ b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java @@ -17,6 +17,8 @@ */ package org.alfresco.web.app; +import java.util.Stack; + import javax.faces.application.NavigationHandler; import javax.faces.application.ViewHandler; import javax.faces.component.UIViewRoot; @@ -38,7 +40,12 @@ import org.springframework.web.jsf.FacesContextUtils; */ public class AlfrescoNavigationHandler extends NavigationHandler { + public final static String DIALOG_SEPARATOR = ":"; + public final static String DIALOG_PREXIX = "dialog" + DIALOG_SEPARATOR; + public final static String CLOSE_DIALOG_OUTCOME = DIALOG_PREXIX + "close"; + private final static Log logger = LogFactory.getLog(AlfrescoNavigationHandler.class); + private final static String VIEW_STACK = "_alfViewStack"; // The original navigation handler private NavigationHandler origHandler; @@ -58,102 +65,228 @@ public class AlfrescoNavigationHandler extends NavigationHandler * @see javax.faces.application.NavigationHandler#handleNavigation(javax.faces.context.FacesContext, java.lang.String, java.lang.String) */ @Override + @SuppressWarnings("unchecked") public void handleNavigation(FacesContext context, String fromAction, String outcome) { if (logger.isDebugEnabled()) logger.debug("handleNavigation (fromAction=" + fromAction + ", outcome=" + outcome + ")"); boolean useOriginalNavHandler = true; - String finalOutcome = outcome; + boolean closingDialog = false; String viewId = context.getViewRoot().getViewId(); if (logger.isDebugEnabled()) logger.debug("Current view id: " + viewId); - NavigationBean navBean = (NavigationBean)context.getExternalContext(). - getSessionMap().get("NavigationBean"); - - // only continue if we have some dispatching context - if (navBean != null && navBean.getDispatchContextNode() != null) + // determine if we are dealing with a dialog + if (outcome != null && outcome.startsWith(DIALOG_PREXIX)) { - Node node = navBean.getDispatchContextNode(); - - if (logger.isDebugEnabled()) - logger.debug("Found node in dispatch context: " + node); + // determine whether it's being closed or opened + closingDialog = outcome.startsWith(CLOSE_DIALOG_OUTCOME); + + // remove the dialog prefix + outcome = outcome.substring(DIALOG_PREXIX.length()); - // see if there is any navigation config for the node type - ConfigService configSvc = (ConfigService)FacesContextUtils.getRequiredWebApplicationContext( - context).getBean(Application.BEAN_CONFIG_SERVICE); - - Config nodeConfig = configSvc.getConfig(node); - NavigationConfigElement navigationCfg = (NavigationConfigElement)nodeConfig. - getConfigElement(NavigationElementReader.ELEMENT_NAVIGATION); - - if (navigationCfg != null) + if (closingDialog) { - // see if there is config for the current view state - NavigationResult navResult = navigationCfg.getOverride(viewId, outcome); - - if (navResult != null) + // if we are closing the dialog take the view off the + // top of the stack then decide whether to use the view + // or any overridden outcome that may be present + if (getViewStack(context).empty() == false) { - if (logger.isDebugEnabled()) - logger.debug("Found navigation config: " + navResult); - - if (navResult.isOutcome()) + String newViewId = (String)getViewStack(context).pop(); + + // is there an overiddent outcome? + int idx = outcome.indexOf(DIALOG_SEPARATOR); + if (idx == -1) { - finalOutcome = navResult.getResult(); + // there isn't an overidden outcome so go back to the previous view + if (logger.isDebugEnabled()) + logger.debug("Closing dialog, going back to view id: " + newViewId); + + goToView(context, newViewId); } else { - String newViewId = navResult.getResult(); + // there is an overidden outcome so extract it + outcome = outcome.substring(idx+1, outcome.length()); + + if (logger.isDebugEnabled()) + logger.debug("Closing dialog with an overridden outcome of '" + outcome + "'"); - if (newViewId.equals(viewId) == false) + this.origHandler.handleNavigation(context, fromAction, outcome); + } + } + else + { + // we are trying to close a dialog when one hasn't been opened! + // log a warning and return a null outcome to stay on the same page + if (logger.isWarnEnabled()) + { + logger.warn("Attempting to close a dialog with an empty view stack, returning 'browse' outcome"); + } + + // TODO: change this back to returning null outcome as that + // will highlight any areas we have neglected to launch + // in a dilaog, for backwards compatibility for the short + // term return 'browse' outcome. + + this.origHandler.handleNavigation(context, fromAction, "browse"); + } + } + else + { + // if we are opening a dialog push the current view id + // on to the stack, but only if it is different than the + // current view at the top (you can't launch a dialog from + // the same page 2 times in a row!) + + // TODO: This wouldn't happen if we could be sure a dialog is + // ALWAYS exited properly, look into a way of ensuring + // dialogs get closed if a user navigates away from the page, + // would a PhaseListener help in any way?? + + if (getViewStack(context).empty() || + viewId.equals(getViewStack(context).peek()) == false) + { + getViewStack(context).push(viewId); + + if (logger.isDebugEnabled()) + logger.debug("Pushed current view to stack: " + viewId); + } + else + { + if (getViewStack(context).empty() == false && logger.isDebugEnabled()) + { + logger.debug("current view is already top the view stack!"); + } + } + } + + if (logger.isDebugEnabled()) + logger.debug("view stack: " + getViewStack(context)); + } + + if (closingDialog == false) + { + NavigationBean navBean = (NavigationBean)context.getExternalContext(). + getSessionMap().get("NavigationBean"); + + // only continue if we have some dispatching context + if (navBean != null && navBean.getDispatchContextNode() != null) + { + Node node = navBean.getDispatchContextNode(); + + if (logger.isDebugEnabled()) + logger.debug("Found node with type '" + node.getType().toString() + + "' in dispatch context"); + + // see if there is any navigation config for the node type + ConfigService configSvc = (ConfigService)FacesContextUtils.getRequiredWebApplicationContext( + context).getBean(Application.BEAN_CONFIG_SERVICE); + + Config nodeConfig = configSvc.getConfig(node); + NavigationConfigElement navigationCfg = (NavigationConfigElement)nodeConfig. + getConfigElement(NavigationElementReader.ELEMENT_NAVIGATION); + + if (navigationCfg != null) + { + // see if there is config for the current view state + NavigationResult navResult = navigationCfg.getOverride(viewId, outcome); + + if (navResult != null) + { + if (logger.isDebugEnabled()) + logger.debug("Found navigation config: " + navResult); + + if (navResult.isOutcome()) { - useOriginalNavHandler = false; - - if (logger.isDebugEnabled()) - logger.debug("Dispatching to new view id: " + newViewId); - - ViewHandler viewHandler = context.getApplication().getViewHandler(); - UIViewRoot viewRoot = viewHandler.createView(context, newViewId); - viewRoot.setViewId(newViewId); - context.setViewRoot(viewRoot); - context.renderResponse(); + outcome = navResult.getResult(); } else { - if (logger.isDebugEnabled()) - logger.debug("New view id is the same as the current one so setting outcome to null"); + String newViewId = navResult.getResult(); - finalOutcome = null; + if (newViewId.equals(viewId) == false) + { + useOriginalNavHandler = false; + + if (logger.isDebugEnabled()) + logger.debug("Dispatching to new view id: " + newViewId); + + goToView(context, newViewId); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("New view id is the same as the current one so setting outcome to null"); + + outcome = null; + } } } + else if (logger.isDebugEnabled()) + { + logger.debug("No override configuration found for current view or outcome"); + } } else if (logger.isDebugEnabled()) { - logger.debug("No override configuration found for current view or outcome"); + logger.debug("No navigation configuration found for node"); } + + // reset the dispatch context + navBean.resetDispatchContext(); } else if (logger.isDebugEnabled()) { - logger.debug("No navigation configuration found for node"); + logger.debug("No dispatch context found"); } - // reset the dispatch context - navBean.resetDispatchContext(); - } - else if (logger.isDebugEnabled()) - { - logger.debug("No dispatch context found"); - } - - // do the appropriate navigation handling - if (useOriginalNavHandler) - { - if (logger.isDebugEnabled()) - logger.debug("Passing outcome '" + finalOutcome + "' to original navigation handler"); - - this.origHandler.handleNavigation(context, fromAction, finalOutcome); + // do the appropriate navigation handling + if (useOriginalNavHandler) + { + if (logger.isDebugEnabled()) + logger.debug("Passing outcome '" + outcome + "' to original navigation handler"); + + this.origHandler.handleNavigation(context, fromAction, outcome); + } } } + + /** + * Dispatches to the given view id + * + * @param context Faces context + * @param viewId The view id to go to + */ + private void goToView(FacesContext context, String viewId) + { + ViewHandler viewHandler = context.getApplication().getViewHandler(); + UIViewRoot viewRoot = viewHandler.createView(context, viewId); + viewRoot.setViewId(viewId); + context.setViewRoot(viewRoot); + context.renderResponse(); + } + + /** + * Returns the view stack for the current user. + * + * @param context FacesContext + * @return A Stack representing the views that have launched dialogs in + * the users session, will never be null + */ + @SuppressWarnings("unchecked") + private Stack getViewStack(FacesContext context) + { + Stack viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK); + + if (viewStack == null) + { + viewStack = new Stack(); + context.getExternalContext().getSessionMap().put(VIEW_STACK, viewStack); + } + + return viewStack; + } } diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index 5702004ec5..5597cfe59d 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -28,6 +28,7 @@ import javax.faces.event.ActionEvent; import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; +import org.alfresco.model.ForumModel; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.lock.LockService; @@ -43,6 +44,8 @@ import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.IContextListener; import org.alfresco.web.app.context.UIContextService; @@ -399,6 +402,7 @@ public class BrowseBean implements IContextListener node.addPropertyResolver("size", this.resolverSize); node.addPropertyResolver("cancelCheckOut", this.resolverCancelCheckOut); node.addPropertyResolver("checkIn", this.resolverCheckIn); + node.addPropertyResolver("beingDiscussed", this.resolverBeingDiscussed); node.addPropertyResolver("editLinkType", this.resolverEditLinkType); node.addPropertyResolver("webdavUrl", this.resolverWebdavUrl); node.addPropertyResolver("cifsPath", this.resolverCifsPath); @@ -490,9 +494,9 @@ public class BrowseBean implements IContextListener // build a NodeRef for the specified Id and our store parentRef = new NodeRef(Repository.getStoreRef(), parentNodeId); } - - // TODO: can we improve the Get here with an API call for children of a specific type? - List childRefs = this.nodeService.getChildAssocs(parentRef); + + List childRefs = this.nodeService.getChildAssocs(parentRef, + ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); this.containerNodes = new ArrayList(childRefs.size()); this.contentNodes = new ArrayList(childRefs.size()); for (ChildAssociationRef ref: childRefs) @@ -517,6 +521,7 @@ public class BrowseBean implements IContextListener // create our Node representation MapNode node = new MapNode(nodeRef, this.nodeService, true); node.addPropertyResolver("icon", this.resolverSpaceIcon); + node.addPropertyResolver("beingDiscussed", this.resolverBeingDiscussed); this.containerNodes.add(node); } @@ -632,6 +637,7 @@ public class BrowseBean implements IContextListener node.addPropertyResolver("path", this.resolverPath); node.addPropertyResolver("displayPath", this.resolverDisplayPath); node.addPropertyResolver("icon", this.resolverSpaceIcon); + node.addPropertyResolver("beingDiscussed", this.resolverBeingDiscussed); this.containerNodes.add(node); } @@ -732,6 +738,12 @@ public class BrowseBean implements IContextListener } }; + public NodePropertyResolver resolverBeingDiscussed = new NodePropertyResolver() { + public Object get(Node node) { + return node.hasAspect(ForumModel.ASPECT_DISCUSSABLE); + } + }; + public NodePropertyResolver resolverDownload = new NodePropertyResolver() { public Object get(Node node) { return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), node.getName()); @@ -865,9 +877,7 @@ public class BrowseBean implements IContextListener try { NodeRef ref = new NodeRef(Repository.getStoreRef(), id); - - // refresh UI based on node selection - updateUILocation(ref); + clickSpace(ref); } catch (InvalidNodeRefException refErr) { @@ -877,6 +887,17 @@ public class BrowseBean implements IContextListener } } + /** + * Action called when a folder space is clicked. + * + * @param nodeRef The node being clicked + */ + public void clickSpace(NodeRef nodeRef) + { + // refresh UI based on node selection + updateUILocation(nodeRef); + } + /** * Handler called when a path element is clicked - navigate to the appropriate Space */ diff --git a/source/java/org/alfresco/web/bean/ExportBean.java b/source/java/org/alfresco/web/bean/ExportBean.java index fce8cf56b0..d41b71a318 100644 --- a/source/java/org/alfresco/web/bean/ExportBean.java +++ b/source/java/org/alfresco/web/bean/ExportBean.java @@ -48,7 +48,7 @@ public class ExportBean private static final String ALL_SPACES = "all"; private static final String CURRENT_SPACE = "current"; - private static final String DEFAULT_OUTCOME = "browse"; + private static final String DEFAULT_OUTCOME = "dialog:close"; private static final String MSG_ERROR = "error_export"; diff --git a/source/java/org/alfresco/web/bean/ForumsBean.java b/source/java/org/alfresco/web/bean/ForumsBean.java index f7e6a9153d..724528061e 100644 --- a/source/java/org/alfresco/web/bean/ForumsBean.java +++ b/source/java/org/alfresco/web/bean/ForumsBean.java @@ -17,11 +17,15 @@ package org.alfresco.web.bean; import java.io.IOException; +import java.io.Writer; import java.text.MessageFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; @@ -29,6 +33,7 @@ import javax.faces.context.ResponseWriter; import javax.faces.event.ActionEvent; import javax.transaction.UserTransaction; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.model.ForumModel; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -44,6 +49,8 @@ import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.IContextListener; import org.alfresco.web.app.context.UIContextService; @@ -53,6 +60,7 @@ import org.alfresco.web.bean.repository.NodePropertyResolver; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.config.ClientConfigElement; import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIActionLink; import org.alfresco.web.ui.common.component.UIModeList; import org.alfresco.web.ui.common.component.data.UIColumn; import org.alfresco.web.ui.common.component.data.UIRichList; @@ -428,8 +436,8 @@ public class ForumsBean implements IContextListener parentRef = new NodeRef(Repository.getStoreRef(), parentNodeId); } - // TODO: can we improve the Get here with an API call for children of a specific type? - List childRefs = this.nodeService.getChildAssocs(parentRef); + List childRefs = this.nodeService.getChildAssocs(parentRef, + ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); this.forums = new ArrayList(childRefs.size()); this.topics = new ArrayList(childRefs.size()); this.posts = new ArrayList(childRefs.size()); @@ -596,6 +604,13 @@ public class ForumsBean implements IContextListener // push the view mode into the lists setForumsViewMode(viewMode); + + // get the default for the forum page + this.forumsPageSize = this.clientConfig.getDefaultPageSize(PAGE_NAME_FORUMS, + this.forumsViewMode); + + if (logger.isDebugEnabled()) + logger.debug("Set default forums page size to: " + this.forumsPageSize); } /** @@ -612,6 +627,13 @@ public class ForumsBean implements IContextListener // push the view mode into the lists setForumViewMode(viewMode); + + // get the default for the forum page + this.forumPageSize = this.clientConfig.getDefaultPageSize(PAGE_NAME_FORUM, + this.forumViewMode); + + if (logger.isDebugEnabled()) + logger.debug("Set default forum page size to: " + this.forumPageSize); } /** @@ -628,6 +650,137 @@ public class ForumsBean implements IContextListener // push the view mode into the lists setTopicViewMode(viewMode); + + // change the default page size if necessary + this.topicPageSize = this.clientConfig.getDefaultPageSize(PAGE_NAME_TOPIC, + this.topicViewMode); + + if (logger.isDebugEnabled()) + logger.debug("Set default topic page size to: " + this.topicPageSize); + } + + /** + * Event handler called when a user wants to view or participate + * in a discussion on an object + * + * @param event ActionEvent + */ + public void discuss(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String id = params.get("id"); + if (id == null || id.length() == 0) + { + throw new AlfrescoRuntimeException("discuss called without an id"); + } + + FacesContext context = FacesContext.getCurrentInstance(); + + NodeRef nodeRef = new NodeRef(Repository.getStoreRef(), id); + + if (this.nodeService.hasAspect(nodeRef, ForumModel.ASPECT_DISCUSSABLE) == false) + { + throw new AlfrescoRuntimeException("discuss called for an object that does not have a discussion!"); + } + + // as the node has the discussable aspect there must be a discussions child assoc + List children = this.nodeService.getChildAssocs(nodeRef, + ForumModel.ASSOC_DISCUSSION, RegexQNamePattern.MATCH_ALL); + + // there should only be one child, retrieve it if there is + if (children.size() == 1) + { + NodeRef forumNodeRef = children.get(0).getChildRef(); + + // query for the number of topics there are + String repliesXPath = "./*[(subtypeOf('" + ForumModel.TYPE_TOPIC + "'))]"; + List topics = searchService.selectNodes(forumNodeRef, repliesXPath, + new QueryParameterDefinition[] {}, this.namespaceService, false); + if (topics.size() == 1) + { + // if the forum has only one topic go straight into the topic by + // setting the context and navigating to it + NodeRef topicNodeRef = topics.get(0); + this.browseBean.clickSpace(topicNodeRef); + context.getApplication().getNavigationHandler().handleNavigation(context, null, "showTopic"); + } + else + { + // if the forum has more than one topic we need to setup the context + // for the forum and navigate to the forum page + this.browseBean.clickSpace(forumNodeRef); + context.getApplication().getNavigationHandler().handleNavigation(context, null, "showForum"); + } + } + } + + /** + * Called when the user confirms they wish to delete a forum space + * + * @return The outcome + */ + public String deleteForumsOK() + { + String outcome = "browse"; + + // find out what the parent type of the node being deleted + Node node = this.browseBean.getActionSpace(); + ChildAssociationRef assoc = this.nodeService.getPrimaryParent(node.getNodeRef()); + if (assoc != null) + { + NodeRef parent = assoc.getParentRef(); + QName parentType = this.nodeService.getType(parent); + if (parentType.equals(ForumModel.TYPE_FORUMS)) + { + outcome = "forumsDeleted"; + } + } + + // call the generic handler + this.browseBean.deleteSpaceOK(); + + // return an overidden outcome which closes the dialog with an outcome + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + + AlfrescoNavigationHandler.DIALOG_SEPARATOR + outcome; + } + + /** + * Called when the user confirms they wish to delete a forum space + * + * @return The outcome + */ + public String deleteForumOK() + { + this.browseBean.deleteSpaceOK(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + + AlfrescoNavigationHandler.DIALOG_SEPARATOR + "forumDeleted"; + } + + /** + * Called when the user confirms they wish to delete a forum space + * + * @return The outcome + */ + public String deleteTopicOK() + { + this.browseBean.deleteSpaceOK(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + + AlfrescoNavigationHandler.DIALOG_SEPARATOR + "topicDeleted"; + } + + /** + * Called when the user confirms they wish to delete a forum space + * + * @return The outcome + */ + public String deletePostOK() + { + this.browseBean.deleteFileOK(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } // ------------------------------------------------------------------------------ @@ -703,6 +856,25 @@ public class ForumsBean implements IContextListener } }; + /** + * Creates a file name for the message being posted + * + * @return The file name for the post + */ + public static String createPostFileName() + { + StringBuilder name = new StringBuilder("posted-"); + + // add a timestamp + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-hh:mm:ss"); + name.append(dateFormat.format(new Date())); + + // add the HTML file extension + name.append(".html"); + + return name.toString(); + } + // ------------------------------------------------------------------------------ // Private helpers @@ -839,6 +1011,124 @@ public class ForumsBean implements IContextListener out.write(""); } + /** + * Renders the top part of the bubble i.e. before the header + * + * @param out The writer to output to + * @param contextPath Context path of the application + * @param colour The colour of the bubble + * @param titleBgColour Background colour of the header area + */ + public static void renderBubbleTop(Writer out, String contextPath, + String colour, String titleBgColour) throws IOException + { + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write(""); + out.write("
"); + } + + /** + * Renders the middle part of the bubble i.e. after the header and before the body + * + * @param out The writer to output to + * @param contextPath Context path of the application + * @param colour The colour of the bubble + */ + public static void renderBubbleMiddle(Writer out, String contextPath, String colour) + throws IOException + { + out.write("
"); + } + + /** + * Renders the bottom part of the bubble i.e. after the body + * + * @param out The writer to output to + * @param contextPath Context path of the application + * @param colour The colour of the bubble + */ + public static void renderBubbleBottom(Writer out, String contextPath, String colour) + throws IOException + { + out.write("
"); + } + /** * Renders the new post speech bubble * @@ -852,13 +1142,22 @@ public class ForumsBean implements IContextListener private void renderNewPostBubble(FacesContext context, ResponseWriter out, Node node, UIColumn primaryColumn, UIColumn actionsColumn, UIColumn[] columns) throws IOException { + String contextPath = context.getExternalContext().getRequestContextPath(); + String colour = "orange"; + out.write(""); out.write("

"); out.write((String)node.getProperties().get("creator")); out.write("
"); - renderBubble(context, out, "orange", "#FCC75E", primaryColumn, actionsColumn, columns); + + renderBubbleTop(out, contextPath, colour, "#FCC75E"); + renderHeaderContents(context, out, primaryColumn, actionsColumn, columns); + renderBubbleMiddle(out, contextPath, colour); + renderBodyContents(context, primaryColumn); + renderBubbleBottom(out, contextPath, colour); + out.write("
"); } @@ -875,48 +1174,28 @@ public class ForumsBean implements IContextListener private void renderReplyToBubble(FacesContext context, ResponseWriter out, Node node, UIColumn primaryColumn, UIColumn actionsColumn, UIColumn[] columns) throws IOException { + String contextPath = context.getExternalContext().getRequestContextPath(); + String colour = "yellow"; + out.write(""); out.write("
"); - renderBubble(context, out, "yellow", "#FFF5A3", primaryColumn, actionsColumn, columns); + + renderBubbleTop(out, contextPath, colour, "#FFF5A3"); + renderHeaderContents(context, out, primaryColumn, actionsColumn, columns); + renderBubbleMiddle(out, contextPath, colour); + renderBodyContents(context, primaryColumn); + renderBubbleBottom(out, contextPath, colour); + out.write("
"); out.write((String)node.getProperties().get("creator")); out.write("
"); } - /** - * Renders the speech bubble - * - * @param context Faces context - * @param out The response writer - * @param colour The colour of the bubble - * @param titleBgColour The colour of the background of the title area (#rrggbb) - * @param primaryColumn The primary column containing the message content - * @param actionsColumn The actions column containing all the actions - * @param columns All configured columns - */ - private void renderBubble(FacesContext context, ResponseWriter out, - String colour, String titleBgColour, - UIColumn primaryColumn, UIColumn actionsColumn, UIColumn[] columns) - throws IOException + private void renderHeaderContents(FacesContext context, ResponseWriter out, + UIColumn primaryColumn, UIColumn actionsColumn, UIColumn[] columns) throws IOException { - String contextPath = context.getExternalContext().getRequestContextPath(); - - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write("
"); - // render the header area with the configured columns out.write(""); @@ -948,73 +1227,28 @@ public class ForumsBean implements IContextListener } // render the actions column - out.write("
"); + out.write(""); if (actionsColumn != null && actionsColumn.getChildCount() != 0) { Utils.encodeRecursive(context, actionsColumn); } - out.write("
"); - - out.write("
"); - + out.write("
"); + } + + /** + * Renders the body contents for the bubble using the given primary coumn + * + * @param context Faces context + * @param primaryColumn The primary column holding the message text + */ + private void renderBodyContents(FacesContext context, UIColumn primaryColumn) + throws IOException + { // render the primary column if (primaryColumn != null && primaryColumn.getChildCount() != 0) { Utils.encodeRecursive(context, primaryColumn); } - - out.write(""); - - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); } } } diff --git a/source/java/org/alfresco/web/bean/ImportBean.java b/source/java/org/alfresco/web/bean/ImportBean.java index abc3bd32b3..fd8252a9a9 100644 --- a/source/java/org/alfresco/web/bean/ImportBean.java +++ b/source/java/org/alfresco/web/bean/ImportBean.java @@ -53,7 +53,7 @@ public class ImportBean { private static final Log logger = LogFactory.getLog(ImportBean.class); - private static final String DEFAULT_OUTCOME = "browse"; + private static final String DEFAULT_OUTCOME = "dialog:close"; private static final String MSG_ERROR = "error_import"; private static final String MSG_ERROR_NO_FILE = "error_import_no_file"; diff --git a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java index 7598615a40..4b960d46fe 100644 --- a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java +++ b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java @@ -34,6 +34,7 @@ import org.alfresco.service.cmr.repository.TemplateImageResolver; import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; @@ -208,6 +209,7 @@ public class SpaceDetailsBean * * @return model containing current current space info. */ + @SuppressWarnings("unchecked") public Map getTemplateModel() { HashMap model = new HashMap(1, 1.0f); @@ -402,6 +404,6 @@ public class SpaceDetailsBean public String closeDialog() { this.navigator.resetCurrentNodeProperties(); - return "browse"; + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } } diff --git a/source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java b/source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java new file mode 100644 index 0000000000..2c3400369b --- /dev/null +++ b/source/java/org/alfresco/web/bean/wizard/NewDiscussionWizard.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the GNU Lesser General Public License as + * published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + * You may obtain a copy of the License at + * + * http://www.gnu.org/licenses/lgpl.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.bean.wizard; + +import java.io.Serializable; +import java.text.MessageFormat; +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.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.model.ForumModel; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIActionLink; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Backing bean class used to create discussions for documents + * + * @author gavinc + */ +public class NewDiscussionWizard extends NewTopicWizard +{ + private static final Log logger = LogFactory.getLog(NewDiscussionWizard.class); + + private NodeRef discussingNodeRef; + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#startWizard(javax.faces.event.ActionEvent) + */ + @Override + public void startWizard(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String id = params.get("id"); + if (id == null || id.length() == 0) + { + throw new AlfrescoRuntimeException("startDiscussion called without an id"); + } + + FacesContext context = FacesContext.getCurrentInstance(); + UserTransaction tx = null; + NodeRef forumNodeRef = null; + + try + { + tx = Repository.getUserTransaction(context); + tx.begin(); + + this.discussingNodeRef = new NodeRef(Repository.getStoreRef(), id); + + if (this.nodeService.hasAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE)) + { + throw new AlfrescoRuntimeException("startDiscussion called for an object that already has a discussion!"); + } + + // add the discussable aspect + this.nodeService.addAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE, null); + + // create a child forum space using the child association just introduced by + // adding the discussable aspect + String name = (String)this.nodeService.getProperty(this.discussingNodeRef, + ContentModel.PROP_NAME); + String msg = Application.getMessage(FacesContext.getCurrentInstance(), "discussion_for"); + String forumName = MessageFormat.format(msg, new Object[] {name}); + + Map forumProps = new HashMap(1); + forumProps.put(ContentModel.PROP_NAME, forumName); + ChildAssociationRef childRef = this.nodeService.createNode(this.discussingNodeRef, + ForumModel.ASSOC_DISCUSSION, + QName.createQName(ForumModel.FORUMS_MODEL_URI, "discussion"), + ForumModel.TYPE_FORUM, forumProps); + + forumNodeRef = childRef.getChildRef(); + + // apply the uifacets aspect + Map uiFacetsProps = new HashMap(5); + uiFacetsProps.put(ContentModel.PROP_ICON, "forum_large"); + this.nodeService.addAspect(forumNodeRef, ContentModel.ASPECT_UIFACETS, uiFacetsProps); + + if (logger.isDebugEnabled()) + logger.debug("created forum for content: " + forumNodeRef.toString()); + + // commit the transaction + tx.commit(); + } + catch (Exception e) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + context, Repository.ERROR_GENERIC), e.getMessage()), e); + } + + // finally setup the context for the forum we just created + if (forumNodeRef != null) + { + this.browseBean.clickSpace(forumNodeRef); + + // now initialise the wizard and navigate to it + super.startWizard(event); + context.getApplication().getNavigationHandler().handleNavigation(context, null, "dialog:createDiscussion"); + } + } + +} diff --git a/source/java/org/alfresco/web/bean/wizard/NewForumWizard.java b/source/java/org/alfresco/web/bean/wizard/NewForumWizard.java index 66c596a86d..51a3b5e429 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewForumWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewForumWizard.java @@ -17,12 +17,8 @@ */ package org.alfresco.web.bean.wizard; -import java.util.List; - -import javax.faces.context.FacesContext; - import org.alfresco.model.ForumModel; -import org.alfresco.web.ui.common.component.UIListItem; +import org.alfresco.web.app.AlfrescoNavigationHandler; /** * Wizard bean used for creating and editing forum spaces @@ -31,30 +27,6 @@ import org.alfresco.web.ui.common.component.UIListItem; */ public class NewForumWizard extends NewSpaceWizard { - protected String forumStatus; - - protected List forumIcons; - - /** - * Returns the status of the forum - * - * @return The status of the forum - */ - public String getForumStatus() - { - return this.forumStatus; - } - - /** - * Sets the status of the forum - * - * @param forumStatus The status - */ - public void setForumStatus(String forumStatus) - { - this.forumStatus = forumStatus; - } - /** * @see org.alfresco.web.bean.wizard.AbstractWizardBean#init() */ @@ -63,15 +35,27 @@ public class NewForumWizard extends NewSpaceWizard super.init(); this.spaceType = ForumModel.TYPE_FORUM.toString(); - this.forumStatus = "0"; + } + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#finish() + */ + @Override + public String finish() + { + super.finish(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } /** - * @see org.alfresco.web.bean.wizard.NewSpaceWizard#performCustomProcessing(javax.faces.context.FacesContext) + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#cancel() */ @Override - protected void performCustomProcessing(FacesContext context) + public String cancel() { - // add or update the ForumModel.PROP_STATUS property depending on the editMode + super.cancel(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } } diff --git a/source/java/org/alfresco/web/bean/wizard/NewForumsWizard.java b/source/java/org/alfresco/web/bean/wizard/NewForumsWizard.java index bf526c9ce6..8f8644d194 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewForumsWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewForumsWizard.java @@ -17,10 +17,8 @@ */ package org.alfresco.web.bean.wizard; -import java.util.List; - import org.alfresco.model.ForumModel; -import org.alfresco.web.ui.common.component.UIListItem; +import org.alfresco.web.app.AlfrescoNavigationHandler; /** * Wizard bean used for creating and editing forums spaces @@ -29,8 +27,6 @@ import org.alfresco.web.ui.common.component.UIListItem; */ public class NewForumsWizard extends NewSpaceWizard { - protected List forumsIcons; - /** * @see org.alfresco.web.bean.wizard.AbstractWizardBean#init() */ @@ -40,4 +36,26 @@ public class NewForumsWizard extends NewSpaceWizard this.spaceType = ForumModel.TYPE_FORUMS.toString(); } + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#finish() + */ + @Override + public String finish() + { + super.finish(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#cancel() + */ + @Override + public String cancel() + { + super.cancel(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } } diff --git a/source/java/org/alfresco/web/bean/wizard/NewPostWizard.java b/source/java/org/alfresco/web/bean/wizard/NewPostWizard.java index 40b0e9e5df..5766e68210 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewPostWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewPostWizard.java @@ -25,6 +25,8 @@ import org.alfresco.model.ForumModel; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.util.GUID; +import org.alfresco.web.app.AlfrescoNavigationHandler; +import org.alfresco.web.bean.ForumsBean; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.common.Utils; @@ -56,7 +58,8 @@ public class NewPostWizard extends CreateContentWizard public void startWizardForEdit(ActionEvent event) { // TODO: Allow action link to have multiple action listeners - // then we wouldn't need to have this coupling in here + // then we wouldn't need to have this coupling back + // to the browse bean in here // we need to setup the content in the browse bean first this.browseBean.setupContentAction(event); @@ -101,17 +104,18 @@ public class NewPostWizard extends CreateContentWizard } else { - // create appropriate values for filename, title and content type - this.fileName = GUID.generate() + ".html"; + // create appropriate values for filename and content type + this.fileName = ForumsBean.createPostFileName(); this.contentType = Repository.getMimeTypeForFileName( FacesContext.getCurrentInstance(), this.fileName); - this.title = this.fileName; // remove link breaks and replace with
this.content = Utils.replaceLineBreaks(this.content); } - return super.finish(); + super.finish(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } /** @@ -120,16 +124,28 @@ public class NewPostWizard extends CreateContentWizard @Override protected void performCustomProcessing() { - // update the content - Node currentDocument = this.browseBean.getDocument(); - - ContentWriter writer = this.contentService.getWriter(currentDocument.getNodeRef(), - ContentModel.PROP_CONTENT, true); - if (writer != null) + if (this.editMode) { - writer.putContent(this.content); + // update the content + Node currentDocument = this.browseBean.getDocument(); + + ContentWriter writer = this.contentService.getWriter(currentDocument.getNodeRef(), + ContentModel.PROP_CONTENT, true); + if (writer != null) + { + writer.putContent(this.content); + } } } - - + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#cancel() + */ + @Override + public String cancel() + { + super.cancel(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } } diff --git a/source/java/org/alfresco/web/bean/wizard/NewReplyWizard.java b/source/java/org/alfresco/web/bean/wizard/NewReplyWizard.java index c0166f4b70..60e8e55d8c 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewReplyWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewReplyWizard.java @@ -20,6 +20,7 @@ package org.alfresco.web.bean.wizard; import javax.faces.event.ActionEvent; import org.alfresco.model.ContentModel; +import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.ui.common.Utils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -55,7 +56,9 @@ public class NewReplyWizard extends NewPostWizard // remove link breaks and replace with
this.content = Utils.replaceLineBreaks(this.content); - return super.finish(); + super.finish(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } /** @@ -79,4 +82,15 @@ public class NewReplyWizard extends NewPostWizard } } } + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#cancel() + */ + @Override + public String cancel() + { + super.cancel(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } } diff --git a/source/java/org/alfresco/web/bean/wizard/NewSpaceWizard.java b/source/java/org/alfresco/web/bean/wizard/NewSpaceWizard.java index 300f23478a..75899812db 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewSpaceWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewSpaceWizard.java @@ -80,10 +80,10 @@ public class NewSpaceWizard extends AbstractWizardBean private static final String DEFAULT_SPACE_TYPE_ICON = "/images/icons/space.gif"; // new space wizard specific properties - private SearchService searchService; - private NamespaceService namespaceService; - private DictionaryService dictionaryService; - private ConfigService configService; + protected SearchService searchService; + protected NamespaceService namespaceService; + protected DictionaryService dictionaryService; + protected ConfigService configService; protected String spaceType; protected String icon; @@ -996,7 +996,7 @@ public class NewSpaceWizard extends AbstractWizardBean * * @param context Faces context */ - protected void performCustomProcessing(FacesContext context) + protected void performCustomProcessing(FacesContext context) throws Exception { // used by subclasses if necessary } diff --git a/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java b/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java index c81f48c621..5b637f068d 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewTopicWizard.java @@ -18,26 +18,22 @@ package org.alfresco.web.bean.wizard; import java.io.Serializable; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; -import javax.faces.model.SelectItem; import org.alfresco.model.ContentModel; import org.alfresco.model.ForumModel; -import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; -import org.alfresco.util.GUID; +import org.alfresco.web.app.AlfrescoNavigationHandler; +import org.alfresco.web.bean.ForumsBean; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.common.Utils; -import org.alfresco.web.ui.common.component.UIListItem; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,51 +47,8 @@ public class NewTopicWizard extends NewSpaceWizard private static final Log logger = LogFactory.getLog(NewTopicWizard.class); protected String message; - protected String topicType; - protected List topicIcons; - protected List topicTypes; protected ContentService contentService; - - /** - * Returns a list of topic types for the user to select from - * - * @return The topic types - */ - public List getTopicTypes() - { - if (this.topicTypes == null) - { - this.topicTypes = new ArrayList(3); - - // TODO: change this to be based on categories - this.topicTypes.add(new SelectItem("1", "Announcement")); - this.topicTypes.add(new SelectItem("0", "Normal")); - this.topicTypes.add(new SelectItem("2", "Sticky")); - } - - return this.topicTypes; - } - - /** - * Returns the type of the topic - * - * @return The type of topic - */ - public String getTopicType() - { - return this.topicType; - } - - /** - * Sets the type of the topic - * - * @param topicType The type of the topic - */ - public void setTopicType(String topicType) - { - this.topicType = topicType; - } /** * Returns the message entered by the user for the first post @@ -133,7 +86,6 @@ public class NewTopicWizard extends NewSpaceWizard super.init(); this.spaceType = ForumModel.TYPE_TOPIC.toString(); - this.topicType = "0"; this.message = null; } @@ -141,34 +93,19 @@ public class NewTopicWizard extends NewSpaceWizard * @see org.alfresco.web.bean.wizard.NewSpaceWizard#performCustomProcessing(javax.faces.context.FacesContext) */ @Override - protected void performCustomProcessing(FacesContext context) + protected void performCustomProcessing(FacesContext context) throws Exception { if (this.editMode == false) { - // ************************* - // TODO: Add or update the ForumModel.PROP_TYPE property depending on the editMode - // ************************* - // get the node ref of the node that will contain the content NodeRef containerNodeRef = this.createdNode; // create a unique file name for the message content - String fileName = GUID.generate() + ".txt"; + String fileName = ForumsBean.createPostFileName(); - // create properties for content type - Map contentProps = new HashMap(5, 1.0f); - contentProps.put(ContentModel.PROP_NAME, fileName); - - // create the node to represent the content - String assocName = QName.createValidLocalName(fileName); - ChildAssociationRef assocRef = this.nodeService.createNode( - containerNodeRef, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, assocName), - Repository.resolveToQName(ForumModel.TYPE_POST.toString()), - contentProps); - - NodeRef postNodeRef = assocRef.getChildRef(); + FileInfo fileInfo = this.fileFolderService.create(containerNodeRef, + fileName, ForumModel.TYPE_POST); + NodeRef postNodeRef = fileInfo.getNodeRef(); if (logger.isDebugEnabled()) logger.debug("Created post node with filename: " + fileName); @@ -196,4 +133,26 @@ public class NewTopicWizard extends NewSpaceWizard writer.putContent(Utils.replaceLineBreaks(this.message)); } } + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#finish() + */ + @Override + public String finish() + { + super.finish(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + + /** + * @see org.alfresco.web.bean.wizard.AbstractWizardBean#cancel() + */ + @Override + public String cancel() + { + super.cancel(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } } diff --git a/source/java/org/alfresco/web/ui/repo/component/UISpaceSelector.java b/source/java/org/alfresco/web/ui/repo/component/UISpaceSelector.java index 4fe45e78f9..1d8174f0e7 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UISpaceSelector.java +++ b/source/java/org/alfresco/web/ui/repo/component/UISpaceSelector.java @@ -27,6 +27,7 @@ import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.repo.WebResources; @@ -83,7 +84,8 @@ public class UISpaceSelector extends AbstractItemSelector public Collection getChildrenForNode(FacesContext context) { NodeRef nodeRef = new NodeRef(Repository.getStoreRef(), this.navigationId); - List allKids = getNodeService(context).getChildAssocs(nodeRef); + List allKids = getNodeService(context).getChildAssocs(nodeRef, + ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); DictionaryService dd = getDictionaryService(context); NodeService service = getNodeService(context); diff --git a/source/java/org/alfresco/web/ui/repo/renderer/NodeDescendantsLinkRenderer.java b/source/java/org/alfresco/web/ui/repo/renderer/NodeDescendantsLinkRenderer.java index e30379d30d..ce762fcf7e 100644 --- a/source/java/org/alfresco/web/ui/repo/renderer/NodeDescendantsLinkRenderer.java +++ b/source/java/org/alfresco/web/ui/repo/renderer/NodeDescendantsLinkRenderer.java @@ -34,6 +34,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.renderer.BaseRenderer; @@ -115,7 +116,8 @@ public class NodeDescendantsLinkRenderer extends BaseRenderer // calculate the number of displayed child refs if (service.exists(parentRef) == true) { - List childRefs = service.getChildAssocs(parentRef); + List childRefs = service.getChildAssocs(parentRef, + ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); List refs = new ArrayList(childRefs.size()); for (int index=0; indexpreviewSpace /jsp/dialog/preview-space.jsp + + startDiscussion + /jsp/forums/create-topic.jsp + + + showForum + /jsp/forums/forum.jsp + + + showTopic + /jsp/forums/topic.jsp + @@ -900,14 +912,6 @@ /jsp/forums/* - - cancel - /jsp/forums/forums.jsp - - - finish - /jsp/forums/forums.jsp - createForums /jsp/forums/create-forums.jsp @@ -976,14 +980,22 @@ manageInvitedUsers /jsp/roles/manage-invited-users.jsp + + import + /jsp/dialog/import.jsp + + + export + /jsp/dialog/export.jsp + + + createDiscussion + /jsp/forums/create-discussion.jsp + /jsp/forums/forums-details.jsp - - browse - /jsp/forums/forums.jsp - nextItem /jsp/forums/forums-details.jsp @@ -996,10 +1008,6 @@ /jsp/forums/forum-details.jsp - - browse - /jsp/forums/forum.jsp - nextItem /jsp/forums/forum-details.jsp @@ -1009,153 +1017,45 @@ /jsp/forums/forum-details.jsp + + + /jsp/forums/topic-details.jsp + + nextItem + /jsp/forums/topic-details.jsp + + + previousItem + /jsp/forums/topic-details.jsp + + + + + /jsp/forums/delete-forums.jsp + + forumsDeleted + /jsp/forums/forums.jsp + + + browse + /jsp/browse/browse.jsp + + /jsp/forums/delete-forum.jsp - browse + forumDeleted /jsp/forums/forums.jsp - - /jsp/forums/create-topic.jsp - - cancel - /jsp/forums/forum.jsp - - - finish - /jsp/forums/forum.jsp - - - /jsp/forums/delete-topic.jsp - browse + topicDeleted /jsp/forums/forum.jsp - - cancel - /jsp/forums/forum.jsp - - - finish - /jsp/forums/forum.jsp - - - - - /jsp/forums/topic-details.jsp - - browse - /jsp/forums/topic.jsp - - - cancel - /jsp/forums/topic.jsp - - - finish - /jsp/forums/topic.jsp - - - nextItem - /jsp/forums/topic-details.jsp - - - previousItem - /jsp/forums/topic-details.jsp - - - - - /jsp/forums/create-post.jsp - - cancel - /jsp/forums/topic.jsp - - - finish - /jsp/forums/topic.jsp - - - - - /jsp/forums/create-reply.jsp - - cancel - /jsp/forums/topic.jsp - - - finish - /jsp/forums/topic.jsp - - - - - /jsp/forums/delete-post.jsp - - browse - /jsp/forums/topic.jsp - - - cancel - /jsp/forums/topic.jsp - - - finish - /jsp/forums/topic.jsp - - - - - /jsp/forums/edit-forums.jsp - - cancel - /jsp/forums/forums-details.jsp - - - finish - /jsp/forums/forums-details.jsp - - - - - /jsp/forums/edit-forum.jsp - - cancel - /jsp/forums/forum-details.jsp - - - finish - /jsp/forums/forum-details.jsp - - - - - /jsp/forums/edit-topic.jsp - - cancel - /jsp/forums/topic-details.jsp - - - finish - /jsp/forums/topic-details.jsp - - - - - /jsp/forums/edit-post.jsp - - cancel - /jsp/forums/topic.jsp - - - finish - /jsp/forums/topic.jsp - diff --git a/source/web/WEB-INF/faces-config.xml b/source/web/WEB-INF/faces-config.xml index 59a72d3c1b..cd1fce0be4 100644 --- a/source/web/WEB-INF/faces-config.xml +++ b/source/web/WEB-INF/faces-config.xml @@ -1279,6 +1279,51 @@ #{DictionaryService} + + + + The bean that backs up the Create Discussion Dialog + + CreateDiscussionDialog + org.alfresco.web.bean.wizard.NewDiscussionWizard + session + + nodeService + #{NodeService} + + + fileFolderService + #{FileFolderService} + + + searchService + #{SearchService} + + + navigator + #{NavigationBean} + + + browseBean + #{BrowseBean} + + + searchService + #{SearchService} + + + contentService + #{ContentService} + + + configService + #{configService} + + + namespaceService + #{NamespaceService} + + diff --git a/source/web/images/icons/create_forum.gif b/source/web/images/icons/create_forum.gif index fb8e08588b8c1060e33d60e0e102371e5a51e985..982f2b0434443a1a2e4a393084334714c5e22e1c 100644 GIT binary patch delta 486 zcmVuQzLxIBb(UZj?W7l|y!%OnaVMhNoPIs9=ey7gvQX zYn3l-mMv$HK6sx*d!a{tqEdpTSca#Fl$=M5uwa0ZtjyhiK8&(mpukR^!Cb~FX$K&p2w9;#~({;Pnd%oCzz}bq$ z+>glKk;&ea%HN*P;-S&wr_|-B)aAV1>%rjc%H{9Y>+{>~^qsrEslmgfzrnc3$CRzB z#?Z_7_FnmuwE;dG)y==!w|m;Sg4?)=*s_A#xQ*-C#q#CZ|NsA!5dt=UA^8LW003;6e1wu c#s~``7$guBFO!K0kPs;tkTFxoL4g1OJ7#n09{>OV delta 761 zcmVh$4ugZO~%a6R$ zpT*hF;_MlFsT_f>9)z(Wgs>xpu_}nOD}=8thOjP)vM`IZGK{q}jI=e5wl|BkIgqzH zkheUJwLOrxL6f;fmAXWdw?~q;OqaV)n!Zn)zE+;VS)ajwS)jpPpul6K!)>X?ZmP#~ zt;lw+$=dAn-|X@oh_ySO#W|S2LY~7+rpj8a&R(z2U8>4pu+U_((Q38RZMW2Hw$pC6 z)Ofttd%f6vzSw=f*nz;=i^bfG#@&s^-ImMXm&@Rs&f=TR;h@mtq0r-_(d4St=Bw4_ zv)Smm-0Hi3-Rr^M>&WEqT(8exu+L$!&}OsI zYqryGxYTvK)^@wrdA-+qz1M-k+J(d0gu>c~#M_9(+lj^8i^kk$lA?{r-HylIlgi(i z%;1^L;hxXpq|)T2)8wbr<*wJ~w%h5v-s{2O?8M?U?aJlv&gbyb>GIL&@zdz=+wJt= z@b*%SpjDWuVV$jEovdr4ux+EUb*Hm`thZW-l9aBik@`Xs+P8b!xPsfbh}g1%+qjM9 z-qe#$0Y8&)0UeWY0UeWY0UeWY0UeWY0UeWY0UeWY0ULiI`2+y~0IC2i000005C9MW z00{8_RS6uZfPeuODNvLUu_3|0fdg7h3DhT#9VBQtxF~SIzzP)~NSuhG=MJ4WK{9~& zLj{l&Cvwu*2;rno95p>Ipy1n8dx59AmV1tnK3)I7!s7I6rw|gB4`lPBMcZXG-ePYW$KbB zP;3-fxY30RjVxAR3>q~_Qlw9(R3(@o<4Oz%3>1a36baI!N}W)ta?zlQgn_9%Icmg6 rQ>uX&ULb(2X%nSPm~IP1us{IpRH-;27ruJ;LxBmZpG%*vDj)zmuS}Js diff --git a/source/web/images/icons/create_forum_large.gif b/source/web/images/icons/create_forum_large.gif index 95334651ddcf752df924d0e9b6105247eef5f345..0afcaacfd0e09914c79befb8d222b9324e17f095 100644 GIT binary patch delta 1427 zcmV;E1#J4h46F-~7Jm$HpcQkX8F!^1d8Q$Is3w1_CVr_Xf2t{gtSo`6E`h8sgsw1y ztTuv8+xc4d8QnDs2zT*9et`Cd8QtFs2_i)-71==1nGoWnYmyg{GEKbgNafuTg2zeu6QOQypP z%~YkwSgg%ksej2{ug_qx&|9g7Bx7+Hs*yg?7>$%zIzu)Y`;qArZ?tjVT@6YG)(dhEk>hsv_^yBgO z=kxeoug_nw&t|jHX|>X8w$pRE)pxwtd%oCuz1M%h*@ME`gu>c~#M_F++>glKlgi(i z%;1~O;hfIlp3mZ+(Bq-eb~FWz~Jn};_b%c z?#t%z%75kW%;xaY>GIa=^W5(B+wJt;@AcsD_T=*S>h<}FyUU@>+UWH7p2pF;+2ZW> z`N7xQvc|^O;^MQtwY$N$_VhXT^-%ZqR`~W_`1WM@_G21ZjQjbV{Q9x{`+vaw{KfC%P4DDX@8n$YDNi=*jeh?Ve;sk>)L$t>96eDhxF>lv8j^o-n7=QRo1Uo*05dHuwU1)Y}c`F(4=0` zq+`*gY0;%?*s_4wvVyjjZ_T%x(WP_IrgX)icDR;r>)FN9rg_Psci+FD^5xn8|NkNR z1d|X08GnNa6Ds`IuiwIl1O4d}I8UBHef}UO)F{(3Sibvq1$4Hhb`Jfa5?ABc)31$up|guUom& zp?mTVqrjm^lnvD>S^@tmCCbj6 zG=B^1*zv?^PMk}YY}r~-P=}yFZ(q4;6{t@hJf6tGMgg15kx3kHuu%ybkc@FcK@Omz z3M;LwB1kHIkP?a=o4B#Y3vRs81{-ToB1t4;ctJuzIPB5KAE=;miYa-7QU@mjPSU~} zm8gM+B#@LL#ur>9P>>Cw=#d90dFU|;9)EV=*oGQstYC&2XG9_-7+q`;Lk0yc@Chh* zlzE4A)U{EGBxRfc#1B4P;YAmVKrsLY1|cv99h`L12`8Fl;szUPNJ2&!B^+_Y1}jFohLN5P{GOlvHBLs%!Xo;uv5siIRl~1AlE0 zgA^!qfRF-_oMDC}SDrz}7-2NBh$2?ZKo9{<7?4l~HHhKJ7-Kjh1{jTSp+zE8umI*j z8GN9DLKuV~L>G)OQpFBC+;9U8AmB+*5&}GwgbG+-kw^*~D5|JQ2NB@}6;V6@@IoD+ hAO#E?9K4VLOAz4jLK=7=@5BiSkO&0E90ME>06Wjy5F`Kq delta 1574 zcmV+>2HE+n3%(4H7JmqCpc8VT6?LQ)bD|e^r5SgnA99^bJ zx!mfx+2_CC?9S)$%i`?R>GIg@^xf|D-|zO}@b)g4!7`e{Ii18ip2R_+#zUgVN2JI} zrO8XC$xWxqP^rsOsmoKU%vP(+SFFujuFhSr&tI_5VX@FV>Gb%0wa0(9$c4Ge zm&ezZ!Orse`+lspywurmke1iy>X56g(cj>x!GFT9yR`Q7Ir#Qx`S*1C`H%bhr~LfF z{r%SX^;i1%gZlW3`}v&w`myihP4DDb@a1mt=7H(gNb1>L^5~oF+k&g6ko4-u@8Po6 zuT|EtUDvT~*3Q4sq+ZdaW6`B**s_7kwwlqVbjqT4#-Mh@pLN2Xb@=k^-@l;$|NkNR z1d|X08GnKO`W;-z(4aqm4I2)LzyN~9Skh#ev1e}#3~AIN5}Y7`QHEz3kjb-$FP}Si z`s&4#_CVx63=fP&LS_URq-prPwe!|Z-L`r_Z0Hba0Z1c9kB&WZRLy0#ZsWwA+sABG zf`LTBiWRG)M-U;28dbX&ZymR{;=*Z52ajEhe}6*~@c2=If)5@$a^Sd8V+M^BFQTzs z7j9cPaN4rbWrtcL+HK!_Kh62d9B=-crlDvqhgJCfBqF{7cN?N=D7a>bK@F3 zdVl-Sq2o929W_!V8UzzItiG_%g@F4ZT_;W(Ff~|nO*78C^A0nwPy}^4bEJZb8>EEtNg0_~0>TQm^nuGQxb$I5Ewi{n zD8lG%|i6v7wutFZQ=s}Afv*h859jnN33LBw#{~|^gPk*>T z${L}daYh+pe6ht88{}07D|ZyjN|$oLVah0JbfU>6RxqK07hZ%>h9;PFam5J-T<{MH zaik*09CD-*#~Y^f2?{5(Rx$|^5m;cs0AF;W1tm#LFpvmrv{8y1rL@7uD4~GT>8Dmq z(!>!K2&4lNQbYm807VR>gBNM2p?`52pq#yPBhVk(Pk4N0M-UQ{4)V&3j~Bj9~2wia2wtt5wJu7 YfZH@d2Y(md5C#G$ZW9KM8x#-#I}ZFn*8l(j diff --git a/source/web/images/icons/create_forums.gif b/source/web/images/icons/create_forums.gif index f2e52f9d45d8d9c84617202525e79f838cd9a4c9..b3f9b04d9f550ad399fcdd978d2dd50738b78d5e 100644 GIT binary patch delta 522 zcmV+l0`>ig1@{DhM@dFFIbje05CG-?00000|NsAXkExQSxSy}TbdINWkEnl{vLjZ4 zF>RGHZk9K2m`Qw}8e)(nXOb&#nJQ|NHg%m`dW$fCsWE}7TYZjDsLN!s(Py*La=F!y z$K9RI;>hIhak+0(2>FMd{=;-I?=jP_-<>lq%U3Q#l^(L#KRrK!@FMd_=H}()<>ch#$@($Ue;(9qD& z&(F@z&dq<#&CJZq%gf8k%F4;f$;ima$H&LU#>U0P#l*zK!^6YE!otA7z`wu0zP`S_ zy}i7=yt})*y1Kf#xw*KwxVN{rwzjslwY9Xgw6n9bva+(Vv9YkQu&=MLuCA`Ft*xu8 ztE#H1si~=`sHmr>r>3T+qobpuqN1Upp`f6knVAHc|NsA!aRD5YfB_4WjR6yX=74g7 zax+^?OHNW%SX^LQGlOzpGA=GMG&wy%NK$BnGgLG)Gc-3lKtoDWXEQ}hPg7W4V_QBy zK}SwhXi_pTGdMm(PFP<-ModyyYF0NjI6P5FPgr7FPf=D}Y_&ZJ4RL{+F@;A zMMXwcOFBF%A}bppAt!HTP*727T~^xh$4wd=Fh5WrFhBr=7K7Nt`7vk&ga`^AIKU}L2%AVP ZMzoN?q6JYoFLXp2WCGIEt5^d806P&kAsYYy diff --git a/source/web/images/icons/create_forums_large.gif b/source/web/images/icons/create_forums_large.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fa7b794bac179673cd16c918af242052bf35677 GIT binary patch literal 1586 zcmV-22F>|LNk%w1VITk?0QUd@00030|NjPTo)2!G6?38;ccUMArzL-@C4H$YeyA*e zs4j!8FNCf%hOat@tvrgcJBO}4i?U3TwO5w5bf>{}sKRxq!HK%kfv&`nx5|>Z%bvc@ zpuf+t%Ga>T*4f|U1#F%NZlDTrq6~DU4|k^zbfgh?rWb#$8Gx=BccmSBs2_u`Ab_kP zeW@gcu_lSNCV;Cch_Wq;vnztEFpIP}iLgzHq;Rp$fVk1F$kg2J^~%@X%-P=-fUX^g zwH<}BB96K=m%lcZy*r-8Ihnvbox?t##X+IRN~Ot3qQy#|!%nBlSgg%it@ZY%vY?6DNi=*jeh?Ve;sk>)L$t>96eDhxF>l?cJ@`uT|EsR@Sgx*05jh z-n!SZY}c`F(4=0`q+`*gY0;%?*s_4$+t=8#g3+aO(WZ3Ap?1Qab?e#1=i%D#>Eh6( zc+aDE+Pjgwv~=;-I?=jG+)V!YA^8LW00930EC2ui03ZM$000R80RIUbNbuh~d;0t-^rz3>yMf}w6`V-W zo^BwjOjk{`ZwErY)7 zDDxXMYTJ?#)Amf+HH!V@1r-W&oy=9!R1H&=>X#{JP~*J>if(LGcI>ig3pPtuELga- zNhHW`!M0oH-moi|kOucGF3RJIS zhz0g@XSK0ubrLREN~0rErfRoFi3;_p*0ys4@6|)g&Z=+U2qsZNBk7T&W}a-Z>O_kZ zvvDK;`E%EfH(IN_7d$$1#!Q(_$C_FHQ z#|jESP=F9e1ff8rTTV(3L-bt#s)8R_VBtp}dqiOe5^$i&(>&5 kjjTv)7i1AX`P^d<&k*Ym!w=ncQ*=;53pMmm*Z~0mJApiXY5)KL literal 0 HcmV?d00001 diff --git a/source/web/images/icons/create_post.gif b/source/web/images/icons/create_post.gif index e38a2b413e63a4afde7c7d4bc148ab41cdd7974b..e01c5ef9cc0f77d14bd2c228d536e1ec60ae3c07 100644 GIT binary patch delta 710 zcmV;%0y+Jh2>J(qM@dFFIbje05CHc800000|NsBL+05_t@&I5h5^_IantK~{LnVGp zD1J{nguBW0O^XwAiV(*{WHLMYPqXzTK`s zZzaIquejBwzSyb9;TMrvL1*|LwK^?Y95)((Jh_ z^1m+m$vo_TzCQocPwc`_|JGdp*I@tJZ2#ME|J-x=)^Y#bb^qj(|LCLt>Z||kv;Xb4 z|L(m1@WcP|%>VPx|Ml1Z_1ORR+yD9J|M}_0lNijI8qAs=*`^`PnI`jshAqWVFV~qSLS&)=3j6Hta>7ZJ(~KTT(y(J2#GX9smFU literal 1052 zcmeH`TTD^`7{^c6nliW0)R{UGQCpXpINQ|RBrQ!_FU@>uvurlqy6Lj!mYJXy0pewD zc3I|BwDpkCRNS-_F~x!uW85_1a1jm{^&F7HK^Q@;r`~$*d-%V7|Lynt_7xQuW@T64 z0X%>L!SVb36XSdfWEpus;`RDa)a`WcAc(_evsfw|mFs zayXrc!vQ0R#cDMeje3K@U^IX_Pz!1`T8-OPj-hukv<`FAJXnv<=iS`2Ly*~QHknKt z8yiNWF|eQqL9JG+(P-A!*MF?7t?pvI-rXsmcL9bjAeI|WI~&~=DaS6W#;&Nw%T?nQ z@{uw*_o`~VTFtLf^J^8n+iLzp^#pBog0B1!$Tq9$vtVp^d5&*Te$~krjVdv(m#JU= zxVAJ4$`-z_NcHkBh*7mNH?b-abgD1Z}Kh;#U6^}kWx-H5TdjP1xr*?K3xXrNH|VZL?R_!TNFY|J#&4gUMft9&x`Q5 zD**c9fw+_TP0x7)^jBe#$q5t+u_KajIJa&FL@w^dMIY-XlS0GT2^n{kHQDp57nDkA zIIU~$8JnF3vMBd9#C@4D`@7S524YHfSm@Ej(rN+mEF+_doNMYJ7Ca>!$)W0I3Bvm& ziE*#1B}w6JnPzfBRcF#UW(>Kc^JM`+SRV(;?IJ1ZeCMawm~As37ad>5y(SG|g2zkW T-QqR=nai0!ojy*aN}bchGy4mZy+v~mF?Y`me zzT)q}w@Zz52&TZDD4BV_6(xxEau_W@rEcC=N|IIf4&N=_iI{(i- z*|9kP(MA8!M*q@E*|R|M$xZ*%QvcOe|JGXn*IobEVe-vf|Jh~#+G+pVYVyxz|J!c= z+;RWha`Mq^|KEM`)Og~?aR1ekqwH@raA=#=R^1mqj$ua4=E&t3k|IInptT6e>I{(i<|Ia|?yE^Q^Jpa%`^2S2{ z(oFBgNdMDM|I<+a)mQS$Q~%Xi?8a2wxlsStU;o!&|JY;y*=PURX#d)5-@jo0+i?Hf zbpPFV|J``<(sKXad;j2r^3{In&VB#mkn-4z^4gOB=A7)-mjCFZ|LUv%>aG9lum9_? z|LnE@?YIB!xc~0E@87Tg?!Eu-zyI&R|MAK4<-h;)(Es$)|Ml1Z_1ORS-~adE|M=to z`s-#h0RR90A^8LW00930EC2ui03ZM$000R80RIVuh3(d?g9sBQyoC*xz=se8qMAj> z+^UPIQkgPEZk#7@newE8wrduuh!E?|3MZ?dOIiE!*`qhFow`$ZbO_<(t=O!3CJ`3NVDl|)HP4+YbVXipA+m{EHf6K4 z&LZc^-Yb82^X8@Uf{vFSn6^<$6gTKxR;}pi)l0>NoH}AsJa`a!j5NF&JP$*#^4>-^;!wL^Dx78(~h@zo}p@{QICs&|=MR!mb zvBM2E$PmK}EO4;F0v-r7%Ost2^2uU*osdKmJ3Qco6H-(GLj)K!Z~y}r$oR-6n|y=g zUL^owLl251Q^+5)d{Dsx2NWQIlH7PBrkLDpqfI50NCHV1B&;AsGKLW2M_eXUU_b#6 z$mmQqm003uCD~ANO(c*w(g-7AKp;gS!vw-hVGbxTK%V~u(?>PdM53uR)j&dxp^Pk| z$TDO|F$^%j;1bM35(q%)M8-(4GmRtDNF&Xm&xpFrA%+}d2dcW5^w0$ad?^q%v-E+? zGtD%!h^WjY!|O4_2m%N%xXgkLL>wTH{40gpD4C z^m>divw%|1zWi!+!2_^G1j{Uc3^Iryx$vRY!dmfx%P+t5LJKGiR}2v;v_PE8Ef#ky tqb|SHvaQD!M`KH{BzFwYEP6zfa>oV%^>W3UtU7bWu)uTk&Ljr}06UG3Im!S4 literal 0 HcmV?d00001 diff --git a/source/web/images/icons/create_topic.gif b/source/web/images/icons/create_topic.gif index ec62095a671bb0b64ab6dbd29f60c9a40ee59990..d5fc3d5f11f818139972eb3ba3705d5ef33baf26 100644 GIT binary patch delta 498 zcmV z)~{B~r&G+STGp^%%&J@2wrI?(W6Z2%%&u+n(1r5Tk+X|Bzn@*krexZ;aN4(V%&&9I zuy)L`dd#wa-_Nhinmf#+R@ud$?BXKN+P8b!xPr2hW4xSg#-?}MxQN)Yg4?)_>)FL- zGXV1C*^@p3Jbxki1OWg5Yyd0(0000G01yBG2cUp#f`f!p8Gynhq delta 849 zcmV-X1FrnT1e^#9M@dFFIbje05CHd)3nqW`?T+{G$p71I;=^PA-FE-pdg8`!|KNiE z;f4RZHPWc-?1m=w<_ki zG3L59=DR!GvpD9wKmXHE|JGao*I(GRRo}i{|JrN++HC*abLPfr|J``z$ZqDza{qtd zf9A?}|KW$`%Y5d`egEW>|K*tf=A8fQu>b6}|L(j0@yGx2%lz@t|Mb=W_1NFBKkdFt z=(|nYuSnUoTiLc=*|uTUuU6~9W!A7?*|uofw{Y6Gao4eJ>esc}w|m;Sg8%H!`I7m|HW?q$aU4yyBh8N`2+y~0J{Jz000005C9MW00{X2cL^LQLV}JQH)_z3@!-S2fi8xG z08u2!j|~=3=$a*~qbxI`MiCL>p+k=gDPq0SlgG}SIBqh10^(!CjtM7R;kk0BjvP2` z)@b6OAp?#XCR)*n^vDsTL~PVl;(?(;1Q;b&H3|jFe^Vz;gvJP>U<1Mn79=peS)>Tj zp+aQB{E6Yf$qE%CQW@HG$nu bQJ|y+6LDO#9`4FTy$N;V(xt;17!UwE3}fgT diff --git a/source/web/images/icons/create_topic_large.gif b/source/web/images/icons/create_topic_large.gif index 652754cbac8a9a890c65f438f758fe13d817ad6d..8adb6d4c9a5ca7353d5fb91e3b2c70053c676416 100644 GIT binary patch literal 1331 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 V->@yWLjK5echeN_16@!+06Q+%VuAnw diff --git a/source/web/images/icons/edit_post.gif b/source/web/images/icons/edit_post.gif new file mode 100644 index 0000000000000000000000000000000000000000..0cb440496b515abc2971e90984a759fb87e8d76f GIT binary patch literal 519 zcmZ?wbhEHb6krfwc*Xz%|Ns9F3yxm6X!+7*%MYA5TeSaK%h6{Q)0gjg`G4ZV$1j!y&iXFzxBdUPIV0Bm|LbMx@y?rW@YC}H&+hKsyl&3fwNC$Ug#N!3`~P-w zZmyE*^wm;8U)TafDb|M|54Z#O)MJnXZ!vsz_#L zzNFLAZq%3C%#)RsTO&$?CniE8wHCoMp}su~-R!uOD7-1}pMpP_hfj zg|tiB4*(=Gn5h|=yZ=Du?;yB~i}a8;Ok6QSN-fIFlzu3dS58BffoL{^3Wr>|a$p)q z@9RW2(6AW(y=Bm?gJlmc=Hw*s`JE`5mVTDYjgpti2yGx3LSTXdlM(Qc1rOO^bu*cygy47Nw%uQ9?h1Ur+kYl7WrVnt7^81UI4e0D^dFNX18 zLK_5z_f4t*T`Qt%CBsBGOh&>a1Fc5Dcp9d7Fck-;bMPn;rjub>Ak9MH@dbF21v3|6 zCKqPKFn0;&E`vE=n23N`3iE}qPy!33x~?o(lmq@XKL&xNYhby-Wg_sj9acMFO$FJt~z7MbVa)mZqjArBbO-DCBZ^QBjdhCX-5~5{V=)FHa;A z<>uxJg+hTqz~}RMJRXtr?5L?#Vltl$J8t3zUL@v&(gq}2Di|UtCCMIvO7yJu-;xl84sL%&tAtiON~ce z-9*BQIU3!D(`#3^Fw}_CuO9kh&FqXzne~B!JB52UkF2-R*c)2bd_ja`TE*s@C0lNV zifgYWG&JbxQ*kf4e`c<=q|k@cHJVxnbDyoP{X03?#qoYBQh$_#Pf0e7R~Xcf9dE*7 zu(v!mTsgAV%>91*v6W4>R$=0NIU=l literal 0 HcmV?d00001 diff --git a/source/web/images/icons/forum.gif b/source/web/images/icons/forum.gif index c7a167b47d962b27ac3a505525813e50952179e7..7ed3b5d93316e8491ba52c5b9b50ab1c8341e7ca 100644 GIT binary patch delta 650 zcmV;50(Jd@2=NDhM@dFFIbje05CHc800000|NsBrT zlCO1?uP0-VNqL@HhNoSKsA7t$WsIveaF{o7m_d4=MSP)uNPVJ7exgx=r6OjMC~1^6 zbeuMEm^pTyJ9nNvc%MIcpDuc&GIyXjf2T)>t4fHhn!eINh^|PHwN8|`Q=r0Gp1;iH z@Xq4vSEtBive9C!%Wk*Sc)ZttzuAJp+J?j1mdoIk%HNmE;F-+fmB!ne&EcKS;-S#v zrPAc5)8(pv)#kC-=(XDEx!mfz-Rs2S?!)2j&*$;f>GIj^^xyCH;qdlvxYTgC)N{Jk zcf8hnzSw}k*@3~?gTmT`!rF+$+ls~9jmO=O$li{}-I2-Ol*-?i%;25R;-1gqq|)T2 z)8wes<*C)>tk&kW+v&L6>bl+Pyx!}+-|NQX?#ksB@66`#&gbyb>GIL&@!an9#qRhzz9oW5F|y>F?; zd9TWSvCEIV(x1iI&*JP9e5w|Htr>f%9D%MLgs~xnup@=BBY~|dh_fn%uPcPFErzfz ziLx+@v@(pfG>o)0jgG!$ab#DzuD#5?DXI4@)&}!9f-9umAy8T zyE~r6Ihembp2R|)!$zaXOs2|Cr^;BY&04L_Ua!wxs>)!n&}6dFX0y_2wbO04)NHoX zZnxBUyw`hwz1V!d*nPg(fxy{|#oUa>-HpcGmdoIm%ix^O;+xIkpwQ!?(Bq@gbu?R!Qbo1OWGj>p}T%HNpG;F-(&VMn%rjc#NzGB(dhBh=O+1OWg5m;fvQ0000G01yBG2;TrP2^`qqK!O@F zVz^i#g2BLn25ywOH0co|Eq_MfK%gK2jTt6dz!(Fmk)lFVK%}T-#u6DYhyWc?0cO#m zKu`@!>cHW! z=gtx%ZYY$nLP(GwJx$`Yv7iJAks&`Ygvj#*j~zNigs7>|f=7@Y1R8WeGDl94H*0#F zIe`g98V3R}G0*^njgJWt9$aXE$wrO>193<|li}gO0S*U#(6PX^KpdF|E`X5Rwrd=< LeG4BxFdzUsVHt>+ diff --git a/source/web/images/icons/forum_large.gif b/source/web/images/icons/forum_large.gif index d025642a8cf1cf8875a99a94879415e5613ae3b2..96e3b3b5b5b6989683207df1dac2809a515d60aa 100644 GIT binary patch literal 1511 zcmdUu{W}u~0LRC+v*D3EEU%eHBrdMHxZJflZ%Z;u>1EZZxW`N0HIic@E@|X+D$LuM zjd?p$-Zq=r*vw|wyqkBUvh;S(J?GA!ai8b=2Yi0`e!S6MF0R3F037fcu*dH1E+Di7 z6#hypq7)igsuNAti7L~NDc>JoWs+14Po^MJ>%PrwaLS}3^I9>*ucPY+Vrl#sDldsK z^lOXoX_vITU%?R1iItoC;w$&ZRTw5#8{MNEAW)2xYfVz?O_OWQ(r9KWb>{c$4&JY` zOr^rpXja5Vs|Qq@hm0eS+a0r;PCR8gXEmOD+VKO4dAgv(=l3^$CEX#lJUqEKx?%8F zrsNrWqF1pzvA#XGsb2f=W$V*l@T_Ln;%?L{_SqT%x{~Mn-^w}X$Q(=+4@=<(RB!^T zd6(&;s|~}~>W8jT1vePt>kT4&(@043$c;Mwtrp2IZPMHH!SFvvqnNVD_R+gcSp-8E z)g+30Jr>(COz4`p-z`t;RS?;e8C_%9oT;q7$voc7lm00ZfA*PRu6Ss^m_Jh@TzDZ` zC>>UkM;6P)$|}hcWptS;Tc(YzFeX-;&&T*&KXtrtg2^jvu9?bU-@=m@vUI# zooMB~cy(K`xug2{)xCn}OA%nHLlp?UP>~VGg)DsIZ!hj1$5|5#X1c<6ewXeY~NybN# zP?cP;3qeB%rfbZ=wf`+7Ui8j?X`+7)CM3@nHzK=Jz|urou>&bV+2xEt)}jui{WIN{ zr5d+9)3(!9A0KXLcEYbzTe#p3vpka){&hXx5Jn5Eo~_uu>GqS-DW+>~|cVL;e}F55*>|f2aNU{1H=dBpqvXMeo(A z2xPJ}fw~UV?o5N~9Nx4c|CEBOA#y^8G+blPvSUXN8=CsR?8AiH}1KRZm=;0VPq_YJ*{sl54PxYpg5{-xLiG*H_w<@{}YUl~HS?5yMXz}jcX zfgmp^!j zPik)ZJi{3Zb>Qj)b^UO`o(TU`I1;Q0WqFxZc2w9VM^sCc#(2UuA96AfqXDvYFvvRO z=mrQV4NEWdva6^r;MuN673SI$x`p&>x$0W8_WPO_vcMo{6WaC;L0O;m0>t$ZSm$4M z2G;?{$nI81IEDnk;|ifB+|W3vagmQE8W!l0;iFlhUBm{Ua-2{o9r%K$%}tCNT!h66 zAci@*0nd?obSG97Fc^t6$ag!$KwQD2z=#0r%7^-35LtM2gFwgkKr1^LOD!}?cj5zV hL|tk<%`fn#VTUvD^nT=H<(^u-qM~uNDY!`d>dJqvrqs delta 1591 zcmV-72FUs63%U%D7Jn0Rp%rzc6?38&cBL72r5<{xA9$r8d8QXIMV-M&p~Xt2$$w6#%1@}vRI1Eatj$@i&RVU` zUa!w$vCw0((Pp#KYPHjCx72L5({8uaaJbcSxz%*K)_AU8 z>bu?RxqsQ`yxi%(-|WNT?aAct%jNLT=kd$p?9=J;+3fV#>+{|2_22LI;qdk@n87oe z!Zw=0Ii18ip2R($#X+IQL!!q=q{vC7$xEimO{dCGsmoHS%Tub%R;$cctj$}l&Rwt1 zU$D<%vCw6+(Pp#JX|>X8w$pF8)N{Jkbh_1cyMNYuzSw%b*MGp-fx+5%89U!Qkx1+{&`^V;q7-tYD1^Z4cR_v!Tb^7;G!|NkNR z1b+bl0RI3i00000AOIi$00{p8{|OvOu%N+%2owJEP{9EO3KJw0i7>>$j~)yfY*1Jb zgN0cj{DIhaixw<-r`oA22X2W3jsiav$(L&%7k;?#$(k1rm8f)^zG-U`1?C10v})bb zcgt2idh%4c1Jy|!rfk*_49vo{Yu6}Lu76-*WsjCDSg+ur8nup7xJ#5G)mWHdiWLnR zs!Wjr<%ts}N|4-$&}yE%Ri{XW>O}6FrAgChcxa%dABcXrYRP(~s?;ZQ;4E27vLK!+ zRHQ(8+LQ^dBxy4su*!!k7p{CJU7Z@0j-0n_lA;BnQfgEvPv$gX+6H;ij3M;u*?+rd z?x#Vmy#Hk6tW#hEMa}6nfGlMSqx}Ge<5HCQH{; zI&O zOdxx#A%ruCEK>*}g9QK5M;^SC-~kSkU_;5S*i0e`B#uDSj3LJm6AT?@%1BBn9lNCQ#YX=`aeqb}aIhi576V1$harbVY=|<17*otJ!Qc@`8)%eqLKXsT zfr2h+m;nJnTNE(IAS??)%rJcfb4M?5=z<0rDHPQ(7-hInZ9!2SU`H^)0CUF}DyV>h z2_}%Bz|RA1K|&cJAmo7zy~H7h8$7@yPz7FGkPrcCq>)A!P;-=p05E9-9Yz^s4B+)Z p94O>L3T3cB@Z2yB7f=QPe9w)+33~^w&<6q-KKBQTH|}^q06Sd{FSh^y diff --git a/source/web/images/icons/forums.gif b/source/web/images/icons/forums.gif index 9038f3165019e87995201b05a0d02347cd2f4cd6..c5864c242bd8948f3e2910849f46e95eeab50eb0 100644 GIT binary patch literal 648 zcmV;30(bpKNk%w1VGsZi0OkMy00030|Nkpheq4N2KsId+|}$=McVlP-FsIEk=8pvFg^!&a-!Sgg%i zt7mdoIu&*Gubh)8e<=>bczNXSC93wbF06 z)Nr`ehs4{C$K905->B5(!QkxB=<(a_^!@$){QUg;`}_L(`uX|!`1ttu_xJYp_VxAk z^z`)e^YiiX@$c{N?(XjG?d|OB?Cb06>gww0>FMa`=;!C>=H}+*<>ln$U0P#l*zK!^6YE!otD9 z!N0%1zP`S_y}i7=yt=x&xw*Oj|Nj6000000000000000000000A^8LW004OaEC2ui z01yBW000N&fO&#>U2Sh_YjAE|gN<`%M@ULcPEcudjd^rbNl8jeO;1r$UUq|YS4>Mw z4F?bp78Md;m|bX2PEAb+B}PR!G#yrKU2ajW2L}TaIX5;yBv)B)a#FlTL^UxULNYHR zSXy*%Qw2IZLqRShFg+|GSzB{(RR%&rGcYY187LqMTe!@bbA^D9A3Rp1&~SwVg@9h_ zyvZT~gNhR$E-1*dAVC)|U)~hc!oWlXEn2n&{P-mfBRXTa2ynoKOBa@4%3u<7hs;ec iK)-+qV+KzqI&g#z4I@TQolJtdys1Ogj>txV002AeAzCN^ literal 637 zcmZ?wbhEHb6krfwc*Xz%|NsC0`Sa)J&!0bi`t-o1VM_N`mDZr;3kTOTv}xnUjT<&> zSigS#x^?T;u3fuk&6?G#SFc*NYURq6D^{#nzI^$zWy_W!oYs3!LP}W!%$ICMMGQ9 z$jpGF+0T@nnVFrFPe@!&!@ikAi<5(clSe>QQbEIxLt0T)Q_sZGP*_A$}ljE>zcb5}EIX&G%renByn z+s5X$?$&B*>c%>L51NclM@}>gI+lIlXmaroQ1YIo zVVUIIuz=m8havJnk%zFN_l$s!Cq>H?xI6_+GLwn~+7u_wITNx_Nu!b7kyWr^%9hLv H4h+@+NGhpbBxK40NRr zcc%|@q!D+f7k{l8fUX#Kr5$^yAA_$TfUF^XsU(H5CW*BsfU7BpvMq|UD}t;ngRL-& zv@nIPG>5M^iLh|7&VabluE^Bf?e)sn-OSnF%h=u)fUX^gwH<}BB96K&mcTTZzc!V< zJD$ZknZP`q!#$4aHiNutF{pTkb4%224wSgg%itOTFkjUPW$={aC;F-+foX+B%&f=WR;GxjtqtWE6)#k6)=dsx6x7+Hv-0H#L?a1Ws z$K&qP>GIg@^w;b2=kxg5;pF7&?k$(VFPOnHn!-1n!#$tHMx@9`q{vC7$xWxqQK`#P zs>@ZY%vY?ubak+>OWGk;&eZ%HNgC-x zqS51~)8wes<*wJ~t=8tU+32?0>A2kLyx!}+-|N8O?8M^j%;xaR+0(2>FMd{=;-I?=jP_-<>lq%>1Op(4xkqnoZj_bXXzYD;F(VSg;#` zPQ6yuEVp$>395rPOVP&Wb*(pf(QakFS*PThZ>#iFvc6EkaC6?U1%Wz ze&UEzjzZgPbK?Si_~Az%e9+>`DQ9S+gBNL#(FqurOhSbO;mkNrcl&U|O_d1Tkw+eP z)WJ#{poC$`4OwiG2^W+|5`_yTxJk~G`+OrOH#V%&N-L|NQpzV{Tp|e#4Nzdf6IM9k zK%(NjNsc)TnbXaxGmN5!8l!~&;t3d*T=7T@CU|qg3yr`af})GE(-1q_c|$-LoNyAx z7hG%s2^5U9aKbm=NWer2D3nUhq8~X#54GQTPy-f~P%=p*RXDOp5)M!Z4iPGFpe?uN z*z?dnUeeEGV&o#!*H&j;V`!e9k)htj3Qz^^DUp11lKO^2;x88#BY_po7jm z!wq!LJLJ3^f(Agt9P`5Fd~CE)5#i&G&|FVVb=5_qlMXy-Wera`Xs7)(*kPxWjyz>c zbdNphFl_h7RvYa$JNM)&g_Jt_gp9Y*dhb1tK1m}rQAPH|(~dfBtK*JQA=#`rK?fzY LP(u&h6c7MACLMwo literal 1586 zcmeH`{ZrBh7{I^0C{TtFYFJ+vAl|IpExE3-vKO`A_o&PXsF~t8H!Vt*us_ zu2!SbR#(@k)qhu3DoabB2?WB`we^k7&Gn6qmDSay<>hxvOS7+E&&gsCc z@{*DgnM5KU9vWS}fG78e&678c&VeLFwz8XtE$93#WS!$U(ugM)(u+juwI zjc#vib3?7It!{3M#bP#@OwDe5Q&VH(2a>^{cdK4B)YrRZZd;0X}2-MRe}0CEfX6a_{qB?c~X*A8XeNj5#x>!UNN zf*eUk#BoZWp_2`Jj3%tgl~S&Uz9K z)L-Eg4uO*w3WsC{t8IY?BoY(qc4rLCm&#k@fj6zhEOKfH1_5TUiJt!7`!Lz?>*c9% z-*mZCy6e0vCIVz$PR_(piX?PGd~}S(|LWswJU9+7k)o-We}ff(%pJ!0*zCNDRm8-6{Ode++cLi}w~xFc&|L z2Id5Bv0Nl!vx-Gd#E|ae?_t94WBBQddOvj7VKY7nPciJfX^sax?(D^y$cLgh5yT7; z(~MzY2wDD#*`dw5lSE8CJR4+Mzz5Gq&Da!1LKZF8Ck_e0U}9+StmtqKk>L{`35h#O zQ3UZ5Z#ROEFN_HxxL|cjxo30&4Tbah0SJ6(4$U&Ag4omKoxTiI;Df4@22%DBQWW`* z*qj4kN+iodkG!_diHBX3vI8H6r8HvgmsqHvJiCfU-+7*7A?H~i{hoXv zFILSy_`qBYjXXgIPd~W>A)MV4#2%b3qq)MIU)dAbU$JfmAbZ)MFe!h)tt9ogsc6+&qfxeA}!I6Nth>*vYlE#*Sw1bz*nx4*`inxfQ(4dmO zj-}C|rqH0O)1#`=qO8=Vu-B)v*r>JHskhpyx7ew=+pN6Yt-jr^xYnk#(W1fMuf^fA z!{4yS;#w$SFc)91L?>ATwNyx#4;;qJiY@WSfy#Q*>Q zlK}x^eYF06Xh7&Cmb< literal 949 zcmZ?wbhEHb6krfw_|Cu}+;1W}!CZQxqs$~H*~!jwlbsc&xF}9_Q=aCoIn!HjcCh}O z0E4-{hI4%l=J*@T^*5atV!1HXa$%V5;z--YQT9usT$U#Jtxoq}o$a`w(0xgn-}36{ z^>q;&3X-?fhpuXfSkoN6t~GvrN9yL@oSh9h+a~4jm{PWTX6?Rt)dza35A=5)pVf7I zUdy4y?T43j9bM6TY<2&s1=G(hn|gZPlv5jKpWV9b>gGikcdfXxf9sw7YpxyKbo0=r zo5yzEIeqZasRIu#9D98A;)^@iUq8C{{@KG1&mVq#_Vm;1*Iz$;`0?q}&#zy9{rK_c z*RQ{S{{8#+9}E~q!Dt8|g@EEu7DfgJe+C_p7${FLa7<#D&mrTnVZp&>4q>erjSFtA z+ydGs9E>is9Z(VtQ^-8z!YL>!Tx7G6@qwoxo82@O%cPW!2@2L46AC^sc(zK&%DE*l zK5^%lv$8qUFu}>GRf%chgaZwa-FT%8VsusnG%7g?iN$SkC_LoCq!Pw$_8=gsg+qWt jU{Zje@tF~$?WeBC`9h#~@l zi698#g#ZB+Lj+L}Q}LRbm87YeU0hjf+c%f{Cw3mr^Lh9kKa{VBXN(hI3*a+gCCkgp z(DI9im{=dyB?SBO?$W5A7_q*b-%#A7U9|8(Uh;8%YH)R$O9^^A<>VVKd-6j>FImEnJ8h6L9n zUXtSz<+m?4=9(5~zAf@_C_V`1M8=9UlAG?ND)Q1>?xrd7dBY91h5H=HUXElagnY=E z>f=m-ZKEOF=)SucetXM-A|)x<=A5jyf~zfe^L2DuFHbh1(oQ`Z zoFCg!3U{R=+!=mQ_DMMROtd&TOL^~_l91h6aJ{wQhKdO1h9)*%&ruO^ZH0$8=orbB zTn*{AnsleV7+D<_FHOO#iFxhCr|V;}jp>)0ucoxz$WY?$X~_j0lq5wav6E8RNhRrM z*rw!5O{v)`d_gCftS|jlcJZ7Xo36~hsm`Tz(a+1V*{U3>fnM6ppcxox$_%Q3R`%#V zqq_{JxmBnuyx()bqL<0+DbMS;U1?;o`zngM2$g*mM15XWKbzan_PjaSUV}!JQpdSRq0+dbWKV1FB)_vNr$Q4 zFeUAtmi4@p_e{(BUdsDt8V6^ahUS`w=Modg`6}<$KM{V*9J#wR4N@uRnAweC&9)qa)+_QkAjD|!-sqb$4E8mufEVAEVW9QoE z0D)O_7MVc82vJ%9X`nmQ=KG^Ki!W-RUk}akD5e{U58E53tAr&m{(fR)d1p@6dB*t$ zY;bTbv0bWJ@?Q{~ARR|skSdNdy)F)ve&yhA_Z=M6`_G_ZDDhaCJI-Q*hdz4JDiE`1 zZhtmnYlrP_Q8dD*;ptXG6b%py1Rq?Bhg%(%Ov$m?J2( z_5KL-O*61wWW)w#pp5ICju-*Jc&6Je1`xvj2DrurJWEemCk2{=>_oG0)0tD+)n-R2*m_{M@dFFIbje05CG-?00000|NsC0&p!XrM*q@E|I|_c)m8u1R{z&s z|JY*x*=7ISasS?W|KNiE;f4R=iT~u0|K*kc<(B{En*Zsh|LUs$?6Lptwg2t5|Mb%A zxhwL&F8|Iv`N=%&zCQocPyf_Z?7~q0)?EMBU;o!&|Ji7N|JrQ-+i(BdaR1zM`POm& z+;#umcmLpn|Kg1QD@~kM zHfU+CuVyDmoKrJ27#0;UFAgjvN1ReIXRoj$Mx0A85fKnBEet0K21J}n4Q9ozW&}c< zPYWq2C?*OBAOr$FIhs}__{2XKxo^0obHemEeJT2v|MR-;Y*CDtne4Gw^CB}|oybkUL zxJ`J`Dv)}-Y=`HnS8zb0csJpbJp9E_PhTY05lz~nXt#>At7y+6dO4n6Nu<3gPBuxh zYiM5@?thIxzQKd<@GzI}U&~#~!Q*XsTnOj))Vc+ud#G&(9WDk}Mn`tTrK9$})V>d6 zH5fO58u9WXgigHb#haVrct1qD@6BDj{S)3tlE^{0E!FtpOd!rqM`IYwN~s|Ntty<4 z@wLRDEe;nJ<5C)LOaiMWhGcYRplc<%R-yX~^k(x-Yhc*{TZwSF2#yNetHPsS;cOA? zM!0?l9faG07bAF0@R!^3^Axcrn9~P~#}(H7p|m!NEmqPKv24jat1h0L(h%cHQlCZ6 zts~|fV$LPa1>}4oX)7WfrKIx^>DEu^g7}JAynYTnnaJ)|v3nL!!%~kajh;?re_F_v z#;Ieq2q@WKvT$ZORiJEzY_x z$1jyl^i>O%dXM9RNcz3JLlQWj*YiI3f93xd6E6AtF-$WPGr7g&Czz?vn5=-X9<{bA zZ1L7RM|Uwp1KQZbn{9cKw(5Y7R~uyB-<~&rb}TAHQ9P)ro-%)F$+zcdkYZ8p^i&zY z;d<4F^ODT!a_cQa-1?sRrn%v=Dn(>sU4XwkYffrT*9_jTK`op8X@aEpA6^r&qNL?k ze%=RzfivgIwJtV#nldH3@rFMC>_FuVW$fs>A8hhZl6Ri!QK-``dcWCIH{C6_jMPT2 zuHCpKM8oJJnl&F)$}GdD6AM-PCD{$jk7yhH7jz`FdWWWkC<|7J6Rz~|P-VGk<49ML P)|~#2@+)6{I+OA*Q6#yq diff --git a/source/web/images/icons/topic_exclamation.gif b/source/web/images/icons/topic_exclamation.gif new file mode 100644 index 0000000000000000000000000000000000000000..005b4752d74c2023d35d71ffb623db502e600450 GIT binary patch literal 591 zcmaKp`%6=C0L5=Lnk&m`R%$6TADKGSG@H7%N}E}jlYEt$&rC|&Orz+B%vD4ngIW(C zSA~YttOyGVLAD-nEBMlIsncdTZ7vsAQOjUIowojf4u|v8fdikDo*@$@mGLP)WvASN zOGXKXWH24Za5hGAF_H&!F~-Vasl`MczFmg3304)Ru4C#3rf=c98n)Y*xrdqiu(x6M zAspRs=)m@4?j;u9;J1k#h*~nl;FH+-QOxQk_?(5|9QLgoqeU>6z+8&)YJ91IMFEQv z6ZOu~I!s)^*Nd2Jg!LM%uC1GxZiY<*dk1E<`1u&@3(UR3{2&(IVevf{KVXUAml4Zm zERW%j1H4LF2k$(k>wF+Xx-TJP0Qpk)$(*bj6u^l8IJIx(_+$hnN14l zpiSh*?vT@kB7eWl=amVbYqn?6If=f$8+PyVjN+}%q>rulieIOVN{SFh~z<4WwWeF O5pcz3%dQYmDSrWM{xAFh literal 0 HcmV?d00001 diff --git a/source/web/images/icons/topic_exclamation_large.gif b/source/web/images/icons/topic_exclamation_large.gif new file mode 100644 index 0000000000000000000000000000000000000000..87410f57356319f79baeb53b0a64c983e9921800 GIT binary patch literal 1428 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 arW~De8D-1E%NY@CxOL{6N~u)JwtoR<3>~Wg literal 1572 zcmWlYi9gf{1BYkE5iOD^iOitGs!eDU+J;e->}$oFYHLZhy!+NF+1e%VIBKw?7{{uV zBgdE&#@M98eV;pw^g@Mx`g2=7_44uc&1+wQHq?aIz9Bm50>u8L` zVl*COi5TZ$A`S98n7ogvT)Y)1h%6||FejN)bYp%{lKTl!piLC&5qtxp$Y@ezLI_OA z>Meg%SuQs1K!=_DsZD>eHM$%>bhGALUC`?ViJ$bT7k>AbJ@=K@9RqO|#5oLpC#&|y zP>8(gETmz0bp@}kVmKVb5sn98!80Q+aq( zh(Ai85aG`!`0JTcRsv-;-ZhdF)gaq3^BZP+@waS|lwola|0sJ?wdV%%Ka7bmH-_8P zrF1Ipsv%Py_cW2UYAI6}IeN%liwEnGZ-N3k3e8Zo1x1z+SmEJz6n}PiuoyJJe5pTA(OSp6g@KCaORFFdCyXL z+mg(-Zi?PACtywFdq}fA<$NEq>}#?jh{!uZ@V`}7T_he}ARdPiW#NPGK5MwX2C}$K+@l+~e#Wv~f3hQ+>=BTCqHk>} z-66V?Fg?jn8zd17BFdtly@iO~)*oX%S`;!N{NJ0(>x#xKWp~NkX!r8*8H=ja2dZJckOl-%Ws0+SC?e)zW9ZWZ98|H-(#PAn_X=wn>~0DomQcZ38x=?zr#yINHewd zD?8Iz*CEgnc;`3-3G{=L?E-!I5lP~lR-VOy8%ypNOVS=5?Kvs=GAyC5&@*G}Uhf90 z0gmOyOgjWb*V2+T_h$TZtWjX_&^L%bHXm`2XU=++bNO{?z`;c`XXa~4C_hiw5!JRe zMa!mHpQW|4W=YsWuUZl}s2iPO$Er~dl&a`#?F($Pe3yD|G=5WVpa$LGvt+9JIzwky z-PP}UYG{lEmqV6LJhPQs?}zZ>H>Lb{w}$Ccx-e(;evO?}RYz$CGwyx_tt~CR>~!A>uFv%{_j{M)*m z4PCcWSDmhFSMg8ocR35Qrmzt1&&8#?z4}J4`@HzP`M&#nW8$KN#05NxN6k=cV3mO| z3`WBgkD(L{r(-w+=3I;x!di;4a(usqiCRo3FZ(u+OpZ3X5;>>jRcPVyO?y1S@8&jN*?K_MfoNF=}_x z55~f2&x^9wZ)s}aStZks9HmWMlO%}>s4g9b4f8=B5tfMFe6}Yyo zeL^`JY7|P@wX*z+x!IW+rApP6)Kd}RlAz-|wh1q&6z9FdLJO}Kc)0NnouhNaA;Fb~ zitVC+vvl@}leZGv zALKf6qUrQa0zsfW*=aAwA(FnjkIUWf>&RcfC-~81MNER)fgkBDj;!mCP%2C{ym}75 bM|@h+)8*9AUoZ0FGF9%4F0rawiVFD)5WF<< literal 0 HcmV?d00001 diff --git a/source/web/images/icons/topic_question_large.gif b/source/web/images/icons/topic_question_large.gif new file mode 100644 index 0000000000000000000000000000000000000000..f0d7003fcf7f8a2e2e3b9f556dab7d8e2a07a67f GIT binary patch literal 1435 zcmc(e`#;lr9LK*-d$`8KeVW_G$dOJe73$>DjG^OF=j1qb3`Z&FbVlcNB;_s+wM}?% zRMy#)q?%h7U5s37jK!GShLN=uK2hnM$K!oY=bt#QAD%xye|Wz9X;gQQXd*_$-eaEz z01}?QjBh8tMwHb#qE;8w=DO0c1$wumr*6>a0ezmR-5qu8f&o7mprS565Ywa$-l#hO z2E$O#UKk9Ap|4^15Db5hgx|tQH0q0j(W5YW42j}k>?asI4&#YvAOXgc(7=x{@hcK1 zqQT_pP6o&`U@8};^I@hC4d=`X(_rQTDA=GVg4xoA;qx$8jz-yNtOQG(6fCo6akX&)SdgsAB4g%9Y$hd zdN3Lkfnh<3*^~o=&Z8u3``fm3=54EfT9Fu z%V4eo<}NA4OnAvrOG;s$3-eW=ypATWfU+81-2~MgP&XiX4XB&o^*wlfAKpA%klled zk71z&76h>P6c#&RsSB2R&}<8!=YWLpRs?VRVPzOrM&P{+-pk>`41839)*hA~VL3dnSOJ_7yiRl;Ne55@?(fyzcN;jNzrn@Yeq~x&PAp|3O;CX<(Qb zbNQt5=@XbXU{yL+5oG2?vbKry{&{i;JHwFlCLn1pjAgsqb)}3qqxmO3JDfu#T@Ng> zHX@Ya@3%Jj9^fX3#>AApL*{6&F!N4Exw9kr;zewN=$J# zi|FOR3$}3HNYl5gDarG;7!0qN{@ zllIdFIsHZ#AKmBCUR;}ebaJQ&_c>lp-@rdxZKAQGot*8w#HU>LcL-!#DP!Ihme+da zEyRQCOe(#|lx0VYwACrHr#53d{(9oi)G|oyF2hzF4}@I zZJAOS+E#8qPx94H*XR0JSu|#JuA#dyIvGIP z7_CE;*m!R(tzY6fKAMSwuz5nfcW5rYAUx6dfLOt9#|{goaxE=PN2vtkA-P!j1ImvE*bC&g8^m!fPL2o!Xna7YMZp PMwgw`{M#BD*v@|djSk5h literal 0 HcmV?d00001 diff --git a/source/web/jsp/admin/admin-console.jsp b/source/web/jsp/admin/admin-console.jsp index cd6fb87562..144fb9216e 100644 --- a/source/web/jsp/admin/admin-console.jsp +++ b/source/web/jsp/admin/admin-console.jsp @@ -106,14 +106,14 @@ - + - + diff --git a/source/web/jsp/browse/browse.jsp b/source/web/jsp/browse/browse.jsp index f1239ada1a..5165b2ac43 100644 --- a/source/web/jsp/browse/browse.jsp +++ b/source/web/jsp/browse/browse.jsp @@ -103,7 +103,7 @@ <%-- Current space More actions menu --%> - + @@ -124,7 +124,7 @@ - + @@ -315,9 +315,22 @@ - + + <%-- More actions menu --%> + + + + + + + + + + + + @@ -461,7 +474,7 @@ - + @@ -506,6 +519,16 @@ + + + + + + + + + + diff --git a/source/web/jsp/dialog/space-details.jsp b/source/web/jsp/dialog/space-details.jsp index 672a658f9d..eb9e452a45 100644 --- a/source/web/jsp/dialog/space-details.jsp +++ b/source/web/jsp/dialog/space-details.jsp @@ -94,11 +94,11 @@ - + - + diff --git a/source/web/jsp/forums/create-discussion.jsp b/source/web/jsp/forums/create-discussion.jsp new file mode 100644 index 0000000000..a8375f3942 --- /dev/null +++ b/source/web/jsp/forums/create-discussion.jsp @@ -0,0 +1,202 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + <%-- Main outer table --%> + + + <%-- Title bar --%> + + + + + <%-- Main area --%> + + <%-- Shelf --%> + + + <%-- Work Area --%> + + +
+ <%@ include file="../parts/titlebar.jsp" %> +
+ <%@ include file="../parts/shelf.jsp" %> + + + <%-- Breadcrumb --%> + <%@ include file="../parts/breadcrumb.jsp" %> + + <%-- Status and Actions --%> + + + + + + + <%-- separator row with gradient shadow --%> + + + + + + + <%-- Details --%> + + + + + + + <%-- separator row with bottom panel graphics --%> + + + + + + +
+ + <%-- Status and Actions inner contents table --%> + <%-- Generally this consists of an icon, textual summary and actions for the current object --%> + + + + + +
+ +
+
+
+
+ +
+ + + + + + +
+ + + + <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "white", "white"); %> + + + + + + + + + + + + + + + + + + + + + + + + +
: +  * +
: +
+ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %> + + + + <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %> +
+
 
: +  * +
+ <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %> +
+ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %> + + + + + + + +
+ +
+ +
+ <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %> +
+
+
+ +
+ + + +
+ +
\ No newline at end of file diff --git a/source/web/jsp/forums/create-forums.jsp b/source/web/jsp/forums/create-forums.jsp index 7e38c49a06..8cd9954eb9 100644 --- a/source/web/jsp/forums/create-forums.jsp +++ b/source/web/jsp/forums/create-forums.jsp @@ -90,7 +90,7 @@
-
diff --git a/source/web/jsp/forums/create-post.jsp b/source/web/jsp/forums/create-post.jsp index 083ec4a116..c576f09260 100644 --- a/source/web/jsp/forums/create-post.jsp +++ b/source/web/jsp/forums/create-post.jsp @@ -81,7 +81,7 @@
-
diff --git a/source/web/jsp/forums/create-reply.jsp b/source/web/jsp/forums/create-reply.jsp index fb33756ecf..05a5687cf5 100644 --- a/source/web/jsp/forums/create-reply.jsp +++ b/source/web/jsp/forums/create-reply.jsp @@ -81,7 +81,7 @@
-
diff --git a/source/web/jsp/forums/create-topic.jsp b/source/web/jsp/forums/create-topic.jsp index 447ab1aca0..1e398425f9 100644 --- a/source/web/jsp/forums/create-topic.jsp +++ b/source/web/jsp/forums/create-topic.jsp @@ -82,7 +82,7 @@
-
diff --git a/source/web/jsp/forums/delete-forum.jsp b/source/web/jsp/forums/delete-forum.jsp index a7263a1c28..7d1dc556b7 100644 --- a/source/web/jsp/forums/delete-forum.jsp +++ b/source/web/jsp/forums/delete-forum.jsp @@ -137,13 +137,13 @@
- +
- +
diff --git a/source/web/jsp/forums/delete-forums.jsp b/source/web/jsp/forums/delete-forums.jsp index cc8de78fec..f507671394 100644 --- a/source/web/jsp/forums/delete-forums.jsp +++ b/source/web/jsp/forums/delete-forums.jsp @@ -137,13 +137,13 @@
- +
- +
diff --git a/source/web/jsp/forums/delete-post.jsp b/source/web/jsp/forums/delete-post.jsp index 8ceb636834..bc2ef852ef 100644 --- a/source/web/jsp/forums/delete-post.jsp +++ b/source/web/jsp/forums/delete-post.jsp @@ -137,13 +137,13 @@
- +
- +
diff --git a/source/web/jsp/forums/delete-topic.jsp b/source/web/jsp/forums/delete-topic.jsp index 616dcd5579..702c9a8e0f 100644 --- a/source/web/jsp/forums/delete-topic.jsp +++ b/source/web/jsp/forums/delete-topic.jsp @@ -137,13 +137,13 @@
- +
- +
diff --git a/source/web/jsp/forums/edit-forum.jsp b/source/web/jsp/forums/edit-forum.jsp index cce3368c5f..38c77ca97e 100644 --- a/source/web/jsp/forums/edit-forum.jsp +++ b/source/web/jsp/forums/edit-forum.jsp @@ -80,7 +80,7 @@
-
diff --git a/source/web/jsp/forums/edit-forums.jsp b/source/web/jsp/forums/edit-forums.jsp index c6e1455aaa..e2b71863f5 100644 --- a/source/web/jsp/forums/edit-forums.jsp +++ b/source/web/jsp/forums/edit-forums.jsp @@ -80,7 +80,7 @@
-
diff --git a/source/web/jsp/forums/edit-post.jsp b/source/web/jsp/forums/edit-post.jsp index dfa73117b6..08b397a29a 100644 --- a/source/web/jsp/forums/edit-post.jsp +++ b/source/web/jsp/forums/edit-post.jsp @@ -81,7 +81,7 @@
-
diff --git a/source/web/jsp/forums/edit-topic.jsp b/source/web/jsp/forums/edit-topic.jsp index 45a5a956d4..2501131bf8 100644 --- a/source/web/jsp/forums/edit-topic.jsp +++ b/source/web/jsp/forums/edit-topic.jsp @@ -80,7 +80,7 @@ <%-- Navigation --%> @@ -150,7 +130,7 @@ + action="dialog:editForumProperties" actionListener="#{EditForumDialog.startWizardForEdit}" /> diff --git a/source/web/jsp/forums/forum.jsp b/source/web/jsp/forums/forum.jsp index 8a46f62fe6..bf530eb486 100644 --- a/source/web/jsp/forums/forum.jsp +++ b/source/web/jsp/forums/forum.jsp @@ -81,13 +81,13 @@ <%-- Current object actions --%>
- + - + - + @@ -105,7 +105,7 @@ - + @@ -183,11 +183,19 @@ - + - + + + + + + + + + diff --git a/source/web/jsp/forums/forums-details.jsp b/source/web/jsp/forums/forums-details.jsp index b22c3dc554..f61cc13d0e 100644 --- a/source/web/jsp/forums/forums-details.jsp +++ b/source/web/jsp/forums/forums-details.jsp @@ -88,30 +88,10 @@ - + - <%-- - - - - - - - - - - - - - - - - - - - --%> <%-- Navigation --%> @@ -150,7 +130,7 @@ + action="dialog:editForumsProperties" actionListener="#{EditForumsDialog.startWizardForEdit}" /> diff --git a/source/web/jsp/forums/forums.jsp b/source/web/jsp/forums/forums.jsp index ca13fd5813..1063f0351b 100644 --- a/source/web/jsp/forums/forums.jsp +++ b/source/web/jsp/forums/forums.jsp @@ -82,18 +82,18 @@ <%-- Current object actions --%>
- + - + - + <%-- Current space More actions menu --%> - + @@ -107,10 +107,18 @@ - + + + + + + + + + @@ -244,11 +252,19 @@ - + - + + + + + + + + + diff --git a/source/web/jsp/forums/topic-details.jsp b/source/web/jsp/forums/topic-details.jsp index 425153b164..3766e8cc4f 100644 --- a/source/web/jsp/forums/topic-details.jsp +++ b/source/web/jsp/forums/topic-details.jsp @@ -88,30 +88,10 @@ - + - <%-- - - - - - - - - - - - - - - - - - - - --%> <%-- Navigation --%> @@ -150,7 +130,7 @@ + action="dialog:editTopicProperties" actionListener="#{EditTopicDialog.startWizardForEdit}" /> diff --git a/source/web/jsp/forums/topic.jsp b/source/web/jsp/forums/topic.jsp index 445015cf3f..d451a68418 100644 --- a/source/web/jsp/forums/topic.jsp +++ b/source/web/jsp/forums/topic.jsp @@ -68,7 +68,7 @@ <%-- actions for forums --%>
-
diff --git a/source/web/jsp/forums/forum-details.jsp b/source/web/jsp/forums/forum-details.jsp index fef4b7b9d1..48f1a34850 100644 --- a/source/web/jsp/forums/forum-details.jsp +++ b/source/web/jsp/forums/forum-details.jsp @@ -88,30 +88,10 @@ - + - <%-- - - - - - - - - - - - - - - - - - - - --%>
- <%-- Summary --%> @@ -81,13 +81,13 @@ <%-- Current object actions --%>
- + - + - + @@ -105,7 +105,7 @@ - + @@ -217,17 +217,17 @@ - + - + - + diff --git a/source/web/jsp/roles/manage-invited-users.jsp b/source/web/jsp/roles/manage-invited-users.jsp index e9cff7e015..2d08ba1780 100644 --- a/source/web/jsp/roles/manage-invited-users.jsp +++ b/source/web/jsp/roles/manage-invited-users.jsp @@ -173,7 +173,7 @@
- +