Erster Teil einer Ueberarbeitung des Forums: Dokumentation hinzugefuegt, Benennungen systematisiert, Lokalisierung im Java code ergaenzt.

git-svn-id: https://svn.libreccm.org/ccm/trunk@531 8810af33-2d31-482b-a856-94f89814c4df
master
pb 2010-09-13 10:33:25 +00:00
parent 1f25ffe9cb
commit cf586f9cd0
25 changed files with 926 additions and 555 deletions

View File

@ -51,6 +51,13 @@ import com.arsdigita.web.Application;
/** /**
* The Forum class represents a discussion forum. * The Forum class represents a discussion forum.
* *
* XXX: Forum knows about <i>threads</i> which groups a set of posts to the same
* subject, and <i>topics</i> which group a set of threads about the same general
* theme. Currently Forum uses <i>catgegory</i> as synonym for topic, which may be
* misleading in some contexts, because there is <i>forum-categorized</i> which
* uses category in the usual CMS way, esp. navigation categories. Should be
* cleaned up in the future.
*
* @author Kevin Scaldeferri (kevin@arsdigita.com) * @author Kevin Scaldeferri (kevin@arsdigita.com)
* @author chrisg23 * @author chrisg23
* @version $Revision: 1.7 $ * @version $Revision: 1.7 $
@ -62,7 +69,7 @@ public class Forum extends Application {
public static final String THREAD_SUBSCRIPTION_GROUPS_NAME = public static final String THREAD_SUBSCRIPTION_GROUPS_NAME =
"Thread Subscription Groups"; "Thread Subscription Groups";
private static ForumConfig s_config = new ForumConfig(); private static final ForumConfig s_config = new ForumConfig();
static { static {
s_config.load(); s_config.load();
@ -151,7 +158,6 @@ public class Forum extends Application {
* Also sets default values for other forum settings. These can be * Also sets default values for other forum settings. These can be
* amended under the setup tab in the ui * amended under the setup tab in the ui
*/ */
public static Forum create(String urlName, String title, public static Forum create(String urlName, String title,
Application parent, boolean moderated) { Application parent, boolean moderated) {
s_log.debug("creating forum " + title); s_log.debug("creating forum " + title);
@ -182,7 +188,6 @@ public class Forum extends Application {
* @return the Root Category for this forum, or creates a new one * @return the Root Category for this forum, or creates a new one
* does not have a root category, and returns it. * does not have a root category, and returns it.
*/ */
public Category getRootCategory() { public Category getRootCategory() {
DataObject category = (DataObject) get(CATEGORY); DataObject category = (DataObject) get(CATEGORY);
if (category == null) { if (category == null) {
@ -237,7 +242,8 @@ public class Forum extends Application {
// NPE when trying to retrieve sender's email address, thus stopping any // NPE when trying to retrieve sender's email address, thus stopping any
// further message processing. // further message processing.
// Actually, the only hack involved is making the email address unique. // Actually, the only hack involved is making the email address unique.
String email = "forum-moderator-" + getID() + "-" + moderators.getID() + "@" + s_config.getReplyHostName(); String email = "forum-moderator-" + getID() + "-" +
moderators.getID() + "@" + s_config.getReplyHostName();
moderators.setPrimaryEmail(new EmailAddress(email)); moderators.setPrimaryEmail(new EmailAddress(email));
// chris.gilbert@westsussex.gov.uk create additional groups for privilege // chris.gilbert@westsussex.gov.uk create additional groups for privilege
@ -272,6 +278,7 @@ public class Forum extends Application {
} }
@Override
public void initialize() { public void initialize() {
super.initialize(); super.initialize();
@ -290,11 +297,13 @@ public class Forum extends Application {
private boolean m_wasNew; private boolean m_wasNew;
@Override
protected void beforeSave() { protected void beforeSave() {
m_wasNew = isNew(); m_wasNew = isNew();
super.beforeSave(); super.beforeSave();
} }
@Override
protected void afterSave() { protected void afterSave() {
if (m_wasNew) { if (m_wasNew) {
PermissionService.setContext(getRootCategory(), this); PermissionService.setContext(getRootCategory(), this);
@ -462,7 +471,6 @@ public class Forum extends Application {
FilterFactory factory = posts.getFilterFactory(); FilterFactory factory = posts.getFilterFactory();
Filter pending = factory.equals(Post.STATUS, Post.PENDING); Filter pending = factory.equals(Post.STATUS, Post.PENDING);
Filter reapprove = factory.equals(Post.STATUS, Post.REAPPROVE); Filter reapprove = factory.equals(Post.STATUS, Post.REAPPROVE);
;
posts.addFilter(factory.or().addFilter(pending).addFilter(reapprove)); posts.addFilter(factory.or().addFilter(pending).addFilter(reapprove));
@ -471,7 +479,7 @@ public class Forum extends Application {
/** /**
* gets all suppressed messages - allows moderators to see which messages * gets all suppressed messages - allows moderators to see which messages
* heve been rejectedrequire their attention * heve been rejected / require their attention
* @return * @return
*/ */
public DataAssociation getSuppressedPosts() { public DataAssociation getSuppressedPosts() {
@ -963,8 +971,9 @@ public class Forum extends Application {
* *
* @return path name to the applications servlet/JSP * @return path name to the applications servlet/JSP
*/ */
@Override
public String getServletPath() { public String getServletPath() {
// sufficient it installed into its own web appl. context (ccm-forum) // sufficient if installed into its own web appl. context (ccm-forum)
// return "/main"; // return "/main";
return "/forum-main/main"; return "/forum-main/main";
} }

View File

@ -27,62 +27,95 @@ import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.bebop.event.RequestEvent; import com.arsdigita.bebop.event.RequestEvent;
import com.arsdigita.bebop.event.RequestListener; import com.arsdigita.bebop.event.RequestListener;
import com.arsdigita.bebop.parameters.BigDecimalParameter; 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.Constants;
import com.arsdigita.forum.ui.ForumComponent; import com.arsdigita.forum.ui.ForumUserCompactView;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.toolbox.ui.ApplicationAuthenticationListener; import com.arsdigita.toolbox.ui.ApplicationAuthenticationListener;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
/** /**
* @author chris.gilbert@westsussex.gov.uk * Implementation of com.arsdigita.forum.PageBuilder that creates a
* basic forum page with read access check
* *
* Implementation of com.arsdigita.forum.PageBuilder that creates a basic forum page with read access check * @author chris.gilbert@westsussex.gov.uk
*/ */
public class ForumPageBuilder implements PageBuilder, Constants { public class ForumPageBuilder implements PageBuilder, Constants {
/**
*
* @return
*/
public Page buildPage() { public Page buildPage() {
Page page = PageFactory.buildPage(Constants.FORUM_XML_PREFIX, "Forum", "forumPage");
//Output the title in an easy to find place Page page = PageFactory.buildPage(Constants.FORUM_XML_PREFIX,
page.add(new SimpleComponent(){ "Forum",
public void generateXML(PageState state, Element parent) { "forumPage");
Element nameElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":name", Constants.FORUM_XML_NS);
nameElement.setText(ForumContext.getContext(state).getForum().getTitle()); //Output the title in an easy to find place
Element introductionElement = parent.newChildElement(Constants.FORUM_XML_PREFIX + ":introduction", Constants.FORUM_XML_NS); page.add(new SimpleComponent(){
introductionElement.setText(ForumContext.getContext(state).getForum().getIntroduction()); public void generateXML(PageState state, Element parent) {
} Element nameElement = parent.newChildElement(
}); Constants.FORUM_XML_PREFIX +
ForumComponent forumComp = getForumComponent(); ":name",
page.add(forumComp); Constants.FORUM_XML_NS);
BigDecimalParameter topic = new BigDecimalParameter(TOPIC_PARAM); nameElement.setText(
page.addGlobalStateParam(topic); ForumContext.getContext(state).getForum().getTitle());
page.addRequestListener(new ApplicationAuthenticationListener(PrivilegeDescriptor.READ)); Element introductionElement = parent.newChildElement(
page.addRequestListener(new ForumPageRequestListener(topic, forumComp)); Constants.FORUM_XML_PREFIX +
return page; ":introduction",
Constants.FORUM_XML_NS);
introductionElement.setText(
ForumContext.getContext(state).getForum().getIntroduction());
}
});
ForumUserCompactView forumComp = getForumComponent();
page.add(forumComp);
BigDecimalParameter topic = new BigDecimalParameter(TOPIC_PARAM);
page.addGlobalStateParam(topic);
page.addRequestListener(
new ApplicationAuthenticationListener(PrivilegeDescriptor.READ));
page.addRequestListener(new ForumPageRequestListener(topic, forumComp));
return page;
} }
protected ForumComponent getForumComponent() { /**
return new ForumComponent(); *
* @return
*/
protected ForumUserCompactView getForumComponent() {
return new ForumUserCompactView();
} }
/**
* Internal class
*/
private static class ForumPageRequestListener implements RequestListener { private static class ForumPageRequestListener implements RequestListener {
private BigDecimalParameter m_categorySelection;
private ForumComponent m_forumComp;
public ForumPageRequestListener(BigDecimalParameter topicSelection, ForumComponent forumComp) { private BigDecimalParameter m_categorySelection;
m_categorySelection = topicSelection; private ForumUserCompactView m_forumComp;
m_forumComp = forumComp;
}
public void pageRequested(RequestEvent event) { /**
* Default Constructor
* @param topicSelection
* @param forumComp
*/
public ForumPageRequestListener(BigDecimalParameter topicSelection,
ForumUserCompactView forumComp) {
m_categorySelection = topicSelection;
m_forumComp = forumComp;
}
PageState state = event.getPageState(); public void pageRequested(RequestEvent event) {
ForumContext context = ForumContext.getContext(state);
context.setCategorySelection PageState state = event.getPageState();
((BigDecimal) event.getPageState().getValue(m_categorySelection)); ForumContext context = ForumContext.getContext(state);
context.setCategorySelection(
(BigDecimal) event.getPageState().getValue(m_categorySelection));
} }
} }
} }

View File

@ -23,15 +23,15 @@ import java.util.Iterator;
import java.util.Map; import java.util.Map;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.parameters.ParameterModel; // import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
/** /**
* @author chris.gilbert@westsussex.gov.uk
*
* Factory class that enables projects to provide their own page creators. * Factory class that enables projects to provide their own page creators.
* A reason for doing this is that a particular forum project may wish to * A reason for doing this is that a particular forum project may wish to
* include components on the page that introduce dependencies on other projects * include components on the page that introduce dependencies on other projects
*
* @author chris.gilbert@westsussex.gov.uk
*/ */
public class ForumPageFactory { public class ForumPageFactory {
@ -46,8 +46,10 @@ public class ForumPageFactory {
pageBuilders.put(FORUM_PAGE, new ForumPageBuilder()); pageBuilders.put(FORUM_PAGE, new ForumPageBuilder());
} }
public static Page getPage(String pageType) { public static Page getPage(String pageType) {
Assert.isTrue(pageBuilders.containsKey(pageType), "Requested page type (" + pageType + ") does not have a builder registered" ); Assert.isTrue(pageBuilders.containsKey(pageType),
"Requested page type (" + pageType +
") does not have a builder registered" );
PageBuilder builder = (PageBuilder)pageBuilders.get(pageType); PageBuilder builder = (PageBuilder)pageBuilders.get(pageType);
Page page = builder.buildPage(); Page page = builder.buildPage();
page.lock(); page.lock();

View File

@ -18,24 +18,26 @@
*/ */
package com.arsdigita.forum; package com.arsdigita.forum;
import java.util.Iterator;
// unused import
//import java.util.Map;
import com.arsdigita.forum.ui.Constants;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.page.BebopApplicationServlet; import com.arsdigita.bebop.page.BebopApplicationServlet;
// unused import // unused import
// import com.arsdigita.bebop.parameters.BigDecimalParameter; // import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.forum.ui.Constants;
import java.util.Iterator;
// unused import
//import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
*
* @author Justin Ross &lt;<a href="mailto:jross@redhat.com">jross@redhat.com</a>&gt; * @author Justin Ross &lt;<a href="mailto:jross@redhat.com">jross@redhat.com</a>&gt;
* *
* Updated chris.gilbert@westsussex.gov.uk to make use of PageFactory and to enable * @author Chris Gilbert (chris.gilbert@westsussex.gov.uk) updated to make use of
* disablement of client/middleware caching * PageFactory and to enable disablement of client/middleware
* caching
* @version $Id: ForumServlet.java 1628 2007-09-17 08:10:40Z chrisg23 $ * @version $Id: ForumServlet.java 1628 2007-09-17 08:10:40Z chrisg23 $
*/ */
public class ForumServlet extends BebopApplicationServlet public class ForumServlet extends BebopApplicationServlet

View File

@ -52,6 +52,7 @@ import org.apache.log4j.Logger;
*/ */
public class Loader extends PackageLoader { public class Loader extends PackageLoader {
/** Private logger instance for debugging purpose. */
private static final Logger s_log = Logger.getLogger(Loader.class); private static final Logger s_log = Logger.getLogger(Loader.class);
public void run(final ScriptContext ctx) { public void run(final ScriptContext ctx) {
@ -140,22 +141,23 @@ public class Loader extends PackageLoader {
} }
public static void setupPrivileges() { public static void setupPrivileges() {
PrivilegeDescriptor.createPrivilege(
Forum.FORUM_MODERATION_PRIVILEGE);
PrivilegeDescriptor.createPrivilege(
Forum.CREATE_THREAD_PRIVILEGE);
PrivilegeDescriptor.createPrivilege( PrivilegeDescriptor.createPrivilege(
Forum.RESPOND_TO_THREAD_PRIVILEGE); Forum.FORUM_MODERATION_PRIVILEGE);
PrivilegeDescriptor.addChildPrivilege( PrivilegeDescriptor.createPrivilege(
Forum.FORUM_MODERATION_PRIVILEGE, Forum.CREATE_THREAD_PRIVILEGE);
Forum.CREATE_THREAD_PRIVILEGE); PrivilegeDescriptor.createPrivilege(
PrivilegeDescriptor.addChildPrivilege( Forum.RESPOND_TO_THREAD_PRIVILEGE);
Forum.CREATE_THREAD_PRIVILEGE,
Forum.RESPOND_TO_THREAD_PRIVILEGE); PrivilegeDescriptor.addChildPrivilege(
PrivilegeDescriptor.addChildPrivilege( Forum.FORUM_MODERATION_PRIVILEGE,
Forum.RESPOND_TO_THREAD_PRIVILEGE, Forum.CREATE_THREAD_PRIVILEGE);
PrivilegeDescriptor.READ.getName()); PrivilegeDescriptor.addChildPrivilege(
Forum.CREATE_THREAD_PRIVILEGE,
Forum.RESPOND_TO_THREAD_PRIVILEGE);
PrivilegeDescriptor.addChildPrivilege(
Forum.RESPOND_TO_THREAD_PRIVILEGE,
PrivilegeDescriptor.READ.getName());

View File

@ -19,7 +19,7 @@
package com.arsdigita.forum; package com.arsdigita.forum;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.parameters.ParameterModel; // import com.arsdigita.bebop.parameters.ParameterModel;
/** /**
* @author chris.gilbert@westsussex.gov.uk * @author chris.gilbert@westsussex.gov.uk

View File

@ -1,101 +0,0 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of 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.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.forum.ui;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Container;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.ModalContainer;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.ToggleLink;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import org.apache.log4j.Logger;
public class CategoryView extends SimpleContainer
implements ActionListener {
private static Logger s_log = Logger.getLogger(CategoryView.class);
private ModalContainer m_mode;
private Component m_categories;
private Component m_addForm;
private ToggleLink m_addCategoryLink;
public CategoryView() {
m_mode = new ModalContainer();
add(m_mode);
m_categories = createCategoryView();
m_addForm = createAddCategoryForm();
m_mode.add(m_categories);
m_mode.add(m_addForm);
m_mode.setDefaultComponent(m_categories);
}
public void register(Page p) {
super.register(p);
p.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
PageState s = e.getPageState();
if (m_addCategoryLink.isSelected(s)) {
m_mode.setVisibleComponent(s, m_addForm);
} else {
m_mode.setVisibleComponent(s, m_categories);
}
}
private Container createCategoryView() {
Container categories = new SimpleContainer();
Container linksPanel = new SimpleContainer(Constants.FORUM_XML_PREFIX + ":topicOptions",
Constants.FORUM_XML_NS);
m_addCategoryLink = new ToggleLink(new Label(Text.gz("forum.ui.newTopic")));
m_addCategoryLink.setClassAttr("actionLink");
linksPanel.add(m_addCategoryLink);
categories.add(linksPanel);
categories.add(new TopicList());
return categories;
}
private Component createAddCategoryForm() {
Form addForm = new CategoryAddForm();
addForm.addCompletionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PageState s = e.getPageState();
m_addCategoryLink.setSelected(s, false);
m_mode.setVisibleComponent(s, m_categories);
}
});
return addForm;
}
}

View File

@ -40,9 +40,8 @@ import java.util.TooManyListenersException;
* @author ron@arsdigita.com * @author ron@arsdigita.com
* @author sarah@arsdigita.com * @author sarah@arsdigita.com
* *
* @version $Id: CategoryWidget.java 1628 2007-09-17 08:10:40Z chrisg23 $ * @version $Id: CategoryWidget.java 1628 2007-09-17 08:10:40Z chrisg23 $
*/ */
public class CategoryWidget extends SingleSelect implements Constants { public class CategoryWidget extends SingleSelect implements Constants {
public CategoryWidget(ParameterModel categoryParameter) { public CategoryWidget(ParameterModel categoryParameter) {
@ -53,13 +52,14 @@ public class CategoryWidget extends SingleSelect implements Constants {
public void prepare(PrintEvent e) { public void prepare(PrintEvent e) {
PageState s = e.getPageState(); PageState s = e.getPageState();
final Forum forum = getForum(s); final Forum forum = getForum(s);
SingleSelect target = (SingleSelect) e.getTarget(); SingleSelect target = (SingleSelect) e.getTarget();
// Get categories for this forum // Get categories for this forum
if (forum.noCategoryPostsAllowed()) { if (forum.noCategoryPostsAllowed()) {
target.addOption(new Option(TOPIC_NONE.toString(), target.addOption(new Option(
new Label(Text.gz("forum.ui.topic.none")))); TOPIC_NONE.toString(),
} new Label(Text.gz("forum.ui.topic.none"))));
}
final Category root = forum.getRootCategory(); final Category root = forum.getRootCategory();
if (root != null) { if (root != null) {
addCategories(root, target); addCategories(root, target);

View File

@ -51,24 +51,31 @@ import java.math.BigDecimal;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/**
*
*
*/
class ForumAlertsView extends SimpleContainer implements Constants { class ForumAlertsView extends SimpleContainer implements Constants {
private static final Logger s_log = Logger.getLogger private static final Logger s_log = Logger.getLogger
(ForumAlertsView.class); (ForumAlertsView.class);
/**
* Standard Constructor
*/
ForumAlertsView() { ForumAlertsView() {
add(forumAlertsSegment()); add(forumAlertsSegment());
add(threadAlertsSegment()); add(threadAlertsSegment());
} }
private Component forumAlertsSegment() { private Component forumAlertsSegment() {
SimpleContainer seg = new SimpleContainer(FORUM_XML_PREFIX + ":forumAlerts", SimpleContainer seg = new SimpleContainer(FORUM_XML_PREFIX + ":forumAlerts",
FORUM_XML_NS); FORUM_XML_NS);
seg.add(forumAlertsForm()); seg.add(forumAlertsForm());
return seg; return seg;
} }
private Component threadAlertsSegment() { private Component threadAlertsSegment() {
SimpleContainer seg = new SimpleContainer(FORUM_XML_PREFIX + ":threadAlerts", SimpleContainer seg = new SimpleContainer(FORUM_XML_PREFIX + ":threadAlerts",
FORUM_XML_NS); FORUM_XML_NS);
seg.add(threadAlertsForm()); seg.add(threadAlertsForm());
return seg; return seg;
@ -78,19 +85,19 @@ class ForumAlertsView extends SimpleContainer implements Constants {
Form alertsForm = new Form("instantAlerts", new ColumnPanel(2)); Form alertsForm = new Form("instantAlerts", new ColumnPanel(2));
final RadioGroup instant = new RadioGroup("instant"); final RadioGroup instant = new RadioGroup("instant");
instant.addOption(new Option("Yes")); instant.addOption(new Option(Text.gzAsStr("forum.ui.yes")));
instant.addOption(new Option("No")); instant.addOption(new Option(Text.gzAsStr("forum.ui.no")));
alertsForm.add(new Label(Text.gz("forum.ui.receive_instant_alerts"))); alertsForm.add(new Label(Text.gz("forum.ui.receive_instant_alerts")));
alertsForm.add(instant); alertsForm.add(instant);
final RadioGroup daily = new RadioGroup("daily"); final RadioGroup daily = new RadioGroup("daily");
daily.addOption(new Option("Yes")); daily.addOption(new Option(Text.gzAsStr("forum.ui.yes")));
daily.addOption(new Option("No")); daily.addOption(new Option(Text.gzAsStr("forum.ui.no")));
alertsForm.add(new Label(Text.gz("forum.ui.receive_daily_summary"))); alertsForm.add(new Label(Text.gz("forum.ui.receive_daily_summary")));
alertsForm.add(daily); alertsForm.add(daily);
alertsForm.add(new Label("")); alertsForm.add(new Label(""));
alertsForm.add(new Submit("Save")); alertsForm.add(new Submit(Text.gz("forum.ui.save")));
alertsForm.addInitListener(new FormInitListener() { alertsForm.addInitListener(new FormInitListener() {
public void init(FormSectionEvent e) { public void init(FormSectionEvent e) {

View File

@ -1,18 +1,31 @@
forum.ui.name=Name forum.ui.delete=Delete
forum.ui.description=Description
forum.ui.cancel=Cancel
forum.ui.newTopic=New topic forum.ui.noSubscriptions=You are not subscribed to any threads
forum.ui.topic.none=None
forum.ui.receive_instant_alerts=Receive instant alerts forum.ui.receive_instant_alerts=Receive instant alerts
forum.ui.receive_daily_summary=Receive daily summary forum.ui.receive_daily_summary=Receive daily summary
forum.ui.noSubscriptions=You are not subscribed to any threads
forum.ui.delete=Delete forum.ui.modeAlerts=Alerts
forum.ui.newPost=New thread forum.ui.modeThreads=Threads
forum.ui.threads.viewAll=View all threads forum.ui.modeTopics=Topics
forum.ui.modeModeration=Moderation
forum.ui.modeSetup=Setup
forum.ui.modePermissions=Permissions
forum.ui.cancel=Cancel
forum.ui.save=Save
forum.ui.yes=Yes
forum.ui.no=No
forum.ui.thread.newPost=Start New thread
forum.ui.thread.subscribe=Subscribe to thread forum.ui.thread.subscribe=Subscribe to thread
forum.ui.thread.unsubscribe=Unsubscribe to thread forum.ui.thread.unsubscribe=Unsubscribe to thread
forum.ui.topic.save=Create Topic forum.ui.thread.viewAll=View all threads
forum.ui.topic.description=Description
forum.ui.topic.name=Name
forum.ui.topic.newTopic=New topic
forum.ui.topic.none=None
forum.ui.topic.save=Create Topic
forum.ui.moderate.label=Moderation: forum.ui.moderate.label=Moderation:
forum.ui.moderate.switch.on=Turn on forum.ui.moderate.switch.on=Turn on
@ -28,26 +41,26 @@ forum.ui.noticeboard.status.on=On (replying disabled)
forum.ui.noticeboard.status.off=Off (replying enabled) forum.ui.noticeboard.status.off=Off (replying enabled)
forum.ui.noticeboard.expiry_after=Expires after (in days) forum.ui.noticeboard.expiry_after=Expires after (in days)
forum.ui.noticeboard.change_expiry=Update forum.ui.noticeboard.change_expiry=Update
forum.ui.settings.moderated=Moderated forum.ui.settings.moderated=Moderated
forum.ui.settings.noticeboard=Noticeboard (Disable Replying) forum.ui.settings.noticeboard=Noticeboard (Disable Replying)
forum.ui.settings.allowFiles=Allow File Attachments forum.ui.settings.allowFiles=Allow File Attachments
forum.ui.settings.allowImages=Allow images in posts forum.ui.settings.allowImages=Allow images in posts
forum.ui.settings.autosubscribe=Automatically subscribe thread starters forum.ui.settings.autosubscribe=Automatically subscribe thread starters
forum.ui.settings.noCategoryPosts=Allow posts with no topic forum.ui.settings.noCategoryPosts=Allow posts with no topic
forum.ui.settings.anonymousPosts=Allow anonymous posts forum.ui.settings.anonymousPosts=Allow anonymous posts
forum.ui.settings.save=Save Changes forum.ui.settings.save=Save Changes
forum.ui.settings.introduction=Introduction forum.ui.settings.introduction=Introduction
forum.ui.settings.title=Forum Title forum.ui.settings.title=Forum Title
forum.ui.validation.subject_null=Please enter a subject forum.ui.validation.subject_null=Please enter a subject
forum.ui.validation.body_null=Please enter a message forum.ui.validation.body_null=Please enter a message
forum.ui.validation.body_too_long=Your message is too long, only 4000 characters can be stored forum.ui.validation.body_too_long=Your message is too long, only 4000 characters can be stored
forum.ui.validation.image_file_null=Please use the browse button above to find an image to add forum.ui.validation.image_file_null=Please use the browse button above to find an image to add
forum.ui.validation.image_description_null=Please enter a description for the image (This will be displayed to users who cannot see the image) forum.ui.validation.image_description_null=Please enter a description for the image (This will be displayed to users who cannot see the image)
forum.ui.validation.image_description_too_long=Your description is too long, only 4000 characters can be stored forum.ui.validation.image_description_too_long=Your description is too long, only 4000 characters can be stored
forum.ui.validation.file_null=Please use the browse button above to find a file to add forum.ui.validation.file_null=Please use the browse button above to find a file to add
forum.ui.validation.file_description_too_long=Your description is too long, only 4000 characters can be stored forum.ui.validation.file_description_too_long=Your description is too long, only 4000 characters can be stored
forum.ui.validation.image_not_uploaded=To add the specified image, use the Add Image button before leaving this page. If you don't want to add the image, click Next or Previous. forum.ui.validation.image_not_uploaded=To add the specified image, use the Add Image button before leaving this page. If you don't want to add the image, click Next or Previous.
forum.ui.validation.file_not_uploaded=To add the specified file, use the Add File button before leaving this page. If you don't want to add the file, click Next or Previous. forum.ui.validation.file_not_uploaded=To add the specified file, use the Add File button before leaving this page. If you don't want to add the file, click Next or Previous.
forum.ui.validation.introduction_too_long=Your introduction is too long, only 4000 characters can be stored forum.ui.validation.introduction_too_long=Your introduction is too long, only 4000 characters can be stored

View File

@ -1,27 +1,40 @@
forum.ui.name=Name forum.ui.delete=L\u00f6schen
forum.ui.description=Beschreibung
forum.ui.cancel=Abbrechen
forum.ui.newTopic=Neues Thema
forum.ui.topic.none=Nichts
forum.ui.receive_instant_alerts=Sofortige Benachrichtigung
forum.ui.receive_daily_summary=T\u00E4gliche Zusammenfassung
forum.ui.noSubscriptions=You are not subscribed to any threads forum.ui.noSubscriptions=You are not subscribed to any threads
forum.ui.delete=L\u00F6schen forum.ui.receive_instant_alerts=Sofortige Benachrichtigung
forum.ui.newPost=New thread forum.ui.receive_daily_summary=T\u00e4gliche Zusammenfassung
forum.ui.threads.viewAll=View all threads
forum.ui.thread.subscribe=Subscribe to thread forum.ui.modeAlerts=Benachrichtigung
forum.ui.thread.unsubscribe=Unsubscribe to thread forum.ui.modeThreads=Themen
forum.ui.topic.save=Neues Thema erstellen forum.ui.modeTopics=Themenbereiche
forum.ui.modeModeration=Moderation
forum.ui.modeSetup=Einstellungen
forum.ui.modePermissions=Berechtigungen
forum.ui.cancel=Abbrechen
forum.ui.save=Speichern
forum.ui.yes=Ja
forum.ui.no=Nein
forum.ui.thread.newPost=Neues Diskussionsthema er\u00f6ffnen
forum.ui.thread.subscribe=Thema abonnieren
forum.ui.thread.unsubscribe=Thema stornieren
forum.ui.thread.viewAll=Alle Themen
forum.ui.topic.description=Beschreibung
forum.ui.topic.name=Name
forum.ui.topic.newTopic=Neues Thema
forum.ui.topic.none=Nichts
forum.ui.topic.save=Themenbereich erstellen
forum.ui.moderate.label=Moderation: forum.ui.moderate.label=Moderation:
forum.ui.moderate.switch.on=Einschalten forum.ui.moderate.switch.on=Einschalten
forum.ui.moderate.switch.off=Ausschalten forum.ui.moderate.switch.off=Ausschalten
forum.ui.moderate.status.on=Aktiv forum.ui.moderate.status.on=Aktiv
forum.ui.moderate.status.off=Inaktiv forum.ui.moderate.status.off=Inaktiv
forum.ui.moderate.warning=NB. Turning moderation off will change pending posts to approved status forum.ui.moderate.warning=Achtung: Deaktivieren der Modereation \u00e4ndert den Status von ausstehenden Nachrichten auf akzeptiert!
forum.ui.noticeboard.label=Noticeboard functionality (disable replying) forum.ui.noticeboard.label=Noticeboard functionality (Antworten deaktiviert)
forum.ui.noticeboard.switch.on=Turn on (disable replying) forum.ui.noticeboard.switch.on=Turn on (disable replying)
forum.ui.noticeboard.switch.off=Turn off (enable replying) forum.ui.noticeboard.switch.off=Turn off (enable replying)
forum.ui.noticeboard.status.on=An (replying disabled) forum.ui.noticeboard.status.on=An (replying disabled)
@ -29,25 +42,25 @@ forum.ui.noticeboard.status.off=Aus (replying enabled)
forum.ui.noticeboard.expiry_after=Expires after (in days) forum.ui.noticeboard.expiry_after=Expires after (in days)
forum.ui.noticeboard.change_expiry=Update forum.ui.noticeboard.change_expiry=Update
forum.ui.settings.moderated=Moderated forum.ui.settings.moderated=Moderiert
forum.ui.settings.noticeboard=Noticeboard (Disable Replying) forum.ui.settings.noticeboard=Noticeboard (Keine Antworten m\u00f6glich)
forum.ui.settings.allowFiles=Dateianh\u00E4nge zulassen forum.ui.settings.allowFiles=Dateianh\u00e4nge zulassen
forum.ui.settings.allowImages=Bilder in Posts zulassen forum.ui.settings.allowImages=Bilder in Posts zulassen
forum.ui.settings.autosubscribe=Automatically subscribe thread starters forum.ui.settings.autosubscribe=Automatically subscribe thread starters
forum.ui.settings.noCategoryPosts=Allow posts with no topic forum.ui.settings.noCategoryPosts=Allow posts with no topic
forum.ui.settings.anonymousPosts=Allow anonymous posts forum.ui.settings.anonymousPosts=Allow anonymous posts
forum.ui.settings.save=\u00C4nderungen sichern forum.ui.settings.save=\u00c4nderungen sichern
forum.ui.settings.introduction=Einf\u00FChrung forum.ui.settings.introduction=Einf\u00fchrung
forum.ui.settings.title=Forum Titel forum.ui.settings.title=Forum Titel
forum.ui.validation.subject_null=Betreff eingeben forum.ui.validation.subject_null=Betreff eingeben
forum.ui.validation.body_null=Nachricht verfassen forum.ui.validation.body_null=Nachricht verfassen
forum.ui.validation.body_too_long=Your message is too long, only 4000 characters can be stored forum.ui.validation.body_too_long=Die Nachricht is zu lang, maximal 4000 Zeichen sind zugelassen.
forum.ui.validation.image_file_null=Please use the browse button above to find an image to add forum.ui.validation.image_file_null=Bitte den Button Durchsuchen benutzen, um ein Bild anzuf\u00fcgen
forum.ui.validation.image_description_null=Please enter a description for the image (This will be displayed to users who cannot see the image) forum.ui.validation.image_description_null=Bitte eine kurze Bildbeschreibung eingeben (f\u00fcr Benutzer, die das Bild nicht anschauen k\u00f6nnen.)
forum.ui.validation.image_description_too_long=Your description is too long, only 4000 characters can be stored forum.ui.validation.image_description_too_long=Die Beschreibung is zu lang, maximal 4000 Zeichen sind zugelassen.
forum.ui.validation.file_null=Please use the browse button above to find a file to add forum.ui.validation.file_null=Bitte den Button Durchsuchen benutzen, um eine Datei anzuf\u00fcgen
forum.ui.validation.file_description_too_long=Your description is too long, only 4000 characters can be stored forum.ui.validation.file_description_too_long=Die Beschreibung is zu lang, maximal 4000 Zeichen sind zugelassen.
forum.ui.validation.image_not_uploaded=To add the specified image, use the Add Image button before leaving this page. If you don't want to add the image, click Next or Previous. forum.ui.validation.image_not_uploaded=To add the specified image, use the Add Image button before leaving this page. If you don't want to add the image, click Next or Previous.
forum.ui.validation.file_not_uploaded=To add the specified file, use the Add File button before leaving this page. If you don't want to add the file, click Next or Previous. forum.ui.validation.file_not_uploaded=To add the specified file, use the Add File button before leaving this page. If you don't want to add the file, click Next or Previous.
forum.ui.validation.introduction_too_long=Your introduction is too long, only 4000 characters can be stored forum.ui.validation.introduction_too_long=Die Einf\u00fchrung ist zu lang, maximal 4000 Zeichen sind zugelassen.

View File

@ -1,6 +1,6 @@
forum.ui.name=Name forum.ui.name=Name
forum.ui.description=Description forum.ui.description=Description
forum.ui.cancel=Cancel forum.ui.cancel=Cancel
forum.ui.newTopic=New topic forum.ui.newTopic=New topic
forum.ui.topic.none=None forum.ui.topic.none=None
@ -12,7 +12,7 @@ forum.ui.newPost=New thread
forum.ui.threads.viewAll=View all threads forum.ui.threads.viewAll=View all threads
forum.ui.thread.subscribe=Subscribe to thread forum.ui.thread.subscribe=Subscribe to thread
forum.ui.thread.unsubscribe=Unsubscribe to thread forum.ui.thread.unsubscribe=Unsubscribe to thread
forum.ui.topic.save=Create Topic forum.ui.topic.save=Create Topic
forum.ui.moderate.label=Moderation: forum.ui.moderate.label=Moderation:
forum.ui.moderate.switch.on=Turn on forum.ui.moderate.switch.on=Turn on
@ -28,26 +28,33 @@ forum.ui.noticeboard.status.on=On (replying disabled)
forum.ui.noticeboard.status.off=Off (replying enabled) forum.ui.noticeboard.status.off=Off (replying enabled)
forum.ui.noticeboard.expiry_after=Expires after (in days) forum.ui.noticeboard.expiry_after=Expires after (in days)
forum.ui.noticeboard.change_expiry=Update forum.ui.noticeboard.change_expiry=Update
forum.ui.settings.moderated=Moderated forum.ui.settings.moderated=Moderated
forum.ui.settings.noticeboard=Noticeboard (Disable Replying) forum.ui.settings.noticeboard=Noticeboard (Disable Replying)
forum.ui.settings.allowFiles=Allow File Attachments forum.ui.settings.allowFiles=Allow File Attachments
forum.ui.settings.allowImages=Allow images in posts forum.ui.settings.allowImages=Allow images in posts
forum.ui.settings.autosubscribe=Automatically subscribe thread starters forum.ui.settings.autosubscribe=Automatically subscribe thread starters
forum.ui.settings.noCategoryPosts=Allow posts with no topic forum.ui.settings.noCategoryPosts=Allow posts with no topic
forum.ui.settings.anonymousPosts=Allow anonymous posts forum.ui.settings.anonymousPosts=Allow anonymous posts
forum.ui.settings.save=Save Changes forum.ui.settings.save=Save Changes
forum.ui.settings.introduction=Introduction forum.ui.settings.introduction=Introduction
forum.ui.settings.title=Forum Title forum.ui.settings.title=Forum Title
forum.ui.validation.subject_null=Please enter a subject forum.ui.validation.subject_null=Please enter a subject
forum.ui.validation.body_null=Please enter a message forum.ui.validation.body_null=Please enter a message
forum.ui.validation.body_too_long=Your message is too long, only 4000 characters can be stored forum.ui.validation.body_too_long=Your message is too long, only 4000 characters can be stored
forum.ui.validation.image_file_null=Please use the browse button above to find an image to add forum.ui.validation.image_file_null=Please use the browse button above to find an image to add
forum.ui.validation.image_description_null=Please enter a description for the image (This will be displayed to users who cannot see the image) forum.ui.validation.image_description_null=Please enter a description for the image (This will be displayed to users who cannot see the image)
forum.ui.validation.image_description_too_long=Your description is too long, only 4000 characters can be stored forum.ui.validation.image_description_too_long=Your description is too long, only 4000 characters can be stored
forum.ui.validation.file_null=Please use the browse button above to find a file to add forum.ui.validation.file_null=Please use the browse button above to find a file to add
forum.ui.validation.file_description_too_long=Your description is too long, only 4000 characters can be stored forum.ui.validation.file_description_too_long=Your description is too long, only 4000 characters can be stored
forum.ui.validation.image_not_uploaded=To add the specified image, use the Add Image button before leaving this page. If you don't want to add the image, click Next or Previous. forum.ui.validation.image_not_uploaded=To add the specified image, use the Add Image button before leaving this page. If you don't want to add the image, click Next or Previous.
forum.ui.validation.file_not_uploaded=To add the specified file, use the Add File button before leaving this page. If you don't want to add the file, click Next or Previous. forum.ui.validation.file_not_uploaded=To add the specified file, use the Add File button before leaving this page. If you don't want to add the file, click Next or Previous.
forum.ui.validation.introduction_too_long=Your introduction is too long, only 4000 characters can be stored forum.ui.validation.introduction_too_long=Your introduction is too long, only 4000 characters can be stored
forum.ui.yes=Yes
forum.ui.no=No
forum.ui.save=Save
forum.ui.alerts=Alerts
forum.ui.threads=Threads
forum.ui.topics=Topics
forum.ui.thread.viewAll=View all threads

View File

@ -18,120 +18,165 @@
*/ */
package com.arsdigita.forum.ui; package com.arsdigita.forum.ui;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.arsdigita.bebop.ModalContainer; import com.arsdigita.bebop.ModalContainer;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.forum.Forum; import com.arsdigita.forum.Forum;
import com.arsdigita.forum.ForumContext; import com.arsdigita.forum.ForumContext;
import com.arsdigita.forum.ui.admin.ModerationView; import com.arsdigita.forum.ui.admin.ModerationView;
import com.arsdigita.forum.ui.admin.PermissionsView; import com.arsdigita.forum.ui.admin.PermissionsView;
import com.arsdigita.forum.ui.admin.SetupView; import com.arsdigita.forum.ui.admin.SetupView;
import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.Party; import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.permissions.PermissionDescriptor; import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.kernel.security.UserContext; import com.arsdigita.kernel.security.UserContext;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
/** /**
* The Bebop Page which provides the complete UI for the bboard application * A Bebop Page which provides the complete UI for the forum application in a
* CCM specific compact style. Using this style the different components
* (view modes or forum modes) as the threads lists, the list of topics or the
* alerts management panel etc. are presented onto one page in a condensed form.
*
* Main task is to provide a <i>mode selection facility</i> (by default styled
* as a tabulator bar) and to switch to a page component based on the active
* selection (by default displayed beyond the mode selection facility).
* *
* @author Kevin Scaldeferri (kevin@arsdigita.com) * @author Kevin Scaldeferri (kevin@arsdigita.com)
* * @author Chris Gilbert (chrisg23)
* @version $Revision: 1.3 $ $Author: chrisg23 $ $Date: 2006/03/09 13:48:15 $ * @version $Revision: 1.3 $ $Author: chrisg23 $ $Date: 2006/03/09 13:48:15 $
*/ */
public class ForumComponent extends ModalContainer implements Constants { public class ForumUserCompactView extends ModalContainer implements Constants {
private static Logger s_log = Logger.getLogger(ForumComponent.class); /** Private logger instance for debugging purpose. */
private static Logger s_log = Logger.getLogger(ForumUserCompactView.class);
// Denotes the 6 panels of the user interface, also used as marker to store
// and select the active panel
/** Denotation of the 'threads' forum mode */
public static final String MODE_THREADS = "threads"; public static final String MODE_THREADS = "threads";
/** Denominator of the 'topics' forum mode */
public static final String MODE_TOPICS = "topics"; public static final String MODE_TOPICS = "topics";
/** Denominator of the 'alerts handling' forum mode */
public static final String MODE_ALERTS = "alerts"; public static final String MODE_ALERTS = "alerts";
/** Denominator of the 'moderation handling' forum mode */
public static final String MODE_MODERATION = "moderation"; public static final String MODE_MODERATION = "moderation";
public static final String MODE_PERMISSIONS = "permissions"; /** Denominator of the 'permission administration' forum mode (administrators only) */
public static final String MODE_SETUP = "setup"; public static final String MODE_PERMISSIONS = "permissions";
/** Denominator of the 'configuration' forum mode (administrators only)*/
public static final String MODE_SETUP = "setup";
/** Holds the current active mode */
private StringParameter m_mode; private StringParameter m_mode;
/** /** Object containing the threads panel (main working panel for users) */
* Constructs the bboard use interface private ThreadsPanel m_threadsView;
*/ /** Object containing the topics panel */
private SetupView m_setupView; private TopicsPanel m_topicsView;
private ModerationView m_moderationView; /** Object containing the alerts management panel */
private ForumAlertsView m_alertsView; private ForumAlertsView m_alertsView;
private CategoryView m_topicView; /** Object containing the moderation panel */
private ForumUserView m_userView; private ModerationView m_moderationView;
private PermissionsView m_permissionsView; /** Object containing the setup panel */
private SetupView m_setupView;
/** Object containing the permission management panel*/
private PermissionsView m_permissionsView;
public ForumComponent() { /**
super(FORUM_XML_PREFIX + ":forum", FORUM_XML_NS); * Default Constructor. Initializes the forum user interface elements.
*/
public ForumUserCompactView() {
// determine namespace
super(FORUM_XML_PREFIX + ":forum", FORUM_XML_NS);
m_mode = new StringParameter("mode"); m_mode = new StringParameter("mode");
m_setupView = new SetupView(); // setup panels which make up the forum
m_moderationView = new ModerationView(); m_threadsView = new ThreadsPanel();
m_topicsView = new TopicsPanel();
m_alertsView = new ForumAlertsView(); m_alertsView = new ForumAlertsView();
m_topicView = new CategoryView(); // administration section
m_userView = new ForumUserView(); m_moderationView = new ModerationView();
m_permissionsView = new PermissionsView(); m_setupView = new SetupView();
m_permissionsView = new PermissionsView();
add(m_setupView); add(m_threadsView);
add(m_moderationView); add(m_topicsView);
add(m_alertsView); add(m_alertsView);
add(m_topicView); // administration section
add(m_userView); add(m_moderationView);
add(m_permissionsView); add(m_setupView);
add(m_permissionsView);
setDefaultComponent(m_userView); setDefaultComponent(m_threadsView);
} }
/**
*
* @param p
*/
public void register(Page p) { public void register(Page p) {
super.register(p);
super.register(p);
p.addGlobalStateParam(m_mode); p.addGlobalStateParam(m_mode);
} }
public void respond(PageState state) /**
throws ServletException { *
* @param state
* @throws ServletException
*/
public void respond(PageState state) throws ServletException {
super.respond(state); super.respond(state);
Party party = Kernel.getContext().getParty(); Party party = Kernel.getContext().getParty();
Forum forum = ForumContext.getContext(state).getForum(); Forum forum = ForumContext.getContext(state).getForum();
String mode = (String)state.getControlEventValue(); String mode = (String)state.getControlEventValue();
state.setValue(m_mode, mode); state.setValue(m_mode, mode);
setVisible(state, party, forum, mode); setVisible(state, party, forum, mode);
} }
protected void setVisible( /**
PageState state, * Checks for the given forum mode (parameter value) whether its prerequisites
Party party, * are given (currently permission, but additional properties may be added here).
Forum forum, * If positive the panel is set visible, otherwise a login screen is
String mode) { * presented.
PermissionDescriptor forumAdmin = *
new PermissionDescriptor(PrivilegeDescriptor.ADMIN, forum, party); *
* @param state
* @param party currently logged in user (or null if none)
* @param forum the forum instance to handle
* @param mode forum mode to check visibility for
*/
protected void setVisible( PageState state, Party party,
Forum forum, String mode) {
PermissionDescriptor forumAdmin =
new PermissionDescriptor(PrivilegeDescriptor.ADMIN, forum, party);
if (MODE_TOPICS.equals(mode)) { if (MODE_TOPICS.equals(mode)) {
if (Forum.getConfig().topicCreationByAdminOnly()) { if (Forum.getConfig().topicCreationByAdminOnly()) {
if (party == null) { if (party == null) {
UserContext.redirectToLoginPage(state.getRequest()); UserContext.redirectToLoginPage(state.getRequest());
} }
PermissionService.assertPermission(forumAdmin); PermissionService.assertPermission(forumAdmin);
} }
setVisibleComponent(state, m_topicView); setVisibleComponent(state, m_topicsView);
} else if (MODE_ALERTS.equals(mode)) { } else if (MODE_ALERTS.equals(mode)) {
if (party == null) { if (party == null) {
UserContext.redirectToLoginPage(state.getRequest()); UserContext.redirectToLoginPage(state.getRequest());
} }
setVisibleComponent(state, m_alertsView); setVisibleComponent(state, m_alertsView);
@ -139,85 +184,134 @@ public class ForumComponent extends ModalContainer implements Constants {
if (party == null) { if (party == null) {
UserContext.redirectToLoginPage(state.getRequest()); UserContext.redirectToLoginPage(state.getRequest());
} }
PermissionService.assertPermission(forumAdmin); PermissionService.assertPermission(forumAdmin);
setVisibleComponent(state, m_moderationView); setVisibleComponent(state, m_moderationView);
} else if (MODE_PERMISSIONS.equals(mode)) { } else if (MODE_PERMISSIONS.equals(mode)) {
if (party == null) { if (party == null) {
UserContext.redirectToLoginPage(state.getRequest()); UserContext.redirectToLoginPage(state.getRequest());
} }
PermissionService.assertPermission(forumAdmin); PermissionService.assertPermission(forumAdmin);
setVisibleComponent(state, m_permissionsView); setVisibleComponent(state, m_permissionsView);
} else if (MODE_SETUP.equals(mode)) { } else if (MODE_SETUP.equals(mode)) {
if (party == null) { if (party == null) {
UserContext.redirectToLoginPage(state.getRequest()); UserContext.redirectToLoginPage(state.getRequest());
} }
PermissionService.assertPermission(forumAdmin); PermissionService.assertPermission(forumAdmin);
setVisibleComponent(state, m_setupView); setVisibleComponent(state, m_setupView);
} else if (MODE_THREADS.equals(mode)) { } else if (MODE_THREADS.equals(mode)) {
setVisibleComponent(state, m_userView); setVisibleComponent(state, m_threadsView);
} }
} }
public void generateXML(PageState state, /**
Element parent) { * Generate the page XML.
* Overwrites SimpleContainer standard method
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, Element parent) {
Element content = generateParent(parent); Element content = generateParent(parent);
Forum forum = ForumContext.getContext(state).getForum(); Forum forum = ForumContext.getContext(state).getForum();
content.addAttribute("title", forum.getTitle()); content.addAttribute("title", forum.getTitle());
content.addAttribute( content.addAttribute(
"noticeboard", "noticeboard",
(new Boolean(forum.isNoticeboard())).toString()); (new Boolean(forum.isNoticeboard())).toString());
Party party = Kernel.getContext().getParty(); Party party = Kernel.getContext().getParty();
if (party == null) { if (party == null) {
party = Kernel.getPublicUser(); party = Kernel.getPublicUser();
} }
generateModes(state, content, party, forum);
generateChildrenXML(state, content);
}
protected void generateModes(
PageState state,
Element content,
Party party,
Forum forum) {
PermissionDescriptor permission =
new PermissionDescriptor(PrivilegeDescriptor.ADMIN, forum, party);
generateModeXML(state, content, MODE_THREADS);
if (!Forum.getConfig().topicCreationByAdminOnly()) {
generateModeXML(state, content, MODE_TOPICS);
}
generateModeXML(state, content, MODE_ALERTS);
if (PermissionService.checkPermission(permission)) { // generate tab bar for panel (mode) selection
generateModeXML(state, content, MODE_MODERATION); generateModes(state, content, party, forum);
if (Forum.getConfig().showNewTabs()) { // generate
generateModeXML(state, content, MODE_SETUP); generateChildrenXML(state, content);
generateModeXML(state, content, MODE_PERMISSIONS); }
}
if (Forum.getConfig().topicCreationByAdminOnly()) { /**
generateModeXML(state, content, MODE_TOPICS); * Initializes the mode selection facility (usually a tab bar)
*
* @param state
* @param content
* @param party
* @param forum
*/
protected void generateModes(PageState state, Element content,
Party party, Forum forum) {
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);
// topics panel is always shoen as well if not restricted to admins.
if (!Forum.getConfig().topicCreationByAdminOnly()) {
generateModeXML(state, content, MODE_TOPICS);
}
// alerts panel is always shown as well, no private read access avail.
generateModeXML(state, content, MODE_ALERTS);
// admin section
if (PermissionService.checkPermission(permission)) {
generateModeXML(state, content, MODE_MODERATION);
if (Forum.getConfig().showNewTabs()) {
generateModeXML(state, content, MODE_SETUP);
generateModeXML(state, content, MODE_PERMISSIONS);
}
// 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);
} }
} }
} }
/**
* Generates a forum mode selection entry (usually a tab).
*
* Currently the mode string is used to create the label in xsl file.
*
* @param state
* @param parent
* @param mode forum mode (threadspanel, topicspanel, alertpanel, ...) to
* create entry for
*/
protected void generateModeXML(PageState state, protected void generateModeXML(PageState state,
Element parent, Element parent,
String mode) { String mode) {
String current = (String)state.getValue(m_mode); String current = (String)state.getValue(m_mode);
if (current == null) { if (current == null) {
current = MODE_THREADS; current = MODE_THREADS;
} }
Element content = Element content =
parent.newChildElement(FORUM_XML_PREFIX + ":forumMode", FORUM_XML_NS); parent.newChildElement(FORUM_XML_PREFIX + ":forumMode", FORUM_XML_NS);
state.setControlEvent(this, "mode", mode); state.setControlEvent(this, "mode", mode);
content.addAttribute("mode", content.addAttribute("mode",
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 { try {
content.addAttribute("url", content.addAttribute("url",
state.stateAsURL()); state.stateAsURL());

View File

@ -48,8 +48,8 @@ import com.arsdigita.xml.Element;
* differently in final processing (final meaning on the last step * differently in final processing (final meaning on the last step
* of the wizard) by overriding the processWidgets method. * of the wizard) by overriding the processWidgets method.
* *
* They all share the remainder of the steps (currently add files, add images and preview) * They all share the remainder of the steps (currently add files, add images
* and processing relating to shared behaviour * and preview) and processing relating to shared behaviour
* *
* @author Jon Orris (jorris@arsdigita.com) * @author Jon Orris (jorris@arsdigita.com)
* @author rewritten by Chris Gilbert * @author rewritten by Chris Gilbert

View File

@ -18,22 +18,22 @@
*/ */
package com.arsdigita.forum.ui; package com.arsdigita.forum.ui;
import com.arsdigita.bebop.Container; // import com.arsdigita.bebop.Container;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.parameters.BigDecimalParameter; // import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.categorization.Category; // import com.arsdigita.categorization.Category;
import com.arsdigita.forum.ForumContext; import com.arsdigita.forum.ForumContext;
import com.arsdigita.forum.Post; import com.arsdigita.forum.Post;
import com.arsdigita.forum.Forum; // import com.arsdigita.forum.Forum;
import com.arsdigita.forum.ThreadSubscription; // import com.arsdigita.forum.ThreadSubscription;
import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.Party; import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.User; // import com.arsdigita.kernel.User;
import com.arsdigita.kernel.ui.ACSObjectSelectionModel; import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
import com.arsdigita.web.RedirectSignal; // import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL; // import com.arsdigita.web.URL;
import java.math.BigDecimal; // import java.math.BigDecimal;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;

View File

@ -34,6 +34,10 @@ public class Text {
return new GlobalizedMessage(key, BUNDLE_NAME); return new GlobalizedMessage(key, BUNDLE_NAME);
} }
public static String gzAsStr(String key) {
return (String) new GlobalizedMessage(key, BUNDLE_NAME).localize();
}
public static GlobalizedMessage gz(String key, Object[] args) { public static GlobalizedMessage gz(String key, Object[] args) {
return new GlobalizedMessage(key, BUNDLE_NAME, args); return new GlobalizedMessage(key, BUNDLE_NAME, args);
} }

View File

@ -19,7 +19,7 @@
package com.arsdigita.forum.ui; package com.arsdigita.forum.ui;
import com.arsdigita.forum.ForumContext; import com.arsdigita.forum.ForumContext;
import com.arsdigita.forum.Post; import com.arsdigita.forum.Post;
import com.arsdigita.forum.ThreadSubscription; import com.arsdigita.forum.ThreadSubscription;
import com.arsdigita.forum.ui.admin.RejectionForm; import com.arsdigita.forum.ui.admin.RejectionForm;
@ -60,8 +60,8 @@ public class ThreadComponent extends ModalContainer implements Constants {
// References to sub-components for event access. // References to sub-components for event access.
private Container m_threadView; private Container m_threadView;
private PostForm m_rootForm; private PostForm m_rootForm;
private PostForm m_replyForm; private PostForm m_replyForm;
private Form m_rejectForm; private Form m_rejectForm;
private static final Logger s_log private static final Logger s_log
@ -84,22 +84,22 @@ public class ThreadComponent extends ModalContainer implements Constants {
private void initComponents() { private void initComponents() {
// Add the thread components to the modal container and maintain // Add the thread components to the modal container and maintain
// references for event manipulation purposes. // 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_rootForm = new RootPostForm(m_postModel);
m_replyForm = new ReplyToPostForm(m_postModel); m_replyForm = new ReplyToPostForm(m_postModel);
s_log.debug("creating reply to post form"); s_log.debug("creating reply to post form");
s_log.debug("creating reject form"); s_log.debug("creating reject form");
m_rejectForm = new RejectionForm(m_postModel); m_rejectForm = new RejectionForm(m_postModel);
addForm(m_rootForm); addForm(m_rootForm);
addForm(m_replyForm); addForm(m_replyForm);
addForm(m_rejectForm); addForm(m_rejectForm);
m_threadView = new SimpleContainer(); m_threadView = new SimpleContainer();
Container linksPanel = new SimpleContainer(FORUM_XML_PREFIX + ":threadOptions", Container linksPanel = new SimpleContainer(FORUM_XML_PREFIX + ":threadOptions",
Constants.FORUM_XML_NS); Constants.FORUM_XML_NS);
// Offer links to return to index or control alerts. // Offer links to return to index or control alerts.
Link returnLink = new Link(new Label(Text.gz("forum.ui.threads.viewAll")), Link returnLink = new Link(new Label(Text.gz("forum.ui.thread.viewAll")),
"index.jsp"); "index.jsp");
returnLink.setClassAttr("actionLink"); returnLink.setClassAttr("actionLink");
linksPanel.add(returnLink); linksPanel.add(returnLink);
@ -123,21 +123,21 @@ public class ThreadComponent extends ModalContainer implements Constants {
} }
public void makeEditFormVisible(PageState state) { public void makeEditFormVisible(PageState state) {
s_log.debug("making edit form visible"); s_log.debug("making edit form visible");
Post post = (Post)m_postModel.getSelectedObject(state); Post post = (Post)m_postModel.getSelectedObject(state);
if (post.getRoot() == null) { if (post.getRoot() == null) {
m_rootForm.setContext(state, ReplyToPostForm.EDIT_CONTEXT); m_rootForm.setContext(state, ReplyToPostForm.EDIT_CONTEXT);
setVisibleComponent(state, m_rootForm); setVisibleComponent(state, m_rootForm);
} else { } else {
m_replyForm.setContext(state, ReplyToPostForm.EDIT_CONTEXT); m_replyForm.setContext(state, ReplyToPostForm.EDIT_CONTEXT);
setVisibleComponent(state, m_replyForm); setVisibleComponent(state, m_replyForm);
} }
} }
public void makeReplyFormVisible(PageState state) { public void makeReplyFormVisible(PageState state) {
s_log.debug("making reply form visible"); s_log.debug("making reply form visible");
m_replyForm.setContext(state, PostForm.REPLY_CONTEXT); m_replyForm.setContext(state, PostForm.REPLY_CONTEXT);
setVisibleComponent(state, m_replyForm); setVisibleComponent(state, m_replyForm);
} }
@ -149,14 +149,14 @@ public class ThreadComponent extends ModalContainer implements Constants {
* Creates the component for viewing a thread. * Creates the component for viewing a thread.
*/ */
private final void addForm(final Form form) { private final void addForm(final Form form) {
add(form); add(form);
form.addCompletionListener(new ActionListener() { form.addCompletionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
s_log.debug("FORM ACTION COMPLETED"); s_log.debug("FORM ACTION COMPLETED");
PageState ps = e.getPageState(); PageState ps = e.getPageState();
// ps.reset(form); // ps.reset(form);
makeListViewVisible(ps); makeListViewVisible(ps);
} }
}); });
@ -164,8 +164,8 @@ public class ThreadComponent extends ModalContainer implements Constants {
public void cancel(FormSectionEvent e) { public void cancel(FormSectionEvent e) {
s_log.debug("fire cancel listener"); s_log.debug("fire cancel listener");
PageState ps = e.getPageState(); PageState ps = e.getPageState();
// ps.reset(form); // ps.reset(form);
makeListViewVisible(ps); makeListViewVisible(ps);
} }
}); });
} }

View File

@ -56,6 +56,13 @@ import com.arsdigita.web.Web;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import com.arsdigita.xml.XML; 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
* MessageView.
*/
public class ThreadDisplay extends SimpleComponent implements Constants { public class ThreadDisplay extends SimpleComponent implements Constants {
private static final Logger s_log = private static final Logger s_log =

View File

@ -44,11 +44,18 @@ import com.arsdigita.forum.ThreadCollection;
import java.math.BigDecimal; import java.math.BigDecimal;
/**
* Creates a list of existing threads as a GUI component. Currently invoked
* by ThreadsPanel only.
* A paginator is added to handle a high number of threads.
*
*/
public class ThreadList extends SimpleComponent implements Constants { public class ThreadList extends SimpleComponent implements Constants {
/** */
private IntegerParameter m_pageNumber = private IntegerParameter m_pageNumber =
new IntegerParameter(PAGINATOR_PARAM); new IntegerParameter(PAGINATOR_PARAM);
/** Default max number of threads (rows) per page */
private int m_pageSize = 15; private int m_pageSize = 15;
public void register(Page p) { public void register(Page p) {
@ -57,7 +64,13 @@ public class ThreadList extends SimpleComponent implements Constants {
p.addGlobalStateParam(m_pageNumber); p.addGlobalStateParam(m_pageNumber);
} }
/**
*
* @param state
* @return
*/
private ThreadCollection getThreads(PageState state) { private ThreadCollection getThreads(PageState state) {
ForumContext context = ForumContext.getContext(state); ForumContext context = ForumContext.getContext(state);
Party party = Kernel.getContext().getParty(); Party party = Kernel.getContext().getParty();
Forum forum = context.getForum(); Forum forum = context.getForum();
@ -75,9 +88,15 @@ public class ThreadList extends SimpleComponent implements Constants {
return threads; return threads;
} }
/**
* Create the xml for this component.
* @param state
* @param parent
*/
public void generateXML(PageState state, public void generateXML(PageState state,
Element parent) { Element parent) {
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":threadList", FORUM_XML_NS); Element content = parent.newChildElement(FORUM_XML_PREFIX +
":threadList", FORUM_XML_NS);
ThreadCollection threads = getThreads(state); ThreadCollection threads = getThreads(state);
@ -113,7 +132,8 @@ public class ThreadList extends SimpleComponent implements Constants {
while (threads.next()) { while (threads.next()) {
MessageThread thread = threads.getMessageThread(); MessageThread thread = threads.getMessageThread();
Element threadEl = content.newChildElement(FORUM_XML_PREFIX + ":thread", FORUM_XML_NS); Element threadEl = content.newChildElement(FORUM_XML_PREFIX +
":thread", FORUM_XML_NS);
ParameterMap map = new ParameterMap(); ParameterMap map = new ParameterMap();
map.setParameter(THREAD_PARAM, thread.getID()); map.setParameter(THREAD_PARAM, thread.getID());
@ -132,6 +152,16 @@ public class ThreadList extends SimpleComponent implements Constants {
} }
/**
* Create the paginators xml
* @param parent
* @param pageNumber
* @param pageCount
* @param pageSize
* @param begin
* @param end
* @param objectCount
*/
protected void generatePaginatorXML(Element parent, protected void generatePaginatorXML(Element parent,
int pageNumber, int pageNumber,
int pageCount, int pageCount,
@ -139,7 +169,8 @@ public class ThreadList extends SimpleComponent implements Constants {
long begin, long begin,
long end, long end,
long objectCount) { 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(); URL here = Web.getContext().getRequestURL();
ParameterMap params = new ParameterMap(here.getParameterMap()); ParameterMap params = new ParameterMap(here.getParameterMap());

View File

@ -20,7 +20,7 @@ package com.arsdigita.forum.ui;
import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Container; import com.arsdigita.bebop.Container;
import com.arsdigita.bebop.Form; // import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.ModalContainer; import com.arsdigita.bebop.ModalContainer;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
@ -30,51 +30,82 @@ import com.arsdigita.bebop.ToggleLink;
import com.arsdigita.bebop.event.ActionEvent; import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.forum.Forum; import com.arsdigita.forum.Forum;
import com.arsdigita.forum.ForumContext; import com.arsdigita.forum.ForumContext;
import com.arsdigita.kernel.Party; import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.permissions.PermissionDescriptor; import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.toolbox.ui.SecurityContainer; import com.arsdigita.toolbox.ui.SecurityContainer;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* A reusable Bebop component to display the user view on a Forum * A reusable Bebop component to display and maintain threads in a given forum
* instance. Currently used as a page component in ForumUserCompactView but may
* be used (in future) by other styles of forum display or even standalone as
* part of other pages as well. In any case it is the main user view and
* working area of a forum.
*
* It consists of two (sub) <i>components</i> which provide
* (a) a list of existing threads including author, number of replies and date
* of last post for each, and a link to create a new thread. (By createing
* a new root post, i.e. including specifying a subject line).
* (b) an add new post form including an editable subject line to make up a new
* thread.
* *
* @author Kevin Scaldeferri (kevin@arsdigita.com) * @author Kevin Scaldeferri (kevin@arsdigita.com)
* * @version $Revision: 1.8 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $
* @version $Revision: 1.8 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $ * @version $Id:
*/ */
public class ForumUserView extends SimpleContainer public class ThreadsPanel extends SimpleContainer
implements Constants { implements Constants {
private static Logger s_log = Logger.getLogger(ForumUserView.class); /** Private logger instance for debugging purpose. */
private static Logger s_log = Logger.getLogger(ThreadsPanel.class);
private Component m_forumView;
private PostForm m_forumPost;
/** Modal container for components, only one of its children can be visibal */
private ModalContainer m_mode; private ModalContainer m_mode;
/** Bebop Component, list of threads along with some othere elements, will
private ToggleLink m_newTopicLink; * be one child of ModalContainer */
private Component m_threadsComponent;
/** Bebop Component, add new post to a thread form. Will be another child of
* ModalContainer */
private PostForm m_postComponent;
/** Reusable Bebop component. Link providing access to new thread form */
private ToggleLink m_newThreadLink;
/** Switch from threadsComponent to forum post NOCH ÜBERPRÜFEN! */
private StringParameter m_newPostParam; private StringParameter m_newPostParam;
public ForumUserView() { /**
* Default Constructor creates the containing components.
*
* The threads panel contains two components: a threads List and a New Post
* input form.
*/
public ThreadsPanel() {
// Create a modal container: shows only one component at a time.
m_mode = new ModalContainer(); m_mode = new ModalContainer();
add(m_mode); add(m_mode);
m_forumView = createForumView(); m_threadsComponent = createThreadsComponent();
m_forumPost = createForumPost(); m_postComponent = createPostComponent();
m_mode.add(m_forumView); m_mode.add(m_threadsComponent);
m_mode.add(m_forumPost); m_mode.add(m_postComponent);
m_mode.setDefaultComponent(m_forumView); m_mode.setDefaultComponent(m_threadsComponent);
} }
/**
*
* @param p
*/
public void register(Page p) { public void register(Page p) {
super.register(p); super.register(p);
// XXX new post param // XXX new post param
/* /*
@ -83,24 +114,19 @@ public class ForumUserView extends SimpleContainer
p.addGlobalStateParam(m_newPostParam); p.addGlobalStateParam(m_newPostParam);
*/ */
p.addActionListener( new ActionListener() { p.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
s_log.debug("create link pressed"); s_log.debug("create link pressed");
PageState s = e.getPageState();
/*
if ("t".equals((String)s.getValue(m_newPostParam))) {
m_newTopicLink.setSelected(s, true);
s.setValue(m_newPostParam, null);
}
*/
if (m_newTopicLink.isSelected(s)) { PageState s = e.getPageState();
m_forumPost.setContext(s, PostForm.NEW_CONTEXT); // switch between modes (components to display)
m_mode.setVisibleComponent(s, m_forumPost); if (m_newThreadLink.isSelected(s)) {
} else { m_postComponent.setContext(s, PostForm.NEW_CONTEXT);
m_mode.setVisibleComponent(s, m_forumView); m_mode.setVisibleComponent(s, m_postComponent);
} } else {
m_mode.setVisibleComponent(s, m_threadsComponent);
} }
}); }
});
} }
@ -109,29 +135,34 @@ public class ForumUserView extends SimpleContainer
* with author, # of responses, etc. Filtered for approved * with author, # of responses, etc. Filtered for approved
* messages if the forum is moderated. * messages if the forum is moderated.
*/ */
private Component createThreadsComponent() {
private Component createForumView() {
Container forums = new SimpleContainer(); Container forums = new SimpleContainer();
Container forumOptions = new SimpleContainer( Container forumOptions = new SimpleContainer(
FORUM_XML_PREFIX + ":forumOptions", Constants.FORUM_XML_NS); FORUM_XML_PREFIX + ":forumOptions", Constants.FORUM_XML_NS);
m_newTopicLink = new ToggleLink(new Label(Text.gz("forum.ui.newPost"))); // XXX APLAWS standard theme currently (2010-09) does not use the label!
m_newTopicLink.setClassAttr("actionLink"); m_newThreadLink = new ToggleLink(new Label(Text.gz("forum.ui.thread.newPost")));
// chris.gilbert@westsussex.gov.uk - security container added m_newThreadLink.setClassAttr("actionLink");
SecurityContainer sc = new SecurityContainer(m_newTopicLink) {
// chris.gilbert@westsussex.gov.uk - security container added
protected boolean canAccess(Party party, PageState state) { SecurityContainer sc = new SecurityContainer(m_newThreadLink) {
Forum forum = ForumContext.getContext(state).getForum();
PermissionDescriptor createThread = new PermissionDescriptor(PrivilegeDescriptor.get(Forum.CREATE_THREAD_PRIVILEGE), forum, party); protected boolean canAccess(Party party, PageState state) {
return PermissionService.checkPermission(createThread); Forum forum = ForumContext.getContext(state).getForum();
PermissionDescriptor createThread = new PermissionDescriptor(
} PrivilegeDescriptor.get(Forum.CREATE_THREAD_PRIVILEGE),
}; forum,
party);
forumOptions.add(sc); return PermissionService.checkPermission(createThread);
}
};
forumOptions.add(sc);
forums.add(forumOptions); forums.add(forumOptions);
// list of categories // list of topics (if one or more actually available)
TopicSelector topics = new TopicSelector(); TopicSelector topics = new TopicSelector();
forums.add(topics); forums.add(topics);
@ -143,11 +174,15 @@ public class ForumUserView extends SimpleContainer
return forums; return forums;
} }
private PostForm createForumPost() { /**
PostForm editForm = new RootPostForm(); *
* @return
*/
private PostForm createPostComponent() {
PostForm editForm = new RootPostForm();
editForm.addCompletionListener(new ActionListener() { editForm.addCompletionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
ForumUserView.this ThreadsPanel.this
.editPageStateCleanup(e.getPageState()); .editPageStateCleanup(e.getPageState());
} }
}); });
@ -155,8 +190,12 @@ public class ForumUserView extends SimpleContainer
return editForm; return editForm;
} }
/**
*
* @param state
*/
private void editPageStateCleanup(PageState state) { private void editPageStateCleanup(PageState state) {
m_newTopicLink.setSelected(state, false); m_newThreadLink.setSelected(state, false);
ForumContext.getContext(state).setCategorySelection ForumContext.getContext(state).setCategorySelection
(Constants.TOPIC_ANY); (Constants.TOPIC_ANY);
} }

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
* Copyright (C) 2006-2007 Chris Gilbert (Westsussex)
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -24,7 +25,7 @@ import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SaveCancelSection; // import com.arsdigita.bebop.SaveCancelSection;
import com.arsdigita.bebop.event.FormInitListener; import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormSectionEvent;
@ -43,36 +44,40 @@ import org.apache.log4j.Logger;
/** /**
* <b><font color="red">Experimental</font></b> * Class to create a form for adding new topics.
* class to create form to add categories and map them to the forum *
* parent category. temporary hack for testing purposes * A created topic is mapped to the forum parent category.
* *
* @author <a href=mailto:sarah@arsdigita.com>Sarah Barwig</a> * @author <a href=mailto:sarah@arsdigita.com>Sarah Barwig</a>
* @author rewritten by Chris Gilbert * @author rewritten by Chris Gilbert
* @version $Revision: 1.2 $ $Author: chrisg23 $ $DateTime: 2004/08/17 23:26:27 $ * @version $Id: TopicAddForm.java 1628 2007-09-17 08:10:40Z chrisg23 $
* @version $Id: CategoryAddForm.java 1628 2007-09-17 08:10:40Z chrisg23 $
*/ */
public class CategoryAddForm extends Form { public class TopicAddForm extends Form {
/** Private logger instance for debugging purpose. */
private static final Logger s_log = Logger.getLogger private static final Logger s_log = Logger.getLogger
(CategoryAddForm.class); (TopicAddForm.class);
/** Input field for name of new topic*/
private TextField m_name; private TextField m_name;
/** Input field for (short) description of new topic */
private TextArea m_description; private TextArea m_description;
/** /**
* Builds a form to add a category. * Default Constructor builds a form to add a category.
*
*/ */
public CategoryAddForm() { public TopicAddForm() {
super("categoryAdd"); super("categoryAdd");
setRedirecting(true); setRedirecting(true); // clear form and redirect back
add(new Label(Text.gz("forum.ui.name"))); add(new Label(Text.gz("forum.ui.topic.name")));
m_name = new TextField("name"); m_name = new TextField("name");
m_name.addValidationListener(new NotNullValidationListener()); m_name.addValidationListener(new NotNullValidationListener());
add(m_name); add(m_name);
add(new Label(Text.gz("forum.ui.description"))); add(new Label(Text.gz("forum.ui.topic.description")));
m_description = new TextArea("description"); m_description = new TextArea("description");
m_description.setRows(5); m_description.setRows(5);
m_description.setCols(60); m_description.setCols(60);
@ -83,52 +88,52 @@ public class CategoryAddForm extends Form {
// Would have used a saveCancel section but this would make existing // Would have used a saveCancel section but this would make existing
// stylesheets for legacy forums miss the buttons // stylesheets for legacy forums miss the buttons
Submit submit = new Submit(Text.gz("forum.ui.topic.save")); Submit submit = new Submit(Text.gz("forum.ui.topic.save"));
final Submit cancel = new Submit(Text.gz("forum.ui.cancel")); final Submit cancel = new Submit(Text.gz("forum.ui.cancel"));
add(submit); add(submit);
add(cancel); add(cancel);
addSubmissionListener(new FormSubmissionListener(){ addSubmissionListener(new FormSubmissionListener(){
public void submitted(FormSectionEvent e) throws FormProcessException { public void submitted(FormSectionEvent e)
PageState state = e.getPageState(); throws FormProcessException {
if (cancel.isSelected(state)){ PageState state = e.getPageState();
fireCompletionEvent(state); if (cancel.isSelected(state)){
throw new FormProcessException("cancelled"); fireCompletionEvent(state);
} throw new FormProcessException("cancelled");
} }
}); }
});
/* /*
* Listener to process form data. Just adds the categories, then * Listener to process form data. Just adds the topic, then
* adds mappings. * adds mappings.
*/ */
addProcessListener addProcessListener
(new FormProcessListener() { (new FormProcessListener() {
public void process( FormSectionEvent e ) { public void process( FormSectionEvent e ) {
PageState state = e.getPageState(); PageState state = e.getPageState();
Forum forum = ForumContext.getContext(state).getForum();
String name = (String)m_name.getValue(state); Forum forum = ForumContext.getContext(state).getForum();
String description = (String)m_description.getValue(state);
Category topic = new Category(); String name = (String)m_name.getValue(state);
topic.setName(name); String description = (String)m_description.getValue(state);
topic.setDescription(description);
topic.save();
Category parent = forum.getRootCategory(); Category topic = new Category();
parent.addChild(topic); topic.setName(name);
parent.save(); topic.setDescription(description);
topic.setDefaultParentCategory(parent); topic.save();
topic.save();
fireCompletionEvent(state); Category parent = forum.getRootCategory();
} parent.addChild(topic);
}); parent.save();
topic.setDefaultParentCategory(parent);
topic.save();
fireCompletionEvent(state);
}
});
/* /*
* Generates the object id for the new category * Generates the object id for the new topic (category)
*/ */
addInitListener addInitListener
(new FormInitListener() { (new FormInitListener() {

View File

@ -20,11 +20,8 @@ package com.arsdigita.forum.ui;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleComponent; import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.persistence.DataQuery; import com.arsdigita.persistence.DataQuery;
import com.arsdigita.web.URL; import com.arsdigita.web.URL;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import com.arsdigita.xml.XML; import com.arsdigita.xml.XML;
@ -36,20 +33,41 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
/**
* Creates a list of defined (available) topics as a GUI component. Currently
* invoked by TopicsPanel only.
*
* XXX: Forum knows about <i>threads</i> which groups a set of posts to the same
* subject, and <i>topics</i> which group a set of threads about the same general
* theme. Currently Forum uses <i>catgegory</i> as synonym for topic, which may be
* misleading in some contexts, because there is <i>forum-categorized</i> which
* uses category in the usual CMS way, esp. navigation categories.
*
*/
public class TopicList extends SimpleComponent implements Constants { public class TopicList extends SimpleComponent implements Constants {
private static Set s_catProps; /** List of properties a topic may have. */
private final static Set s_catProps;
static { static {
s_catProps = new HashSet(); s_catProps = new HashSet();
s_catProps.add("id"); s_catProps.add("id");
s_catProps.add("latestPost");
s_catProps.add("numThreads");
s_catProps.add("name"); s_catProps.add("name");
s_catProps.add("numThreads");
s_catProps.add("latestPost");
} }
/**
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, public void generateXML(PageState state,
Element parent) { Element parent) {
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":topicList",
// Header of list is constructed in xsl, no globalization here
// Globalization has currently to be done in theme.
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":topicList",
FORUM_XML_NS); FORUM_XML_NS);
exportAttributes(content); exportAttributes(content);
@ -57,13 +75,17 @@ public class TopicList extends SimpleComponent implements Constants {
content.addAttribute("baseURL", url.toString()); content.addAttribute("baseURL", url.toString());
content.addAttribute("param", TOPIC_PARAM); content.addAttribute("param", TOPIC_PARAM);
// Get handle to current forum instance
Forum forum = ForumContext.getContext(state).getForum(); Forum forum = ForumContext.getContext(state).getForum();
// Get categories for the forum instance
DataQuery categories = forum.getCategories(); DataQuery categories = forum.getCategories();
// Generate xml for the retrieved topics (categories)
generateQueryXML(content, categories); generateQueryXML(content, categories);
DataQuery unCategory = forum.getUnCategory(); DataQuery unCategory = forum.getUnCategory();
while (unCategory.next()) { while (unCategory.next()) {
Element noTopic = content.newChildElement(FORUM_XML_PREFIX + ":noTopicSummary", Element noTopic = content.newChildElement(FORUM_XML_PREFIX +
":noTopicSummary",
FORUM_XML_NS); FORUM_XML_NS);
Element id = noTopic.newChildElement("id"); Element id = noTopic.newChildElement("id");
@ -78,10 +100,16 @@ public class TopicList extends SimpleComponent implements Constants {
} }
/**
*
* @param parent
* @param query
*/
public void generateQueryXML(Element parent, public void generateQueryXML(Element parent,
DataQuery query) { DataQuery query) {
while (query.next()) { while (query.next()) {
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":topicSummary", Element content = parent.newChildElement(FORUM_XML_PREFIX +
":topicSummary",
FORUM_XML_NS); FORUM_XML_NS);
Iterator keys = s_catProps.iterator(); Iterator keys = s_catProps.iterator();

View File

@ -36,11 +36,24 @@ import com.arsdigita.categorization.Category;
import java.math.BigDecimal; import java.math.BigDecimal;
/**
* Helper Class which generates the XML for a topic selection box.
* Used with ThreadsPanel to filter the threads listing by a topic.
*
* XXX: Forum knows about <i>threads</i> which groups a set of posts to the same
* subject, and <i>topics</i> which group a set of threads about the same general
* theme. Currently Forum uses <i>catgegory</i> as synonym for topic, which may be
* misleading in some contexts, because there is <i>forum-categorized</i> which
* uses category in the usual CMS way, esp. navigation categories.
*
*/
public class TopicSelector extends SimpleComponent implements Constants { public class TopicSelector extends SimpleComponent implements Constants {
@Override
public void generateXML(PageState state, public void generateXML(PageState state,
Element parent) { Element parent) {
Element content = parent.newChildElement(FORUM_XML_PREFIX + ":topicSelector", Element content = parent.newChildElement(FORUM_XML_PREFIX +
":topicSelector",
FORUM_XML_NS); FORUM_XML_NS);
URL url = URL.request(state.getRequest(), null); URL url = URL.request(state.getRequest(), null);
@ -60,7 +73,8 @@ public class TopicSelector extends SimpleComponent implements Constants {
while (cursor.next()) { while (cursor.next()) {
Category c = new Category(cursor.getDataObject()); Category c = new Category(cursor.getDataObject());
Element topicEl = content.newChildElement(FORUM_XML_PREFIX + ":topic", FORUM_XML_NS); Element topicEl = content.newChildElement(FORUM_XML_PREFIX +
":topic", FORUM_XML_NS);
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(topicEl); DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(topicEl);
xr.setWrapRoot(false); xr.setWrapRoot(false);
xr.setWrapAttributes(true); xr.setWrapAttributes(true);

View File

@ -0,0 +1,162 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of 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.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.forum.ui;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Container;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.ModalContainer;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.ToggleLink;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import org.apache.log4j.Logger;
/**
* Reusable Bebop UI component (container) to display and maintain topics a given
* forum instance is dealing with. It consists of two (sub) <i>components</i>
* which provide
* (a) a list of existing topics including number of assoziated threads and date
* of last post for each topic, and a link to create a new topic.
* (b) an add new topic form to add a new topic.
*
* Used eg. by ForumUserCompactView as a component (sub-panel) to maintain
* topics. May be used (in future) by other styles of forum display or even
* standalone as part of other pages.
*
* XXX: Forum knows about <i>threads</i> which groups a set of posts to the same
* subject, and <i>topics</i> which group a set of threads about the same general
* theme. Currently Forum uses <i>catgegory</i> as synonym for topic, which may be
* misleading in some contexts, because there is <i>forum-categorized</i> which
* uses category in the usual CMS way, esp. navigation categories. We use topic
* here where possible.
*/
public class TopicsPanel extends SimpleContainer
implements ActionListener {
/** Private logger instance for debugging purpose. */
private static Logger s_log = Logger.getLogger(TopicsPanel.class);
/** Modal container for components, only one of its children can be visibal */
private ModalContainer m_mode;
/** Bebop Component, list of topics. Will be one child of ModalContainer */
private Component m_topicslist;
/** Bebop Component, add new topic form. Will be another child of
* ModalContainer */
private Component m_addTopicForm;
/** Link providing access to new topic form from topic list */
private ToggleLink m_addNewTopicLink;
/**
* Default Constructor creates the containing components.
*
* The topic panel contains two components: a Topics List and a Add New Topic
* input form.
*
*/
public TopicsPanel() {
// Create a modal container: shows only one component at a time.
m_mode = new ModalContainer();
add(m_mode);
// References to sub-components for event access.
m_topicslist = createTopicsList();
m_addTopicForm = createAddTopicForm();
m_mode.add(m_topicslist);
m_mode.add(m_addTopicForm);
m_mode.setDefaultComponent(m_topicslist);
}
/**
*
* @param p
*/
public void register(Page p) {
super.register(p);
p.addActionListener(this);
}
/**
* Switch between the two available components, only one may be visible at
* a time.
*
* @param e action event.
*/
public void actionPerformed(ActionEvent e) {
PageState s = e.getPageState();
if (m_addNewTopicLink.isSelected(s)) {
m_mode.setVisibleComponent(s, m_addTopicForm);
} else {
m_mode.setVisibleComponent(s, m_topicslist);
}
}
/**
* Creates the component TopicsList. It consists of a link to add a new
* topic and a list of currently defined (available) topics.
* @return
*/
private Container createTopicsList() {
Container topicslist = new SimpleContainer();
// Create the Add Topic Link.
Container linksPanel = new SimpleContainer(
Constants.FORUM_XML_PREFIX + ":topicOptions",
Constants.FORUM_XML_NS);
m_addNewTopicLink = new ToggleLink(
new Label(Text.gz("forum.ui.topic.newTopic")));
m_addNewTopicLink.setClassAttr("actionLink");
linksPanel.add(m_addNewTopicLink);
// add to component
topicslist.add(linksPanel);
// create and add topics list
topicslist.add(new TopicList()); // separate class
return topicslist;
}
/**
* Creates the component AddTopicForm. It consists of a name field and a
* description field.
* @return
*/
private Component createAddTopicForm() {
Form addForm = new TopicAddForm(); //separate class of package
addForm.addCompletionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PageState s = e.getPageState();
m_addNewTopicLink.setSelected(s, false);
m_mode.setVisibleComponent(s, m_topicslist);
}
});
return addForm;
}
}