Greetings,
I just got Jyve up & running this weekend, and thought I would contribute
a patch for something that has been bothering me. After trying to read
through the entire FAQ for the Java Apache Project, I discovered that
navigation between questions in the FAQ is annoyingly hard. So I created
a new navigation element that adds previous/next question links to the top
of the question/answer page. The patch is included below, and it is also
available at http://www.pscs.org/~gmorris/source.html.
I do not have a publicly-accessible server on which to put a working demo,
but I have included a screen shot of the changes at the URL above.
I do not consider this patch quite finished. There are a couple issues I
would like to polish up. One, I am not sure the link style I chose fits
with the motif of the page. I created the links in the style of the
bottom option links (i.e. "[ Link ]") - mostly for simplicity - but I am
wondering if they would be better off in a table, using the same style as
the top navigation.
What are the implications of adding localization strings and configuration
settings? I assume any strings added to the localization files must be
added to *all* the localization files. Is it ok to add English strings to
the non-English locales until somebody else can correct them? Also, if I
wanted to add a configuration option to the TurbineResources.properties
file, should I get permission from somebody to do that first? (I was
considering making inclusion of the prev/next navbar configurable via the
properties file. I guess the other question would be, does anybody else
think that is really necessary?)
I am considering taking on these two items from the Jyve TODO, unless
somebody else is already working on them:
o add the ability to move items around in the system.
o allow someone to be able to add a new question without having to
select the topic heading first.
-- Greg Morris
PS: This patch applies cleanly using "patch -p0" from the top-level Jyve
source directory, as of 14:30 PDT today.
################## patch starts here
--- src/java/org/apache/jyve/navigations/PrevNextQuestion.java.orig Sun Jul 2
11:31:36 2000
+++ src/java/org/apache/jyve/navigations/PrevNextQuestion.java Sun Jul 2 11:23:17
+2000
@@ -0,0 +1,345 @@
+package org.apache.jyve.navigations;
+
+/*
+ * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Java Apache
+ * Project for use in the Apache JServ servlet engine project
+ * <http://java.apache.org/>."
+ *
+ * 4. The names "Apache JServ", "Apache JServ Servlet Engine", "Jyve",
+ * "Apache Jyve", "Jyve Project", "Apache Jyve Project" and
+ * "Java Apache Project" must not be used to endorse or promote products
+ * derived from this software without prior written permission.
+ *
+ * 5. Products derived from this software may not be called "Apache JServ"
+ * nor may "Apache" nor "Apache JServ" appear in their names without
+ * prior written permission of the Java Apache Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Java Apache
+ * Project for use in the Apache JServ servlet engine project
+ * <http://java.apache.org/>."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Java Apache Group. For more information
+ * on the Java Apache Project and the Apache JServ Servlet Engine project,
+ * please see <http://java.apache.org/>.
+ *
+ */
+
+// TODO: Below is all the stuff TopBar.java imports.
+// It would be nice to figure out how much of it we
+// truly need & remove the rest
+
+
+// Java Core Classes
+import java.io.*;
+import java.sql.*;
+import java.util.*;
+
+// Java Servlet Classes
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+// External Stuff
+import org.apache.turbine.modules.*;
+import org.apache.turbine.services.localization.Localization;
+import org.apache.turbine.services.resources.TurbineResources;
+import org.apache.turbine.util.*;
+import org.apache.turbine.om.security.*;
+import org.apache.turbine.util.db.*;
+import org.apache.turbine.util.db.pool.*;
+import org.apache.jyve.util.*;
+import com.workingdogs.village.*;
+import org.apache.ecs.*;
+import org.apache.ecs.html.*;
+
+/**
+ * A navigation element providing previous/next navigation within
+ * question screens.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Greg Morris</a>
+ */
+
+public class PrevNextQuestion extends Navigation
+{
+ public ConcreteElement doBuild( RunData data ) throws Exception
+ {
+ int visitorid = data.getUser().getId();
+ Integer project_id = (Integer) data.getUser().getTemp("project_id",
+ data.getParameters().getInteger("project_id", -1));
+ Integer faq_id = (Integer) data.getUser().getTemp("faq_id",
+ data.getParameters().getInteger("faq_id", -1));
+ Integer topic_id = (Integer) data.getUser().getTemp("topic_id",
+ data.getParameters().getInteger("topic_id", -1));
+ Integer question_id = (Integer) data.getUser().getTemp("question_id",
+ data.getParameters().getInteger("question_id", -1));
+
+ JSecurityCheck secCheck = new JSecurityCheck(data);
+ boolean showUnreleasedQuestion =
+ ( secCheck.permissionToRelease("question") )
+ || ( secCheck.permissionToSeeUnreleased("question") );
+ boolean showUnreleasedTopic =
+ ( secCheck.permissionToRelease("topic") )
+ || ( secCheck.permissionToSeeUnreleased("topic") );
+
+ StringBuffer sql = new StringBuffer();
+ sql.append ( "select" );
+ sql.append ( " question.question_id, question.question_value,
+question.released" );
+ sql.append ( " from question" );
+ sql.append ( " where" );
+ sql.append ( " question.topic_id=" );
+ sql.append ( topic_id );
+ sql.append ( " and question.deleted='N'" );
+
+ if (!showUnreleasedQuestion)
+ {
+ // select if the question is released or it was created by the current
+visitor
+ sql.append ( " AND (question.released='Y' OR question.visitorid=");
+ sql.append ( visitorid );
+ sql.append ( ")");
+ }
+
+ sql.append ( " order by" );
+ sql.append ( " question.display_order" );
+ // Order alphabetical, if same order number
+ sql.append ( ",question.question_value" );
+
+ // get a connection to the db
+ DBConnection db = DBBroker.getInstance().getConnection();
+ Connection connection = db.getConnection();
+
+ // execute the query
+ QueryDataSet qds = new QueryDataSet( connection, sql.toString() );
+
+ try
+ {
+ qds.fetchRecords();
+ int size = qds.size();
+ if ( size == 0 )
+ {
+ // huh? no questions for the topic this question is
+ // supposedly in?
+ return null;
+ }
+
+ int qid = question_id.intValue();
+ int thisIndex = -1;
+ for ( int i = 0; i < size; ++i )
+ {
+ if ( qid == qds.getRecord(i).getValue("question_id").asInt() )
+ {
+ thisIndex = i;
+ break;
+ }
+ }
+
+ if ( thisIndex == -1 )
+ {
+ // our question was not found in the
+ // list of questions for this topic
+ return null;
+ }
+
+ Record prevQuestion;
+ Record nextQuestion;
+ if ( (thisIndex-1) >= 0 )
+ prevQuestion = qds.getRecord(thisIndex - 1);
+ else
+ prevQuestion = null; // the current question is the first question
+
+ if ( (thisIndex+1) < size )
+ nextQuestion = qds.getRecord(thisIndex + 1);
+ else
+ nextQuestion = null; // the current question is the last question
+
+ A prevLink = null;
+ A nextLink = null;
+
+ if ( prevQuestion != null )
+ {
+ prevLink = new A().setHref(
+ new DynamicURI(data, "DisplayQuestionAnswer", "SetAll")
+ .addPathInfo("project_id", project_id)
+ .addPathInfo("faq_id", faq_id)
+ .addPathInfo("topic_id", topic_id)
+ .addPathInfo("question_id",
+ prevQuestion.getValue("question_id").asInt())
+ .toString()
+
+).addElement(prevQuestion.getValue("question_value").asString());
+ }
+ if ( nextQuestion != null )
+ {
+ nextLink = new A().setHref(
+ new DynamicURI(data, "DisplayQuestionAnswer", "SetAll")
+ .addPathInfo("project_id", project_id)
+ .addPathInfo("faq_id", faq_id)
+ .addPathInfo("topic_id", topic_id)
+ .addPathInfo("question_id",
+ nextQuestion.getValue("question_id").asInt())
+ .toString()
+
+).addElement(nextQuestion.getValue("question_value").asString());
+ }
+
+
+ sql = new StringBuffer();
+ sql.append ( "select" );
+ sql.append ( " topic.topic_id, topic.topic_value, topic.released" );
+ sql.append ( " from topic, faq" );
+ sql.append ( " where" );
+ sql.append ( " faq.faq_id=topic.faq_id" );
+ sql.append ( " and topic.faq_id=" );
+ sql.append ( faq_id );
+ sql.append ( " and topic.deleted='N'" );
+
+ if ( !showUnreleasedTopic )
+ {
+ sql.append ( " AND (topic.released='Y' OR topic.visitorid=" );
+ sql.append ( visitorid );
+ sql.append ( ")" );
+ }
+
+ sql.append ( " and faq.deleted='N'" );
+ sql.append ( " order by" );
+ sql.append ( " topic.display_order,topic.topic_value" );
+
+ qds = new QueryDataSet ( connection, sql.toString() );
+ qds.fetchRecords();
+
+ size = qds.size();
+ if ( size == 0 )
+ {
+ // huh? no topics for the faq this topic is
+ // supposedly in?
+ return null;
+ }
+
+ int tid = topic_id.intValue();
+ thisIndex = -1;
+ for ( int i = 0; i < size; ++i )
+ {
+ if ( tid == qds.getRecord(i).getValue("topic_id").asInt() )
+ {
+ thisIndex = i;
+ break;
+ }
+ }
+
+ if ( thisIndex == -1 )
+ {
+ // our topic was not found in the
+ // list of topics for this faq
+ return null;
+ }
+
+ Record thisTopic = qds.getRecord(thisIndex);
+ Record prevTopic;
+ Record nextTopic;
+
+ if ( (thisIndex-1) < 0 )
+ prevTopic = null; // the current topic is the first topic
+ else
+ prevTopic = qds.getRecord(thisIndex - 1);
+
+ if ( (thisIndex+1) >= size )
+ nextTopic = null; // the current topic is the last topic
+ else
+ nextTopic = qds.getRecord(thisIndex + 1);
+
+ A topicLink = new A().setHref(
+ new DynamicURI(data, "DisplayOneTopic", "SetAll")
+ .addPathInfo("project_id", project_id)
+ .addPathInfo("faq_id", faq_id)
+ .addPathInfo("topic_id", topic_id)
+ .toString()
+ ).addElement(thisTopic.getValue("topic_value").asString());
+
+ if ( prevLink == null && prevTopic != null )
+ {
+ prevLink = new A().setHref(
+ new DynamicURI(data, "DisplayOneTopic", "SetAll")
+ .addPathInfo("project_id", project_id)
+ .addPathInfo("faq_id", faq_id)
+ .addPathInfo("topic_id",
+ prevTopic.getValue("topic_id").asInt())
+ .toString()
+ ).addElement(prevTopic.getValue("topic_value").asString());
+ }
+ if ( nextLink == null && nextTopic != null )
+ {
+ nextLink = new A().setHref(
+ new DynamicURI(data, "DisplayOneTopic", "SetAll")
+ .addPathInfo("project_id", project_id)
+ .addPathInfo("faq_id", faq_id)
+ .addPathInfo("topic_id",
+ nextTopic.getValue("topic_id").asInt())
+ .toString()
+ ).addElement(nextTopic.getValue("topic_value").asString());
+ }
+
+ P navText = new P();
+ // TODO: Add localization
+ if ( prevLink != null )
+ {
+ navText.addElement ( "[ Previous: " );
+ navText.addElement ( prevLink );
+ navText.addElement ( " ]" );
+ }
+ else
+ {
+ navText.addElement ( "[ First question in first topic ]" );
+ }
+
+ navText.addElement ( " [ Current Topic: " );
+ navText.addElement ( topicLink );
+ navText.addElement ( " ] " );
+
+ if ( nextLink != null )
+ {
+ navText.addElement ( "[ Next: " );
+ navText.addElement ( nextLink );
+ navText.addElement ( " ]" );
+ }
+ else
+ {
+ navText.addElement ( "[ Last question in last topic ]" );
+ }
+
+ return navText;
+ }
+ finally
+ {
+ qds.close();
+ DBBroker.getInstance().releaseConnection(db);
+ }
+ }
+}
--- src/java/org/apache/jyve/screens/DisplayQuestionAnswer.java.orig Sun Jul 2
11:30:53 2000
+++ src/java/org/apache/jyve/screens/DisplayQuestionAnswer.java Sun Jul 2 11:04:33
+2000
@@ -130,6 +130,15 @@
NavigationLoader.getInstance().eval ( data, "TopBar" ) );
ec.addElement ( new P() );
+ // Added Sat Jul 1 16:57:28 PDT 2000
+ // by Greg Morris <[EMAIL PROTECTED]>
+ // in an attempt to put a previous/next
+ // navigation on the question page
+
+ Element prevNext = NavigationLoader.getInstance().eval ( data,
+"PrevNextQuestion" );
+ if ( prevNext != null )
+ ec.addElement ( prevNext );
+
// get a connection to the db
DBConnection db = DBBroker.getInstance().getConnection();
Connection connection = db.getConnection();
--
--------------------------------------------------------------
To subscribe: [EMAIL PROTECTED]
To unsubscribe: [EMAIL PROTECTED]
Archives and Other: <http://java.apache.org/main/mail.html>
Problems?: [EMAIL PROTECTED]