TwoDue has been in its own separate repository for a while.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@1614 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,2 +0,0 @@
|
|||||||
twodue.war
|
|
||||||
.jde-project.el
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
<!-- build configuration for 'Two Due' project -->
|
|
||||||
<project name="Two Due" default="compile" basedir=".">
|
|
||||||
|
|
||||||
<!-- the base directory from which we get our bundles and jar files -->
|
|
||||||
<property name="base.dir" value="../.."/>
|
|
||||||
|
|
||||||
<!-- import properties -->
|
|
||||||
<property file="build.properties"/>
|
|
||||||
|
|
||||||
<!-- configuration parameters -->
|
|
||||||
<property name="app.name" value="twodue"/>
|
|
||||||
<property name="install.dir" value="${base.dir}/webapps"/>
|
|
||||||
<property name="deploy.dir" value="${base.dir}/pages/${app.name}"/>
|
|
||||||
<property name="dist.war" value="${app.name}.war"/>
|
|
||||||
|
|
||||||
<!-- we want to access the environment -->
|
|
||||||
<property environment="env"/>
|
|
||||||
<property name="java.libraries" value="${env.JAVA_LIBS}"/>
|
|
||||||
|
|
||||||
<!-- prepares the application directories -->
|
|
||||||
<target name="prepare">
|
|
||||||
<mkdir dir="${deploy.dir}"/>
|
|
||||||
<copy todir="${deploy.dir}">
|
|
||||||
<fileset dir="web"/>
|
|
||||||
</copy>
|
|
||||||
<mkdir dir="${deploy.dir}/WEB-INF"/>
|
|
||||||
<copy file="etc/web.xml" tofile="${deploy.dir}/WEB-INF/web.xml"/>
|
|
||||||
<copy todir="${deploy.dir}/WEB-INF/classes">
|
|
||||||
<fileset dir="etc" includes="**/*.properties"/>
|
|
||||||
</copy>
|
|
||||||
<mkdir dir="${deploy.dir}/WEB-INF/classes"/>
|
|
||||||
<mkdir dir="${deploy.dir}/WEB-INF/lib"/>
|
|
||||||
<!-- copy the library jar files -->
|
|
||||||
<copy todir="${deploy.dir}/WEB-INF/lib">
|
|
||||||
<fileset dir="${java.libraries}" includesfile="lib/REQUIRED_LIBS"/>
|
|
||||||
</copy>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- cleans out the installed application -->
|
|
||||||
<target name="clean">
|
|
||||||
<delete dir="${deploy.dir}"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- build the java class files -->
|
|
||||||
<target name="compile" depends="prepare">
|
|
||||||
<javac srcdir="src" destdir="${deploy.dir}/WEB-INF/classes"
|
|
||||||
debug="on" optimize="off" deprecation="on">
|
|
||||||
<classpath>
|
|
||||||
<pathelement location="${deploy.dir}/WEB-INF/classes"/>
|
|
||||||
<fileset dir="${java.libraries}" includes="**/*.jar"/>
|
|
||||||
<fileset dir="lib" includes="**/*.jar"/>
|
|
||||||
</classpath>
|
|
||||||
</javac>
|
|
||||||
<copy todir="${deploy.dir}/WEB-INF/classes">
|
|
||||||
<fileset dir="src" includes="**/*.properties"/>
|
|
||||||
</copy>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- the default target is to rebuild everything -->
|
|
||||||
<target name="all" depends="clean,prepare,compile"/>
|
|
||||||
|
|
||||||
<!-- builds our distribution files (war and jar) -->
|
|
||||||
<target name="dist" depends="prepare,compile">
|
|
||||||
<jar file="${dist.war}" basedir="${deploy.dir}"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- builds the .war file and installs it into the webapp directory -->
|
|
||||||
<target name="install" depends="dist">
|
|
||||||
<copy file="${dist.war}" todir="${install.dir}"/>
|
|
||||||
</target>
|
|
||||||
</project>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
repository.properties
|
|
||||||
user.properties
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#
|
|
||||||
# $Id: exceptionmap.properties,v 1.1 2002/11/08 09:14:20 mdb Exp $
|
|
||||||
#
|
|
||||||
# Maps exceptions to friendly error messages
|
|
||||||
|
|
||||||
java.sql.SQLException: A database error has occurred: {m}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
# -*- mode: makefile -*-
|
|
||||||
#
|
|
||||||
# $Id: messages.properties,v 1.6 2003/12/10 20:33:42 mdb Exp $
|
|
||||||
#
|
|
||||||
# Translation messages for Two Due application
|
|
||||||
|
|
||||||
#
|
|
||||||
# common translations
|
|
||||||
|
|
||||||
app_name=Two Due
|
|
||||||
|
|
||||||
error.no_such_task = No task exists with that task id.
|
|
||||||
|
|
||||||
#
|
|
||||||
# header.wm
|
|
||||||
|
|
||||||
header.combined_title={0}: {1}
|
|
||||||
header.title={0}
|
|
||||||
|
|
||||||
#
|
|
||||||
# app_footer.wm
|
|
||||||
|
|
||||||
app_footer.summary_link=Task status
|
|
||||||
app_footer.tasks_link=By priority
|
|
||||||
app_footer.bycategory_link=By category
|
|
||||||
app_footer.account_link=Login/out
|
|
||||||
|
|
||||||
#
|
|
||||||
# General task editing messages
|
|
||||||
|
|
||||||
task.error.missing_summary = No summary provided for task.
|
|
||||||
task.error.missing_category = No category provided for task.
|
|
||||||
task.error.missing_complexity = No complexity selection for task.
|
|
||||||
task.error.invalid_priority = No priority selection for task.
|
|
||||||
task.error.invalid_creator = Creator not specified.
|
|
||||||
task.error.missing_taskid = Internal error. No task id provided.
|
|
||||||
|
|
||||||
#
|
|
||||||
# index.wm
|
|
||||||
|
|
||||||
index.title=Task Summary
|
|
||||||
|
|
||||||
index.message.task_created = Task created.
|
|
||||||
index.message.task_claimed = Task claimed.
|
|
||||||
index.message.task_completed = Task marked as completed.
|
|
||||||
|
|
||||||
index.error.invalid_detail_task = Task id specified for inspection not valid.
|
|
||||||
index.error.no_matching_tasks = No tasks matched that query string.
|
|
||||||
|
|
||||||
#
|
|
||||||
# edit.wm
|
|
||||||
|
|
||||||
edit.title = Edit Task
|
|
||||||
|
|
||||||
edit.message.task_updated = Task updated.
|
|
||||||
edit.message.note_added = Note added.
|
|
||||||
edit.message.notes_updated = Notes updated.
|
|
||||||
edit.message.task_deleted = Task deleted.
|
|
||||||
|
|
||||||
edit.error.missing_note = Can\'t add blank note.
|
|
||||||
|
|
||||||
#
|
|
||||||
# detail.wm
|
|
||||||
|
|
||||||
detail.title = Task Details
|
|
||||||
|
|
||||||
#
|
|
||||||
# bulkedit.wm
|
|
||||||
|
|
||||||
bulkedit.title = Bulk task update
|
|
||||||
bulkedit.no_tasks = No tasks at this priority.
|
|
||||||
|
|
||||||
bulkedit.message.task_updated = Task updated.
|
|
||||||
bulkedit.message.tasks_updated = Tasks updated.
|
|
||||||
bulkedit.message.nothing_updated = No updates were detected.
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#
|
|
||||||
# $Id: user.properties.dist,v 1.1 2003/11/15 22:55:32 mdb Exp $
|
|
||||||
#
|
|
||||||
# Configuration parameters for the Two Due web appication
|
|
||||||
|
|
||||||
#
|
|
||||||
# These are standard configurations that you probably don't want to change
|
|
||||||
|
|
||||||
login_url = /register/login.wm?from=%R
|
|
||||||
access_denied_url = access_denied.wm
|
|
||||||
|
|
||||||
#
|
|
||||||
# The name of the auth cookie
|
|
||||||
|
|
||||||
auth_cookie.name = id_
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#
|
|
||||||
# $Id: velocity.properties,v 1.2 2002/11/08 21:54:50 mdb Exp $
|
|
||||||
#
|
|
||||||
# Velocity engine configuration overrides
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# F O R E A C H P R O P E R T I E S
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# These properties control how the counter is accessed in the #foreach
|
|
||||||
# directive. By default the reference $velocityCount will be available
|
|
||||||
# in the body of the #foreach directive. The default starting value
|
|
||||||
# for this reference is 1.
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
directive.foreach.counter.name = vidx
|
|
||||||
directive.foreach.counter.initial.value = 0
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
||||||
|
|
||||||
<!DOCTYPE web-app
|
|
||||||
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
|
|
||||||
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
|
|
||||||
|
|
||||||
<web-app>
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>dispatcher</servlet-name>
|
|
||||||
<servlet-class>com.samskivert.velocity.DispatcherServlet</servlet-class>
|
|
||||||
<init-param>
|
|
||||||
<param-name>org.apache.velocity.properties</param-name>
|
|
||||||
<param-value>/velocity.properties</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<param-name>app_class</param-name>
|
|
||||||
<param-value>com.samskivert.twodue.TwoDueApp</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<param-name>logic_package</param-name>
|
|
||||||
<param-value>com.samskivert.twodue.logic</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<param-name>messages_path</param-name>
|
|
||||||
<param-value>messages</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<param-name>site_jar_path</param-name>
|
|
||||||
<param-value>/export/threerings/webapps/site-data</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<param-name>site_messages_path</param-name>
|
|
||||||
<param-value>site_messages</param-value>
|
|
||||||
</init-param>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>dispatcher</servlet-name>
|
|
||||||
<url-pattern>*.wm</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<welcome-file-list>
|
|
||||||
<welcome-file>index.wm</welcome-file>
|
|
||||||
</welcome-file-list>
|
|
||||||
</web-app>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
*.jar
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
commons-collections.jar
|
|
||||||
commons-lang.jar
|
|
||||||
jakarta-regexp-1.2.jar
|
|
||||||
mm.mysql-2.0.14-bin.jar
|
|
||||||
samskivert.jar
|
|
||||||
velocity-1.4-dev.jar
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: Log.java,v 1.1 2002/11/08 09:14:21 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder class that contains a reference to the log object used by
|
|
||||||
* this package.
|
|
||||||
*/
|
|
||||||
public class Log
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This is the log instance that will be used to log all messages for
|
|
||||||
* this package.
|
|
||||||
*/
|
|
||||||
public static com.samskivert.util.Log log =
|
|
||||||
new com.samskivert.util.Log("twodue");
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void debug (String message)
|
|
||||||
{
|
|
||||||
log.debug(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void info (String message)
|
|
||||||
{
|
|
||||||
log.info(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void warning (String message)
|
|
||||||
{
|
|
||||||
log.warning(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void logStackTrace (Throwable t)
|
|
||||||
{
|
|
||||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: TwoDueApp.java,v 1.2 2003/11/15 22:55:32 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
import javax.servlet.ServletConfig;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
import com.samskivert.io.PersistenceException;
|
|
||||||
import com.samskivert.jdbc.ConnectionProvider;
|
|
||||||
import com.samskivert.jdbc.StaticConnectionProvider;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.JDBCTableSiteIdentifier;
|
|
||||||
import com.samskivert.servlet.SiteIdentifier;
|
|
||||||
import com.samskivert.servlet.user.UserManager;
|
|
||||||
import com.samskivert.util.ConfigUtil;
|
|
||||||
import com.samskivert.util.ServiceUnavailableException;
|
|
||||||
import com.samskivert.velocity.Application;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.data.TaskRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains references to application-wide resources (like the database
|
|
||||||
* repository) and handles initialization and cleanup for those resources.
|
|
||||||
*/
|
|
||||||
public class TwoDueApp extends Application
|
|
||||||
{
|
|
||||||
/** Returns the connection provider in use by this application. */
|
|
||||||
public final ConnectionProvider getConnectionProvider ()
|
|
||||||
{
|
|
||||||
return _conprov;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the task repository in use by the application. */
|
|
||||||
public TaskRepository getRepository ()
|
|
||||||
{
|
|
||||||
return _taskrep;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the user manager in use by the application. */
|
|
||||||
public UserManager getUserManager ()
|
|
||||||
{
|
|
||||||
return _usermgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void willInit (ServletConfig config)
|
|
||||||
{
|
|
||||||
super.willInit(config);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// create a static connection provider
|
|
||||||
_conprov = new StaticConnectionProvider(CONN_CONFIG);
|
|
||||||
|
|
||||||
// load up our configuration properties
|
|
||||||
Properties props = ConfigUtil.loadProperties("user.properties");
|
|
||||||
_usermgr = new UserManager(props, _conprov);
|
|
||||||
|
|
||||||
// initialize the task repository
|
|
||||||
_taskrep = new TaskRepository(_conprov);
|
|
||||||
|
|
||||||
Log.info("TwoDue application initialized.");
|
|
||||||
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.warning("Error initializing application: " + t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutdown ()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
_usermgr.shutdown();
|
|
||||||
Log.info("TwoDue application shutdown.");
|
|
||||||
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.warning("Error shutting down repository: " + t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** We want a special site identifier. */
|
|
||||||
protected SiteIdentifier createSiteIdentifier (ServletContext ctx)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return new JDBCTableSiteIdentifier(_conprov);
|
|
||||||
} catch (PersistenceException pe) {
|
|
||||||
throw new ServiceUnavailableException(
|
|
||||||
"Can't access site database.", pe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A reference to our connection provider. */
|
|
||||||
protected ConnectionProvider _conprov;
|
|
||||||
|
|
||||||
/** A reference to our user manager. */
|
|
||||||
protected UserManager _usermgr;
|
|
||||||
|
|
||||||
/** A reference to our task repository. */
|
|
||||||
protected TaskRepository _taskrep;
|
|
||||||
|
|
||||||
/** The path to our database configuration file. */
|
|
||||||
protected static final String CONN_CONFIG = "repository.properties";
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: Task.java,v 1.8 2003/12/11 00:13:48 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.data;
|
|
||||||
|
|
||||||
import java.sql.Date;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains the basic data associated with a task.
|
|
||||||
*/
|
|
||||||
public class Task
|
|
||||||
{
|
|
||||||
public static final String[] COMPLEXITIES = {
|
|
||||||
"Simple hack", "Minor feature", "Major feature",
|
|
||||||
"Subsystem", "Major refactor",
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final int[] COMPLEXITY_VALUES = {
|
|
||||||
5, 10, 15, 20, 25,
|
|
||||||
};
|
|
||||||
|
|
||||||
public int taskId;
|
|
||||||
|
|
||||||
public String summary;
|
|
||||||
|
|
||||||
public String category;
|
|
||||||
|
|
||||||
public String complexity;
|
|
||||||
|
|
||||||
public int priority;
|
|
||||||
|
|
||||||
public String creator;
|
|
||||||
|
|
||||||
public Date creation;
|
|
||||||
|
|
||||||
public String owner;
|
|
||||||
|
|
||||||
public String completor;
|
|
||||||
|
|
||||||
public Date completion;
|
|
||||||
|
|
||||||
public String notes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts numerical priority to a string.
|
|
||||||
*/
|
|
||||||
public String getPriorityName ()
|
|
||||||
{
|
|
||||||
if (priority > 25) {
|
|
||||||
return "Urgent";
|
|
||||||
} else if (priority > 15) {
|
|
||||||
return "Next up";
|
|
||||||
} else if (priority > 10) {
|
|
||||||
return "Near term";
|
|
||||||
} else if (priority > 5) {
|
|
||||||
return "Medium term";
|
|
||||||
} else if (priority > 1) {
|
|
||||||
return "Long term";
|
|
||||||
} else {
|
|
||||||
return "On the list";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts string complexity to a value, lower meaning less complex,
|
|
||||||
* higher meaning more complex.
|
|
||||||
*/
|
|
||||||
public int getComplexityValue ()
|
|
||||||
{
|
|
||||||
for (int ii = 0; ii < COMPLEXITIES.length; ii++) {
|
|
||||||
if (COMPLEXITIES[ii].equals(complexity)) {
|
|
||||||
return COMPLEXITY_VALUES[ii];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDisplayCategory ()
|
|
||||||
{
|
|
||||||
return StringUtil.replace(category, ",", "<br>");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a string representation of this instance.
|
|
||||||
*/
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return StringUtil.fieldsToString(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: TaskRepository.java,v 1.5 2003/01/23 21:22:56 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.data;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.Date;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.samskivert.io.PersistenceException;
|
|
||||||
import com.samskivert.jdbc.ConnectionProvider;
|
|
||||||
import com.samskivert.jdbc.DatabaseLiaison;
|
|
||||||
import com.samskivert.jdbc.JDBCUtil;
|
|
||||||
import com.samskivert.jdbc.JORARepository;
|
|
||||||
import com.samskivert.jdbc.jora.Cursor;
|
|
||||||
import com.samskivert.jdbc.jora.Session;
|
|
||||||
import com.samskivert.jdbc.jora.Table;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides access to the task table.
|
|
||||||
*/
|
|
||||||
public class TaskRepository extends JORARepository
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The database identifier that the repository will use when fetching
|
|
||||||
* a connection from the connection provider. The value is
|
|
||||||
* <code>twodue</code> which you'll probably need to know to properly
|
|
||||||
* configure your connection provider.
|
|
||||||
*/
|
|
||||||
public static final String REPOSITORY_DB_IDENT = "twodue";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the repository and opens the task database. A connection
|
|
||||||
* provider should be supplied that will be used to obtain the
|
|
||||||
* necessary database connection. The database identifier used to
|
|
||||||
* obtain our connection is documented by {@link
|
|
||||||
* #REPOSITORY_DB_IDENT}.
|
|
||||||
*
|
|
||||||
* @param provider a connection provider via which the repository will
|
|
||||||
* get its database connection.
|
|
||||||
*/
|
|
||||||
public TaskRepository (ConnectionProvider provider)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
super(provider, REPOSITORY_DB_IDENT);
|
|
||||||
|
|
||||||
// make sure we can get our database connection
|
|
||||||
Connection conn = provider.getConnection(REPOSITORY_DB_IDENT);
|
|
||||||
provider.releaseConnection(REPOSITORY_DB_IDENT, conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documented inherited
|
|
||||||
protected void createTables (Session session)
|
|
||||||
{
|
|
||||||
// create our table objects
|
|
||||||
_ttable = new Table(Task.class.getName(),
|
|
||||||
"TASKS", session, "TASK_ID", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a task and inserts it into the repository.
|
|
||||||
*
|
|
||||||
* @return the newly created task.
|
|
||||||
*/
|
|
||||||
public Task createTask (String summary, String category, String complexity,
|
|
||||||
int priority, String creator)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
// create and configure a task instance
|
|
||||||
Task task = new Task();
|
|
||||||
task.summary = summary;
|
|
||||||
task.category = category;
|
|
||||||
task.complexity = complexity;
|
|
||||||
task.priority = priority;
|
|
||||||
task.creator = creator;
|
|
||||||
task.notes = "";
|
|
||||||
createTask(task);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts the supplied (properly populated) new task into the task
|
|
||||||
* repository.
|
|
||||||
*/
|
|
||||||
public void createTask (final Task task)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
task.creation = new Date(System.currentTimeMillis());
|
|
||||||
execute(new Operation() {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
// insert the task into the entry table
|
|
||||||
_ttable.insert(task);
|
|
||||||
// update the taskId now that it's known
|
|
||||||
task.taskId = liaison.lastInsertedId(conn);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads up the specified task.
|
|
||||||
*
|
|
||||||
* @return the requested task or null if no tasks exists with that id.
|
|
||||||
*/
|
|
||||||
public Task loadTask (final int taskId)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
return (Task)execute(new Operation () {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
String query = "where TASK_ID = " + taskId;
|
|
||||||
Cursor ec = _ttable.select(query);
|
|
||||||
Task task = (Task)ec.next();
|
|
||||||
if (task != null) {
|
|
||||||
// call next() again to cause the cursor to close itself
|
|
||||||
ec.next();
|
|
||||||
}
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads up and returns all unowned, uncompleted tasks.
|
|
||||||
*/
|
|
||||||
public ArrayList loadTasks ()
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
return loadTasks("where COMPLETOR IS NULL AND OWNER IS NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads up and returns all unowned, uncompleted tasks, whose summary
|
|
||||||
* or category contain the specified string.
|
|
||||||
*/
|
|
||||||
public ArrayList findTasks (String query)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
return loadTasks("where COMPLETOR IS NULL AND OWNER IS NULL " +
|
|
||||||
" AND (SUMMARY LIKE '%" + query +
|
|
||||||
"%' OR CATEGORY LIKE '%" + query + "%')");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads up all owned tasks, ordered by priority.
|
|
||||||
*/
|
|
||||||
public ArrayList loadOwnedTasks ()
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
return loadTasks("where COMPLETOR IS NULL AND OWNER IS NOT NULL " +
|
|
||||||
"ORDER BY PRIORITY DESC");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads up and returns all completed tasks, sorted by completion
|
|
||||||
* date.
|
|
||||||
*
|
|
||||||
* @param start the offset into the sorted list of completed tasks to
|
|
||||||
* start returning tasks.
|
|
||||||
* @param limit the limit to the number of tasks to be returned, or -1
|
|
||||||
* if all completed should be returned.
|
|
||||||
*/
|
|
||||||
public ArrayList loadCompletedTasks (int start, int limit)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
String query = "where COMPLETOR IS NOT NULL " +
|
|
||||||
"ORDER BY COMPLETION DESC LIMIT " + start;
|
|
||||||
if (limit != -1) {
|
|
||||||
query += (", " + limit);
|
|
||||||
}
|
|
||||||
return loadTasks(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Loads lists of tasks. */
|
|
||||||
protected ArrayList loadTasks (final String query)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
return (ArrayList)execute(new Operation () {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
Cursor tc = _ttable.select(query);
|
|
||||||
return tc.toArrayList();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the specified task as completed by the specified user.
|
|
||||||
*/
|
|
||||||
public void completeTask (final int taskId, final String completor)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
execute(new Operation () {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
String query = "update TASKS " +
|
|
||||||
"set COMPLETOR = ?, COMPLETION = ? where TASK_ID = ?";
|
|
||||||
PreparedStatement stmt = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
stmt = conn.prepareStatement(query);
|
|
||||||
stmt.setString(1, completor);
|
|
||||||
stmt.setDate(2, new Date(System.currentTimeMillis()));
|
|
||||||
stmt.setInt(3, taskId);
|
|
||||||
JDBCUtil.checkedUpdate(stmt, 1);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
JDBCUtil.close(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the specified task as owned by the specified user.
|
|
||||||
*/
|
|
||||||
public void claimTask (final int taskId, final String owner)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
execute(new Operation () {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
String query = "update TASKS " +
|
|
||||||
"set OWNER = ? where TASK_ID = ?";
|
|
||||||
PreparedStatement stmt = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
stmt = conn.prepareStatement(query);
|
|
||||||
stmt.setString(1, owner);
|
|
||||||
stmt.setInt(2, taskId);
|
|
||||||
JDBCUtil.checkedUpdate(stmt, 1);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
JDBCUtil.close(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the specified task.
|
|
||||||
*/
|
|
||||||
public void deleteTask (final int taskId)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
execute(new Operation () {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
String query = "delete from TASKS where TASK_ID = ?";
|
|
||||||
PreparedStatement stmt = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
stmt = conn.prepareStatement(query);
|
|
||||||
stmt.setInt(1, taskId);
|
|
||||||
JDBCUtil.checkedUpdate(stmt, 1);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
JDBCUtil.close(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates a task that was previously loaded from the repository.
|
|
||||||
*/
|
|
||||||
public void updateTask (final Task task)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
execute(new Operation() {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
_ttable.update(task);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Table _ttable;
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: CatList.java,v 1.1 2003/12/10 20:33:42 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.data.Task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to categorize tasks.
|
|
||||||
*/
|
|
||||||
public class CatList
|
|
||||||
implements Comparable
|
|
||||||
{
|
|
||||||
/** This indicates which task to which a category belongs. */
|
|
||||||
public static interface Categorizer
|
|
||||||
{
|
|
||||||
public String category (Task task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used to ease category generation in UI. */
|
|
||||||
public static class CategoryTool
|
|
||||||
{
|
|
||||||
public boolean checkCategory (String category)
|
|
||||||
{
|
|
||||||
if (category.equals(_category)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
_category = category;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear ()
|
|
||||||
{
|
|
||||||
_category = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String _category;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The name of the category. */
|
|
||||||
public String name;
|
|
||||||
|
|
||||||
/** The tasks within it. */
|
|
||||||
public ArrayList tasks;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public int compareTo (Object other)
|
|
||||||
{
|
|
||||||
return name.compareTo(((CatList)other).name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Categorizes a list of tasks.
|
|
||||||
*/
|
|
||||||
public static CatList[] categorize (ArrayList tasks, Categorizer catter)
|
|
||||||
{
|
|
||||||
if (tasks == null) {
|
|
||||||
return new CatList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList cats = new ArrayList();
|
|
||||||
HashMap cmap = new HashMap();
|
|
||||||
int tcount = tasks.size();
|
|
||||||
for (int ii = 0; ii < tcount; ii++) {
|
|
||||||
Task task = (Task)tasks.get(ii);
|
|
||||||
String category = catter.category(task);
|
|
||||||
CatList clist = (CatList)cmap.get(category);
|
|
||||||
if (clist == null) {
|
|
||||||
clist = new CatList();
|
|
||||||
clist.name = category;
|
|
||||||
clist.tasks = new ArrayList();
|
|
||||||
cats.add(clist);
|
|
||||||
cmap.put(category, clist);
|
|
||||||
}
|
|
||||||
clist.tasks.add(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
CatList[] ctasks = new CatList[cats.size()];
|
|
||||||
cats.toArray(ctasks);
|
|
||||||
|
|
||||||
return ctasks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: UserLogic.java,v 1.2 2003/12/10 20:33:42 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.user.User;
|
|
||||||
import com.samskivert.velocity.Application;
|
|
||||||
import com.samskivert.velocity.InvocationContext;
|
|
||||||
import com.samskivert.velocity.Logic;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.TwoDueApp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A base logic class for pages that require an authenticated user.
|
|
||||||
*/
|
|
||||||
public abstract class UserLogic implements Logic
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Logic classes should implement this method to perform their normal
|
|
||||||
* duties.
|
|
||||||
*
|
|
||||||
* @param ctx the context in which the request is being invoked.
|
|
||||||
* @param app the web application.
|
|
||||||
* @param user the user record for the authenticated user.
|
|
||||||
*/
|
|
||||||
public abstract void invoke (
|
|
||||||
InvocationContext ctx, TwoDueApp app, User user)
|
|
||||||
throws Exception;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void invoke (Application app, InvocationContext ctx)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
TwoDueApp tdapp = (TwoDueApp)app;
|
|
||||||
User user = tdapp.getUserManager().requireUser(ctx.getRequest());
|
|
||||||
ctx.put("username", user.username);
|
|
||||||
invoke(ctx, tdapp, user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: bulkedit.java,v 1.1 2003/12/10 20:33:42 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.RedirectException;
|
|
||||||
import com.samskivert.servlet.user.User;
|
|
||||||
import com.samskivert.servlet.util.ParameterUtil;
|
|
||||||
import com.samskivert.velocity.InvocationContext;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.Log;
|
|
||||||
import com.samskivert.twodue.TwoDueApp;
|
|
||||||
import com.samskivert.twodue.data.Task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the bulk update of task properties.
|
|
||||||
*/
|
|
||||||
public class bulkedit extends UserLogic
|
|
||||||
{
|
|
||||||
public void invoke (InvocationContext ctx, TwoDueApp app, User user)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
HttpServletRequest req = ctx.getRequest();
|
|
||||||
|
|
||||||
// display any message we've been asked to display
|
|
||||||
String msg = ParameterUtil.getParameter(req, "message", true);
|
|
||||||
if (!StringUtil.blank(msg)) {
|
|
||||||
ctx.put("error", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// load up our tasks
|
|
||||||
ArrayList tasks = app.getRepository().loadTasks();
|
|
||||||
|
|
||||||
// if they've submitted the form, we update the task database
|
|
||||||
if (ParameterUtil.parameterEquals(
|
|
||||||
ctx.getRequest(), "action", "update")) {
|
|
||||||
int updated = 0;
|
|
||||||
for (Iterator iter = tasks.iterator(); iter.hasNext(); ) {
|
|
||||||
Task task = (Task)iter.next();
|
|
||||||
// check to see if category or priority have been updated
|
|
||||||
int nprio = ParameterUtil.getIntParameter(
|
|
||||||
req, "priority" + task.taskId, task.priority,
|
|
||||||
"bulkedit.error.invalid_task_priority");
|
|
||||||
String ncat = ParameterUtil.getParameter(
|
|
||||||
req, "category" + task.taskId, false);
|
|
||||||
if (nprio != task.priority ||
|
|
||||||
(!StringUtil.blank(ncat) && !ncat.equals(task.category))) {
|
|
||||||
task.priority = nprio;
|
|
||||||
task.category = ncat;
|
|
||||||
app.getRepository().updateTask(task);
|
|
||||||
updated++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String rspmsg;
|
|
||||||
switch (updated) {
|
|
||||||
case 0: rspmsg = "bulkedit.message.nothing_updated"; break;
|
|
||||||
case 1: rspmsg = "bulkedit.message.task_updated"; break;
|
|
||||||
default: rspmsg = "bulkedit.message.tasks_updated"; break;
|
|
||||||
}
|
|
||||||
ctx.put("error", rspmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now filter them
|
|
||||||
int priority = ParameterUtil.getIntParameter(
|
|
||||||
req, "priority", 10, "bulkedit.error.invalid_priority");
|
|
||||||
ctx.put("priority", priority);
|
|
||||||
for (Iterator iter = tasks.iterator(); iter.hasNext(); ) {
|
|
||||||
Task task = (Task)iter.next();
|
|
||||||
if (task.priority != priority) {
|
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Collections.sort(tasks, TASK_PARATOR);
|
|
||||||
|
|
||||||
CatList[] xtasks = CatList.categorize(tasks, new CatList.Categorizer() {
|
|
||||||
public String category (Task task) {
|
|
||||||
return task.getPriorityName();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ctx.put("xtasks", xtasks);
|
|
||||||
ctx.put("xcats", new CatList.CategoryTool());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static final Comparator TASK_PARATOR = new Comparator() {
|
|
||||||
public int compare (Object o1, Object o2) {
|
|
||||||
Task t1 = (Task)o1, t2 = (Task)o2;
|
|
||||||
// sort first by reverse priority, then by category, then complexity
|
|
||||||
if (t1.priority == t2.priority) {
|
|
||||||
if (t1.category.equals(t2.category)) {
|
|
||||||
return t1.getComplexityValue() - t2.getComplexityValue();
|
|
||||||
} else {
|
|
||||||
return t1.category.compareTo(t2.category);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return t2.priority - t1.priority;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: bycategory.java,v 1.3 2003/12/10 21:57:31 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.RedirectException;
|
|
||||||
import com.samskivert.servlet.user.User;
|
|
||||||
import com.samskivert.servlet.util.ParameterUtil;
|
|
||||||
import com.samskivert.velocity.InvocationContext;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.Log;
|
|
||||||
import com.samskivert.twodue.TwoDueApp;
|
|
||||||
import com.samskivert.twodue.data.Task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a summary of unclaimed tasks by category.
|
|
||||||
*/
|
|
||||||
public class bycategory extends UserLogic
|
|
||||||
{
|
|
||||||
public void invoke (InvocationContext ctx, TwoDueApp app, User user)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
HttpServletRequest req = ctx.getRequest();
|
|
||||||
|
|
||||||
// display any message we've been asked to display
|
|
||||||
String msg = ParameterUtil.getParameter(req, "message", true);
|
|
||||||
if (!StringUtil.blank(msg)) {
|
|
||||||
ctx.put("error", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// put any filter into the context
|
|
||||||
ctx.put("filter", ParameterUtil.getParameter(req, "filter", false));
|
|
||||||
|
|
||||||
ArrayList tasks = null;
|
|
||||||
String query = ParameterUtil.getParameter(req, "query", false);
|
|
||||||
if (StringUtil.blank(query)) {
|
|
||||||
tasks = app.getRepository().loadTasks();
|
|
||||||
} else {
|
|
||||||
ctx.put("query", query);
|
|
||||||
tasks = app.getRepository().findTasks(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the tasks by priority, then complexity
|
|
||||||
Collections.sort(tasks, OPEN_PARATOR);
|
|
||||||
|
|
||||||
CatList[] xtasks = categorize(tasks, new Categorizer() {
|
|
||||||
public String category (Task task) {
|
|
||||||
return task.category;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ctx.put("xtasks", xtasks);
|
|
||||||
ctx.put("xcats", new CategoryTool());
|
|
||||||
|
|
||||||
// figure out where to start the second column
|
|
||||||
int total = 0, current = 0;
|
|
||||||
for (int ii = 0; ii < xtasks.length; ii++) {
|
|
||||||
total += xtasks[ii].tasks.size();
|
|
||||||
}
|
|
||||||
for (int ii = 0; ii < xtasks.length; ii++) {
|
|
||||||
current += xtasks[ii].tasks.size();
|
|
||||||
if (current >= total/2) {
|
|
||||||
ctx.put("break", ii);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!StringUtil.blank(query) && xtasks.length == 0) {
|
|
||||||
ctx.put("error", "index.error.no_matching_tasks");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class CatList
|
|
||||||
implements Comparable
|
|
||||||
{
|
|
||||||
public String name;
|
|
||||||
public ArrayList tasks;
|
|
||||||
public int compareTo (Object other)
|
|
||||||
{
|
|
||||||
return name.compareTo(((CatList)other).name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static interface Categorizer
|
|
||||||
{
|
|
||||||
public String category (Task task);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CatList[] categorize (ArrayList tasks, Categorizer catter)
|
|
||||||
{
|
|
||||||
if (tasks == null) {
|
|
||||||
return new CatList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList cats = new ArrayList();
|
|
||||||
HashMap cmap = new HashMap();
|
|
||||||
int tcount = tasks.size();
|
|
||||||
for (int ii = 0; ii < tcount; ii++) {
|
|
||||||
Task task = (Task)tasks.get(ii);
|
|
||||||
String category = catter.category(task);
|
|
||||||
CatList clist = (CatList)cmap.get(category);
|
|
||||||
if (clist == null) {
|
|
||||||
clist = new CatList();
|
|
||||||
clist.name = category;
|
|
||||||
clist.tasks = new ArrayList();
|
|
||||||
cats.add(clist);
|
|
||||||
cmap.put(category, clist);
|
|
||||||
}
|
|
||||||
clist.tasks.add(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
CatList[] ctasks = new CatList[cats.size()];
|
|
||||||
cats.toArray(ctasks);
|
|
||||||
|
|
||||||
return ctasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static final Comparator OPEN_PARATOR = new Comparator() {
|
|
||||||
public int compare (Object o1, Object o2) {
|
|
||||||
Task t1 = (Task)o1, t2 = (Task)o2;
|
|
||||||
// sort first by category, then reverse priority, then by complexity
|
|
||||||
if (t1.category.equals(t2.category)) {
|
|
||||||
if (t1.priority == t2.priority) {
|
|
||||||
return t1.getComplexityValue() - t2.getComplexityValue();
|
|
||||||
} else {
|
|
||||||
return t2.priority - t1.priority;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return t1.category.compareTo(t2.category);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected static final Comparator OWNED_PARATOR = new Comparator() {
|
|
||||||
public int compare (Object o1, Object o2) {
|
|
||||||
Task t1 = (Task)o1, t2 = (Task)o2;
|
|
||||||
// sort by complexity
|
|
||||||
return t1.getComplexityValue() - t2.getComplexityValue();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// used to easy category generation in UI
|
|
||||||
public static class CategoryTool
|
|
||||||
{
|
|
||||||
public boolean checkCategory (String category)
|
|
||||||
{
|
|
||||||
if (category.equals(_category)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
_category = category;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear ()
|
|
||||||
{
|
|
||||||
_category = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String _category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: detail.java,v 1.3 2003/12/10 20:33:42 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.user.User;
|
|
||||||
import com.samskivert.servlet.util.ParameterUtil;
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
import com.samskivert.velocity.InvocationContext;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.Log;
|
|
||||||
import com.samskivert.twodue.TwoDueApp;
|
|
||||||
import com.samskivert.twodue.data.Task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the details of a single task.
|
|
||||||
*/
|
|
||||||
public class detail extends UserLogic
|
|
||||||
{
|
|
||||||
public void invoke (InvocationContext ctx, TwoDueApp app, User user)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
HttpServletRequest req = ctx.getRequest();
|
|
||||||
|
|
||||||
int taskId = ParameterUtil.requireIntParameter(
|
|
||||||
ctx.getRequest(), "task", "task.error.missing_taskid");
|
|
||||||
|
|
||||||
// load up the task in question
|
|
||||||
Task task = app.getRepository().loadTask(taskId);
|
|
||||||
if (task == null) {
|
|
||||||
ctx.put("error", "error.no_such_task");
|
|
||||||
} else {
|
|
||||||
// format the notes and stuff those in the context
|
|
||||||
ctx.put("notes", formatNotes(task.notes));
|
|
||||||
// stick the task in the context
|
|
||||||
ctx.put("task", task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String formatNotes (String notes)
|
|
||||||
{
|
|
||||||
if (StringUtil.blank(notes)) {
|
|
||||||
return notes;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuffer fnotes = new StringBuffer();
|
|
||||||
StringTokenizer tok = new StringTokenizer(notes, "\n", true);
|
|
||||||
boolean excepting = false, eatnewline = false;
|
|
||||||
|
|
||||||
while (tok.hasMoreTokens()) {
|
|
||||||
String line = tok.nextToken();
|
|
||||||
boolean sawexcept = false;
|
|
||||||
if (line.indexOf("Exception:") != -1) {
|
|
||||||
sawexcept = true;
|
|
||||||
fnotes.append("<pre>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.equals("\n")) {
|
|
||||||
if (!eatnewline) {
|
|
||||||
fnotes.append("<p>\n");
|
|
||||||
} else {
|
|
||||||
eatnewline = false;
|
|
||||||
}
|
|
||||||
// no further processing on newlines
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
fnotes.append(line).append("\n");
|
|
||||||
eatnewline = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excepting && line.indexOf(" at ") == -1) {
|
|
||||||
excepting = false;
|
|
||||||
fnotes.append("</pre>");
|
|
||||||
}
|
|
||||||
if (sawexcept) {
|
|
||||||
excepting = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fnotes.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: edit.java,v 1.2 2003/01/23 21:22:56 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import com.samskivert.util.QuickSort;
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.RedirectException;
|
|
||||||
import com.samskivert.servlet.user.User;
|
|
||||||
import com.samskivert.servlet.util.ParameterUtil;
|
|
||||||
import com.samskivert.velocity.InvocationContext;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.Log;
|
|
||||||
import com.samskivert.twodue.TwoDueApp;
|
|
||||||
import com.samskivert.twodue.data.Task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows a single task to be edited.
|
|
||||||
*/
|
|
||||||
public class edit extends UserLogic
|
|
||||||
{
|
|
||||||
public void invoke (InvocationContext ctx, TwoDueApp app, User user)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
HttpServletRequest req = ctx.getRequest();
|
|
||||||
|
|
||||||
int taskId = ParameterUtil.requireIntParameter(
|
|
||||||
ctx.getRequest(), "task", "task.error.missing_taskid");
|
|
||||||
|
|
||||||
// load up the task in question
|
|
||||||
Task task = app.getRepository().loadTask(taskId);
|
|
||||||
if (task == null) {
|
|
||||||
ctx.put("error", "error.no_such_task");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stick the task in the context
|
|
||||||
ctx.put("task", task);
|
|
||||||
|
|
||||||
// if they've submitted the form, we update the task database
|
|
||||||
if (ParameterUtil.parameterEquals(
|
|
||||||
ctx.getRequest(), "action", "update")) {
|
|
||||||
// extract our fields
|
|
||||||
task.summary = ParameterUtil.requireParameter(
|
|
||||||
ctx.getRequest(), "summary", "task.error.missing_summary");
|
|
||||||
// remove extra spaces introduced by our friend the textarea
|
|
||||||
task.summary = task.summary.trim();
|
|
||||||
|
|
||||||
task.category = ParameterUtil.requireParameter(
|
|
||||||
ctx.getRequest(), "category",
|
|
||||||
"task.error.missing_category");
|
|
||||||
task.complexity = ParameterUtil.requireParameter(
|
|
||||||
ctx.getRequest(), "complexity",
|
|
||||||
"task.error.missing_complexity");
|
|
||||||
task.priority = ParameterUtil.requireIntParameter(
|
|
||||||
ctx.getRequest(), "priority",
|
|
||||||
"task.error.invalid_priority");
|
|
||||||
task.creator = ParameterUtil.requireParameter(
|
|
||||||
ctx.getRequest(), "creator",
|
|
||||||
"task.error.missing_creator");
|
|
||||||
|
|
||||||
// preserve the null-status of non-owned tasks
|
|
||||||
String owner = ParameterUtil.getParameter(
|
|
||||||
ctx.getRequest(), "owner", true);
|
|
||||||
task.owner = (StringUtil.blank(owner)) ? null : owner;
|
|
||||||
|
|
||||||
app.getRepository().updateTask(task);
|
|
||||||
ctx.put("error", "edit.message.task_updated");
|
|
||||||
|
|
||||||
} else if (ParameterUtil.parameterEquals(
|
|
||||||
ctx.getRequest(), "action", "delete")) {
|
|
||||||
app.getRepository().deleteTask(taskId);
|
|
||||||
ctx.put("error", "edit.message.task_deleted");
|
|
||||||
ctx.remove("task"); // clear out the task
|
|
||||||
|
|
||||||
} else if (ParameterUtil.parameterEquals(
|
|
||||||
ctx.getRequest(), "action", "reopen")) {
|
|
||||||
// clear out the completor and completion dates
|
|
||||||
task.completor = null;
|
|
||||||
task.completion = null;
|
|
||||||
|
|
||||||
app.getRepository().updateTask(task);
|
|
||||||
ctx.put("error", "edit.message.task_reopened");
|
|
||||||
|
|
||||||
} else if (ParameterUtil.parameterEquals(
|
|
||||||
ctx.getRequest(), "action", "addnote")) {
|
|
||||||
// extract our fields
|
|
||||||
String note = ParameterUtil.requireParameter(
|
|
||||||
ctx.getRequest(), "note", "edit.error.missing_note");
|
|
||||||
// prefix the note with a creator identifier
|
|
||||||
note = "[" + user.username + "] " + note.trim();
|
|
||||||
|
|
||||||
if (StringUtil.blank(task.notes)) {
|
|
||||||
task.notes = note;
|
|
||||||
} else {
|
|
||||||
task.notes += "\n\n" + note;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.getRepository().updateTask(task);
|
|
||||||
ctx.put("error", "edit.message.note_added");
|
|
||||||
|
|
||||||
} else if (ParameterUtil.parameterEquals(
|
|
||||||
ctx.getRequest(), "action", "editnotes")) {
|
|
||||||
task.notes = ParameterUtil.getParameter(
|
|
||||||
ctx.getRequest(), "notes", false).trim();
|
|
||||||
app.getRepository().updateTask(task);
|
|
||||||
ctx.put("error", "edit.message.notes_updated");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: index.java,v 1.12 2003/12/10 20:33:42 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.RedirectException;
|
|
||||||
import com.samskivert.servlet.user.User;
|
|
||||||
import com.samskivert.servlet.util.ParameterUtil;
|
|
||||||
import com.samskivert.velocity.InvocationContext;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.Log;
|
|
||||||
import com.samskivert.twodue.TwoDueApp;
|
|
||||||
import com.samskivert.twodue.data.Task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a summary out outstanding and completed tasks.
|
|
||||||
*/
|
|
||||||
public class index extends UserLogic
|
|
||||||
{
|
|
||||||
public void invoke (InvocationContext ctx, TwoDueApp app, User user)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
HttpServletRequest req = ctx.getRequest();
|
|
||||||
|
|
||||||
// display any message we've been asked to display
|
|
||||||
String msg = ParameterUtil.getParameter(req, "message", true);
|
|
||||||
if (!StringUtil.blank(msg)) {
|
|
||||||
ctx.put("error", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if they've submitted the form, we create a new task and stick
|
|
||||||
// it into the dataabse
|
|
||||||
if (ParameterUtil.parameterEquals(req, "action", "create")) {
|
|
||||||
// set the creator from the username of the calling user
|
|
||||||
Task task = new Task();
|
|
||||||
task.creator = user.username;
|
|
||||||
// if they requested to do so, claim the task for them
|
|
||||||
if (ParameterUtil.isSet(req, "claim")) {
|
|
||||||
task.owner = user.username;
|
|
||||||
}
|
|
||||||
task.notes = ""; // no notes to start
|
|
||||||
|
|
||||||
// parse our fields
|
|
||||||
task.summary = ParameterUtil.requireParameter(
|
|
||||||
req, "summary", "task.error.missing_summary");
|
|
||||||
task.category = ParameterUtil.requireParameter(
|
|
||||||
req, "category", "task.error.missing_category");
|
|
||||||
task.complexity = ParameterUtil.requireParameter(
|
|
||||||
req, "complexity",
|
|
||||||
"task.error.missing_complexity");
|
|
||||||
task.priority = ParameterUtil.requireIntParameter(
|
|
||||||
req, "priority", "task.error.invalid_priority");
|
|
||||||
|
|
||||||
// insert the task into the repository
|
|
||||||
app.getRepository().createTask(task);
|
|
||||||
|
|
||||||
// if they want to edit this task, shoot them to the edit
|
|
||||||
// page, otherwise flip back to this same page minus our query
|
|
||||||
// parameters to clear out the creation form
|
|
||||||
if (ParameterUtil.isSet(req, "edit")) {
|
|
||||||
throw new RedirectException("edit.wm?task=" + task.taskId);
|
|
||||||
} else {
|
|
||||||
throw new RedirectException(
|
|
||||||
"index.wm?msg=index.message.task_created");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (ParameterUtil.parameterEquals(req, "action", "complete")) {
|
|
||||||
int taskId = ParameterUtil.requireIntParameter(
|
|
||||||
req, "task", "task.error.missing_taskid");
|
|
||||||
app.getRepository().completeTask(taskId, user.username);
|
|
||||||
|
|
||||||
// let the user know we updated the database
|
|
||||||
ctx.put("error", "index.message.task_completed");
|
|
||||||
|
|
||||||
} else if (ParameterUtil.parameterEquals(req, "action", "claim")) {
|
|
||||||
int taskId = ParameterUtil.requireIntParameter(
|
|
||||||
req, "task", "task.error.missing_taskid");
|
|
||||||
app.getRepository().claimTask(taskId, user.username);
|
|
||||||
|
|
||||||
// let the user know we updated the database
|
|
||||||
ctx.put("error", "index.message.task_claimed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// load up owned tasks and break them down by owner
|
|
||||||
ArrayList tasks = app.getRepository().loadOwnedTasks();
|
|
||||||
Collections.sort(tasks, OWNED_PARATOR);
|
|
||||||
CatList[] otasks = categorize(tasks, new Categorizer() {
|
|
||||||
public String category (Task task) {
|
|
||||||
return task.owner;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// look for our name and swap that into the zeroth position
|
|
||||||
for (int ii = 0; ii < otasks.length; ii++) {
|
|
||||||
if (otasks[ii].name.equals(user.username)) {
|
|
||||||
CatList tlist = otasks[0];
|
|
||||||
otasks[0] = otasks[ii];
|
|
||||||
otasks[ii] = tlist;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.put("otasks", otasks);
|
|
||||||
ctx.put("ocats", new CategoryTool());
|
|
||||||
|
|
||||||
// load up recently completed tasks
|
|
||||||
tasks = app.getRepository().loadCompletedTasks(0, 6);
|
|
||||||
ctx.put("dtasks", tasks);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class CatList
|
|
||||||
implements Comparable
|
|
||||||
{
|
|
||||||
public String name;
|
|
||||||
public ArrayList tasks;
|
|
||||||
public int compareTo (Object other)
|
|
||||||
{
|
|
||||||
return name.compareTo(((CatList)other).name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static interface Categorizer
|
|
||||||
{
|
|
||||||
public String category (Task task);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CatList[] categorize (ArrayList tasks, Categorizer catter)
|
|
||||||
{
|
|
||||||
if (tasks == null) {
|
|
||||||
return new CatList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList cats = new ArrayList();
|
|
||||||
HashMap cmap = new HashMap();
|
|
||||||
int tcount = tasks.size();
|
|
||||||
for (int ii = 0; ii < tcount; ii++) {
|
|
||||||
Task task = (Task)tasks.get(ii);
|
|
||||||
String category = catter.category(task);
|
|
||||||
CatList clist = (CatList)cmap.get(category);
|
|
||||||
if (clist == null) {
|
|
||||||
clist = new CatList();
|
|
||||||
clist.name = category;
|
|
||||||
clist.tasks = new ArrayList();
|
|
||||||
cats.add(clist);
|
|
||||||
cmap.put(category, clist);
|
|
||||||
}
|
|
||||||
clist.tasks.add(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
CatList[] ctasks = new CatList[cats.size()];
|
|
||||||
cats.toArray(ctasks);
|
|
||||||
|
|
||||||
return ctasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static final Comparator OPEN_PARATOR = new Comparator() {
|
|
||||||
public int compare (Object o1, Object o2) {
|
|
||||||
Task t1 = (Task)o1, t2 = (Task)o2;
|
|
||||||
// sort first by reverse priority, then by complexity
|
|
||||||
if (t1.priority == t2.priority) {
|
|
||||||
return t1.getComplexityValue() - t2.getComplexityValue();
|
|
||||||
} else {
|
|
||||||
return t2.priority - t1.priority;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected static final Comparator OWNED_PARATOR = new Comparator() {
|
|
||||||
public int compare (Object o1, Object o2) {
|
|
||||||
Task t1 = (Task)o1, t2 = (Task)o2;
|
|
||||||
// sort by complexity
|
|
||||||
return t1.getComplexityValue() - t2.getComplexityValue();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// used to easy category generation in UI
|
|
||||||
public static class CategoryTool
|
|
||||||
{
|
|
||||||
public boolean checkCategory (String category)
|
|
||||||
{
|
|
||||||
if (category.equals(_category)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
_category = category;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear ()
|
|
||||||
{
|
|
||||||
_category = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String _category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: tasks.java,v 1.3 2003/12/10 20:33:42 mdb Exp $
|
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.samskivert.servlet.RedirectException;
|
|
||||||
import com.samskivert.servlet.user.User;
|
|
||||||
import com.samskivert.servlet.util.ParameterUtil;
|
|
||||||
import com.samskivert.velocity.InvocationContext;
|
|
||||||
|
|
||||||
import com.samskivert.twodue.Log;
|
|
||||||
import com.samskivert.twodue.TwoDueApp;
|
|
||||||
import com.samskivert.twodue.data.Task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a summary of unclaimed tasks.
|
|
||||||
*/
|
|
||||||
public class tasks extends UserLogic
|
|
||||||
{
|
|
||||||
public void invoke (InvocationContext ctx, TwoDueApp app, User user)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
HttpServletRequest req = ctx.getRequest();
|
|
||||||
|
|
||||||
// display any message we've been asked to display
|
|
||||||
String msg = ParameterUtil.getParameter(req, "message", true);
|
|
||||||
if (!StringUtil.blank(msg)) {
|
|
||||||
ctx.put("error", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList tasks = null;
|
|
||||||
String query = ParameterUtil.getParameter(req, "query", false);
|
|
||||||
if (StringUtil.blank(query)) {
|
|
||||||
tasks = app.getRepository().loadTasks();
|
|
||||||
} else {
|
|
||||||
ctx.put("query", query);
|
|
||||||
tasks = app.getRepository().findTasks(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the tasks by priority, then complexity
|
|
||||||
Collections.sort(tasks, TASK_PARATOR);
|
|
||||||
|
|
||||||
CatList[] xtasks = categorize(tasks, new Categorizer() {
|
|
||||||
public String category (Task task) {
|
|
||||||
return task.getPriorityName();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ctx.put("xtasks", xtasks);
|
|
||||||
ctx.put("xcats", new CategoryTool());
|
|
||||||
|
|
||||||
if (!StringUtil.blank(query) && xtasks.length == 0) {
|
|
||||||
ctx.put("error", "index.error.no_matching_tasks");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class CatList
|
|
||||||
implements Comparable
|
|
||||||
{
|
|
||||||
public String name;
|
|
||||||
public ArrayList tasks;
|
|
||||||
public int compareTo (Object other)
|
|
||||||
{
|
|
||||||
return name.compareTo(((CatList)other).name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static interface Categorizer
|
|
||||||
{
|
|
||||||
public String category (Task task);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CatList[] categorize (ArrayList tasks, Categorizer catter)
|
|
||||||
{
|
|
||||||
if (tasks == null) {
|
|
||||||
return new CatList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList cats = new ArrayList();
|
|
||||||
HashMap cmap = new HashMap();
|
|
||||||
int tcount = tasks.size();
|
|
||||||
for (int ii = 0; ii < tcount; ii++) {
|
|
||||||
Task task = (Task)tasks.get(ii);
|
|
||||||
String category = catter.category(task);
|
|
||||||
CatList clist = (CatList)cmap.get(category);
|
|
||||||
if (clist == null) {
|
|
||||||
clist = new CatList();
|
|
||||||
clist.name = category;
|
|
||||||
clist.tasks = new ArrayList();
|
|
||||||
cats.add(clist);
|
|
||||||
cmap.put(category, clist);
|
|
||||||
}
|
|
||||||
clist.tasks.add(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
CatList[] ctasks = new CatList[cats.size()];
|
|
||||||
cats.toArray(ctasks);
|
|
||||||
|
|
||||||
return ctasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static final Comparator TASK_PARATOR = new Comparator() {
|
|
||||||
public int compare (Object o1, Object o2) {
|
|
||||||
Task t1 = (Task)o1, t2 = (Task)o2;
|
|
||||||
// sort first by reverse priority, then by category, then complexity
|
|
||||||
if (t1.priority == t2.priority) {
|
|
||||||
if (t1.category.equals(t2.category)) {
|
|
||||||
return t1.getComplexityValue() - t2.getComplexityValue();
|
|
||||||
} else {
|
|
||||||
return t1.category.compareTo(t2.category);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return t2.priority - t1.priority;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// used to easy category generation in UI
|
|
||||||
public static class CategoryTool
|
|
||||||
{
|
|
||||||
public boolean checkCategory (String category)
|
|
||||||
{
|
|
||||||
if (category.equals(_category)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
_category = category;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear ()
|
|
||||||
{
|
|
||||||
_category = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String _category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* $Id: tasks-schema.sql,v 1.2 2002/11/08 21:49:18 mdb Exp $
|
|
||||||
*
|
|
||||||
* Schema for the Two Due tasks and notes table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
drop table if exists TASKS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains basic data for every task in the system.
|
|
||||||
*/
|
|
||||||
CREATE TABLE TASKS
|
|
||||||
(
|
|
||||||
/**
|
|
||||||
* A unique identifier for this task.
|
|
||||||
*/
|
|
||||||
TASK_ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The summary description of this task.
|
|
||||||
*/
|
|
||||||
SUMMARY VARCHAR(255) NOT NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The comma separated list of categories occupied by this task.
|
|
||||||
*/
|
|
||||||
CATEGORY VARCHAR(255) NOT NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The complexity identifier for this task.
|
|
||||||
*/
|
|
||||||
COMPLEXITY VARCHAR(32) NOT NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The priority of this task.
|
|
||||||
*/
|
|
||||||
PRIORITY INTEGER UNSIGNED NOT NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user to which this task is currently assigned.
|
|
||||||
*/
|
|
||||||
OWNER VARCHAR(255),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the creator of this task.
|
|
||||||
*/
|
|
||||||
CREATOR VARCHAR(255) NOT NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The time of creation of this task.
|
|
||||||
*/
|
|
||||||
CREATION DATE NOT NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the completor(s) of this task.
|
|
||||||
*/
|
|
||||||
COMPLETOR VARCHAR(255),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The time of completion of this task.
|
|
||||||
*/
|
|
||||||
COMPLETION DATE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free form notes associated with this task.
|
|
||||||
*/
|
|
||||||
NOTES TEXT NOT NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines our table keys.
|
|
||||||
*/
|
|
||||||
PRIMARY KEY (TASK_ID),
|
|
||||||
KEY (CATEGORY),
|
|
||||||
KEY (PRIORITY),
|
|
||||||
KEY (CREATION),
|
|
||||||
KEY (COMPLETION)
|
|
||||||
);
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Two Due:
|
|
||||||
<a href="index.wm">$i18n.xlate("app_footer.summary_link")</a> |
|
|
||||||
<a href="tasks.wm">$i18n.xlate("app_footer.tasks_link")</a> |
|
|
||||||
<a href="bycategory.wm">$i18n.xlate("app_footer.bycategory_link")</a> |
|
|
||||||
<a href="/register/">$i18n.xlate("app_footer.account_link")</a>
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#set ($title = $i18n.xlate("bulkedit.title"))
|
|
||||||
#import ("/header.wm")
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<table><tr>
|
|
||||||
<td><a href="index.wm">Task summary</a></td>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<td><a href="bycategory.wm">By category</a></td>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<td>
|
|
||||||
<form method="POST" action="bulkedit.wm">
|
|
||||||
Priority:
|
|
||||||
<select name="priority">
|
|
||||||
#set ($dpri = "15")
|
|
||||||
$form.option("priority", "50", "Urgent", $dpri)
|
|
||||||
$form.option("priority", "25", "Next up", $dpri)
|
|
||||||
$form.option("priority", "15", "Near term", $dpri)
|
|
||||||
$form.option("priority", "10", "Medium term", $dpri)
|
|
||||||
$form.option("priority", "5", "Long term", $dpri)
|
|
||||||
$form.option("priority", "1", "On the list", $dpri)
|
|
||||||
</select>
|
|
||||||
$form.submit("submit", "Go")
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</td>
|
|
||||||
</tr></table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<b>
|
|
||||||
Outstanding tasks:
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<form method="POST" action="bulkedit.wm">
|
|
||||||
$form.hidden("priority", $priority)
|
|
||||||
$form.hidden("action", "update")
|
|
||||||
#if ($data.length($xtasks) > 0)
|
|
||||||
#foreach ($xtask in $xtasks)
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="100%">
|
|
||||||
|
|
||||||
$xcats.clear()
|
|
||||||
#foreach ($task in $xtask.tasks)
|
|
||||||
#set ($id = $task.taskId)
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">$task.summary
|
|
||||||
<span class="small">[$task.creator]</span>
|
|
||||||
#if (!$string.blank($task.notes))
|
|
||||||
<a href="detail.wm?task=$task.taskId">[...]</a>
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td valign="top">$form.text("category$id", "size='10'", $task.category)</td>
|
|
||||||
|
|
||||||
<td valign="top"><select name="priority$id">
|
|
||||||
#set ($cpri = $string.valueOf($task.priority))
|
|
||||||
$form.option("priority$id", "50", "Urgent", $cpri)
|
|
||||||
$form.option("priority$id", "25", "Next up", $cpri)
|
|
||||||
$form.option("priority$id", "15", "Near term", $cpri)
|
|
||||||
$form.option("priority$id", "10", "Medium term", $cpri)
|
|
||||||
$form.option("priority$id", "5", "Long term", $cpri)
|
|
||||||
$form.option("priority$id", "1", "On the list", $cpri)
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
#end
|
|
||||||
</table>
|
|
||||||
#end
|
|
||||||
#else
|
|
||||||
<p>$i18n.xlate("bulkedit.no_tasks")
|
|
||||||
#end
|
|
||||||
|
|
||||||
<center>$form.submit("submit", "Update")</center>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
#import ("/footer.wm")
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
#set ($title = $i18n.xlate("index.title"))
|
|
||||||
#import ("/header.wm")
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<table><tr>
|
|
||||||
<td><a href="index.wm">Task summary</a></td>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<td><a href="tasks.wm">By priority</a></td>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<form action="bycategory.wm">
|
|
||||||
<td>Filter: <input name="query" size="10"></td>
|
|
||||||
</form>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<td>Click the wrench to claim a task.</td>
|
|
||||||
</tr></table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<b>
|
|
||||||
#if ($query)
|
|
||||||
Tasks matching '$query':
|
|
||||||
#else
|
|
||||||
Outstanding tasks:
|
|
||||||
#end
|
|
||||||
</b>
|
|
||||||
|
|
||||||
#if ($filter != "")
|
|
||||||
<a href="bycategory.wm">all</a>
|
|
||||||
#foreach ($xtask in $xtasks)
|
|
||||||
<a href="bycategory.wm?filter=$xtask.name">$xtask.name</a>
|
|
||||||
#end
|
|
||||||
|
|
||||||
#foreach ($xtask in $xtasks)
|
|
||||||
#if ($filter == $xtask.name)
|
|
||||||
<p>
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="100%">
|
|
||||||
<tr style="color: $fcolor" bgcolor="$scolor"><td colspan="2" align="left">
|
|
||||||
<a href="bycategory.wm?filter=$xtask.name">$xtask.name</a>
|
|
||||||
($xtask.tasks.size())</td>
|
|
||||||
<td colspan="2"> </td></tr>
|
|
||||||
|
|
||||||
$xcats.clear()
|
|
||||||
#foreach ($task in $xtask.tasks)
|
|
||||||
#if ($xcats.checkCategory($task.complexity))
|
|
||||||
<tr><td colspan="4" class="small" style="border-bottom: 1px solid"><i>$task.complexity</i></td></tr>
|
|
||||||
#set ($border = "")
|
|
||||||
#else
|
|
||||||
#set ($border = 'style="border-top: 1px solid"')
|
|
||||||
#end
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><a href="index.wm?action=claim&task=$task.taskId">
|
|
||||||
<img src="images/claim.png" border="0" alt="Claim this task"></a></td>
|
|
||||||
<td $border>$task.summary
|
|
||||||
<span class="small">[$task.creator]</span>
|
|
||||||
#if (!$string.blank($task.notes))
|
|
||||||
<a href="detail.wm?task=$task.taskId">[...]</a>
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
<td valign="top" $border>$task.getPriorityName()</td>
|
|
||||||
<td valign="top" $border><a href="edit.wm?task=$task.taskId">
|
|
||||||
<img src="images/edit.png" border="0" alt="Edit this task"></a></td>
|
|
||||||
</tr>
|
|
||||||
#end
|
|
||||||
</table>
|
|
||||||
<p><center>
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
|
|
||||||
#else
|
|
||||||
<table><tr><td valign="top"> <!-- two column table -->
|
|
||||||
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="100%">
|
|
||||||
#foreach ($xtask in $xtasks)
|
|
||||||
#if ($vidx == $break)
|
|
||||||
</table>
|
|
||||||
</td><td width="15"> </td><td valign="top">
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="100%">
|
|
||||||
#else
|
|
||||||
#if ($vidx > 0)
|
|
||||||
<tr><td colspan="4"> </td></tr>
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
<tr style="color: $fcolor" bgcolor="$scolor"><td colspan="2" align="left">
|
|
||||||
<a href="bycategory.wm?filter=$xtask.name">$xtask.name</a>
|
|
||||||
($xtask.tasks.size())</td>
|
|
||||||
<td colspan="2"> </td></tr>
|
|
||||||
|
|
||||||
$xcats.clear()
|
|
||||||
#foreach ($task in $xtask.tasks)
|
|
||||||
|
|
||||||
#if ($xcats.checkCategory($task.complexity))
|
|
||||||
<tr><td colspan="4" class="small" style="border-bottom: 1px solid"><i>$task.complexity</i></td></tr>
|
|
||||||
#set ($border = "")
|
|
||||||
#else
|
|
||||||
#set ($border = 'style="border-top: 1px solid"')
|
|
||||||
#end
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><a href="index.wm?action=claim&task=$task.taskId">
|
|
||||||
<img src="images/claim.png" border="0" alt="Claim this task"></a></td>
|
|
||||||
<td $border>$task.summary
|
|
||||||
<span class="small">[$task.creator]</span>
|
|
||||||
#if (!$string.blank($task.notes))
|
|
||||||
<a href="detail.wm?task=$task.taskId">[...]</a>
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
<td valign="top" $border>$task.getPriorityName()</td>
|
|
||||||
<td valign="top" $border><a href="edit.wm?task=$task.taskId">
|
|
||||||
<img src="images/edit.png" border="0" alt="Edit this task"></a></td>
|
|
||||||
</tr>
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
</table>
|
|
||||||
</table>
|
|
||||||
#end
|
|
||||||
|
|
||||||
#import ("/footer.wm")
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#set ($title = $i18n.xlate("detail.title"))
|
|
||||||
#import ("/header.wm")
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="60%">
|
|
||||||
<tr bgcolor="$scolor"><td colspan="4" align="left">$task.complexity</td></tr>
|
|
||||||
|
|
||||||
<form action="index.wm">
|
|
||||||
$form.fixedHidden("task", "$task.taskId")
|
|
||||||
|
|
||||||
<tr><td>
|
|
||||||
#if ($task.owner)
|
|
||||||
#if ($username == $task.owner)
|
|
||||||
$form.imageSubmit("submit", "", "images/complete.png", "Mark as completed")
|
|
||||||
#else
|
|
||||||
|
|
||||||
#end
|
|
||||||
#else
|
|
||||||
$form.imageSubmit("action", "claim", "images/claim.png", "Claim this task")
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>$task.summary
|
|
||||||
<span class="small">[$task.creator]</span>
|
|
||||||
</td>
|
|
||||||
<td valign="top">$task.category</td>
|
|
||||||
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
|
||||||
<img src="images/edit.png" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
#if (!$string.blank($notes))
|
|
||||||
<tr><td colspan="4"> </td></tr>
|
|
||||||
<tr><td style="border-bottom: 1px, solid" colspan="4"><i>Notes</i></td></tr>
|
|
||||||
<tr><td> </td>
|
|
||||||
<td colspan="3">
|
|
||||||
<pre>$notes</pre>
|
|
||||||
</td></tr>
|
|
||||||
#end
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
#import ("/footer.wm")
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
#set ($title = $i18n.xlate("edit.title"))
|
|
||||||
#import ("/header.wm")
|
|
||||||
|
|
||||||
#if ($task)
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr><td>
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0">
|
|
||||||
|
|
||||||
#if ($task.completor)
|
|
||||||
<form action="edit.wm">
|
|
||||||
$form.fixedHidden("action", "reopen")
|
|
||||||
<input type="hidden" name="task" value="$task.taskId">
|
|
||||||
<tr><td colspan="3" valign="center">
|
|
||||||
Task is completed.
|
|
||||||
</td></tr>
|
|
||||||
<tr><td colspan="3" bgcolor="$scolor" align="right">
|
|
||||||
$form.submit("submit", "Reopen")</td></tr>
|
|
||||||
<tr><td colspan="3"> </td></tr>
|
|
||||||
</form>
|
|
||||||
#end
|
|
||||||
|
|
||||||
<form action="edit.wm">
|
|
||||||
$form.fixedHidden("action", "update")
|
|
||||||
<input type="hidden" name="task" value="$task.taskId">
|
|
||||||
|
|
||||||
<tr><td rowspan="3" valign="top">Summary:<br>
|
|
||||||
<textarea name="summary" rows="8" cols="50">
|
|
||||||
$task.summary
|
|
||||||
</textarea>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td valign="top">Category:<br>
|
|
||||||
$form.text("category", "size='10'", $task.category)
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>Complexity:<br>
|
|
||||||
<select name="complexity">
|
|
||||||
$form.option("complexity", "Simple hack", "Simple hack", $task.complexity)
|
|
||||||
$form.option("complexity", "Minor feature", "Minor feature", $task.complexity)
|
|
||||||
$form.option("complexity", "Major feature", "Major feature", $task.complexity)
|
|
||||||
$form.option("complexity", "Subsystem", "Subsystem", $task.complexity)
|
|
||||||
$form.option("complexity", "Major refactor", "Major refactor", $task.complexity)
|
|
||||||
</select>
|
|
||||||
</td></tr>
|
|
||||||
|
|
||||||
<tr><td valign="top">Creator:<br>
|
|
||||||
$form.text("creator", "size='10'", $task.creator)
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>Priority:<br>
|
|
||||||
<select name="priority">
|
|
||||||
$form.option("priority", "50", "Urgent", $string.valueOf($task.priority))
|
|
||||||
$form.option("priority", "25", "Next up", $string.valueOf($task.priority))
|
|
||||||
$form.option("priority", "15", "Near term", $string.valueOf($task.priority))
|
|
||||||
$form.option("priority", "10", "Medium term", $string.valueOf($task.priority))
|
|
||||||
$form.option("priority", "5", "Long term", $string.valueOf($task.priority))
|
|
||||||
$form.option("priority", "1", "On the list", $string.valueOf($task.priority))
|
|
||||||
</select>
|
|
||||||
</td></tr>
|
|
||||||
|
|
||||||
<tr><td>Owner:<br>
|
|
||||||
#if ($task.owner)
|
|
||||||
$form.text("owner", "size='10'", $task.owner)
|
|
||||||
#else
|
|
||||||
$form.text("owner", "size='10'", "")
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
<td> </td></tr>
|
|
||||||
|
|
||||||
<tr><td colspan="4" align="right" bgcolor="$scolor">
|
|
||||||
$form.submit("submit", "Update")</td></tr>
|
|
||||||
</form>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td><td width="15"> </td><td valign="bottom">
|
|
||||||
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0">
|
|
||||||
<tr><td>Other actions:</td></tr>
|
|
||||||
<tr><td align="right" bgcolor="$scolor">
|
|
||||||
|
|
||||||
<form action="edit.wm">
|
|
||||||
$form.fixedHidden("action", "delete")
|
|
||||||
<input type="hidden" name="task" value="$task.taskId">
|
|
||||||
$form.submit("submit", "Delete")
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</td></tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td></tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0">
|
|
||||||
|
|
||||||
<form action="edit.wm">
|
|
||||||
$form.fixedHidden("action", "addnote")
|
|
||||||
<input type="hidden" name="task" value="$task.taskId">
|
|
||||||
|
|
||||||
<tr><td>Add a note:<br>
|
|
||||||
<code>
|
|
||||||
<textarea name="note" rows="5" cols="80" wrap="hard">
|
|
||||||
</textarea>
|
|
||||||
</code>
|
|
||||||
</td></tr>
|
|
||||||
|
|
||||||
<tr><td align="right" bgcolor="$scolor">
|
|
||||||
$form.submit("submit", "Add")</td></tr>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<tr><td> </td></tr>
|
|
||||||
|
|
||||||
<form action="edit.wm">
|
|
||||||
$form.fixedHidden("action", "editnotes")
|
|
||||||
<input type="hidden" name="task" value="$task.taskId">
|
|
||||||
|
|
||||||
<tr><td>Notes:<br>
|
|
||||||
<code>
|
|
||||||
<textarea name="notes" rows="10" cols="80" wrap="hard">
|
|
||||||
$task.notes
|
|
||||||
</textarea>
|
|
||||||
</code>
|
|
||||||
</td></tr>
|
|
||||||
|
|
||||||
<tr><td align="right" bgcolor="$scolor">
|
|
||||||
$form.submit("submit", "Update")</td></tr>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
#end
|
|
||||||
|
|
||||||
#import ("/footer.wm")
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<p>
|
|
||||||
<table cellpadding=6 cellspacing=0 border=0 width="100%">
|
|
||||||
<tr bgcolor="$hcolor">
|
|
||||||
<td>
|
|
||||||
#import ("app_footer.wm")
|
|
||||||
</td>
|
|
||||||
<!--
|
|
||||||
<td align="right">
|
|
||||||
©2002
|
|
||||||
<a href="http://www.samskivert.com/">Michael Bayne</a>
|
|
||||||
</td>
|
|
||||||
-->
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
## This is the header and footer color
|
|
||||||
#set ($hcolor = "#CCCCCC")
|
|
||||||
## These colors are used for common UI elements
|
|
||||||
#set ($tcolor = "#99CCFF")
|
|
||||||
#set ($scolor = "#CCCCCC")
|
|
||||||
#set ($fcolor = "#000000")
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>$i18n.xlate("header.combined_title", $i18n.xlate("app_name"), $title)</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/twodue/style.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" vlink="#003366">
|
|
||||||
|
|
||||||
<table cellpadding="6" cellspacing="0" border="0" width="100%">
|
|
||||||
<tr bgcolor="$hcolor"><td align=right>
|
|
||||||
<span class="big"><b>$i18n.xlate("header.title", $i18n.xlate("app_name"))</b></span><br>
|
|
||||||
$title</td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
#if ($error)
|
|
||||||
<p>
|
|
||||||
<table cellpadding="6" cellspacing="0" border="0" width="100%">
|
|
||||||
<tr><td><font color="#FF0000">$i18n.xlate($error)</font></td></tr>
|
|
||||||
</table>
|
|
||||||
#end
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 461 B |
Binary file not shown.
|
Before Width: | Height: | Size: 472 B |
Binary file not shown.
|
Before Width: | Height: | Size: 731 B |
Binary file not shown.
|
Before Width: | Height: | Size: 546 B |
@@ -1,125 +0,0 @@
|
|||||||
#set ($title = $i18n.xlate("index.title"))
|
|
||||||
#import ("/header.wm")
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr><td width="50%" valign="top">
|
|
||||||
|
|
||||||
<b>Owned tasks:</b>
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="100%">
|
|
||||||
|
|
||||||
#foreach ($otask in $otasks)
|
|
||||||
#if ($vidx > 0)
|
|
||||||
<tr><td colspan="4"> </td></tr>
|
|
||||||
#end
|
|
||||||
<tr><td colspan="4" align="left" style="color: $fcolor" bgcolor="$scolor">$otask.name</td></tr>
|
|
||||||
|
|
||||||
$ocats.clear()
|
|
||||||
#foreach ($task in $otask.tasks)
|
|
||||||
#if ($ocats.checkCategory($task.complexity))
|
|
||||||
<tr><td colspan="4" class="small" style="border-bottom: 1px solid"><i>$task.complexity</i></td></tr>
|
|
||||||
#set ($border = "")
|
|
||||||
#else
|
|
||||||
#set ($border = 'style="border-top: 1px solid"')
|
|
||||||
#end
|
|
||||||
|
|
||||||
<tr><td>
|
|
||||||
#if ($username == $task.owner)
|
|
||||||
<a href="index.wm?action=complete&task=$task.taskId">
|
|
||||||
<img src="images/complete.png" border="0" alt="Mark as completed"></a>
|
|
||||||
#else
|
|
||||||
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
<td $border>$task.summary
|
|
||||||
#if (!$string.blank($task.notes))
|
|
||||||
<a href="detail.wm?task=$task.taskId">[...]</a>
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
<td valign="top" $border>$task.getDisplayCategory()</td>
|
|
||||||
<td valign="top" $border><a href="edit.wm?task=$task.taskId">
|
|
||||||
<img src="images/edit.png" border="0" alt="Edit this task"></a></td></tr>
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<td valign="top">
|
|
||||||
|
|
||||||
<b>Recent completed tasks:</b>
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="100%">
|
|
||||||
#foreach ($task in $dtasks)
|
|
||||||
#if ($vidx%2 == 0)
|
|
||||||
#set ($rowcolor = "#EEEEEE")
|
|
||||||
#else
|
|
||||||
#set ($rowcolor = "#FFFFFF")
|
|
||||||
#end
|
|
||||||
<tr bgcolor="$rowcolor">
|
|
||||||
<td valign="top"><img src="images/completed.png"></td>
|
|
||||||
<td valign="top" align="center">$task.completion<br>[$task.completor]</td>
|
|
||||||
<td>$task.summary
|
|
||||||
#if (!$string.blank($task.notes))
|
|
||||||
<a href="detail.wm?task=$task.taskId">[...]</a>
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
<td valign="top">$task.getDisplayCategory()</td>
|
|
||||||
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
|
||||||
<img src="images/edit.png" border="0" alt="Edit this task"></a></td></tr>
|
|
||||||
#end
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p><b>Browse: <a href="bycategory.wm">by category</a>
|
|
||||||
<a href="tasks.wm">by priority</a></b>
|
|
||||||
|
|
||||||
<p><b>Create new task:</b>
|
|
||||||
<form action="index.wm">
|
|
||||||
$form.fixedHidden("action", "create")
|
|
||||||
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0">
|
|
||||||
<tr><td colspan="3" bgcolor="$scolor"> <br></td></tr>
|
|
||||||
|
|
||||||
<tr><td colspan="3">Summary:<br>
|
|
||||||
<textarea name="summary" rows="5" cols="50">
|
|
||||||
</textarea>
|
|
||||||
</td></tr>
|
|
||||||
|
|
||||||
<tr><td>Category:<br>
|
|
||||||
$form.text("category", "size='10'", "")
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>Complexity:<br>
|
|
||||||
<select name="complexity">
|
|
||||||
$form.option("complexity", "Simple hack", "Simple hack", "Simple hack")
|
|
||||||
$form.option("complexity", "Minor feature", "Minor feature", "Simple hack")
|
|
||||||
$form.option("complexity", "Major feature", "Major feature", "Simple hack")
|
|
||||||
$form.option("complexity", "Subsystem", "Subsystem", "Simple hack")
|
|
||||||
$form.option("complexity", "Major refactor", "Major refactor", "Simple hack")
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>Priority:<br>
|
|
||||||
<select name="priority">
|
|
||||||
$form.option("priority", "50", "Urgent", "5")
|
|
||||||
$form.option("priority", "25", "Next up", "5")
|
|
||||||
$form.option("priority", "15", "Near term", "5")
|
|
||||||
$form.option("priority", "10", "Medium term", "5")
|
|
||||||
$form.option("priority", "5", "Long term", "5")
|
|
||||||
$form.option("priority", "1", "On the list", "5")
|
|
||||||
</select>
|
|
||||||
</td></tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td colspan="2" align="left" style="color: $fcolor" bgcolor="$scolor">
|
|
||||||
$form.checkbox("claim", false) Claim created task
|
|
||||||
$form.checkbox("edit", false) Edit created task</td>
|
|
||||||
<td align="right" bgcolor="$scolor">
|
|
||||||
$form.submit("submit", "Create")</td></tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</td></tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
#import ("/footer.wm")
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
i, em {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
th, td, center, div { /* ns 4 */
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre, code {
|
|
||||||
font-family: Courier;
|
|
||||||
}
|
|
||||||
|
|
||||||
.big {
|
|
||||||
font-size: x-large;
|
|
||||||
}
|
|
||||||
|
|
||||||
.small {
|
|
||||||
font-size: small;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#set ($title = $i18n.xlate("index.title"))
|
|
||||||
#import ("/header.wm")
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<table><tr>
|
|
||||||
<td><a href="index.wm">Task summary</a></td>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<td><a href="bycategory.wm">By category</a></td>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<form action="tasks.wm">
|
|
||||||
<td>Filter: <input name="query" size="10"></td>
|
|
||||||
</form>
|
|
||||||
<td width="15"> </td>
|
|
||||||
<td>Click the wrench to claim a task.</td>
|
|
||||||
</tr></table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<b>
|
|
||||||
#if ($query)
|
|
||||||
Tasks matching '$query':
|
|
||||||
#else
|
|
||||||
Outstanding tasks:
|
|
||||||
#end
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<table border=0><tr><td valign="top"> <!-- two column table -->
|
|
||||||
|
|
||||||
#foreach ($xtask in $xtasks)
|
|
||||||
<table cellpadding="2" cellspacing="0" border="0" width="100%">
|
|
||||||
<tr style="color: $fcolor" bgcolor="$scolor"><td colspan="2" align="left">$xtask.name</td>
|
|
||||||
<td colspan="2"> </td></tr>
|
|
||||||
|
|
||||||
$xcats.clear()
|
|
||||||
#foreach ($task in $xtask.tasks)
|
|
||||||
|
|
||||||
#if ($xcats.checkCategory($task.category))
|
|
||||||
<tr><td colspan="4" class="small" style="border-bottom: 1px solid"><i>$task.category</i></td></tr>
|
|
||||||
#set ($border = "")
|
|
||||||
#else
|
|
||||||
#set ($border = 'style="border-top: 1px solid"')
|
|
||||||
#end
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><a href="index.wm?action=claim&task=$task.taskId">
|
|
||||||
<img src="images/claim.png" border="0" alt="Claim this task"></a></td>
|
|
||||||
<td $border>$task.summary
|
|
||||||
<span class="small">[$task.creator]</span>
|
|
||||||
#if (!$string.blank($task.notes))
|
|
||||||
<a href="detail.wm?task=$task.taskId">[...]</a>
|
|
||||||
#end
|
|
||||||
</td>
|
|
||||||
<td valign="top" $border>$task.complexity</td>
|
|
||||||
<td valign="top" $border><a href="edit.wm?task=$task.taskId">
|
|
||||||
<img src="images/edit.png" border="0" alt="Edit this task"></a></td>
|
|
||||||
</tr>
|
|
||||||
#end
|
|
||||||
</table>
|
|
||||||
|
|
||||||
#if ($vidx%2 == 1)
|
|
||||||
</td></tr><tr><td valign="top">
|
|
||||||
#else
|
|
||||||
</td><td width="15"> </td><td valign="top">
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
</table>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
#import ("/footer.wm")
|
|
||||||
Reference in New Issue
Block a user