Notes, edits, tigers, oh my!

git-svn-id: https://samskivert.googlecode.com/svn/trunk@898 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2002-11-08 21:49:18 +00:00
parent aa4c37541a
commit 2de6a6923b
10 changed files with 404 additions and 58 deletions
+29 -6
View File
@@ -1,6 +1,6 @@
# -*- mode: makefile -*-
#
# $Id: messages.properties,v 1.1 2002/11/08 09:14:20 mdb Exp $
# $Id: messages.properties,v 1.2 2002/11/08 21:49:17 mdb Exp $
#
# Translation messages for Two Due application
@@ -21,6 +21,17 @@ header.title={0}
app_footer.summary_link=Task Summary
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.
task.error.no_such_task = No task exists with that task id.
#
# index.wm
@@ -30,8 +41,20 @@ index.message.task_created = Task created.
index.message.task_claimed = Task claimed.
index.message.task_completed = Task marked as completed.
index.error.missing_summary = No summary provided for new task.
index.error.missing_category = No category provided for new task.
index.error.missing_complexity = No complexity selection for new task.
index.error.invalid_priority = No priority selection for new task.
index.error.missing_taskid = Internal error. No task id provided.
index.error.invalid_detail_task = Task id specified for inspection not valid.
#
# 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.error.missing_note = Can\'t add blank note.
#
# detail.wm
detail.title = Task Details
@@ -1,5 +1,5 @@
//
// $Id: Task.java,v 1.1 2002/11/08 09:14:21 mdb Exp $
// $Id: Task.java,v 1.2 2002/11/08 21:49:17 mdb Exp $
package com.samskivert.twodue.data;
@@ -31,5 +31,5 @@ public class Task
public Date completion;
public transient ArrayList notes;
public String notes;
}
@@ -1,5 +1,5 @@
//
// $Id: TaskRepository.java,v 1.1 2002/11/08 09:14:21 mdb Exp $
// $Id: TaskRepository.java,v 1.2 2002/11/08 21:49:17 mdb Exp $
package com.samskivert.twodue.data;
@@ -75,6 +75,7 @@ public class TaskRepository extends JORARepository
task.complexity = complexity;
task.priority = priority;
task.creator = creator;
task.notes = "";
createTask(task);
return task;
}
@@ -102,18 +103,24 @@ public class TaskRepository extends JORARepository
/**
* Loads up the specified task.
*
* @return the requested task or null if no tasks exists with that id.
*/
public Task loadTask (int taskId)
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 COMPLETOR IS NULL AND OWNER IS NULL " +
"ORDER BY CATEGORY, PRIORITY";
Cursor tc = _ttable.select(query);
return tc.toArrayList();
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;
}
});
}
@@ -0,0 +1,89 @@
//
// $Id: detail.java,v 1.1 2002/11/08 21:49:17 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");
// we use this to determine whether to show "complete" buttons for
// tasks
ctx.put("username", user.username);
// load up the task in question
Task task = app.getRepository().loadTask(taskId);
if (task == null) {
ctx.put("error", "task.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();
}
}
@@ -0,0 +1,109 @@
//
// $Id: edit.java,v 1.1 2002/11/08 21:49:17 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", "edit.error.no_such_task");
} else {
// 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", "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,5 +1,5 @@
//
// $Id: index.java,v 1.1 2002/11/08 09:14:21 mdb Exp $
// $Id: index.java,v 1.2 2002/11/08 21:49:17 mdb Exp $
package com.samskivert.twodue.logic;
@@ -47,19 +47,18 @@ public class index extends UserLogic
// set the creator from the username of the calling user
Task task = new Task();
task.creator = user.username;
task.notes = ""; // no notes to start
// parse our fields
task.summary = ParameterUtil.requireParameter(
ctx.getRequest(), "summary", "index.error.missing_summary");
ctx.getRequest(), "summary", "task.error.missing_summary");
task.category = ParameterUtil.requireParameter(
ctx.getRequest(), "category",
"index.error.missing_category");
ctx.getRequest(), "category", "task.error.missing_category");
task.complexity = ParameterUtil.requireParameter(
ctx.getRequest(), "complexity",
"index.error.missing_complexity");
"task.error.missing_complexity");
task.priority = ParameterUtil.requireIntParameter(
ctx.getRequest(), "priority",
"index.error.invalid_priority");
ctx.getRequest(), "priority", "task.error.invalid_priority");
// insert the task into the repository
app.getRepository().createTask(task);
@@ -72,7 +71,7 @@ public class index extends UserLogic
} else if (ParameterUtil.parameterEquals(
ctx.getRequest(), "action", "complete")) {
int taskId = ParameterUtil.requireIntParameter(
ctx.getRequest(), "task", "index.error.missing_taskid");
ctx.getRequest(), "task", "task.error.missing_taskid");
app.getRepository().completeTask(taskId, user.username);
// let the user know we updated the database
@@ -81,7 +80,7 @@ public class index extends UserLogic
} else if (ParameterUtil.parameterEquals(
ctx.getRequest(), "action", "claim")) {
int taskId = ParameterUtil.requireIntParameter(
ctx.getRequest(), "task", "index.error.missing_taskid");
ctx.getRequest(), "task", "task.error.missing_taskid");
app.getRepository().claimTask(taskId, user.username);
// let the user know we updated the database
+6 -1
View File
@@ -1,5 +1,5 @@
/**
* $Id: tasks-schema.sql,v 1.1 2002/11/08 09:14:21 mdb Exp $
* $Id: tasks-schema.sql,v 1.2 2002/11/08 21:49:18 mdb Exp $
*
* Schema for the Two Due tasks and notes table.
*/
@@ -61,6 +61,11 @@ CREATE TABLE TASKS
*/
COMPLETION DATE,
/**
* Free form notes associated with this task.
*/
NOTES TEXT NOT NULL,
/**
* Defines our table keys.
*/
+43
View File
@@ -0,0 +1,43 @@
#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
&nbsp;
#end
#else
$form.imageSubmit("action", "claim", "images/claim.png", "Claim this task")
#end
</td>
<td>$task.summary &nbsp;
<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>&nbsp;</td>
<td colspan="3">
<p>
<code>$notes</code>
</td></tr>
#end
</form>
</table>
#import ("/footer.wm")
+85 -21
View File
@@ -3,49 +3,113 @@
<p>
<form action="index.wm">
$form.fixedHidden("action", "update")
<table cellpadding="0" cellspacing="10"> <!-- two colum layout table -->
<tr><td valign="top">
<table cellpadding="2" cellspacing="0" border="0">
<tr><td colspan="3" bgcolor="$scolor">&nbsp;<br></td></tr>
#if ($task && $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">&nbsp;</td></tr>
#end
<form action="edit.wm">
$form.fixedHidden("action", "update")
<input type="hidden" name="task" value="$task.taskId">
<tr><td colspan="3">Summary:<br>
<textarea name="summary" rows="5" cols="50">
#if ($task)
$task.summary
#end
</textarea>
</td></tr>
<tr><td>Category:<br>
<font face="courier">
$form.text("category", "size='10'", "")
</font></td>
$form.text("category", "size='10'", $task.category)
</td>
<td>Complexity:<br>
<font face="courier">
<select name="complexity">
$form.option("complexity", "1 - Simple hack", "Simple hack", "1 - Simple hack")
$form.option("complexity", "2 - Minor feature", "Minor feature", "1 - Simple hack")
$form.option("complexity", "3 - Major feature", "Major feature", "1 - Simple hack")
$form.option("complexity", "4 - Subsystem", "Subsystem", "1 - Simple hack")
$form.option("complexity", "5 - Major refactor", "Major refactor", "1 - Simple hack")
$form.option("complexity", "1 - Simple hack", "Simple hack", $task.complexity)
$form.option("complexity", "2 - Minor feature", "Minor feature", $task.complexity)
$form.option("complexity", "3 - Major feature", "Major feature", $task.complexity)
$form.option("complexity", "4 - Subsystem", "Subsystem", $task.complexity)
$form.option("complexity", "5 - Major refactor", "Major refactor", $task.complexity)
</select>
</font></td>
</td>
<td>Priority:<br>
<font face="courier">
<select name="priority">
$form.option("priority", "50", "Urgent", "15")
$form.option("priority", "25", "Next release", "15")
$form.option("priority", "15", "Soon", "15")
$form.option("priority", "10", "Before launch", "15")
$form.option("priority", "5", "Post launch", "15")
$form.option("priority", "1", "On the list", "15")
$form.option("priority", "50", "Urgent", $task.priority)
$form.option("priority", "25", "Next release", $task.priority)
$form.option("priority", "15", "Soon", $task.priority)
$form.option("priority", "10", "Before launch", $task.priority)
$form.option("priority", "5", "Post launch", $task.priority)
$form.option("priority", "1", "On the list", $task.priority)
</select>
</font></td></tr>
</td></tr>
<tr><td>Creator:<br>
$form.text("creator", "size='10'", $task.creator)
</td>
<td>&nbsp;</td>
<td>Owner:<br>
#if ($task.owner)
$form.text("owner", "size='10'", $task.owner)
#else
$form.text("owner", "size='10'", "")
#end
</td>
<tr><td colspan="3" align="right" bgcolor="$scolor">
$form.submit("submit", "Update")</td></tr>
</form>
</table>
</td><td valign="top"> <!-- two colum layout table -->
<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>
<textarea name="note" rows="5" cols="50">
</textarea>
</td></tr>
<tr><td align="right" bgcolor="$scolor">
$form.submit("submit", "Add")</td></tr>
</form>
<form action="edit.wm">
$form.fixedHidden("action", "editnotes")
<input type="hidden" name="task" value="$task.taskId">
<tr><td>Notes:<br>
<textarea name="notes" rows="10" cols="50">
#if ($task)
$task.notes
#end
</textarea>
</td></tr>
<tr><td align="right" bgcolor="$scolor">
$form.submit("submit", "Update")</td></tr>
</form>
</table>
</td></tr> <!-- two colum layout table -->
</table>
#import ("/footer.wm")
+20 -13
View File
@@ -13,9 +13,9 @@
#foreach ($otask in $otasks)
#if ($vidx > 0)
<tr><td colspan="3">&nbsp;</td></tr>
<tr><td colspan="4">&nbsp;</td></tr>
#end
<tr><td colspan="3" align="left" bgcolor="$scolor">$otask.name</td></tr>
<tr><td colspan="4" align="left" bgcolor="$scolor">$otask.name</td></tr>
#foreach ($task in $otask.tasks)
<form action="index.wm">
@@ -34,7 +34,9 @@ $form.imageSubmit("submit", "", "images/complete.png", "Mark as completed")
#end
</td>
<td>$task.summary</td>
<td valign="top">$task.category</td></tr>
<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>
</form>
#end
#end
@@ -48,10 +50,10 @@ $form.imageSubmit("submit", "", "images/complete.png", "Mark as completed")
<table cellpadding="2" cellspacing="0" border="0" width="100%">
#foreach ($xtask in $xtasks)
#if ($vidx > 0)
<tr><td colspan="3">&nbsp;</td></tr>
<tr><td colspan="4">&nbsp;</td></tr>
#end
<tr bgcolor="$scolor"><td colspan="2" align="left">$xtask.name</td>
<td>
<td colspan="2">
#if ($xtask.pruned > 0)
<a href="index.wm?expand=$xtask.name">($xtask.pruned ...)</a>
#else
@@ -70,8 +72,14 @@ $form.fixedHidden("task", "$task.taskId")
<tr bgcolor="$rowcolor">
<td>$form.imageSubmit("action", "claim", "images/claim.png", "Claim this task")</td>
<td>$task.summary &nbsp;
<span class="small">[$task.creator]</span></td>
<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">$task.category</td>
<td valign="top"><a href="edit.wm?task=$task.taskId">
<img src="images/edit.png" border="0"></a></td>
</tr>
</form>
#end
@@ -99,7 +107,9 @@ $form.fixedHidden("task", "$task.taskId")
<tr bgcolor="$rowcolor">
<td valign="top" align="center">$task.completion<br>[$task.completor]</td>
<td>$task.summary</td>
<td valign="top">$task.category</td></tr>
<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>
#end
</table>
@@ -117,12 +127,10 @@ $form.fixedHidden("action", "create")
</td></tr>
<tr><td>Category:<br>
<font face="courier">
$form.text("category", "size='10'", "")
</font></td>
</td>
<td>Complexity:<br>
<font face="courier">
<select name="complexity">
$form.option("complexity", "1 - Simple hack", "Simple hack", "1 - Simple hack")
$form.option("complexity", "2 - Minor feature", "Minor feature", "1 - Simple hack")
@@ -130,10 +138,9 @@ $form.text("category", "size='10'", "")
$form.option("complexity", "4 - Subsystem", "Subsystem", "1 - Simple hack")
$form.option("complexity", "5 - Major refactor", "Major refactor", "1 - Simple hack")
</select>
</font></td>
</td>
<td>Priority:<br>
<font face="courier">
<select name="priority">
$form.option("priority", "50", "Urgent", "15")
$form.option("priority", "25", "Next release", "15")
@@ -142,7 +149,7 @@ $form.text("category", "size='10'", "")
$form.option("priority", "5", "Post launch", "15")
$form.option("priority", "1", "On the list", "15")
</select>
</font></td></tr>
</td></tr>
<tr><td colspan="3" align="right" bgcolor="$scolor">
$form.submit("submit", "Create")</td></tr>