Definition of todomgr_overview

Previous: Definition of todomgr_show ] [ Top: To-do manager ] [ Next: Definition of todomgr_update ]

The overview URL is used for reporting and listing of tasks. This is the most complicated function in the application, because there are lots of interesting ways to sort and filter tasks. The two input values which control which report we'll generate are filter and order. The filter parameter sets a default order, and can take the following values:
FilterDefault orderWhat it shows
active (the default)priority Shows all outstanding active tasks.
scheduledschedule Shows only tasks for which scheduling information has been entered.
todayschedule Same as schedule, but includes only those tasks for which the scheduled time is sometime today.
completeprocess Shows all completed tasks.
fullprocess Shows everything in the task list.
The order parameter which the above makes use of selects among the following orders:
OrderDatabase orderWhat it's used for
prioritypriority desc, created Shows tasks in descending priority order.
schedulesched_date, sched_time Shows tasks in order of scheduled time.
processprocess.title, created Shows tasks in order of process, then creation time within the process.
So let's figure out all that first:
 
global todomgr_pool
set db [ns_db gethandle $todomgr_pool]
See Checking authuser

set form [ns_conn form $conn]
if {$form == ""} {
   set form [ns_set create]
   set filter active
   set order priority
} else {
   set filter [ns_set get $form filter]

   set order [ns_set get $form order]
   if ![string compare $order ""] {
      switch -- $filter {
         active { set order priority }
         scheduled { set order schedule }
         complete { set order process }
         full { set order process }
         default { set order priority }
      }
   }
}
The default filter is active -- except in the case of the process home, where I think the default should be full (i.e. show all tasks, whether active, rejected, or complete.) Let's make that behavior explicit.
 
set process [ns_set get $form process]
if ![string compare $filter ""] {
   if [string compare $process ""] {
      set filter full
   } else {
      set filter active
   }
}
OK, at this point we know at least what we're doing. Let's go ahead and translate our filter and order parameters into actual where and order by clauses suitable for building our query. set process [ns_set get $form process]
 
switch -- $filter {
   active    { set where "and task.status='active'" }
   scheduled { set where "and not sched_date is null" }
   complete  { set where "and task.status='complete'" }
   full      { set where "" }
   default   { set where "and task.status='active'" }
}

switch -- $order {
   priority { set orderby "order by priority desc, created" }
   schedule { set orderby "order by sched_date, sched_time, created" }
   process  { set orderby "order by title, created" }
   default  { set orderby "order by created" }
}

switch -- $filter {
   active    { set tags(title) "To do" }
   scheduled { set tags(title) "To do on date" }
   complete  { set tags(title) "Completed tasks" }
   full      { set tags(title) "All tasks" }
   default   { set tags(title) "To do" }
}
The who parameter selects the user or users for which we'll be displaying tasks. Default is the login user. For all tasks, use who=all
 
set who [ns_set get $form who]
if ![string compare $who ""] { set who $user }
if [string compare $who all] {
   append where " and task.owner='[sql_safe_string $who]'"
}
If there is a process named in the process then this is a process home page we're displaying. In this case, we restrict the task list to tasks with this process, and we also display process information (process description and owner contact info.)
 
if [string compare $process ""] {
   set prow [ns_db select $db "select * from process where id='[sql_safe_string $process]'"]
   if ![ns_db getrow $db $prow] {
      set tags(title) "Process not found"
      set tags(body) "The process $process couldn't be found in the database."
      return [todomgr_pageout $conn message.html]
   }
   foreach field {title description owner} { set tags($field) [ns_set get $prow $field] }

   See Getting owner info for task/process display

   if ![string compare $tags(owner) $user] {
      set tags(modlink) "show?process=$process"
      append tags(modlink) "&back=[ns_urlencode [ns_conn url $conn]?[ns_conn query $conn]]"
      set tags(requestlink) "create?what=task&process=$process"
      append tags(requestlink) "&back=[ns_urlencode [ns_conn url $conn]?[ns_conn query $conn]]"
   } else {
      set    query "select flags from keyword, permission "
      append query   "where keyword.process='[sql_safe_string $process]' "
      append query     "and keyword.keyword=permission.keyword "
      append query     "and permission.userid='[sql_safe_string $user]'"
      set tags(requestlink) ""
      if ![catch {set row [ns_db select $db $query]} result] {
         while {[ns_db getrow $db $row]} {
            if [string match *t* [ns_set get $row flags]] {
               set tags(requestlink) "create?what=task&process=$process"
               append tags(requestlink) "&back=[ns_urlencode [ns_conn url $conn]?[ns_conn query $conn]]"
            }
         }
      }
   }

   append where " and task.process='[sql_safe_string $process]'"
   set tags(process) $process
}
Now let's go ahead and build our query. Since we're working with PostgreSQL, we can't do an outer join to get process information only when tasks are associated with processes; instead, we are forced to build two selects and join them with a union.
 
