diff --git a/runtime/twodue/etc/messages.properties b/runtime/twodue/etc/messages.properties index 0eea413d..065af633 100644 --- a/runtime/twodue/etc/messages.properties +++ b/runtime/twodue/etc/messages.properties @@ -1,6 +1,6 @@ # -*- mode: makefile -*- # -# $Id: messages.properties,v 1.5 2003/11/15 22:55:32 mdb Exp $ +# $Id: messages.properties,v 1.6 2003/12/10 20:33:42 mdb Exp $ # # Translation messages for Two Due application @@ -63,3 +63,13 @@ 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. 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 30b87472..b21178a4 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.6 2003/12/10 19:12:31 mdb Exp $ +// $Id: Task.java,v 1.7 2003/12/10 20:33:42 mdb Exp $ package com.samskivert.twodue.data; @@ -82,4 +82,12 @@ public class Task { return StringUtil.replace(category, ",", "
"); } + + /** + * Returns a string representation of this instance. + */ + public String toString () + { + return StringUtil.fieldsToString(this); + } } diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/CatList.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/CatList.java new file mode 100644 index 00000000..44bc39f6 --- /dev/null +++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/CatList.java @@ -0,0 +1,87 @@ +// +// $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; + } +} diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/UserLogic.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/UserLogic.java index 359a5119..5cbbdceb 100644 --- a/runtime/twodue/src/java/com/samskivert/twodue/logic/UserLogic.java +++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/UserLogic.java @@ -1,5 +1,5 @@ // -// $Id: UserLogic.java,v 1.1 2002/11/08 09:14:21 mdb Exp $ +// $Id: UserLogic.java,v 1.2 2003/12/10 20:33:42 mdb Exp $ package com.samskivert.twodue.logic; @@ -33,6 +33,7 @@ public abstract class UserLogic implements Logic { TwoDueApp tdapp = (TwoDueApp)app; User user = tdapp.getUserManager().requireUser(ctx.getRequest()); + ctx.put("username", user.username); invoke(ctx, tdapp, user); } } diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/bulkedit.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/bulkedit.java new file mode 100644 index 00000000..4ecc27e6 --- /dev/null +++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/bulkedit.java @@ -0,0 +1,107 @@ +// +// $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; + } + } + }; +} diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/bycategory.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/bycategory.java index 0043acf7..d9fb49c1 100644 --- a/runtime/twodue/src/java/com/samskivert/twodue/logic/bycategory.java +++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/bycategory.java @@ -1,5 +1,5 @@ // -// $Id: bycategory.java,v 1.1 2003/11/15 22:55:32 mdb Exp $ +// $Id: bycategory.java,v 1.2 2003/12/10 20:33:42 mdb Exp $ package com.samskivert.twodue.logic; @@ -37,10 +37,6 @@ public class bycategory extends UserLogic 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)) { diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/detail.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/detail.java index 4284018a..e0e56e5e 100644 --- a/runtime/twodue/src/java/com/samskivert/twodue/logic/detail.java +++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/detail.java @@ -1,5 +1,5 @@ // -// $Id: detail.java,v 1.2 2003/01/23 21:22:56 mdb Exp $ +// $Id: detail.java,v 1.3 2003/12/10 20:33:42 mdb Exp $ package com.samskivert.twodue.logic; @@ -28,10 +28,6 @@ public class detail extends UserLogic 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) { 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 a1aebcb2..7fc9af76 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.11 2003/11/15 22:55:32 mdb Exp $ +// $Id: index.java,v 1.12 2003/12/10 20:33:42 mdb Exp $ package com.samskivert.twodue.logic; @@ -37,10 +37,6 @@ public class index extends UserLogic ctx.put("error", msg); } - // we use this to determine whether to show "complete" buttons for - // tasks - ctx.put("username", user.username); - // if they've submitted the form, we create a new task and stick // it into the dataabse if (ParameterUtil.parameterEquals(req, "action", "create")) { diff --git a/runtime/twodue/src/java/com/samskivert/twodue/logic/tasks.java b/runtime/twodue/src/java/com/samskivert/twodue/logic/tasks.java index 84290fd0..0e4f8cc0 100644 --- a/runtime/twodue/src/java/com/samskivert/twodue/logic/tasks.java +++ b/runtime/twodue/src/java/com/samskivert/twodue/logic/tasks.java @@ -1,5 +1,5 @@ // -// $Id: tasks.java,v 1.2 2003/12/10 19:39:26 mdb Exp $ +// $Id: tasks.java,v 1.3 2003/12/10 20:33:42 mdb Exp $ package com.samskivert.twodue.logic; @@ -37,10 +37,6 @@ public class tasks extends UserLogic 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)) { diff --git a/runtime/twodue/web/bulkedit.wm b/runtime/twodue/web/bulkedit.wm new file mode 100644 index 00000000..4998a626 --- /dev/null +++ b/runtime/twodue/web/bulkedit.wm @@ -0,0 +1,81 @@ +#set ($title = $i18n.xlate("bulkedit.title")) +#import ("/header.wm") + +

+ + + + + + + +
Task summary By category  +
+Priority: + +$form.submit("submit", "Go") +
+
+ +

+ + +Outstanding tasks: + + +

+$form.hidden("priority", $priority) +$form.hidden("action", "update") +#if ($data.length($xtasks) > 0) +#foreach ($xtask in $xtasks) + + +$xcats.clear() +#foreach ($task in $xtask.tasks) +#set ($id = $task.taskId) + + + + + + + + + + + +#end +
+Claim this task$task.summary   +[$task.creator] +#if (!$string.blank($task.notes)) +  [...] +#end +$form.text("category$id", "size='10'", $task.category) + +Edit this task
+#end +#else +

$i18n.xlate("bulkedit.no_tasks") +#end + +

$form.submit("submit", "Update")
+
+ +#import ("/footer.wm")