git-svn-id: https://samskivert.googlecode.com/svn/trunk@1317 6335cc39-0255-0410-8fd6-9bcaacd3b74c

This commit is contained in:
mdb
2003-11-15 22:55:32 +00:00
parent c8d6a29c89
commit 5202d2a61e
13 changed files with 507 additions and 134 deletions
+1
View File
@@ -1 +1,2 @@
repository.properties
user.properties
+4 -2
View File
@@ -1,6 +1,6 @@
# -*- mode: makefile -*-
#
# $Id: messages.properties,v 1.4 2003/01/23 21:22:56 mdb Exp $
# $Id: messages.properties,v 1.5 2003/11/15 22:55:32 mdb Exp $
#
# Translation messages for Two Due application
@@ -20,7 +20,9 @@ header.title={0}
#
# app_footer.wm
app_footer.summary_link=Task Summary
app_footer.summary_link=Task status
app_footer.tasks_link=By priority
app_footer.bycategory_link=By category
app_footer.account_link=Login/out
#
+15
View File
@@ -0,0 +1,15 @@
#
# $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 -1
View File
@@ -26,7 +26,7 @@
</init-param>
<init-param>
<param-name>site_jar_path</param-name>
<param-value>/usr/share/java/webapps/site-data</param-value>
<param-value>/export/threerings/webapps/site-data</param-value>
</init-param>
<init-param>
<param-name>site_messages_path</param-name>
@@ -1,5 +1,5 @@
//
// $Id: TwoDueApp.java,v 1.1 2002/11/08 09:14:21 mdb Exp $
// $Id: TwoDueApp.java,v 1.2 2003/11/15 22:55:32 mdb Exp $
package com.samskivert.twodue;
@@ -14,6 +14,7 @@ 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;
@@ -51,9 +52,8 @@ public class TwoDueApp extends Application
// create a static connection provider
_conprov = new StaticConnectionProvider(CONN_CONFIG);
// initialize the user manager
Properties props = new Properties();
props.put("login_url", "/register/login.wm?from=%R");
// load up our configuration properties
Properties props = ConfigUtil.loadProperties("user.properties");
_usermgr = new UserManager(props, _conprov);
// initialize the task repository
@@ -0,0 +1,171 @@
//
// $Id: bycategory.java,v 1.1 2003/11/15 22:55:32 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);
}
// we use this to determine whether to show "complete" buttons for
// tasks
ctx.put("username", user.username);
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,5 +1,5 @@
//
// $Id: index.java,v 1.10 2003/05/21 02:40:13 mdb Exp $
// $Id: index.java,v 1.11 2003/11/15 22:55:32 mdb Exp $
package com.samskivert.twodue.logic;
@@ -94,40 +94,10 @@ public class index extends UserLogic
ctx.put("error", "index.message.task_claimed");
}
// load up outstanding tasks and break them down by complexity
String expand = ParameterUtil.getParameter(req, "expand", false);
ctx.put("expand", expand);
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);
// force expand to all
expand = "all";
}
// sort the tasks by priority, then complexity
Collections.sort(tasks, OPEN_PARATOR);
CatList[] xtasks = categorize(tasks, expand, 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");
}
// load up owned tasks and break them down by owner
tasks = app.getRepository().loadOwnedTasks();
ArrayList tasks = app.getRepository().loadOwnedTasks();
Collections.sort(tasks, OWNED_PARATOR);
CatList[] otasks = categorize(tasks, null, new Categorizer() {
CatList[] otasks = categorize(tasks, new Categorizer() {
public String category (Task task) {
return task.owner;
}
@@ -154,7 +124,6 @@ public class index extends UserLogic
{
public String name;
public ArrayList tasks;
public int pruned;
public int compareTo (Object other)
{
return name.compareTo(((CatList)other).name);
@@ -166,8 +135,7 @@ public class index extends UserLogic
public String category (Task task);
}
protected CatList[] categorize (
ArrayList tasks, String expand, Categorizer catter)
protected CatList[] categorize (ArrayList tasks, Categorizer catter)
{
if (tasks == null) {
return new CatList[0];
@@ -187,13 +155,7 @@ public class index extends UserLogic
cats.add(clist);
cmap.put(category, clist);
}
if (expand == null || clist.tasks.size() < 2 ||
expand.equals("all") ||
(task.priority > 15) || expand.equals(category)) {
clist.tasks.add(task);
} else {
clist.pruned++;
}
clist.tasks.add(task);
}
CatList[] ctasks = new CatList[cats.size()];
@@ -0,0 +1,154 @@
//
// $Id: tasks.java,v 1.1 2003/11/15 22:55:32 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);
}
// we use this to determine whether to show "complete" buttons for
// tasks
ctx.put("username", user.username);
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.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 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;
}
}
+2
View File
@@ -1,3 +1,5 @@
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>
+71
View File
@@ -0,0 +1,71 @@
#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">&nbsp;</td>
<td><a href="tasks.wm">By priority</a></td>
<td width="15">&nbsp;</td>
<form action="bycategory.wm">
<td>Filter: <input name="query" size="10"></td>
</form>
<td width="15">&nbsp;</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><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">&nbsp;</td><td valign="top">
<table cellpadding="2" cellspacing="0" border="0" width="100%">
#else
#if ($vidx > 0)
<tr><td colspan="4">&nbsp;</td></tr>
#end
#end
<tr style="color: $fcolor" bgcolor="$scolor"><td colspan="2" align="left">$xtask.name</td>
<td colspan="2">&nbsp;</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 &nbsp;
<span class="small">[$task.creator]</span>
#if (!$string.blank($task.notes))
&nbsp; <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>
#import ("/footer.wm")
+1
View File
@@ -3,6 +3,7 @@
## These colors are used for common UI elements
#set ($tcolor = "#99CCFF")
#set ($scolor = "#CCCCCC")
#set ($fcolor = "#000000")
<html>
<head>
+7 -84
View File
@@ -4,7 +4,8 @@
<p>
<table cellpadding="0" cellspacing="0" border="0">
<tr><td valign="top">
<tr><td width="50%">
<b>Owned tasks:</b>
<table cellpadding="2" cellspacing="0" border="0" width="100%">
@@ -12,7 +13,7 @@
#if ($vidx > 0)
<tr><td colspan="4">&nbsp;</td></tr>
#end
<tr><td colspan="4" align="left" bgcolor="$scolor">$otask.name</td></tr>
<tr><td colspan="4" align="left" style="color: $fcolor" bgcolor="$scolor">$otask.name</td></tr>
$ocats.clear()
#foreach ($task in $otask.tasks)
@@ -43,85 +44,10 @@ $ocats.clear()
#end
</table>
<p>
<center class="small">Check the box to mark a task as completed.</center>
</td>
<td width="15">&nbsp;</td>
<td valign="top">
<b>
#if ($query)
Tasks matching '$query':
#else
Outstanding tasks:
#if ($expand == "all")
<a href="index.wm">[trim]</a>
#else
<a href="index.wm?expand=all">[show all]</a>
#end
#end
</b>
<table cellpadding="2" cellspacing="0" border="0" width="100%">
#foreach ($xtask in $xtasks)
#if ($vidx > 0)
<tr><td colspan="4">&nbsp;</td></tr>
#end
<tr bgcolor="$scolor"><td colspan="2" align="left">$xtask.name</td>
<td colspan="2">
#if ($xtask.pruned > 0)
<a href="index.wm?expand=$xtask.name">($xtask.pruned ...)</a>
#else
&nbsp;
#end
</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 &nbsp;
<span class="small">[$task.creator]</span>
#if (!$string.blank($task.notes))
&nbsp; <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>
<p align="center">
<table width="100%">
<tr><td class="small" valign="top">Click the wrench to claim a task.</td>
<td class="small"><form action="index.wm">
Filter on single word:<br>
<input name="query" size="10">
</form>
</center>
</td></tr>
</table>
</td></tr>
<tr><td colspan="3">&nbsp;</td></tr>
<tr><td valign="top">
<b>Recent completed tasks:</b>
<table cellpadding="2" cellspacing="0" border="0" width="100%">
#foreach ($task in $dtasks)
@@ -144,12 +70,10 @@ Filter on single word:<br>
#end
</table>
</td>
<p><b>Browse:&nbsp;&nbsp;<a href="bycategory.wm">by category</a>
&nbsp;&nbsp;<a href="tasks.wm">by priority</a></b>
<td>&nbsp;</td>
<td valign="top">
<b>Create new task:</b>
<p><b>Create new task:</b>
<form action="index.wm">
$form.fixedHidden("action", "create")
@@ -187,13 +111,12 @@ $form.text("category", "size='10'", "")
</td></tr>
<tr>
<td colspan="2" align="left" bgcolor="$scolor">
<td colspan="2" align="left" style="color: $fcolor" bgcolor="$scolor">
$form.checkbox("claim", false) Claim created task&nbsp;&nbsp;
$form.checkbox("edit", false) Edit created task</td>
<td align="right" bgcolor="$scolor">
$form.submit("submit", "Create")</td></tr>
</table>
</form>
</td></tr>
+71
View File
@@ -0,0 +1,71 @@
#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">&nbsp;</td>
<td><a href="bycategory.wm">By category</a></td>
<td width="15">&nbsp;</td>
<form action="tasks.wm">
<td>Filter: <input name="query" size="10"></td>
</form>
<td width="15">&nbsp;</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><tr><td> <!-- two column table -->
<table cellpadding="2" cellspacing="0" border="0" width="100%">
#foreach ($xtask in $xtasks)
#if ($xtask.name == "On the list")
</table>
</td><td width="15">&nbsp;</td><td valign="top">
<table cellpadding="2" cellspacing="0" border="0" width="100%">
#else
#if ($vidx > 0)
<tr><td colspan="4">&nbsp;</td></tr>
#end
#end
<tr style="color: $fcolor" bgcolor="$scolor"><td colspan="2" align="left">$xtask.name</td>
<td colspan="2">&nbsp;</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 &nbsp;
<span class="small">[$task.creator]</span>
#if (!$string.blank($task.notes))
&nbsp; <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>
</table>
#import ("/footer.wm")