set query "
select task.*, text '' as title from task where process is null $where
union
select task.*, process.title as title from task, process where task.process=process.id $where
$orderby"
The header is easy to build, with the caveat that I only want a Priority column if I'm looking at priority. Otherwise it's just clutter.
 
set tags(header) "<tr bgcolor=\"cccccc\"><td>Task</td><td>Owner</td>"
set cols 3
if ![string compare $process ""] {
   append tags(header) "<td>Process</td>"
   incr cols
}
if {$order == "priority"} {
   append tags(header) "<td>Priority</td>"
   incr cols
}

if {$filter == "scheduled"} {
   append tags(header) "<td>Scheduled</td>"
} else {
   append tags(header) "<td>Created</td>"
}

if {$filter == "full"} {
   append tags(header) "<td>Status</td>"
}

append tags(header) "</tr>\n"
Let's build a quick back link (this can be passed to the show screens to allow us to return to the current list after doing something with a task.) This handoff technique is something I've always thought was kind of a kludge, but it works in situations where you have different URLs doing different tasks and they all have to work togther (a more structured flow of control than your standard database-search paradigm.)
 
set back "[ns_conn url $conn]"
if [string compare "" [ns_conn query $conn]] { append back "?[ns_conn query $conn]" }
set back [ns_urlencode $back]
And now we get to the meat of the routine. We submit the query, and organize the rows as they come back. The formatting of the rows is unfortunately embedded in the code instead of being specified in the template file. I guess I could get around that with style sheets, but I just don't use them very often. This would be a dandy thing to come back to later, after the application is basically working.

The rows variable keeps track of whether we're in an even or odd row, so that we can make the table stripey. I do like those stripey tables.
 
set rows 0
set tags(table) ""
if ![catch {set row [ns_db select $db $query]} result] {
   while {[ns_db getrow $db $row]} {
      append tags(table) "<tr bgcolor=\""
      if [expr $rows % 2] {
         append tags(table) eeeeee
      } else {
         append tags(table) ffffff
      }
      append tags(table) "\">"
      append tags(table) "<td><a href=\"show?task=[ns_set get $row id]&back=$back\">"
      if [string compare "" [ns_set get $row description]] {
         append tags(table) [ns_set get $row description]
      } else {
         append tags(table) [ns_set get $row id]
      }
      append tags(table) "</a></td>"
      append tags(table) "<td>[ns_set get $row owner]</td>"
      if ![string compare $process ""] {
         if {[ns_set get $row process] != ""} {
            append tags(table) "<td>"
            append tags(table) "<a href=\"overview?process=[ns_set get $row process]&who=all&filter=active\">"
            append tags(table) "[ns_set get $row title]</a></td>"
         } else {
            append tags(table) "<td>&nbsp;</td>"
         }
      }
      if {$order == "priority"} {
         set p [ns_set get $row priority]
         if {$p == ""} { set p 1 }
         append tags(table) "<td><center>"
         append tags(table) "<a href=update?task=[ns_set get $row id]"
         append tags(table) "&priority=[expr $p + 1]&back=$back>up</a> "
         append tags(table) "$p "
         if {$p < 2} {
            append tags(table) "dn"
         } else {
            append tags(table) "<a href=update?task=[ns_set get $row id]"
            append tags(table) "&priority=[expr $p - 1]&back=$back>dn</a> "
         }
         append tags(table) "</center></td>"
      }
      if {$filter == "scheduled"} {
         append tags(table) "<td>[ns_set get $row sched_date] [ns_set get $row sched_time]</td>"
      } else {
         append tags(table) "<td>[ns_set get $row created]</td>"
      }
      if {$filter == "full"} {
         append tags(table) "<td><i>[ns_set get $row status]</i></td>"
      }
      append tags(table) "</tr>\n"
      incr rows
   }
}

if {$rows == 0} {
   set tags(table) "<tr><td colspan=$cols><i>No tasks found</i></td></tr>\n"
}

if [string compare $process ""] {
   set tags(backhere) "[ns_conn url $conn]?[ns_conn query $conn]"
   set tags(processdata) [datasheet_showdata view "" $process ""]
   todomgr_pageout $conn processhome.html
} else {
   todomgr_pageout $conn overview.html
}

Previous: Definition of todomgr_show ] [ Top: To-do manager ] [ Next: Definition of todomgr_update ]


This code and documentation are released under the terms of the GNU license. They are additionally copyright (c) 2000, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license.