From 1d86f7e869744915c9dfc81a5a2591e1ba660f8d Mon Sep 17 00:00:00 2001 From: pb Date: Wed, 22 Sep 2010 19:00:55 +0000 Subject: [PATCH] Weitere Schritte zur Ueberarbeitung und Lokalisierung des Forums. Reiterliste der Hauptsicht angepasst. git-svn-id: https://svn.libreccm.org/ccm/trunk@539 8810af33-2d31-482b-a856-94f89814c4df --- ccm-forum/pdl/com/arsdigita/forum/Forum.pdl | 2 + .../src/WEB-INF/resources/forum-adapters.xml | 2 +- ccm-forum/src/com/arsdigita/forum/Forum.java | 44 ++++--- .../src/com/arsdigita/forum/ForumContext.java | 50 ++++++-- .../com/arsdigita/forum/ForumPageBuilder.java | 6 +- .../src/com/arsdigita/forum/ForumServlet.java | 6 + .../arsdigita/forum/ThreadPageBuilder.java | 50 +++++--- .../src/com/arsdigita/forum/package.html | 16 ++- .../forum/portlet/MyForumsPortlet.java | 2 +- .../forum/portlet/RecentPostingsPortlet.java | 4 +- ...dDisplay.java => DiscussionPostsList.java} | 80 +++++++++---- ...t.java => DiscussionThreadSimpleView.java} | 67 +++++++---- .../forum/ui/ForumResources_de.properties | 2 +- .../forum/ui/ForumUserCompactView.java | 107 +++++++++++++----- .../com/arsdigita/forum/ui/MessageView.java | 28 ++--- .../forum/ui/MessageXMLFormatter.java | 4 +- .../ui/{ThreadList.java => ThreadsList.java} | 15 ++- .../com/arsdigita/forum/ui/ThreadsPanel.java | 26 +++-- .../ui/{TopicList.java => TopicsList.java} | 2 +- .../com/arsdigita/forum/ui/TopicsPanel.java | 2 +- ccm-forum/web/WEB-INF/web.ccm-forum.xml | 5 +- ccm-forum/web/packages/forum/xsl/forum.xsl | 4 +- 22 files changed, 359 insertions(+), 165 deletions(-) rename ccm-forum/src/com/arsdigita/forum/ui/{ThreadDisplay.java => DiscussionPostsList.java} (85%) rename ccm-forum/src/com/arsdigita/forum/ui/{ThreadComponent.java => DiscussionThreadSimpleView.java} (80%) rename ccm-forum/src/com/arsdigita/forum/ui/{ThreadList.java => ThreadsList.java} (91%) rename ccm-forum/src/com/arsdigita/forum/ui/{TopicList.java => TopicsList.java} (98%) diff --git a/ccm-forum/pdl/com/arsdigita/forum/Forum.pdl b/ccm-forum/pdl/com/arsdigita/forum/Forum.pdl index 617d6ceba..e1fd1690b 100755 --- a/ccm-forum/pdl/com/arsdigita/forum/Forum.pdl +++ b/ccm-forum/pdl/com/arsdigita/forum/Forum.pdl @@ -32,6 +32,7 @@ object type Forum extends Application { Boolean [1..1] isModerated = forum_forums.is_moderated; Boolean [1..1] isNoticeboard = forum_forums.is_noticeboard; + component Group [0..1] adminGroup = join forum_forums.admin_group_id to groups.group_id; component Group [0..1] moderationGroup = @@ -45,6 +46,7 @@ object type Forum extends Application { component ForumSubscription[0..n] subscriptions = join forum_forums.forum_id to forum_subscriptions.forum_id; + component Category[1..1] category = join forum_forums.category_id to cat_categories.category_id; diff --git a/ccm-forum/src/WEB-INF/resources/forum-adapters.xml b/ccm-forum/src/WEB-INF/resources/forum-adapters.xml index 0951e26ab..261688740 100755 --- a/ccm-forum/src/WEB-INF/resources/forum-adapters.xml +++ b/ccm-forum/src/WEB-INF/resources/forum-adapters.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://rhea.redhat.com/schemas/waf/xml-renderer-rules xml-renderer-rules.xsd"> - + threads which groups a set of posts to the same * subject, and topics which group a set of threads about the same general @@ -66,11 +66,17 @@ import com.arsdigita.web.Application; public class Forum extends Application { - public static final String THREAD_SUBSCRIPTION_GROUPS_NAME = + /** Private logger instance for debugging purpose */ + private static final Logger s_log = Logger.getLogger(Forum.class); + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.forum.Forum"; + public static final String PACKAGE_TYPE = "forum"; + + public static final String THREAD_SUBSCRIPTION_GROUPS_NAME = "Thread Subscription Groups"; private static final ForumConfig s_config = new ForumConfig(); - static { s_config.load(); } @@ -80,12 +86,6 @@ public class Forum extends Application { } - private static final Logger s_log = Logger.getLogger(Forum.class); - - public static final String BASE_DATA_OBJECT_TYPE = - "com.arsdigita.forum.Forum"; - - public static final String PACKAGE_TYPE = "forum"; ////// //Forum specific privileges ///// @@ -102,7 +102,11 @@ public class Forum extends Application { // returned for non public posts. This means there is no longer // any need for a separate forum_read privilege, though it // does no harm. Now removed - // public static final String FORUM_READ_PRIVILEGE = "forum_read"; + // + // pb: Reactivated READ privilege in order to provide forums for different + // groups of users for their internal use and to provide private forums + // for logged in users only (no public read access). + public static final String FORUM_READ_PRIVILEGE = "forum_read"; /////// // pdl forum attribute/association names @@ -111,24 +115,29 @@ public class Forum extends Application { private static final String SUBSCRIPTIONS = "subscriptions"; private static final String MODERATION = "isModerated"; private static final String NOTICEBOARD = "isNoticeboard"; + private static final String ADMIN_GROUP = "adminGroup"; private static final String MODERATION_GROUP = "moderationGroup"; private static final String THREAD_CREATE_GROUP = "threadCreateGroup"; private static final String THREAD_RESPONDER_GROUP = "threadRespondGroup"; private static final String READ_GROUP = "readGroup"; + private static final String CATEGORY = "category"; private static final String EXPIRE_AFTER = "expireAfter"; private static final String LIFECYCLE_DEFINITION = "lifecycleDefinition"; // additional attributes added chris.gilbert@westsussex.gov.uk - private static final String ALLOW_FILE_ATTACHMENTS = - "fileAttachmentsAllowed"; + private static final String ALLOW_FILE_ATTACHMENTS = "fileAttachmentsAllowed"; private static final String ALLOW_IMAGE_UPLOADS = "imageUploadsAllowed"; private static final String AUTOSUBSCRIBE_THREAD_STARTER = - "autoSubscribeThreadStarter"; + "autoSubscribeThreadStarter"; private static final String INTRODUCTION = "introduction"; private static final String NO_CATEGORY_POSTS = "noCategoryPostsAllowed"; private static final String ANONYMOUS_POSTS = "anonymousPostsAllowed"; + /** + * + * @param data + */ public Forum(DataObject data) { super(data); } @@ -226,7 +235,10 @@ public class Forum extends Application { return category; } - private void createGroups() { + /** + * + */ + private void createGroups() { Group administrators = new Group(); administrators.setName(getTitle() + " Administrators"); setAssociation(ADMIN_GROUP, administrators); @@ -864,8 +876,8 @@ public class Forum extends Application { group)); } /** - * method required for upgrade - normally groups are set during forum creation and so - * creation and so there is no need to invoke a setter + * method required for upgrade - normally groups are set during forum + * creation and so creation and so there is no need to invoke a setter * @author cgyg9330 * */ diff --git a/ccm-forum/src/com/arsdigita/forum/ForumContext.java b/ccm-forum/src/com/arsdigita/forum/ForumContext.java index 408f93ee7..fe7e295a8 100755 --- a/ccm-forum/src/com/arsdigita/forum/ForumContext.java +++ b/ccm-forum/src/com/arsdigita/forum/ForumContext.java @@ -27,11 +27,11 @@ import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Party; import com.arsdigita.util.Assert; -import java.io.IOException; +import java.io.IOException; import java.math.BigDecimal; -import javax.servlet.http.HttpServletResponse; - +import javax.servlet.http.HttpServletResponse; + import org.apache.log4j.Logger; /** @@ -46,9 +46,11 @@ import org.apache.log4j.Logger; */ public final class ForumContext { + /** Private logger instance for debugging purpose */ private static final Logger s_log = Logger.getLogger(ForumContext.class); private static final RequestLocal s_context = new RequestLocal() { + @Override public Object initialValue(PageState state) { return new ForumContext(); } @@ -63,7 +65,11 @@ public final class ForumContext { private boolean m_canAdminister; private boolean m_canModerate; + /** + * Default Constructor + */ ForumContext() { + m_forum = (Forum)Kernel.getContext().getResource(); Assert.exists(m_forum, Forum.class); @@ -106,15 +112,15 @@ public final class ForumContext { // thread.assertPrivilege(PrivilegeDescriptor.READ); m_thread = thread; } catch (DataObjectNotFoundException ex) { - PageState state = PageState.getPageState(); - if (state != null) { - try { - state.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND); - return; - } catch (IOException e) { - s_log.warn("Thread not found, but failed to send a response to user"); - } - } + PageState state = PageState.getPageState(); + if (state != null) { + try { + state.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } catch (IOException e) { + s_log.warn("Thread not found, but failed to send a response to user"); + } + } throw new UncheckedWrapperException( "Couldn't find a MessageThread for " + threadID, ex); } @@ -135,23 +141,43 @@ public final class ForumContext { } + /** + * + * @return + */ public boolean canEdit() { return m_canEdit; } + /** + * + * @return + */ public boolean canAdminister() { return m_canAdminister; } + /** + * + * @return + */ public boolean canModerate() { return m_canModerate; } + /** + * + * @return + */ public BigDecimal getCategorySelection() { return m_categorySelection; } + /** + * + * @param categorySelection + */ public void setCategorySelection(BigDecimal categorySelection) { m_categorySelection = categorySelection; } diff --git a/ccm-forum/src/com/arsdigita/forum/ForumPageBuilder.java b/ccm-forum/src/com/arsdigita/forum/ForumPageBuilder.java index efd3ca2a1..0c64040ff 100644 --- a/ccm-forum/src/com/arsdigita/forum/ForumPageBuilder.java +++ b/ccm-forum/src/com/arsdigita/forum/ForumPageBuilder.java @@ -36,7 +36,9 @@ import com.arsdigita.xml.Element; /** * Implementation of com.arsdigita.forum.PageBuilder that creates a - * basic forum page with read access check + * basic forum page with read access check. + * Controls forum.ui classes to generate the xml and display the desired + * elements (here esp. ForumUserCompactView). * * @author chris.gilbert@westsussex.gov.uk */ @@ -116,6 +118,6 @@ public class ForumPageBuilder implements PageBuilder, Constants { context.setCategorySelection( (BigDecimal) event.getPageState().getValue(m_categorySelection)); - } + } } } diff --git a/ccm-forum/src/com/arsdigita/forum/ForumServlet.java b/ccm-forum/src/com/arsdigita/forum/ForumServlet.java index 2fc9fdc6a..22e47109e 100755 --- a/ccm-forum/src/com/arsdigita/forum/ForumServlet.java +++ b/ccm-forum/src/com/arsdigita/forum/ForumServlet.java @@ -43,8 +43,14 @@ import org.apache.log4j.Logger; public class ForumServlet extends BebopApplicationServlet implements Constants { + /** Private logger instance for debugging purpose */ private static final Logger s_log = Logger.getLogger(ForumServlet.class); + /** + * + * @throws ServletException + */ + @Override public void init() throws ServletException { super.init(); s_log.debug("creating forum page"); diff --git a/ccm-forum/src/com/arsdigita/forum/ThreadPageBuilder.java b/ccm-forum/src/com/arsdigita/forum/ThreadPageBuilder.java index 63585d73f..312e52576 100644 --- a/ccm-forum/src/com/arsdigita/forum/ThreadPageBuilder.java +++ b/ccm-forum/src/com/arsdigita/forum/ThreadPageBuilder.java @@ -27,46 +27,66 @@ import com.arsdigita.bebop.SimpleComponent; import com.arsdigita.bebop.event.RequestEvent; import com.arsdigita.bebop.event.RequestListener; import com.arsdigita.bebop.parameters.BigDecimalParameter; -import com.arsdigita.bebop.parameters.ParameterModel; +// import com.arsdigita.bebop.parameters.ParameterModel; import com.arsdigita.forum.ui.Constants; -import com.arsdigita.forum.ui.ThreadComponent; +import com.arsdigita.forum.ui.DiscussionThreadSimpleView; import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.toolbox.ui.ApplicationAuthenticationListener; import com.arsdigita.xml.Element; /** - * @author chris.gilbert@westsussex.gov.uk + * Implementation of com.arsdigita.forum.PageBuilder that creates a basic + * thread page with read access check * - * Implementation of com.arsdigita.forum.PageBuilder that creates a basic thread page with read access check + * @author chris.gilbert@westsussex.gov.uk */ public class ThreadPageBuilder implements PageBuilder, Constants { /* (non-Javadoc) - * @see com.arsdigita.forum.PageBuilder#buildPage(com.arsdigita.bebop.parameters.ParameterModel) + * @see com.arsdigita.forum.PageBuilder#buildPage( + * com.arsdigita.bebop.parameters.ParameterModel) */ - public Page buildPage() { - Page threadPage = PageFactory.buildPage(Constants.FORUM_XML_PREFIX, "Threads", "forumThreadPage"); + /** + * + * @return + */ + public Page buildPage() { + Page threadPage = PageFactory.buildPage(Constants.FORUM_XML_PREFIX, + "Threads", "forumThreadPage"); //Output the title in an easy to find place threadPage.add(new SimpleComponent(){ public void generateXML(PageState state, Element parent) { - Element nameElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":name", Constants.FORUM_XML_NS); - nameElement.setText(ForumContext.getContext(state).getForum().getTitle()); - Element introductionElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":introduction", Constants.FORUM_XML_NS); - introductionElement.setText(ForumContext.getContext(state).getForum().getIntroduction()); + Element nameElement = parent.newChildElement( + Constants.FORUM_XML_PREFIX + ":name", + Constants.FORUM_XML_NS); + nameElement.setText(ForumContext.getContext(state).getForum(). + getTitle()); + Element introductionElement = parent.newChildElement( + Constants.FORUM_XML_PREFIX + + ":introduction", + Constants.FORUM_XML_NS); + introductionElement.setText(ForumContext.getContext(state). + getForum(). + getIntroduction()); } - }); - threadPage.add(new ThreadComponent()); + }); + // + threadPage.add(new DiscussionThreadSimpleView()); // Register the thread id parameter as a global state parameter. BigDecimalParameter threadID = new BigDecimalParameter(THREAD_PARAM); threadPage.addGlobalStateParam(threadID); - threadPage.addRequestListener(new ApplicationAuthenticationListener(PrivilegeDescriptor.READ)); + threadPage.addRequestListener( + new ApplicationAuthenticationListener(PrivilegeDescriptor.READ)); threadPage.addRequestListener (new ThreadPageRequestListener(threadID)); return threadPage; } - private static class ThreadPageRequestListener implements RequestListener { + /** + * + */ + private static class ThreadPageRequestListener implements RequestListener { private BigDecimalParameter m_threadID; public ThreadPageRequestListener(BigDecimalParameter threadID) { diff --git a/ccm-forum/src/com/arsdigita/forum/package.html b/ccm-forum/src/com/arsdigita/forum/package.html index 152f90de4..4b224b0b8 100755 --- a/ccm-forum/src/com/arsdigita/forum/package.html +++ b/ccm-forum/src/com/arsdigita/forum/package.html @@ -1,20 +1,18 @@ -com.arsdigita.bboard +com.arsdigita.forum

