Workflow goodness. Tasks are now sorted by priority in the main summary
display, those with priority >= Next release all shown so that project managers can move tasks from Soon or below into the "Next release" priority where developers will see them and "claim" them. git-svn-id: https://samskivert.googlecode.com/svn/trunk@928 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,16 +1,27 @@
|
|||||||
//
|
//
|
||||||
// $Id: Task.java,v 1.4 2002/11/09 02:11:22 mdb Exp $
|
// $Id: Task.java,v 1.5 2002/11/12 22:32:02 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.twodue.data;
|
package com.samskivert.twodue.data;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the basic data associated with a task.
|
* Contains the basic data associated with a task.
|
||||||
*/
|
*/
|
||||||
public class 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 int taskId;
|
||||||
|
|
||||||
public String summary;
|
public String summary;
|
||||||
@@ -33,16 +44,42 @@ public class Task
|
|||||||
|
|
||||||
public String notes;
|
public String notes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts numerical priority to a string.
|
||||||
|
*/
|
||||||
public String getPriorityName ()
|
public String getPriorityName ()
|
||||||
{
|
{
|
||||||
switch (priority) {
|
if (priority > 25) {
|
||||||
case 50: return "Urgent";
|
return "Urgent";
|
||||||
case 25: return "Next release";
|
} else if (priority > 15) {
|
||||||
case 15: return "Soon";
|
return "Next release";
|
||||||
case 10: return "Before launch";
|
} else if (priority > 10) {
|
||||||
case 5: return "Post launch";
|
return "Soon";
|
||||||
case 1: return "On the list";
|
} else if (priority > 5) {
|
||||||
default: return "Unknown";
|
return "Before launch";
|
||||||
|
} else if (priority > 1) {
|
||||||
|
return "Post launch";
|
||||||
|
} 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>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: TaskRepository.java,v 1.3 2002/11/09 01:40:01 mdb Exp $
|
// $Id: TaskRepository.java,v 1.4 2002/11/12 22:32:02 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.twodue.data;
|
package com.samskivert.twodue.data;
|
||||||
|
|
||||||
@@ -126,27 +126,24 @@ public class TaskRepository extends JORARepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads up and returns all unowned, uncompleted tasks, ordered by
|
* Loads up and returns all unowned, uncompleted tasks.
|
||||||
* priority.
|
|
||||||
*/
|
*/
|
||||||
public ArrayList loadTasks ()
|
public ArrayList loadTasks ()
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return loadTasks("where COMPLETOR IS NULL AND OWNER IS NULL " +
|
return loadTasks("where COMPLETOR IS NULL AND OWNER IS NULL");
|
||||||
"ORDER BY PRIORITY DESC");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads up and returns all unowned, uncompleted tasks, whose summary
|
* Loads up and returns all unowned, uncompleted tasks, whose summary
|
||||||
* or category contain the specified string, ordered by priority.
|
* or category contain the specified string.
|
||||||
*/
|
*/
|
||||||
public ArrayList findTasks (String query)
|
public ArrayList findTasks (String query)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return loadTasks("where COMPLETOR IS NULL AND OWNER IS NULL " +
|
return loadTasks("where COMPLETOR IS NULL AND OWNER IS NULL " +
|
||||||
" AND (SUMMARY LIKE '%" + query +
|
" AND (SUMMARY LIKE '%" + query +
|
||||||
"%' OR CATEGORY LIKE '%" + query + "%') " +
|
"%' OR CATEGORY LIKE '%" + query + "%')");
|
||||||
"ORDER BY PRIORITY DESC");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
//
|
//
|
||||||
// $Id: index.java,v 1.3 2002/11/09 01:40:01 mdb Exp $
|
// $Id: index.java,v 1.4 2002/11/12 22:32:02 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.twodue.logic;
|
package com.samskivert.twodue.logic;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import com.samskivert.util.QuickSort;
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.samskivert.servlet.RedirectException;
|
import com.samskivert.servlet.RedirectException;
|
||||||
@@ -89,6 +90,8 @@ public class index extends UserLogic
|
|||||||
|
|
||||||
// load up outstanding tasks and break them down by complexity
|
// load up outstanding tasks and break them down by complexity
|
||||||
String expand = ParameterUtil.getParameter(req, "expand", false);
|
String expand = ParameterUtil.getParameter(req, "expand", false);
|
||||||
|
ctx.put("expand", expand);
|
||||||
|
|
||||||
ArrayList tasks = null;
|
ArrayList tasks = null;
|
||||||
String query = ParameterUtil.getParameter(req, "query", false);
|
String query = ParameterUtil.getParameter(req, "query", false);
|
||||||
if (StringUtil.blank(query)) {
|
if (StringUtil.blank(query)) {
|
||||||
@@ -98,9 +101,12 @@ public class index extends UserLogic
|
|||||||
tasks = app.getRepository().findTasks(query);
|
tasks = app.getRepository().findTasks(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort the tasks by priority, then complexity
|
||||||
|
Collections.sort(tasks, PLEX_PARATOR);
|
||||||
|
|
||||||
CatList[] xtasks = categorize(tasks, expand, new Categorizer() {
|
CatList[] xtasks = categorize(tasks, expand, new Categorizer() {
|
||||||
public String category (Task task) {
|
public String category (Task task) {
|
||||||
return task.complexity;
|
return task.getPriorityName();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ctx.put("xtasks", xtasks);
|
ctx.put("xtasks", xtasks);
|
||||||
@@ -111,6 +117,7 @@ public class index extends UserLogic
|
|||||||
|
|
||||||
// load up owned tasks and break them down by owner
|
// load up owned tasks and break them down by owner
|
||||||
tasks = app.getRepository().loadOwnedTasks();
|
tasks = app.getRepository().loadOwnedTasks();
|
||||||
|
Collections.sort(tasks, PLEX_PARATOR);
|
||||||
CatList[] otasks = categorize(tasks, null, new Categorizer() {
|
CatList[] otasks = categorize(tasks, null, new Categorizer() {
|
||||||
public String category (Task task) {
|
public String category (Task task) {
|
||||||
return task.owner;
|
return task.owner;
|
||||||
@@ -147,6 +154,7 @@ public class index extends UserLogic
|
|||||||
return new CatList[0];
|
return new CatList[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList cats = new ArrayList();
|
||||||
HashMap cmap = new HashMap();
|
HashMap cmap = new HashMap();
|
||||||
int tcount = tasks.size();
|
int tcount = tasks.size();
|
||||||
for (int ii = 0; ii < tcount; ii++) {
|
for (int ii = 0; ii < tcount; ii++) {
|
||||||
@@ -157,23 +165,34 @@ public class index extends UserLogic
|
|||||||
clist = new CatList();
|
clist = new CatList();
|
||||||
clist.name = category;
|
clist.name = category;
|
||||||
clist.tasks = new ArrayList();
|
clist.tasks = new ArrayList();
|
||||||
|
cats.add(clist);
|
||||||
cmap.put(category, clist);
|
cmap.put(category, clist);
|
||||||
}
|
}
|
||||||
if (expand == null || clist.tasks.size() < 2 ||
|
if (expand == null || clist.tasks.size() < 2 ||
|
||||||
expand.equals("all") || expand.equals(category)) {
|
expand.equals("all") ||
|
||||||
|
(task.priority > 15) || expand.equals(category)) {
|
||||||
clist.tasks.add(task);
|
clist.tasks.add(task);
|
||||||
} else {
|
} else {
|
||||||
clist.pruned++;
|
clist.pruned++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CatList[] ctasks = new CatList[cmap.size()];
|
CatList[] ctasks = new CatList[cats.size()];
|
||||||
Iterator iter = cmap.values().iterator();
|
cats.toArray(ctasks);
|
||||||
for (int ii = 0; iter.hasNext(); ii++) {
|
|
||||||
ctasks[ii] = (CatList)iter.next();
|
|
||||||
}
|
|
||||||
QuickSort.sort(ctasks);
|
|
||||||
|
|
||||||
return ctasks;
|
return ctasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sorts tasks by relative complexity, simplest to most complex
|
||||||
|
protected static final Comparator PLEX_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-12
@@ -11,6 +11,11 @@
|
|||||||
Tasks matching '$query':
|
Tasks matching '$query':
|
||||||
#else
|
#else
|
||||||
Outstanding tasks:
|
Outstanding tasks:
|
||||||
|
#if ($expand == "all")
|
||||||
|
<a href="index.wm">[trim]</a>
|
||||||
|
#else
|
||||||
|
<a href="index.wm?expand=all">[show all]</a>
|
||||||
|
#end
|
||||||
#end
|
#end
|
||||||
</b></td></tr>
|
</b></td></tr>
|
||||||
|
|
||||||
@@ -40,7 +45,7 @@ $form.imageSubmit("submit", "", "images/complete.png", "Mark as completed")
|
|||||||
#end
|
#end
|
||||||
</td>
|
</td>
|
||||||
<td>$task.summary</td>
|
<td>$task.summary</td>
|
||||||
<td valign="top">$task.category</td>
|
<td valign="top">$task.getDisplayCategory()</td>
|
||||||
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
||||||
<img src="images/edit.png" border="0"></a></td></tr>
|
<img src="images/edit.png" border="0"></a></td></tr>
|
||||||
</form>
|
</form>
|
||||||
@@ -67,15 +72,15 @@ $form.imageSubmit("submit", "", "images/complete.png", "Mark as completed")
|
|||||||
#end
|
#end
|
||||||
</td></tr>
|
</td></tr>
|
||||||
|
|
||||||
#set ($priority = "")
|
#set ($complexity = "")
|
||||||
|
|
||||||
#foreach ($task in $xtask.tasks)
|
#foreach ($task in $xtask.tasks)
|
||||||
<form action="index.wm">
|
<form action="index.wm">
|
||||||
$form.fixedHidden("task", "$task.taskId")
|
$form.fixedHidden("task", "$task.taskId")
|
||||||
|
|
||||||
#if ($task.getPriorityName() != $priority)
|
#if ($task.complexity != $complexity)
|
||||||
#set ($priority = $task.getPriorityName())
|
#set ($complexity = $task.complexity)
|
||||||
<tr><td colspan="4" class="small">$task.getPriorityName()</td></tr>
|
<tr><td colspan="4" class="small">$task.complexity</td></tr>
|
||||||
#end
|
#end
|
||||||
|
|
||||||
#if ($vidx%2 == 0)
|
#if ($vidx%2 == 0)
|
||||||
@@ -91,7 +96,7 @@ $form.fixedHidden("task", "$task.taskId")
|
|||||||
<a href="detail.wm?task=$task.taskId">[...]</a>
|
<a href="detail.wm?task=$task.taskId">[...]</a>
|
||||||
#end
|
#end
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">$task.category</td>
|
<td valign="top">$task.getDisplayCategory()</td>
|
||||||
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
||||||
<img src="images/edit.png" border="0"></a></td>
|
<img src="images/edit.png" border="0"></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -130,7 +135,7 @@ Filter on single word:<br>
|
|||||||
<tr bgcolor="$rowcolor">
|
<tr bgcolor="$rowcolor">
|
||||||
<td valign="top" align="center">$task.completion<br>[$task.completor]</td>
|
<td valign="top" align="center">$task.completion<br>[$task.completor]</td>
|
||||||
<td>$task.summary</td>
|
<td>$task.summary</td>
|
||||||
<td valign="top">$task.category</td>
|
<td valign="top">$task.getDisplayCategory()</td>
|
||||||
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
<td valign="top"><a href="edit.wm?task=$task.taskId">
|
||||||
<img src="images/edit.png" border="0"></a></td></tr>
|
<img src="images/edit.png" border="0"></a></td></tr>
|
||||||
#end
|
#end
|
||||||
@@ -155,11 +160,11 @@ $form.text("category", "size='10'", "")
|
|||||||
|
|
||||||
<td>Complexity:<br>
|
<td>Complexity:<br>
|
||||||
<select name="complexity">
|
<select name="complexity">
|
||||||
$form.option("complexity", "1 - Simple hack", "Simple hack", "1 - Simple hack")
|
$form.option("complexity", "Simple hack", "Simple hack", "Simple hack")
|
||||||
$form.option("complexity", "2 - Minor feature", "Minor feature", "1 - Simple hack")
|
$form.option("complexity", "Minor feature", "Minor feature", "Simple hack")
|
||||||
$form.option("complexity", "3 - Major feature", "Major feature", "1 - Simple hack")
|
$form.option("complexity", "Major feature", "Major feature", "Simple hack")
|
||||||
$form.option("complexity", "4 - Subsystem", "Subsystem", "1 - Simple hack")
|
$form.option("complexity", "Subsystem", "Subsystem", "Simple hack")
|
||||||
$form.option("complexity", "5 - Major refactor", "Major refactor", "1 - Simple hack")
|
$form.option("complexity", "Major refactor", "Major refactor", "Simple hack")
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user