diff --git a/runtime/twodue/etc/messages.properties b/runtime/twodue/etc/messages.properties index 0d9eb334..aed2c177 100644 --- a/runtime/twodue/etc/messages.properties +++ b/runtime/twodue/etc/messages.properties @@ -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 diff --git a/runtime/twodue/src/java/com/samskivert/twodue/data/Task.java b/runtime/twodue/src/java/com/samskivert/twodue/data/Task.java index c67656e0..78ae89a1 100644 --- a/runtime/twodue/src/java/com/samskivert/twodue/data/Task.java +++ b/runtime/twodue/src/java/com/samskivert/twodue/data/Task.java @@ -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; } diff --git a/runtime/twodue/src/java/com/samskivert/twodue/data/TaskRepository.java b/runtime/twodue/src/java/com/samskivert/twodue/data/TaskRepository.java index 07fdcb64..58bb1c3a 100644 --- a/runtime/twodue/src/java/com/samskivert/twodue/data/TaskRepository.java +++ b/runtime/twodue/src/java/com/samskivert/twodue/data/TaskRepository.java @@ -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; } }); } diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/detail.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/detail.java new file mode 100644 index 00000000..1c44b5f8 --- /dev/null +++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/detail.java @@ -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("
\n");
+ }
+
+ if (line.equals("\n")) {
+ if (!eatnewline) {
+ fnotes.append("\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("
");
+ }
+ if (sawexcept) {
+ excepting = true;
+ }
+ }
+ return fnotes.toString();
+ }
+}
diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/edit.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/edit.java
new file mode 100644
index 00000000..90cb771c
--- /dev/null
+++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/edit.java
@@ -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");
+ }
+ }
+}
diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/index.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/index.java
index ab0cef3e..028b0070 100644
--- a/runtime/twodue/src/java/com/samskivert/twodue/logic/index.java
+++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/index.java
@@ -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
diff --git a/runtime/twodue/src/sql/tasks-schema.sql b/runtime/twodue/src/sql/tasks-schema.sql
index bf7ca300..8ab5d807 100644
--- a/runtime/twodue/src/sql/tasks-schema.sql
+++ b/runtime/twodue/src/sql/tasks-schema.sql
@@ -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.
*/
diff --git a/runtime/twodue/web/detail.wm b/runtime/twodue/web/detail.wm
new file mode 100644
index 00000000..78d4ecba
--- /dev/null
+++ b/runtime/twodue/web/detail.wm
@@ -0,0 +1,43 @@
+#set ($title = $i18n.xlate("detail.title"))
+#import ("/header.wm")
+
++ +
| $task.complexity |
-

| $xtask.name | -+ | #if ($xtask.pruned > 0) ($xtask.pruned ...) #else @@ -70,8 +72,14 @@ $form.fixedHidden("task", "$task.taskId") | ||
| $form.imageSubmit("action", "claim", "images/claim.png", "Claim this task") | $task.summary -[$task.creator] | +[$task.creator] +#if (!$string.blank($task.notes)) + [...] +#end +$task.category | +
+![]() |
|
| $task.completion [$task.completor] |
$task.summary | -$task.category | $task.category | +
+![]() |
#end