- -Experimental - - The bboard package provides - discussion forums in which users can post and reply to messages. - Additionally, users may register for notifications of new posts to - the system. + The forum package provides discussion forums in which users can post and + reply to messages. Additionally, users may register for notifications of + new posts to the system. +

+

+ Forum.java is the main domain class.

- diff --git a/ccm-forum/src/com/arsdigita/forum/portlet/MyForumsPortlet.java b/ccm-forum/src/com/arsdigita/forum/portlet/MyForumsPortlet.java index e4d6fcc45..4e6a1fbf7 100644 --- a/ccm-forum/src/com/arsdigita/forum/portlet/MyForumsPortlet.java +++ b/ccm-forum/src/com/arsdigita/forum/portlet/MyForumsPortlet.java @@ -21,7 +21,7 @@ package com.arsdigita.forum.portlet; import com.arsdigita.forum.Forum; import com.arsdigita.forum.ThreadCollection; import com.arsdigita.forum.ui.Constants; -import com.arsdigita.forum.ui.ThreadList; +import com.arsdigita.forum.ui.ThreadsList; import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainObjectXMLRenderer; import com.arsdigita.bebop.portal.AbstractPortletRenderer; diff --git a/ccm-forum/src/com/arsdigita/forum/portlet/RecentPostingsPortlet.java b/ccm-forum/src/com/arsdigita/forum/portlet/RecentPostingsPortlet.java index c6a2ed3b4..b39d67f3b 100755 --- a/ccm-forum/src/com/arsdigita/forum/portlet/RecentPostingsPortlet.java +++ b/ccm-forum/src/com/arsdigita/forum/portlet/RecentPostingsPortlet.java @@ -21,7 +21,7 @@ package com.arsdigita.forum.portlet; import com.arsdigita.forum.Forum; import com.arsdigita.forum.ThreadCollection; import com.arsdigita.forum.ui.Constants; -import com.arsdigita.forum.ui.ThreadList; +import com.arsdigita.forum.ui.ThreadsList; import com.arsdigita.domain.DomainObjectXMLRenderer; import com.arsdigita.bebop.portal.AbstractPortletRenderer; import com.arsdigita.bebop.PageState; @@ -122,7 +122,7 @@ class RecentPostingsPortletRenderer xr.setWrapAttributes(true); xr.setWrapObjects(false); - xr.walk(thread, ThreadList.class.getName()); + xr.walk(thread, ThreadsList.class.getName()); } } diff --git a/ccm-forum/src/com/arsdigita/forum/ui/ThreadDisplay.java b/ccm-forum/src/com/arsdigita/forum/ui/DiscussionPostsList.java similarity index 85% rename from ccm-forum/src/com/arsdigita/forum/ui/ThreadDisplay.java rename to ccm-forum/src/com/arsdigita/forum/ui/DiscussionPostsList.java index 87d98608e..f7a748d8f 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/ThreadDisplay.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/DiscussionPostsList.java @@ -57,19 +57,21 @@ import com.arsdigita.xml.Element; import com.arsdigita.xml.XML; /** - * Provides List of posts for a thread with links to edit, delete, etc - * according to authorisation. - * - * Curently used by ThreadComponent to create the actual list of threads and by + * Child panel of DiscussionThreadSimpleVew. Provides for the given thread (usually + * selected from the list of threads created by ThreadsPanel) a list of its posts + * along with a reply link and additionally links to edit, delete, etc (according + * to given authorisation) for each listed post. + * + * So it creates the actual list of threads for DiscussionThreadSimpleVew and by * MessageView. */ -public class ThreadDisplay extends SimpleComponent implements Constants { +public class DiscussionPostsList extends SimpleComponent implements Constants { private static final Logger s_log = - Logger.getLogger(ThreadDisplay.class); + Logger.getLogger(DiscussionPostsList.class); private IntegerParameter m_pageNumber = - new IntegerParameter(PAGINATOR_PARAM); + new IntegerParameter(PAGINATOR_PARAM); private int m_pageSize = Forum.getConfig().getThreadPageSize(); private static final String ACTION_EDIT = "edit"; @@ -78,22 +80,37 @@ public class ThreadDisplay extends SimpleComponent implements Constants { private static final String ACTION_APPROVE = "approve"; private static final String ACTION_REJECT = "reject"; - private ThreadComponent m_threadComponent; + private DiscussionThreadSimpleView m_threadMessagesPanel; private ACSObjectSelectionModel m_post; - public ThreadDisplay(ACSObjectSelectionModel post, - ThreadComponent threadComponent) { - m_threadComponent = threadComponent; + /** + * Defaultg Constructor + * + * @param post + * @param threadMessagesPanel + */ + public DiscussionPostsList(ACSObjectSelectionModel post, + DiscussionThreadSimpleView threadMessagesPanel) { + m_threadMessagesPanel = threadMessagesPanel; m_post = post; } + /** + * + * @param p + */ public void register(Page p) { super.register(p); p.addGlobalStateParam(m_pageNumber); } + /** + * + * @param state + * @throws ServletException + */ public void respond(PageState state) throws ServletException { super.respond(state); @@ -109,7 +126,7 @@ public class ThreadDisplay extends SimpleComponent implements Constants { if (ACTION_EDIT.equals(key)) { m_post.setSelectedObject(state, post); - m_threadComponent.makeEditFormVisible(state); + m_threadMessagesPanel.makeEditFormVisible(state); } else if (ACTION_DELETE.equals(key)) { Assert.isTrue(ctx.canAdminister(), "can administer forums"); @@ -150,14 +167,14 @@ public class ThreadDisplay extends SimpleComponent implements Constants { } } else if (ACTION_REPLY.equals(key)) { m_post.setSelectedObject(state, post); - m_threadComponent.makeReplyFormVisible(state); + m_threadMessagesPanel.makeReplyFormVisible(state); } else if (ACTION_APPROVE.equals(key)) { post.setStatus(Post.APPROVED); post.save(); post.sendNotifications(null); } else if (ACTION_REJECT.equals(key)) { m_post.setSelectedObject(state, post); - m_threadComponent.makeRejectFormVisible(state); + m_threadMessagesPanel.makeRejectFormVisible(state); } state.clearControlEvent(); @@ -168,6 +185,11 @@ public class ThreadDisplay extends SimpleComponent implements Constants { } } + /** + * + * @param state + * @return + */ private DomainCollection getMessages(PageState state) { ForumContext context = ForumContext.getContext(state); @@ -208,15 +230,23 @@ public class ThreadDisplay extends SimpleComponent implements Constants { return new DomainCollection(messages); } + /** + * + * @param state + * @param parent + */ + @Override public void generateXML(PageState state, Element parent) { - Element content = parent.newChildElement(FORUM_XML_PREFIX + ":threadDisplay", + Element content = parent.newChildElement(FORUM_XML_PREFIX + + ":threadDisplay", FORUM_XML_NS); exportAttributes(content); Forum forum = ForumContext.getContext(state).getForum(); content.addAttribute("forumTitle", forum.getTitle()); - content.addAttribute("noticeboard", (new Boolean(forum.isNoticeboard())).toString()); + content.addAttribute("noticeboard", (new Boolean(forum.isNoticeboard())). + toString()); DomainCollection messages = getMessages(state); Integer page = (Integer)state.getValue(m_pageNumber); @@ -261,11 +291,17 @@ public class ThreadDisplay extends SimpleComponent implements Constants { xr.setWrapAttributes(true); xr.setWrapObjects(false); - xr.walk(message, ThreadDisplay.class.getName()); + xr.walk(message, DiscussionPostsList.class.getName()); } } + /** + * + * @param state + * @param parent + * @param post + */ protected void generateActionXML(PageState state, Element parent, Post post) { @@ -301,9 +337,12 @@ public class ThreadDisplay extends SimpleComponent implements Constants { makeURL(state, ACTION_EDIT, post)); } - PermissionDescriptor canRespond = new PermissionDescriptor(PrivilegeDescriptor.get(Forum.RESPOND_TO_THREAD_PRIVILEGE), Kernel.getContext().getResource(), party); + PermissionDescriptor canRespond = new PermissionDescriptor( + PrivilegeDescriptor.get(Forum.RESPOND_TO_THREAD_PRIVILEGE), + Kernel.getContext().getResource(), party); - if (!ctx.getForum().isNoticeboard() && PermissionService.checkPermission(canRespond)) { + if (!ctx.getForum().isNoticeboard() && PermissionService. + checkPermission(canRespond)) { parent.addAttribute("replyURL", makeURL(state, ACTION_REPLY, post)); } @@ -332,7 +371,8 @@ public class ThreadDisplay extends SimpleComponent implements Constants { long begin, long end, long objectCount) { - Element paginator = parent.newChildElement(FORUM_XML_PREFIX + ":paginator", FORUM_XML_NS); + Element paginator = parent.newChildElement(FORUM_XML_PREFIX + + ":paginator", FORUM_XML_NS); URL here = Web.getContext().getRequestURL(); ParameterMap params = new ParameterMap(here.getParameterMap()); diff --git a/ccm-forum/src/com/arsdigita/forum/ui/ThreadComponent.java b/ccm-forum/src/com/arsdigita/forum/ui/DiscussionThreadSimpleView.java similarity index 80% rename from ccm-forum/src/com/arsdigita/forum/ui/ThreadComponent.java rename to ccm-forum/src/com/arsdigita/forum/ui/DiscussionThreadSimpleView.java index 7ef80b08b..093618c09 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/ThreadComponent.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/DiscussionThreadSimpleView.java @@ -47,55 +47,73 @@ import com.arsdigita.messaging.MessageThread; import org.apache.log4j.Logger; /** - * Display for looking at a single thread and posting new messages and - * replying to it. Contains MessagesComponent, EditPostForm, and - * ReplyToPostForm + * A Bebop component which provides the dynamic parts of the UI for looking at + * a single thread of the forum and posting new messages as well as replying to it. + * (The invoking class forum.ThreadPageBuilder creates the static parts as the + * title of the forum and the forum introcuction text). + * + * The dynamic part of the discussion page contains three components: + * a MessageList, a ThreadEdit component, and a ThreadReply component. + * + * Contains MessagesComponent, EditPostForm, and ReplyToPostForm * @see com.arsdigita.forum.ui.MessagesComponent * @see com.arsdigita.forum.ui.EditPostForm * @see com.arsdigita.forum.ui.ReplyToPostForm */ -public class ThreadComponent extends ModalContainer implements Constants { +public class DiscussionThreadSimpleView extends ModalContainer implements Constants { + + /** Private logger instance for debugging purpose. */ + private static final Logger s_log + = Logger.getLogger(DiscussionThreadSimpleView.class); // References to sub-components for event access. - - private Container m_threadView; + /** The message list component */ + private Container m_threadMessagesPanel; + /** The post component for a root mesage */ private PostForm m_rootForm; + /** The post component for a reply mesage */ private PostForm m_replyForm; + /** A message component for moderators */ private Form m_rejectForm; - private static final Logger s_log - = Logger.getLogger(ThreadComponent.class); - + /** */ private ACSObjectSelectionModel m_postModel; /** - * The forum page contains three components: a MessageList, + * Default Constructor creates the component of the discussio view. + * The discussion page contains three components: a MessageList, * a ThreadEdit component, and a ThreadReply component. - * Creates the component. + * */ - public ThreadComponent() { + public DiscussionThreadSimpleView() { // Create a modal container: shows only one containee at a time. m_postModel = new ACSObjectSelectionModel("post"); initComponents(); } + /** + * Internal helper method for constructor + * Add the thread components to the modal container and maintain + * references for event manipulation purposes. + */ private void initComponents() { - // Add the thread components to the modal container and maintain - // references for event manipulation purposes. - s_log.debug("creating edit post form"); + + s_log.debug("creating edit post form"); m_rootForm = new RootPostForm(m_postModel); - m_replyForm = new ReplyToPostForm(m_postModel); s_log.debug("creating reply to post form"); + m_replyForm = new ReplyToPostForm(m_postModel); s_log.debug("creating reject form"); m_rejectForm = new RejectionForm(m_postModel); + addForm(m_rootForm); addForm(m_replyForm); addForm(m_rejectForm); - m_threadView = new SimpleContainer(); - Container linksPanel = new SimpleContainer(FORUM_XML_PREFIX + ":threadOptions", + m_threadMessagesPanel = new SimpleContainer(); + Container linksPanel = new SimpleContainer(FORUM_XML_PREFIX + + ":threadOptions", Constants.FORUM_XML_NS); // Offer links to return to index or control alerts. @@ -110,16 +128,16 @@ public class ThreadComponent extends ModalContainer implements Constants { linksPanel.add(subLinks); // Add the panel to the view. - m_threadView.add(linksPanel); - m_threadView.add(new ThreadDisplay(m_postModel, this)); - add(m_threadView); + m_threadMessagesPanel.add(linksPanel); + m_threadMessagesPanel.add(new DiscussionPostsList(m_postModel, this)); + add(m_threadMessagesPanel); - // The thread view is the default component. - setDefaultComponent(m_threadView); + // The threadMessagesPanel is the default component. + setDefaultComponent(m_threadMessagesPanel); } public void makeListViewVisible(PageState state) { - setVisibleComponent(state, m_threadView); + setVisibleComponent(state, m_threadMessagesPanel); } public void makeEditFormVisible(PageState state) { @@ -208,6 +226,7 @@ public class ThreadComponent extends ModalContainer implements Constants { private Component createThreadUnsubscribeLink() { ActionLink unsubscribeLink = new ActionLink( new Label(Text.gz("forum.ui.thread.unsubscribe"))) { + @Override public boolean isVisible(PageState s) { Party party = Kernel.getContext().getParty(); diff --git a/ccm-forum/src/com/arsdigita/forum/ui/ForumResources_de.properties b/ccm-forum/src/com/arsdigita/forum/ui/ForumResources_de.properties index ee40b69b0..06595b455 100644 --- a/ccm-forum/src/com/arsdigita/forum/ui/ForumResources_de.properties +++ b/ccm-forum/src/com/arsdigita/forum/ui/ForumResources_de.properties @@ -32,7 +32,7 @@ forum.ui.moderate.switch.on=Einschalten forum.ui.moderate.switch.off=Ausschalten forum.ui.moderate.status.on=Aktiv forum.ui.moderate.status.off=Inaktiv -forum.ui.moderate.warning=Achtung: Deaktivieren der Modereation \u00e4ndert den Status von ausstehenden Nachrichten auf akzeptiert! +forum.ui.moderate.warning=Achtung: Deaktivieren der Moderation \u00e4ndert den Status von ausstehenden Nachrichten auf akzeptiert! forum.ui.noticeboard.label=Noticeboard functionality (Antworten deaktiviert) forum.ui.noticeboard.switch.on=Turn on (disable replying) diff --git a/ccm-forum/src/com/arsdigita/forum/ui/ForumUserCompactView.java b/ccm-forum/src/com/arsdigita/forum/ui/ForumUserCompactView.java index c5800d958..7f27d4625 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/ForumUserCompactView.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/ForumUserCompactView.java @@ -33,6 +33,7 @@ import com.arsdigita.forum.ForumContext; import com.arsdigita.forum.ui.admin.ModerationView; import com.arsdigita.forum.ui.admin.PermissionsView; import com.arsdigita.forum.ui.admin.SetupView; +import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Party; import com.arsdigita.kernel.permissions.PermissionDescriptor; @@ -71,7 +72,8 @@ public class ForumUserCompactView extends ModalContainer implements Constants { public static final String MODE_ALERTS = "alerts"; /** Denominator of the 'moderation handling' forum mode */ public static final String MODE_MODERATION = "moderation"; - /** Denominator of the 'permission administration' forum mode (administrators only) */ + /** Denominator of the 'permission administration' forum mode + * (administrators only) */ public static final String MODE_PERMISSIONS = "permissions"; /** Denominator of the 'configuration' forum mode (administrators only)*/ public static final String MODE_SETUP = "setup"; @@ -167,6 +169,8 @@ public class ForumUserCompactView extends ModalContainer implements Constants { PermissionDescriptor forumAdmin = new PermissionDescriptor(PrivilegeDescriptor.ADMIN, forum, party); + PermissionService.assertPermission(forumAdmin); + if (MODE_TOPICS.equals(mode)) { if (Forum.getConfig().topicCreationByAdminOnly()) { if (party == null) { @@ -200,6 +204,7 @@ public class ForumUserCompactView extends ModalContainer implements Constants { PermissionService.assertPermission(forumAdmin); setVisibleComponent(state, m_setupView); } else if (MODE_THREADS.equals(mode)) { + PermissionService.assertPermission(forumAdmin); setVisibleComponent(state, m_threadsView); } } @@ -221,6 +226,7 @@ public class ForumUserCompactView extends ModalContainer implements Constants { "noticeboard", (new Boolean(forum.isNoticeboard())).toString()); + // If visitor not logged in, set user (=party) to publicUser Party party = Kernel.getContext().getParty(); if (party == null) { party = Kernel.getPublicUser(); @@ -246,27 +252,34 @@ public class ForumUserCompactView extends ModalContainer implements Constants { PermissionDescriptor permission = new PermissionDescriptor(PrivilegeDescriptor.ADMIN, forum, party); - // currently thread panel is alwasy shown. If read access should be - // bound to logged in users, additional logic is frequired here. - generateModeXML(state, content, MODE_THREADS); + // currently thread panel is always shown. If read access should be + // bound to logged in users, additional logic is required here. + generateModeXML(state, content, MODE_THREADS, + Text.gz("forum.ui.modeThreads")); // topics panel is always shoen as well if not restricted to admins. if (!Forum.getConfig().topicCreationByAdminOnly()) { - generateModeXML(state, content, MODE_TOPICS); + generateModeXML(state, content, MODE_TOPICS, + Text.gz("forum.ui.modeTopics")); } // alerts panel is always shown as well, no private read access avail. - generateModeXML(state, content, MODE_ALERTS); + generateModeXML(state, content, MODE_ALERTS, + Text.gz("forum.ui.modeAlerts")); // admin section if (PermissionService.checkPermission(permission)) { - generateModeXML(state, content, MODE_MODERATION); + generateModeXML(state, content, MODE_MODERATION, + Text.gz("forum.ui.modeAlerts")); if (Forum.getConfig().showNewTabs()) { - generateModeXML(state, content, MODE_SETUP); - generateModeXML(state, content, MODE_PERMISSIONS); + generateModeXML(state, content, MODE_SETUP, + Text.gz("forum.ui.modeSetup")); + generateModeXML(state, content, MODE_PERMISSIONS, + Text.gz("forum.ui.modePermissions")); } // In case topic creation is bound to admin (and therefore not // created above) we must create xml here. if (Forum.getConfig().topicCreationByAdminOnly()) { - generateModeXML(state, content, MODE_TOPICS); + generateModeXML(state, content, MODE_TOPICS, + Text.gz("forum.ui.modeTopics")); } } } @@ -280,14 +293,17 @@ public class ForumUserCompactView extends ModalContainer implements Constants { * @param parent * @param mode forum mode (threadspanel, topicspanel, alertpanel, ...) to * create entry for + * @deprecated use generateModeXML(PageState, Element, String, + * GlobalizedMessage) instead */ protected void generateModeXML(PageState state, Element parent, String mode) { - + generateModeXML(state, parent, mode, null); + /* String current = (String)state.getValue(m_mode); if (current == null) { - current = MODE_THREADS; + current = MODE_THREADS; // used as default mode } Element content = @@ -297,20 +313,6 @@ public class ForumUserCompactView extends ModalContainer implements Constants { content.addAttribute("mode", mode); - // add localized label here - // content.addAttribute("label", - if (MODE_THREADS.equals(mode)) - content.addAttribute("label",Text.gzAsStr("forum.ui.modeThreads")); - else if(MODE_TOPICS.equals(mode)) - content.addAttribute("label",Text.gzAsStr("forum.ui.modeTopics")); - else if(MODE_ALERTS.equals(mode)) - content.addAttribute("label",Text.gzAsStr("forum.ui.modeAlerts")); - else if(MODE_MODERATION.equals(mode)) - content.addAttribute("label",Text.gzAsStr("forum.ui.modeModeration")); - else if(MODE_SETUP.equals(mode)) - content.addAttribute("label",Text.gzAsStr("forum.ui.modeSetup")); - else if(MODE_PERMISSIONS.equals(mode)) - content.addAttribute("label",Text.gzAsStr("forum.ui.modePermissions")); try { content.addAttribute("url", @@ -321,7 +323,60 @@ public class ForumUserCompactView extends ModalContainer implements Constants { content.addAttribute("selected", current.equals(mode) ? "1" : "0"); state.clearControlEvent(); + + */ } + + /** + * Generates a forum mode selection entry (usually a tab). + * + * + * @param state + * @param parent + * @param mode forum mode (threadspanel, topicspanel, alertpanel, ...) to + * create entry for + * @param label to denominate the mode + */ + protected void generateModeXML(PageState state, + Element parent, + String mode, + GlobalizedMessage label ) { + + String current = (String)state.getValue(m_mode); + if (current == null) { + current = MODE_THREADS; // used as default mode + } + + Element content = + parent.newChildElement(FORUM_XML_PREFIX + ":forumMode", FORUM_XML_NS); + + state.setControlEvent(this, "mode", mode); + + content.addAttribute("mode", + mode); + + // add link to switch to 'mode' + try { + content.addAttribute("url", + state.stateAsURL()); + } catch (IOException ex) { + throw new UncheckedWrapperException("cannot create url", ex); + } + // add localized mode label + // if-else should be removed when deprecated method above is removed! + if (label == null) { + content.addAttribute("label", + "UNAVAILABLE"); + } else { + content.addAttribute("label", + (String)label.localize()); + } + // add if current mode is actually selected + content.addAttribute("selected", + current.equals(mode) ? "1" : "0"); + state.clearControlEvent(); + } + } diff --git a/ccm-forum/src/com/arsdigita/forum/ui/MessageView.java b/ccm-forum/src/com/arsdigita/forum/ui/MessageView.java index d23c97441..39ffaa09d 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/MessageView.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/MessageView.java @@ -23,7 +23,7 @@ import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.SimpleComponent; import com.arsdigita.forum.Post; import com.arsdigita.kernel.ui.ACSObjectSelectionModel; -import com.arsdigita.messaging.Message; +import com.arsdigita.messaging.Message; import com.arsdigita.domain.DomainObjectXMLRenderer; import com.arsdigita.xml.Element; @@ -34,20 +34,21 @@ import org.apache.log4j.Logger; class MessageView extends SimpleComponent implements Constants { private static final Logger s_log = Logger.getLogger(MessageView.class); - private ReplyToPostForm m_container; + private ReplyToPostForm m_container; private ACSObjectSelectionModel m_postModel; private Post m_post; /** For dynamically selected message views */ - public MessageView(ACSObjectSelectionModel postModel, ReplyToPostForm container) { + public MessageView(ACSObjectSelectionModel postModel, ReplyToPostForm container) { m_postModel = postModel; - m_container = container; + m_container = container; } public MessageView(Post post) { m_post = post; } + @Override public void register(Page page) { super.register(page); if (m_postModel != null) { @@ -56,20 +57,21 @@ class MessageView extends SimpleComponent implements Constants { } } + @Override public void generateXML(PageState state, Element parent) { - Message post = m_post; + Message post = m_post; if (m_post == null) { post = (Post)m_postModel.getSelectedObject(state); } - if (m_container.getContext(state).equals(ReplyToPostForm.EDIT_CONTEXT)) { - // post in postmodel is the reply being edited, not the parent - post = post.getParent(); - } - - + if (m_container.getContext(state).equals(ReplyToPostForm.EDIT_CONTEXT)) { + // post in postmodel is the reply being edited, not the parent + post = post.getParent(); + } - Element messageEl = parent.newChildElement(FORUM_XML_PREFIX + ":message", + + + Element messageEl = parent.newChildElement(FORUM_XML_PREFIX + ":message", FORUM_XML_NS); exportAttributes(messageEl); @@ -78,7 +80,7 @@ class MessageView extends SimpleComponent implements Constants { xr.setWrapAttributes(true); xr.setWrapObjects(false); - xr.walk(post, ThreadDisplay.class.getName()); + xr.walk(post, DiscussionPostsList.class.getName()); } } diff --git a/ccm-forum/src/com/arsdigita/forum/ui/MessageXMLFormatter.java b/ccm-forum/src/com/arsdigita/forum/ui/MessageXMLFormatter.java index 7599c7596..784503f5c 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/MessageXMLFormatter.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/MessageXMLFormatter.java @@ -25,8 +25,9 @@ import com.arsdigita.persistence.metadata.Property; public class MessageXMLFormatter - extends SimpleDomainObjectXMLFormatter { + extends SimpleDomainObjectXMLFormatter { + @Override public Object format(DomainObject obj, String path, Property prop, @@ -39,6 +40,7 @@ public class MessageXMLFormatter return super.format(obj, path, prop, value); } + @Override public boolean isEmpty() { return false; } diff --git a/ccm-forum/src/com/arsdigita/forum/ui/ThreadList.java b/ccm-forum/src/com/arsdigita/forum/ui/ThreadsList.java similarity index 91% rename from ccm-forum/src/com/arsdigita/forum/ui/ThreadList.java rename to ccm-forum/src/com/arsdigita/forum/ui/ThreadsList.java index ecb4fc983..5f9c012f2 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/ThreadList.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/ThreadsList.java @@ -50,7 +50,7 @@ import java.math.BigDecimal; * A paginator is added to handle a high number of threads. * */ -public class ThreadList extends SimpleComponent implements Constants { +public class ThreadsList extends SimpleComponent implements Constants { /** */ private IntegerParameter m_pageNumber = @@ -81,9 +81,8 @@ public class ThreadList extends SimpleComponent implements Constants { categoryID = null; } - ThreadCollection threads = forum.getThreads( - categoryID, - Kernel.getContext().getParty()); + ThreadCollection threads = forum.getThreads(categoryID, + Kernel.getContext().getParty()); return threads; } @@ -95,6 +94,7 @@ public class ThreadList extends SimpleComponent implements Constants { */ public void generateXML(PageState state, Element parent) { + // Begin of thread list, XSL constructs (and localizes) the list title bar Element content = parent.newChildElement(FORUM_XML_PREFIX + ":threadList", FORUM_XML_NS); @@ -130,11 +130,14 @@ public class ThreadList extends SimpleComponent implements Constants { new Integer((int)end+1)); } - while (threads.next()) { + while (threads.next()) { // step through ThreadCollections + MessageThread thread = threads.getMessageThread(); Element threadEl = content.newChildElement(FORUM_XML_PREFIX + ":thread", FORUM_XML_NS); + // create link to a JSP which provide a List of messages for the + // thread, i.e. this first message and all its followup messages ParameterMap map = new ParameterMap(); map.setParameter(THREAD_PARAM, thread.getID()); URL url = URL.there((Application)Kernel.getContext().getResource(), @@ -147,7 +150,7 @@ public class ThreadList extends SimpleComponent implements Constants { xr.setWrapAttributes(true); xr.setWrapObjects(false); - xr.walk(thread, ThreadList.class.getName()); + xr.walk(thread, ThreadsList.class.getName()); } } diff --git a/ccm-forum/src/com/arsdigita/forum/ui/ThreadsPanel.java b/ccm-forum/src/com/arsdigita/forum/ui/ThreadsPanel.java index c30ec102e..f5b8e8038 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/ThreadsPanel.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/ThreadsPanel.java @@ -69,7 +69,7 @@ public class ThreadsPanel extends SimpleContainer private ModalContainer m_mode; /** Bebop Component, list of threads along with some othere elements, will * be one child of ModalContainer */ - private Component m_threadsComponent; + private Component m_threadsListing; /** Bebop Component, add new post to a thread form. Will be another child of * ModalContainer */ private PostForm m_postComponent; @@ -90,13 +90,13 @@ public class ThreadsPanel extends SimpleContainer m_mode = new ModalContainer(); add(m_mode); - m_threadsComponent = createThreadsComponent(); - m_postComponent = createPostComponent(); + m_threadsListing = createThreadsListing(); + m_postComponent = createNewThreadForm(); - m_mode.add(m_threadsComponent); + m_mode.add(m_threadsListing); m_mode.add(m_postComponent); - m_mode.setDefaultComponent(m_threadsComponent); + m_mode.setDefaultComponent(m_threadsListing); } @@ -123,7 +123,7 @@ public class ThreadsPanel extends SimpleContainer m_postComponent.setContext(s, PostForm.NEW_CONTEXT); m_mode.setVisibleComponent(s, m_postComponent); } else { - m_mode.setVisibleComponent(s, m_threadsComponent); + m_mode.setVisibleComponent(s, m_threadsListing); } } }); @@ -135,7 +135,7 @@ public class ThreadsPanel extends SimpleContainer * with author, # of responses, etc. Filtered for approved * messages if the forum is moderated. */ - private Component createThreadsComponent() { + private Component createThreadsListing() { Container forums = new SimpleContainer(); @@ -166,8 +166,8 @@ public class ThreadsPanel extends SimpleContainer TopicSelector topics = new TopicSelector(); forums.add(topics); - ThreadList threads - = new ThreadList(); + ThreadsList threads + = new ThreadsList(); forums.add(threads); @@ -175,10 +175,14 @@ public class ThreadsPanel extends SimpleContainer } /** + * Provides a Form to create a new Thread. It is accomplished by constructing + * a RootPostForm to create a new post which contains a subject line and + * a selection box for a topic the new thread should be associated to. * - * @return + * @return a form to create the first post of a new thread which implicitly + * creates a new thread. */ - private PostForm createPostComponent() { + private PostForm createNewThreadForm() { PostForm editForm = new RootPostForm(); editForm.addCompletionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { diff --git a/ccm-forum/src/com/arsdigita/forum/ui/TopicList.java b/ccm-forum/src/com/arsdigita/forum/ui/TopicsList.java similarity index 98% rename from ccm-forum/src/com/arsdigita/forum/ui/TopicList.java rename to ccm-forum/src/com/arsdigita/forum/ui/TopicsList.java index 06df61d38..a79420dd5 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/TopicList.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/TopicsList.java @@ -44,7 +44,7 @@ import java.util.Iterator; * uses category in the usual CMS way, esp. navigation categories. * */ -public class TopicList extends SimpleComponent implements Constants { +public class TopicsList extends SimpleComponent implements Constants { /** List of properties a topic may have. */ private final static Set s_catProps; diff --git a/ccm-forum/src/com/arsdigita/forum/ui/TopicsPanel.java b/ccm-forum/src/com/arsdigita/forum/ui/TopicsPanel.java index d39327431..8eecf5bca 100755 --- a/ccm-forum/src/com/arsdigita/forum/ui/TopicsPanel.java +++ b/ccm-forum/src/com/arsdigita/forum/ui/TopicsPanel.java @@ -138,7 +138,7 @@ public class TopicsPanel extends SimpleContainer topicslist.add(linksPanel); // create and add topics list - topicslist.add(new TopicList()); // separate class + topicslist.add(new TopicsList()); // separate class return topicslist; } diff --git a/ccm-forum/web/WEB-INF/web.ccm-forum.xml b/ccm-forum/web/WEB-INF/web.ccm-forum.xml index d0e397590..86722f1d1 100644 --- a/ccm-forum/web/WEB-INF/web.ccm-forum.xml +++ b/ccm-forum/web/WEB-INF/web.ccm-forum.xml @@ -1,5 +1,8 @@ - + diff --git a/ccm-forum/web/packages/forum/xsl/forum.xsl b/ccm-forum/web/packages/forum/xsl/forum.xsl index 6eb32e53b..4128e02f3 100755 --- a/ccm-forum/web/packages/forum/xsl/forum.xsl +++ b/ccm-forum/web/packages/forum/xsl/forum.xsl @@ -4,11 +4,11 @@ xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> - -