diff --git a/bootstrap.php b/bootstrap.php
index cae6611cd72c486129c81d70afa70205cae921ee..a49d8dcd98530af5842123898776108b9411c606 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -103,7 +103,8 @@ class Bootstrap {
         define('TICKET_STATUS_TABLE', $prefix.'ticket_status');
         define('TICKET_PRIORITY_TABLE',$prefix.'ticket_priority');
 
-        define('TASK_TABLE',$prefix.'task');
+        define('TASK_TABLE', $prefix.'task');
+        define('TASK_CDATA_TABLE', $prefix.'task__cdata');
 
         define('PRIORITY_TABLE',TICKET_PRIORITY_TABLE);
 
diff --git a/include/ajax.tasks.php b/include/ajax.tasks.php
index cb6728a2dbd0eee8245c2050184e4cb1c795cffe..31671f9e11043976f9a3113446b5efa65bbf5884 100644
--- a/include/ajax.tasks.php
+++ b/include/ajax.tasks.php
@@ -54,6 +54,175 @@ class TasksAjaxAPI extends AjaxController {
         include STAFFINC_DIR . 'templates/task-edit.tmpl.php';
     }
 
+    function massProcess($action)  {
+        global $thisstaff;
+
+        $actions = array(
+                'transfer' => array(
+                    'verbed' => __('transferred'),
+                    ),
+                'assign' => array(
+                    'verbed' => __('assigned'),
+                    ),
+                'delete' => array(
+                    'verbed' => __('deleted'),
+                    ),
+                );
+
+        if (!isset($actions[$action]))
+            Http::response(404, __('Unknown action'));
+
+
+        $errors = $e = array();
+        $inc = null;
+        $i = $count = 0;
+        if ($_POST) {
+            if (!$_POST['tids'] || !($count=count($_POST['tids'])))
+                $errors['err'] = sprintf(
+                        __('You must select at least %s.'),
+                        __('one task'));
+        } else {
+            $count  =  $_REQUEST['count'];
+        }
+
+        switch ($action) {
+        case 'assign':
+            $inc = 'task-assign.tmpl.php';
+            if ($_POST && !$errors) {
+                if (!isset($_POST['staff_id']) || !is_numeric($_POST['staff_id']))
+                    $errors['staff_id'] = __('Assignee selection required');
+                else {
+                    foreach ($_POST['tids'] as $tid) {
+                        if (($t=Task::lookup($tid))
+                                && $t->getDeptId() != $_POST['dept_id']
+                                // Make sure the agent is allowed to
+                                // access and assign the task.
+                                && $t->checkStaffPerm($thisstaff, Task::PERM_ASSIGN)
+                                // Do the transfer
+                                && $t->assign($_POST, $e)
+                                )
+                            $i++;
+                    }
+
+                    if (!$i) {
+                        $info['error'] = sprintf(
+                                __('Unable to %1$s %2$s'),
+                                __('assign'),
+                                _N('selected task', 'selected tasks', $count));
+                    }
+                }
+            }
+            break;
+        case 'transfer':
+            $inc = 'task-transfer.tmpl.php';
+            if ($_POST && !$errors) {
+                if (!isset($_POST['dept_id']) || !is_numeric($_POST['dept_id']))
+                    $errors['dept_id'] = __('Department selection required');
+                else {
+                    foreach ($_POST['tids'] as $tid) {
+                        if (($t=Task::lookup($tid))
+                                && $t->getDeptId() != $_POST['dept_id']
+                                // Make sure the agent is allowed to
+                                // access and transfer the task.
+                                && $t->checkStaffPerm($thisstaff, Task::PERM_TRANSFER)
+                                // Do the transfer
+                                && $t->transfer($_POST, $e)
+                                )
+                            $i++;
+                    }
+
+                    if (!$i) {
+                        $info['error'] = sprintf(
+                                __('Unable to %1$s %2$s'),
+                                __('transfer'),
+                                _N('selected task', 'selected tasks', $count));
+                    }
+                }
+            }
+            break;
+        case 'delete':
+            $inc = 'task-delete.tmpl.php';
+            $info[':placeholder'] = sprintf(__(
+                        'Optional reason for deleting %s'),
+                    _N('selected task', 'selected tasks', $count));
+            $info['warn'] = sprintf(__(
+                        'Are you sure you want to DELETE %s?'),
+                    _N('selected task', 'selected tasks', $count));
+            $info[':extra'] = sprintf('<strong>%s</strong>',
+                        __('Deleted tasks CANNOT be recovered, including any associated attachments.')
+                        );
+
+            if ($_POST && !$errors) {
+                foreach ($_POST['tids'] as $tid) {
+                    if (($t=Task::lookup($tid))
+                            && $t->getDeptId() != $_POST['dept_id']
+                            && $t->checkStaffPerm($thisstaff, Task::PERM_DELETE)
+                            && $t->delete($_POST, $e)
+                            )
+                        $i++;
+                }
+
+                if (!$i) {
+                    $info['error'] = sprintf(
+                            __('Unable to %1$s %2$s'),
+                            __('delete'),
+                            _N('selected task', 'selected tasks', $count));
+                }
+            }
+            break;
+        default:
+            Http::response(404, __('Unknown action'));
+        }
+
+
+        if ($_POST && $i) {
+
+            // Assume success
+            if ($i==$count) {
+                $msg = sprintf(__('Successfully %s %s.'),
+                        $actions[$action]['verbed'],
+                        sprintf(__('%1$d %2$s'),
+                            $count,
+                            _N('selected task', 'selected tasks', $count))
+                        );
+                $_SESSION['::sysmsgs']['msg'] = $msg;
+            } else {
+                $warn = sprintf(
+                        __('%1$d of %2$d %3$s %4$s'), $i, $count,
+                        _N('selected task', 'selected tasks',
+                            $count),
+                        $actions[$action]['verbed']);
+                $_SESSION['::sysmsgs']['warn'] = $warn;
+            }
+            Http::response(201, 'processed');
+        } elseif($_POST && !isset($info['error'])) {
+            $info['error'] = $errors['err'] ?: sprintf(
+                    __('Unable to %1$s  %2$s'),
+                    $actions[$action]['verbed'],
+                    _N('selected task', 'selected tasks', $count));
+        }
+
+        if ($_POST)
+            $info = array_merge($info, Format::htmlchars($_POST));
+
+
+        include STAFFINC_DIR . "templates/$inc";
+        //  Copy checked tasks to the form.
+        echo "
+        <script type=\"text/javascript\">
+        $(function() {
+            $('form#tasks input[name=\"tids[]\"]:checkbox:checked')
+            .each(function() {
+                $('<input>')
+                .prop('type', 'hidden')
+                .attr('name', 'tids[]')
+                .val($(this).val())
+                .appendTo('form.mass-action');
+            });
+        });
+        </script>";
+    }
+
     function transfer($tid) {
         global $thisstaff;
 
@@ -63,40 +232,75 @@ class TasksAjaxAPI extends AjaxController {
         if (!$task->checkStaffPerm($thisstaff, Task::PERM_TRANSFER))
             Http::response(403, __('Permission Denied'));
 
-        $info = $errors = array();
+        $errors = array();
+
+        $info = array(
+                ':title' => sprintf(__('Task #%s: %s'),
+                    $task->getNumber(),
+                    __('Tranfer')),
+                ':action' => sprintf('#tasks/%d/transfer',
+                    $task->getId())
+                );
+
         if ($_POST) {
-            if ($task->transfer($_POST,  $errors)) {
+            if ($task->transfer($_POST, $errors)) {
+                $_SESSION['::sysmsgs']['msg'] = sprintf(
+                        __('%s successfully'),
+                        sprintf(
+                            __('%s transferred to %s department'),
+                            __('Task'),
+                            $task->getDept()
+                            )
+                        );
                 Http::response(201, $task->getId());
-
             }
 
-            $info = Format::htmlchars($_POST);
+            $info = array_merge($info, Format::htmlchars($_POST));
             $info['error'] = $errors['err'] ?: __('Unable to transfer task');
         }
 
+        $info['dept_id'] = $info['dept_id'] ?: $task->getDeptId();
+
         include STAFFINC_DIR . 'templates/task-transfer.tmpl.php';
     }
 
     function assign($tid) {
         global $thisstaff;
 
-        if(!($task=Task::lookup($tid)))
+        if (!($task=Task::lookup($tid)))
             Http::response(404, __('No such task'));
 
         if (!$task->checkStaffPerm($thisstaff, Task::PERM_ASSIGN))
             Http::response(403, __('Permission Denied'));
 
-        $info = $errors = array();
+        $errors = array();
+        $info = array(
+                ':title' => sprintf(__('Task #%s: %s'),
+                    $task->getNumber(),
+                    $task->isAssigned() ? __('Reassign') :  __('Assign')),
+                ':action' => sprintf('#tasks/%d/assign',
+                    $task->getId()),
+                );
         if ($_POST) {
             if ($task->assign($_POST,  $errors)) {
-                Http::response(201, $task->getId());
+                $_SESSION['::sysmsgs']['msg'] = sprintf(
+                        __('%s successfully'),
+                        sprintf(
+                            __('%s assigned to %s'),
+                            __('Task'),
+                            $task->getStaff()
+                            )
+                        );
 
+                Http::response(201, $task->getId());
             }
 
-            $info = Format::htmlchars($_POST);
+            $info = array_merge($info, Format::htmlchars($_POST));
             $info['error'] = $errors['err'] ?: __('Unable to assign task');
         }
 
+        $info['staff_id'] = $info['staff_id'] ?: $task->getStaffId();
+
         include STAFFINC_DIR . 'templates/task-assign.tmpl.php';
     }
 
@@ -109,23 +313,34 @@ class TasksAjaxAPI extends AjaxController {
         if (!$task->checkStaffPerm($thisstaff, Task::PERM_DELETE))
             Http::response(403, __('Permission Denied'));
 
-        $info = $errors = array();
+        $errors = array();
+        $info = array(
+                ':title' => sprintf(__('Task #%s: %s'),
+                    $task->getNumber(),
+                    __('Delete')),
+                ':action' => sprintf('#tasks/%d/delete',
+                    $task->getId()),
+                );
+
         if ($_POST) {
             if ($task->delete($_POST,  $errors)) {
+                $_SESSION['::sysmsgs']['msg'] = sprintf(
+                            __('%s #%s deleted successfully'),
+                            __('Task'),
+                            $task->getNumber(),
+                            $task->getDept());
                 Http::response(201, 0);
-
             }
-
-            $info = Format::htmlchars($_POST);
+            $info = array_merge($info, Format::htmlchars($_POST));
             $info['error'] = $errors['err'] ?: __('Unable to delete task');
         }
-        $info['placeholder'] = sprintf(__(
+        $info[':placeholder'] = sprintf(__(
                     'Optional reason for deleting %s'),
                 __('this task'));
         $info['warn'] = sprintf(__(
                     'Are you sure you want to DELETE %s?'),
                     __('this task'));
-        $info['extra'] = sprintf('<strong>%s</strong>',
+        $info[':extra'] = sprintf('<strong>%s</strong>',
                     __('Deleted tasks CANNOT be recovered, including any associated attachments.')
                     );
 
diff --git a/include/class.nav.php b/include/class.nav.php
index 6dee08171b05fbf4c7fb7c6eb7658980b89c641a..c5c296d4733cfb17ec4cde98e795e1ecbe4ce547 100644
--- a/include/class.nav.php
+++ b/include/class.nav.php
@@ -123,7 +123,9 @@ class StaffNav {
                     'desc' => __('Users'), 'href' => 'users.php', 'title' => __('User Directory')
                 );
             }
+            $this->tabs['tasks'] = array('desc'=>__('Tasks'), 'href'=>'tasks.php', 'title'=>__('Task Queue'));
             $this->tabs['tickets'] = array('desc'=>__('Tickets'),'href'=>'tickets.php','title'=>__('Ticket Queue'));
+
             $this->tabs['kbase'] = array('desc'=>__('Knowledgebase'),'href'=>'kb.php','title'=>__('Knowledgebase'));
             if (count($this->getRegisteredApps()))
                 $this->tabs['apps']=array('desc'=>__('Applications'),'href'=>'apps.php','title'=>__('Applications'));
@@ -140,6 +142,9 @@ class StaffNav {
         foreach($this->getTabs() as $k=>$tab){
             $subnav=array();
             switch(strtolower($k)){
+                case 'tasks':
+                    $subnav[]=array('desc'=>__('Tasks'), 'href'=>'tasks.php', 'iconclass'=>'Ticket', 'droponly'=>true);
+                    break;
                 case 'tickets':
                     $subnav[]=array('desc'=>__('Tickets'),'href'=>'tickets.php','iconclass'=>'Ticket', 'droponly'=>true);
                     if($staff) {
diff --git a/include/class.staff.php b/include/class.staff.php
index 9e093d7fcc93dcf349b1761f1bacd1a77ef2d839..bcd3ed16f3f2c111d033a6ccd1df2cf39d674795 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -490,6 +490,22 @@ implements AuthenticatedUser, EmailContact, TemplateVariable {
         return ($stats=$this->getTicketsStats())?$stats['closed']:0;
     }
 
+    function getTasksStats() {
+
+        if (!$this->stats['tasks'])
+            $this->stats['tasks'] = Task::getStaffStats($this);
+
+        return  $this->stats['tasks'];
+    }
+
+    function getNumAssignedTasks() {
+        return ($stats=$this->getTasksStats()) ? $stats['assigned'] : 0;
+    }
+
+    function getNumClosedTasks() {
+        return ($stats=$this->getTasksStats()) ? $stats['closed'] : 0;
+    }
+
     function getExtraAttr($attr=false, $default=null) {
         if (!isset($this->_extra) && isset($this->extra))
             $this->_extra = JsonDataParser::decode($this->extra);
diff --git a/include/class.task.php b/include/class.task.php
index a39c28a00ceecbc306086a94bf0afe3dba85c4df..599be600983e6d6109d37b9bbf9724e88200c85e 100644
--- a/include/class.task.php
+++ b/include/class.task.php
@@ -33,6 +33,22 @@ class TaskModel extends VerySimpleModel {
                 'constraint' => array('staff_id' => 'Staff.staff_id'),
                 'null' => true,
             ),
+            'team' => array(
+                'constraint' => array('team_id' => 'Team.team_id'),
+                'null' => true,
+            ),
+            'thread' => array(
+                'constraint' => array(
+                    'id'  => 'ThreadModel.object_id',
+                    "'A'" => 'ThreadModel.object_type',
+                ),
+                'list' => false,
+                'null' => false,
+            ),
+            'cdata' => array(
+                'constraint' => array('id' => 'TaskCData.task_id'),
+                'list' => false,
+            ),
         ),
     );
 
@@ -104,14 +120,26 @@ class TaskModel extends VerySimpleModel {
         return $this->staff_id;
     }
 
+    function getStaff() {
+        return $this->staff;
+    }
+
     function getTeamId() {
         return $this->team_id;
     }
 
+    function getTeam() {
+        return $this->team;
+    }
+
     function getDeptId() {
         return $this->dept_id;
     }
 
+    function getDept() {
+        return $this->dept;
+    }
+
     function getCreateDate() {
         return $this->created;
     }
@@ -156,11 +184,10 @@ RolePermission::register(/* @trans */ 'Tasks', TaskModel::getPermissions());
 class Task extends TaskModel {
     var $form;
     var $entry;
-    var $thread;
 
+    var $_thread;
     var $_entries;
 
-
     function getStatus() {
         return $this->isOpen() ? _('Open') : _('Closed');
     }
@@ -202,7 +229,7 @@ class Task extends TaskModel {
             $assignees[] = $this->staff->getName();
 
         //Add team assignment
-        if (isset($this->team))
+        if ($this->team)
             $assignees[] = $this->team->getName();
 
         return $assignees;
@@ -216,13 +243,14 @@ class Task extends TaskModel {
 
     function getThread() {
 
-        if (!$this->thread)
-            $this->thread = TaskThread::lookup(array(
+        //FIXME: use $this->thread once thread classes get ORMed.
+        if (!$this->_thread)
+            $this->_thread = TaskThread::lookup(array(
                         'object_id' => $this->getId(),
                         'object_type' => ObjectModel::OBJECT_TYPE_TASK)
                     );
 
-        return $this->thread;
+        return $this->_thread;
     }
 
     function getThreadEntry($id) {
@@ -360,7 +388,8 @@ class Task extends TaskModel {
             return false;
 
         // Transfer completed... post internal note.
-        $title = sprintf(__('Task transfered to %s department'),
+        $title = sprintf(__('%s transferred to %s department'),
+                __('Task'),
                 $dept->getName());
         if ($vars['comments']) {
             $note = $vars['comments'];
@@ -496,8 +525,79 @@ class Task extends TaskModel {
             }
         }
     }
+
+    /* Quick staff's stats */
+    static function getStaffStats($staff) {
+        global $cfg;
+
+        /* Unknown or invalid staff */
+        if (!$staff
+                || (!is_object($staff) && !($staff=Staff::lookup($staff)))
+                || !$staff->isStaff())
+            return null;
+
+        $where = array('(task.staff_id='.db_input($staff->getId())
+                    .sprintf(' AND task.flags & %d != 0 ', TaskModel::ISOPEN)
+                    .') ');
+        $where2 = '';
+
+        if(($teams=$staff->getTeams()))
+            $where[] = ' ( flags.team_id IN('.implode(',', db_input(array_filter($teams)))
+                        .') AND '
+                        .sprintf('task.flags & %d != 0 ', TaskModel::ISOPEN)
+                        .')';
+
+        if(!$staff->showAssignedOnly() && ($depts=$staff->getDepts())) //Staff with limited access just see Assigned tickets.
+            $where[] = 'task.dept_id IN('.implode(',', db_input($depts)).') ';
+
+        $where = implode(' OR ', $where);
+        if ($where) $where = 'AND ( '.$where.' ) ';
+
+        $sql =  'SELECT \'open\', count(task.id ) AS tasks '
+                .'FROM ' . TASK_TABLE . ' task '
+                . sprintf(' WHERE task.flags & %d != 0 ', TaskModel::ISOPEN)
+                . $where . $where2
+
+                .'UNION SELECT \'overdue\', count( task.id ) AS tasks '
+                .'FROM ' . TASK_TABLE . ' task '
+                . sprintf(' WHERE task.flags & %d != 0 ', TaskModel::ISOPEN)
+                . sprintf(' AND task.flags & %d != 0 ', TaskModel::ISOVERDUE)
+                . $where
+
+                .'UNION SELECT \'assigned\', count( task.id ) AS tasks '
+                .'FROM ' . TASK_TABLE . ' task '
+                . sprintf(' WHERE task.flags & %d != 0 ', TaskModel::ISOPEN)
+                .'AND task.staff_id = ' . db_input($staff->getId()) . ' '
+                . $where
+
+                .'UNION SELECT \'closed\', count( task.id ) AS tasks '
+                .'FROM ' . TASK_TABLE . ' task '
+                . sprintf(' WHERE task.flags & %d = 0 ', TaskModel::ISOPEN)
+                . $where;
+
+        $res = db_query($sql);
+        $stats = array();
+        while ($row = db_fetch_row($res))
+            $stats[$row[0]] = $row[1];
+
+        return $stats;
+    }
+}
+
+
+class TaskCData extends VerySimpleModel {
+    static $meta = array(
+        'pk' => array('task_id'),
+        'table' => TASK_CDATA_TABLE,
+        'joins' => array(
+            'task' => array(
+                'constraint' => array('task_id' => 'TaskModel.task_id'),
+            ),
+        ),
+    );
 }
 
+
 class TaskForm extends DynamicForm {
     static $instance;
     static $defaultForm;
@@ -505,6 +605,12 @@ class TaskForm extends DynamicForm {
 
     static $forms;
 
+    static $cdata = array(
+            'table' => TASK_CDATA_TABLE,
+            'object_id' => 'task_id',
+            'object_type' => 'A',
+        );
+
     static function objects() {
         $os = parent::objects();
         return $os->filter(array('type'=>ObjectModel::OBJECT_TYPE_TASK));
diff --git a/include/staff/tasks.inc.php b/include/staff/tasks.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..74381d7a914349a11c87277b560976a2395729be
--- /dev/null
+++ b/include/staff/tasks.inc.php
@@ -0,0 +1,433 @@
+<?php
+$tasks = TaskModel::objects();
+$date_header = $date_col = false;
+
+// Figure out REFRESH url — which might not be accurate after posting a
+// response
+list($path,) = explode('?', $_SERVER['REQUEST_URI'], 2);
+$args = array();
+parse_str($_SERVER['QUERY_STRING'], $args);
+
+// Remove commands from query
+unset($args['id']);
+unset($args['a']);
+
+$refresh_url = $path . '?' . http_build_query($args);
+
+$queue_name = strtolower($_GET['status'] ?: $_GET['a']); //Status is overloaded
+switch ($queue_name) {
+case 'closed':
+    $status='closed';
+    $results_type=__('Closed Tasks');
+    $showassigned=true; //closed by.
+    break;
+case 'overdue':
+    $status='open';
+    $results_type=__('Overdue Tasks');
+    $tasks->filter(array('isoverdue'=>1));
+    break;
+case 'assigned':
+    $status='open';
+    $staffId=$thisstaff->getId();
+    $results_type=__('My Tasks');
+    $tasks->filter(array('staff_id'=>$thisstaff->getId()));
+    break;
+default:
+case 'search':
+    // Consider basic search
+    if ($_REQUEST['query']) {
+        $results_type=__('Search Results');
+        // Use an index if possible
+        if (Validator::is_email($_REQUEST['query'])) {
+            $tickets = $tickets->filter(array(
+                'user__emails__address' => $_REQUEST['query'],
+            ));
+        }
+        else {
+            $tickets = $tickets->filter(Q::any(array(
+                'number__startswith' => $_REQUEST['query'],
+                'user__emails__address__contains' => $_REQUEST['query'],
+            )));
+        }
+        break;
+    }
+    elseif (isset($_GET['uid'])) {
+        // Apply user filter
+        $tickets->filter(array('user__id'=>$_GET['uid']));
+    }
+    elseif (isset($_SESSION['advsearch'])) {
+        // XXX: De-duplicate and simplify this code
+        $form = $search->getFormFromSession('advsearch');
+        $form->loadState($_SESSION['advsearch']);
+        $tasks = $search->mangleQuerySet($tasks, $form);
+        $results_type=__('Advanced Search')
+            . '<a class="action-button" href="?clear_filter"><i class="icon-ban-circle"></i> <em>' . __('clear') . '</em></a>';
+        break;
+    }
+    // Fall-through and show open tickets
+case 'open':
+    $status='open';
+    $results_type=__('Open Tasks');
+    break;
+}
+
+// Apply filters
+$filters = array();
+$SQ = new Q(array('flags__hasbit' => TaskModel::ISOPEN));
+if ($status && !strcasecmp($status, 'closed'))
+    $SQ->negate();
+
+$filters[] = $SQ;
+$tasks->filter($filters);
+
+// Impose visibility constraints
+// ------------------------------------------------------------
+// -- Open and assigned to me
+$visibility = array(
+    new Q(array('flags__hasbit' => TaskModel::ISOPEN, 'staff_id' => $thisstaff->getId()))
+);
+// -- Routed to a department of mine
+if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
+    $visibility[] = new Q(array('dept_id__in' => $depts));
+// -- Open and assigned to a team of mine
+if (($teams = $thisstaff->getTeams()) && count(array_filter($teams)))
+    $visibility[] = new Q(array(
+        'team_id__in' => array_filter($teams),
+        'flags__hasbit' => TaskModel::ISOPEN
+    ));
+$tasks->filter(Q::any($visibility));
+
+// Add in annotations
+$tasks->annotate(array(
+    //'collab_count' => SqlAggregate::COUNT('collaborators'),
+    'attachment_count' => SqlAggregate::COUNT('thread__entries__attachments'),
+    'thread_count' => SqlAggregate::COUNT('thread__entries'),
+    // 'isopen' => new SqlExpr(array('flags__hasbit' => TaskModel::ISOPEN)),
+));
+
+$tasks->values('id', 'number', 'created', 'staff_id', 'team_id',
+        'staff__firstname', 'staff__lastname', 'team__name',
+        'dept__name', 'cdata__title', 'flags');
+// Apply requested quick filter
+
+// Apply requested sorting
+$queue_sort_key = sprintf(':Q:%s:sort', $queue_name);
+
+if (isset($_GET['sort']))
+    $_SESSION[$queue_sort_key] = $_GET['sort'];
+switch ($_SESSION[$queue_sort_key]) {
+case 'number':
+    $tasks->extra(array(
+        'order_by'=>array(SqlExpression::times(new SqlField('number'), 1))
+    ));
+    break;
+case 'priority,due':
+    $tasks->order_by('cdata__:priority__priority_urgency');
+    // Fall through to add in due date filter
+case 'due':
+    $date_header = __('Due Date');
+    $date_col = 'est_duedate';
+    $tasks->values('est_duedate');
+    $tasks->filter(array('est_duedate__isnull'=>false));
+    $tasks->order_by('est_duedate');
+    break;
+case 'updated':
+    $tasks->order_by('cdata__:priority__priority_urgency', '-lastupdate');
+    break;
+case 'created':
+default:
+    $tasks->order_by('-created');
+    break;
+}
+
+// Apply requested pagination
+$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
+$pageNav=new Pagenate($tasks->count(), $page, PAGE_LIMIT);
+$pageNav->setURL('tasks.php', $args);
+$tasks = $pageNav->paginate($tasks);
+
+TaskForm::ensureDynamicDataView();
+
+// Save the query to the session for exporting
+$_SESSION[':Q:tasks'] = $tasks;
+
+// Mass actions
+$actions = array();
+
+if ($thisstaff->hasPerm(Task::PERM_ASSIGN)) {
+    $actions += array(
+            'assign' => array(
+                'icon' => 'icon-user',
+                'action' => __('Assign Tasks')
+            ));
+}
+
+if ($thisstaff->hasPerm(Task::PERM_TRANSFER)) {
+    $actions += array(
+            'transfer' => array(
+                'icon' => 'icon-share',
+                'action' => __('Transfer Tasks')
+            ));
+}
+
+if ($thisstaff->hasPerm(Task::PERM_DELETE)) {
+    $actions += array(
+            'delete' => array(
+                'icon' => 'icon-trash',
+                'action' => __('Delete Tasks')
+            ));
+}
+
+
+?>
+<!-- SEARCH FORM START -->
+<div id='basic_search'>
+    <form action="tasks.php" method="get">
+    <input type="hidden" name="a" value="search">
+    <table>
+        <tr>
+            <td><input type="text" id="basic-ticket-search" name="query"
+            size=30 value="<?php echo Format::htmlchars($_REQUEST['query'],
+            true); ?>"
+                autocomplete="off" autocorrect="off" autocapitalize="off"></td>
+            <td><input type="submit" class="button" value="<?php echo __('Search'); ?>"></td>
+            <td>&nbsp;&nbsp;<a href="#" onclick="javascript:
+                $.dialog('ajax.php/tasks/search', 201);"
+                >[<?php echo __('advanced'); ?>]</a>&nbsp;<i class="help-tip icon-question-sign" href="#advanced"></i></td>
+        </tr>
+    </table>
+    </form>
+</div>
+<!-- SEARCH FORM END -->
+<div class="clear"></div>
+<div style="margin-bottom:20px; padding-top:10px;">
+<div>
+        <div class="pull-left flush-left">
+            <h2><a href="<?php echo $refresh_url; ?>"
+                title="<?php echo __('Refresh'); ?>"><i class="icon-refresh"></i> <?php echo
+                $results_type.$showing; ?></a></h2>
+        </div>
+        <div class="pull-right flush-right">
+            <span style="display:inline-block">
+                <span style="vertical-align: baseline">Sort:</span>
+            <select name="sort" onchange="javascript:addSearchParam('sort', $(this).val());">
+<?php foreach (array(
+    'created' =>    __('Most Recently Created'),
+    'updated' =>    __('Most Recently Updated'),
+    'due' =>        __('Due Soon'),
+    'priority,due' => __('Priority + Due Soon'),
+    'number' =>     __('Task Number'),
+) as $mode => $desc) { ?>
+            <option value="<?php echo $mode; ?>" <?php if ($mode == $_SESSION[$queue_sort_key]) echo 'selected="selected"'; ?>><?php echo $desc; ?></option>
+<?php } ?>
+            </select>
+            </span>
+            <?php
+            if ($thisstaff->canManageTickets()) {
+                echo TicketStatus::status_options();
+            }
+            if ($actions) { ?>
+            <span
+                class="action-button"
+                data-dropdown="#action-dropdown-moreoptions">
+                <i class="icon-caret-down pull-right"></i>
+                <a class="tasks-action"
+                    href="#moreoptions"><i
+                    class="icon-reorder"></i> <?php
+                    echo __('Options'); ?></a>
+            </span>
+            <div id="action-dropdown-moreoptions"
+                class="action-dropdown anchor-right">
+                <ul>
+            <?php foreach ($actions as $a => $action) { ?>
+                    <li>
+                        <a class="no-pjax tasks-action"
+                            <?php
+                            if ($action['dialog'])
+                                echo sprintf("data-dialog='%s'", $action['dialog']);
+                            if ($action['redirect'])
+                                echo sprintf("data-redirect='%s'", $action['redirect']);
+                            ?>
+                            href="<?php
+                            echo sprintf('#tasks/mass/%s', $a); ?>"
+                            ><i class="<?php
+                            echo $action['icon'] ?: 'icon-tag'; ?>"></i> <?php
+                            echo $action['action']; ?></a>
+                    </li>
+                <?php
+                } ?>
+                </ul>
+            </div>
+            <?php
+           } ?>
+        </div>
+</div>
+<div class="clear" style="margin-bottom:10px;"></div>
+<form action="tasks.php" method="POST" name='tasks' id="tasks">
+<?php csrf_token(); ?>
+ <input type="hidden" name="a" value="mass_process" >
+ <input type="hidden" name="do" id="action" value="" >
+ <input type="hidden" name="status" value="<?php echo
+ Format::htmlchars($_REQUEST['status'], true); ?>" >
+ <table class="list" border="0" cellspacing="1" cellpadding="2" width="940">
+    <thead>
+        <tr>
+            <?php if ($thisstaff->canManageTickets()) { ?>
+	        <th width="8px">&nbsp;</th>
+            <?php } ?>
+	        <th width="70">
+                <?php echo __('Number'); ?></th>
+	        <th width="70">
+                <?php echo $date_header ?: __('Date'); ?></th>
+	        <th width="280">
+                <?php echo __('Title'); ?></th>
+            <th width="250">
+                <?php echo __('Department');?></th>
+            <th width="250">
+                <?php echo __('Assignee');?></th>
+        </tr>
+     </thead>
+     <tbody>
+        <?php
+        // Setup Subject field for display
+        $total=0;
+        $title_field = TaskForm::objects()->one()->getField('title');
+        $ids=($errors && $_POST['tids'] && is_array($_POST['tids']))?$_POST['tids']:null;
+        foreach ($tasks as $T) {
+            $T['isopen'] = ($T['flags'] & TaskModel::ISOPEN != 0); //XXX:
+            $total += 1;
+            $tag=$T['staff_id']?'assigned':'openticket';
+            $flag=null;
+            if($T['lock__staff_id'] && $T['lock__staff_id'] != $thisstaff->getId())
+                $flag='locked';
+            elseif($T['isoverdue'])
+                $flag='overdue';
+
+            $assignee = '';
+            $dept = Dept::getLocalById($T['dept_id'], 'name', $T['dept__name']);
+            $assinee ='';
+            if ($T['staff_id']) {
+                $staff =  new PersonsName($T['staff__firstname'].' '.$T['staff__lastname']);
+                $assignee = sprintf('<span class="Icon staffAssigned">%s</span>',
+                        Format::truncate((string) $staff, 40));
+            } elseif($T['team_id']) {
+                $assignee = sprintf('<span class="Icon teamAssigned">%s</span>',
+                    Format::truncate(Team::getLocalById($T['team_id'], 'name', $T['team__name']),40));
+            }
+
+            $threadcount=$T['thread_count'];
+            $number = $T['number'];
+            if ($T['isopen'])
+                $number = sprintf('<b>%s</b>', $number);
+
+            $title = Format::truncate($title_field->display($title_field->to_php($T['cdata__title'])), 40);
+            ?>
+            <tr id="<?php echo $T['id']; ?>">
+                <?php
+                if ($thisstaff->canManageTickets()) {
+                    $sel = false;
+                    if ($ids && in_array($T['id'], $ids))
+                        $sel = true;
+                    ?>
+                <td align="center" class="nohover">
+                    <input class="ckb" type="checkbox" name="tids[]"
+                        value="<?php echo $T['id']; ?>" <?php echo $sel?'checked="checked"':''; ?>>
+                </td>
+                <?php } ?>
+                <td nowrap>
+                  <a class="preview"
+                    href="tasks.php?id=<?php echo $T['id']; ?>"
+                    data-preview="#tasks/<?php echo $T['id']; ?>/preview"
+                    ><?php echo $number; ?></a></td>
+                <td align="center" nowrap><?php echo
+                Format::datetime($T[$date_col ?: 'created']); ?></td>
+                <td><a <?php if ($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?>
+                    href="tasks.php?id=<?php echo $T['id']; ?>"><?php
+                    echo $title; ?></a>
+                     <?php
+                        if ($threadcount>1)
+                            echo "<small>($threadcount)</small>&nbsp;".'<i
+                                class="icon-fixed-width icon-comments-alt"></i>&nbsp;';
+                        if ($T['collab_count'])
+                            echo '<i class="icon-fixed-width icon-group faded"></i>&nbsp;';
+                        if ($T['attachment_count'])
+                            echo '<i class="icon-fixed-width icon-paperclip"></i>&nbsp;';
+                    ?>
+                </td>
+                <td nowrap>&nbsp;<?php echo Format::truncate($dept, 40); ?></td>
+                <td nowrap>&nbsp;<?php echo $assignee; ?></td>
+            </tr>
+            <?php
+            } //end of foreach
+        if (!$total)
+            $ferror=__('There are no tickets matching your criteria.');
+        ?>
+    </tbody>
+    <tfoot>
+     <tr>
+        <td colspan="6">
+            <?php if($total && $thisstaff->canManageTickets()){ ?>
+            <?php echo __('Select');?>:&nbsp;
+            <a id="selectAll" href="#ckb"><?php echo __('All');?></a>&nbsp;&nbsp;
+            <a id="selectNone" href="#ckb"><?php echo __('None');?></a>&nbsp;&nbsp;
+            <a id="selectToggle" href="#ckb"><?php echo __('Toggle');?></a>&nbsp;&nbsp;
+            <?php }else{
+                echo '<i>';
+                echo $ferror?Format::htmlchars($ferror):__('Query returned 0 results.');
+                echo '</i>';
+            } ?>
+        </td>
+     </tr>
+    </tfoot>
+    </table>
+    <?php
+    if ($total>0) { //if we actually had any tickets returned.
+        echo '<div>&nbsp;'.__('Page').':'.$pageNav->getPageLinks().'&nbsp;';
+        echo sprintf('<a class="export-csv no-pjax" href="?%s">%s</a>',
+                Http::build_query(array(
+                        'a' => 'export', 'h' => $hash,
+                        'status' => $_REQUEST['status'])),
+                __('Export'));
+        echo '&nbsp;<i class="help-tip icon-question-sign" href="#export"></i></div>';
+    } ?>
+    </form>
+</div>
+
+<div style="display:none;" class="dialog" id="confirm-action">
+    <h3><?php echo __('Please Confirm');?></h3>
+    <a class="close" href=""><i class="icon-remove-circle"></i></a>
+    <hr/>
+    <p class="confirm-action" style="display:none;" id="mark_overdue-confirm">
+        <?php echo __('Are you sure want to flag the selected tickets as <font color="red"><b>overdue</b></font>?');?>
+    </p>
+    <div><?php echo __('Please confirm to continue.');?></div>
+    <hr style="margin-top:1em"/>
+    <p class="full-width">
+        <span class="buttons pull-left">
+            <input type="button" value="<?php echo __('No, Cancel');?>" class="close">
+        </span>
+        <span class="buttons pull-right">
+            <input type="button" value="<?php echo __('Yes, Do it!');?>" class="confirm">
+        </span>
+     </p>
+    <div class="clear"></div>
+</div>
+<script type="text/javascript">
+$(function() {
+    $(document).off('.tasks');
+    $(document).on('click.tasks', 'a.tasks-action', function(e) {
+        e.preventDefault();
+        var count = checkbox_checker($('form#tasks'), 1);
+        if (count) {
+            var url = 'ajax.php/'
+            +$(this).attr('href').substr(1)
+            +'?count='+count
+            +'&_uid='+new Date().getTime();
+            $.dialog(url, [201], function (xhr) {
+                $.pjax.reload('#pjax-container');
+             });
+        }
+        return false;
+    });
+});
+</script>
diff --git a/include/staff/templates/task-assign.tmpl.php b/include/staff/templates/task-assign.tmpl.php
index 0c5dd7a5eac411e9f78ab99e0096a0dd671187a8..48d389b933d8311526e8850864d2cbbd345e3ecb 100644
--- a/include/staff/templates/task-assign.tmpl.php
+++ b/include/staff/templates/task-assign.tmpl.php
@@ -1,14 +1,11 @@
 <?php
 global $cfg;
 
-if (!$info['title'])
-    $info['title'] = sprintf(__('%s Tasks #%s'),
-            $task->isAssigned() ? __('Reassign') :  __('Assign'),
-            $task->getNumber()
-            );
-
+if (!$info[':title'])
+    $info[':title'] = sprintf(__('%s Selected Tasks'),
+            __('Assign'));
 ?>
-<h3><?php echo $info['title']; ?></h3>
+<h3><?php echo $info[':title']; ?></h3>
 <b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
 <div class="clear"></div>
 <hr/>
@@ -25,10 +22,10 @@ if ($info['error']) {
 }
 
 
-$action = $info['action'] ?: ('#tasks/'.$task->getId().'/assign');
+$action = $info[':action'] ?: ('#tasks/mass/assign');
 ?>
 <div id="ticket-status" style="display:block; margin:5px;">
-<form method="post" name="transfer" id="transfer"
+<form class="mass-action" method="post" name="transfer" id="transfer"
     action="<?php echo $action; ?>">
     <table width="100%">
         <?php
@@ -46,8 +43,13 @@ $action = $info['action'] ?: ('#tasks/'.$task->getId().'/assign');
                 <span>
                 <strong><?php echo __('Agent') ?>:&nbsp;</strong>
                 <select name="staff_id">
+                <option value=""><?php
+                    echo __('Select Assignee'); ?></option>
                 <?php
                 foreach (Staff::getAvailableStaffMembers() as $id => $name) {
+                    if ($task && $task->getStaffId() == $id)
+                        $name .= sprintf(' (%s) ', __('current'));
+
                     echo sprintf('<option value="%d" %s>%s</option>',
                             $id,
                             ($info['staff_id'] == $id)
@@ -58,7 +60,7 @@ $action = $info['action'] ?: ('#tasks/'.$task->getId().'/assign');
                 ?>
                 </select>
                 <font class="error">*&nbsp;<?php echo
-                $errors['dept_id']; ?></font>
+                $errors['staff_id']; ?></font>
                 </span>
             </td> </tr>
         </tbody>
diff --git a/include/staff/templates/task-delete.tmpl.php b/include/staff/templates/task-delete.tmpl.php
index 6014bd88aa6be37d1027d01cbb083ba6b4d03b1b..9a9191e4cc5134849fee8d60a5b4e0aa5d82c21a 100644
--- a/include/staff/templates/task-delete.tmpl.php
+++ b/include/staff/templates/task-delete.tmpl.php
@@ -1,14 +1,11 @@
 <?php
 global $cfg;
-
-if (!$info['title'])
-    $info['title'] = sprintf(__('%s Tasks #%s'),
+if (!$info[':title'])
+    $info[':title'] = sprintf(__('%s %s'),
             __('Delete'),
-            $task->getNumber()
-            );
-
+            _N('selected task', 'selected tasks', $count));
 ?>
-<h3><?php echo $info['title']; ?></h3>
+<h3><?php echo $info[':title']; ?></h3>
 <b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
 <div class="clear"></div>
 <hr/>
@@ -25,17 +22,18 @@ if ($info['error']) {
 }
 
 
-$action = $info['action'] ?: ('#tasks/'.$task->getId().'/delete');
+$action = $info[':action'] ?: ('#tasks/mass/delete');
 ?>
 <div id="ticket-status" style="display:block; margin:5px;">
 <form method="post" name="delete" id="delete"
-    action="<?php echo $action; ?>">
+    action="<?php echo $action; ?>"
+    class="mass-action">
     <table width="100%">
         <?php
-        if ($info['extra']) {
+        if ($info[':extra']) {
             ?>
         <tbody>
-            <tr><td colspan="2"><strong><?php echo $info['extra'];
+            <tr><td colspan="2"><strong><?php echo $info[':extra'];
             ?></strong></td> </tr>
         </tbody>
         <?php
@@ -45,7 +43,7 @@ $action = $info['action'] ?: ('#tasks/'.$task->getId().'/delete');
             <tr>
                 <td colspan="2">
                 <?php
-                $placeholder = $info['placeholder'] ?: __('Optional reason for the deletion');
+                $placeholder = $info[':placeholder'] ?: __('Optional reason for the deletion');
                 ?>
                 <textarea name="comments" id="comments"
                     cols="50" rows="3" wrap="soft" style="width:100%"
diff --git a/include/staff/templates/task-transfer.tmpl.php b/include/staff/templates/task-transfer.tmpl.php
index 8a872f43845ec328c92554f32125e10682173b89..462714bb8a431ad8236d42b580464ee3f7129c12 100644
--- a/include/staff/templates/task-transfer.tmpl.php
+++ b/include/staff/templates/task-transfer.tmpl.php
@@ -1,12 +1,11 @@
 <?php
 global $cfg;
 
-if (!$info['title'])
-    $info['title'] = sprintf(__('%s Tasks #%s'),
-            __('Tranfer'), $task->getNumber());
-
+if (!$info[':title'])
+    $info[':title'] = sprintf(__('%s Selected Tasks'),
+            __('Tranfer'));
 ?>
-<h3><?php echo $info['title']; ?></h3>
+<h3><?php echo $info[':title']; ?></h3>
 <b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
 <div class="clear"></div>
 <hr/>
@@ -23,17 +22,18 @@ if ($info['error']) {
 }
 
 
-$action = $info['action'] ?: ('#tasks/'.$task->getId().'/transfer');
+$action = $info[':action'] ?: ('#tasks/mass/transfer');
 ?>
 <div style="display:block; margin:5px;">
 <form method="post" name="transfer" id="transfer"
+    class="mass-action"
     action="<?php echo $action; ?>">
     <table width="100%">
         <?php
-        if ($info['extra']) {
+        if ($info[':extra']) {
             ?>
         <tbody>
-            <tr><td colspan="2"><strong><?php echo $info['extra'];
+            <tr><td colspan="2"><strong><?php echo $info[':extra'];
             ?></strong></td> </tr>
         </tbody>
         <?php
@@ -46,6 +46,9 @@ $action = $info['action'] ?: ('#tasks/'.$task->getId().'/transfer');
                 <select name="dept_id">
                 <?php
                 foreach (Dept::getDepartments() as $id => $name) {
+                    if ($task && $task->getDeptId() == $id)
+                        $name .= sprintf(' (%s) ', __('current'));
+
                     echo sprintf('<option value="%d" %s>%s</option>',
                             $id,
                             ($info['dept_id'] == $id)
@@ -64,7 +67,7 @@ $action = $info['action'] ?: ('#tasks/'.$task->getId().'/transfer');
             <tr>
                 <td colspan="2">
                 <?php
-                $placeholder = $info['placeholder'] ?: __('Optional reason for the transfer');
+                $placeholder = $info[':placeholder'] ?: __('Optional reason for the transfer');
                 ?>
                 <textarea name="comments" id="comments"
                     cols="50" rows="3" wrap="soft" style="width:100%"
diff --git a/include/staff/templates/task-view.tmpl.php b/include/staff/templates/task-view.tmpl.php
index a9a4c72170780e61cd2edd7ada25a4ab30a6ab3b..8369a396b0a763d31cb8ed199910faa8fa3fe20e 100644
--- a/include/staff/templates/task-view.tmpl.php
+++ b/include/staff/templates/task-view.tmpl.php
@@ -1,50 +1,22 @@
 <?php
 if (!defined('OSTSCPINC')
-        || !$thisstaff
-        || !$task
-        || !($role = $thisstaff->getRole($task->getId())))
+    || !$thisstaff || !$task
+    || !($role = $thisstaff->getRole($task->getDeptId())))
     die('Invalid path');
 
-
-$actions = array();
-
-if ($role->hasPerm(Task::PERM_EDIT)) {
-    $actions += array(
-            'edit' => array(
-                'icon' => 'icon-edit',
-                'dialog' => '{"size":"large"}',
-                'action' => __('Edit')
-            ));
-}
-
-if ($role->hasPerm(Task::PERM_ASSIGN)) {
-    $actions += array(
-            'assign' => array(
-                'icon' => 'icon-user',
-                'action' => $task->isAssigned() ? __('Reassign') : __('Assign')
-            ));
-}
-
-if ($role->hasPerm(Task::PERM_TRANSFER)) {
-    $actions += array(
-            'transfer' => array(
-                'icon' => 'icon-share',
-                'action' => __('Transfer')
-            ));
-}
-
+$more = array();
 if ($role->hasPerm(Task::PERM_DELETE)) {
-    $actions += array(
+    $more += array(
             'delete' => array(
                 'icon' => 'icon-trash',
-                'action' => __('Delete')
+                'redirect' => 'tasks.php',
+                'action' => __('Delete Task')
             ));
 }
 
-
 $info=($_POST && $errors)?Format::input($_POST):array();
 
-$id    = $task->getId();    //Ticket ID.
+$id    = $task->getId();
 if ($task->isOverdue())
     $warn.='&nbsp;&nbsp;<span class="Icon overdueTicket">'.__('Marked overdue!').'</span>';
 
@@ -52,32 +24,58 @@ if ($task->isOverdue())
 <table width="940" cellpadding="2" cellspacing="0" border="0">
     <tr>
         <td width="20%" class="has_bottom_border">
-            <h3><a href="#tasks/<?php echo $task->getId(); ?>/view"
-                    id="reload-task"><i class="icon-refresh"></i> <?php
+            <h2><a href="tasks.php?id=<?php echo $task->getId(); ?>"><i class="icon-refresh"></i> <?php
                 echo sprintf(__('Task #%s'), $task->getNumber()); ?></a>
-            </h3>
+            </h2>
         </td>
         <td width="auto" class="flush-right has_bottom_border">
-        <?php
-           if ($actions) { ?>
+            <a class="action-button"
+                href="tasks.php?id=<?php echo $task->getId(); ?>&a=print"><i class="icon-print"></i> <?php
+                echo __('Print'); ?></a>
+            <?php
+            if ($role->hasPerm(Task::PERM_EDIT)) { ?>
+                <a class="action-button task-action"
+                    href="tasks.php?id=<?php echo $task->getId(); ?>&a=edit"><i class="icon-edit"></i> <?php
+                    echo __('Edit'); ?></a>
+            <?php
+            }
+            if ($role->hasPerm(Task::PERM_ASSIGN)) { ?>
+                <a class="action-button task-action"
+                    href="#tasks/<?php echo $task->getId(); ?>/assign"><i
+                    class="icon-user"></i> <?php
+                    echo $task->isAssigned() ? __('Reassign') : __('Assign');
+                ?></a>
+            <?php
+            }
+            if ($role->hasPerm(Task::PERM_TRANSFER)) { ?>
+                <a class="action-button task-action"
+                    href="#tasks/<?php echo $task->getId(); ?>/transfer"><i
+                    class="icon-share"></i> <?php
+                    echo __('Transfer');
+                ?></a>
+            <?php
+            }
+            if ($more) { ?>
             <span
                 class="action-button"
-                data-dropdown="#action-dropdown-taskoptions">
+                data-dropdown="#action-dropdown-moreoptions">
                 <i class="icon-caret-down pull-right"></i>
                 <a class="task-action"
-                    href="#taskoptions"><i
+                    href="#moreoptions"><i
                     class="icon-reorder"></i> <?php
-                    echo __('Task Options'); ?></a>
+                    echo __('More'); ?></a>
             </span>
-            <div id="action-dropdown-taskoptions"
+            <div id="action-dropdown-moreoptions"
                 class="action-dropdown anchor-right">
                 <ul>
-            <?php foreach ($actions as $a => $action) { ?>
+            <?php foreach ($more as $a => $action) { ?>
                     <li>
                         <a class="no-pjax task-action"
                             <?php
                             if ($action['dialog'])
                                 echo sprintf("data-dialog='%s'", $action['dialog']);
+                            if ($action['redirect'])
+                                echo sprintf("data-redirect='%s'", $action['redirect']);
                             ?>
                             href="<?php
                             echo sprintf('#tasks/%d/%s', $task->getId(), $a); ?>"
@@ -106,14 +104,6 @@ if ($task->isOverdue())
                     <th><?php echo __('Department');?>:</th>
                     <td><?php echo Format::htmlchars($task->dept->getName()); ?></td>
                 </tr>
-                <tr>
-                    <th><?php echo __('Create Date');?>:</th>
-                    <td><?php echo Format::datetime($task->getCreateDate()); ?></td>
-                </tr>
-            </table>
-        </td>
-        <td width="50%" style="vertical-align:top">
-            <table cellspacing="0" cellpadding="4" width="100%" border="0">
                 <?php
                 if ($task->isOpen()) { ?>
                 <tr>
@@ -142,10 +132,18 @@ if ($task->isOverdue())
                 </tr>
                 <?php
                 } ?>
+            </table>
+        </td>
+        <td width="50%" style="vertical-align:top">
+            <table cellspacing="0" cellpadding="4" width="100%" border="0">
                 <tr>
                     <th><?php echo __('SLA Plan');?>:</th>
                     <td><?php echo $sla?Format::htmlchars($sla->getName()):'<span class="faded">&mdash; '.__('None').' &mdash;</span>'; ?></td>
                 </tr>
+                <tr>
+                    <th><?php echo __('Create Date');?>:</th>
+                    <td><?php echo Format::datetime($task->getCreateDate()); ?></td>
+                </tr>
                 <?php
                 if($task->isOpen()){ ?>
                 <tr>
@@ -273,7 +271,7 @@ foreach (DynamicFormEntry::forObject($task->getId(),
 <div id="response_options">
     <ul class="tabs"></ul>
     <form id="task_note"
-        action="#tasks/<?php echo $task->getId(); ?>"
+        action="tasks.php?id=<?php echo $task->getId(); ?>"
         name="task_note"
         method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
@@ -301,8 +299,8 @@ foreach (DynamicFormEntry::forObject($task->getId(),
                         ?></textarea>
                     <div class="attachments">
                     <?php
-                        if ($task_note_form)
-                            print $task_note_form->getField('attachments')->render();
+                        if ($note_form)
+                            print $note_form->getField('attachments')->render();
                     ?>
                     </div>
                 </td>
@@ -333,33 +331,25 @@ foreach (DynamicFormEntry::forObject($task->getId(),
        </p>
     </form>
  </div>
+
 <script type="text/javascript">
 $(function() {
-    $(document).on('click', 'li.active a#ticket_tasks', function(e) {
+    $(document).off('.task-action');
+    $(document).on('click.task-action', 'a.task-action', function(e) {
         e.preventDefault();
-        $('div#task_content').hide().empty();
-        $('div#tasks_content').show();
+        var url = 'ajax.php/'
+        +$(this).attr('href').substr(1)
+        +'?_uid='+new Date().getTime();
+        var $options = $(this).data('dialog');
+        var $redirect = $(this).data('redirect');
+        $.dialog(url, [201], function (xhr) {
+            if ($redirect)
+                window.location.href = $redirect;
+            else
+                $.pjax.reload('#pjax-container');
+        }, $options);
+
         return false;
-     });
-    $(document).off('.tf');
-    $(document).on('submit.tf', 'form#task_note', function(e) {
-        e.preventDefault();
-        var $form = $(this);
-        var $container = $('div#task_content');
-        $.ajax({
-            type:  $form.attr('method'),
-            url: 'ajax.php/'+$form.attr('action').substr(1),
-            data: $form.serialize(),
-            cache: false,
-            success: function(resp, status, xhr) {
-                $container.html(resp);
-                $('#msg_notice, #msg_error',$container)
-                .delay(5000)
-                .slideUp();
-            }
-        })
-        .done(function() { })
-        .fail(function() { });
     });
 });
 </script>
diff --git a/include/staff/ticket-tasks.inc.php b/include/staff/ticket-tasks.inc.php
index 8b8f3fb9d7c13f601ad6c101b4d2f7a32dd0bb43..3dec2c3867c99f6db91ef277667ddc9219450160 100644
--- a/include/staff/ticket-tasks.inc.php
+++ b/include/staff/ticket-tasks.inc.php
@@ -137,8 +137,9 @@ $(function() {
         }).show();
         return false;
      });
-    $(document).off('.task-action');
-    $(document).on('click.task-action', 'a.task-action', function(e) {
+    // Ticket Tasks
+    $(document).off('.ticket-task-action');
+    $(document).on('click.ticket-task-action', 'a.ticket-task-action', function(e) {
         e.preventDefault();
         var url = 'ajax.php/'
         +$(this).attr('href').substr(1)
diff --git a/scp/ajax.php b/scp/ajax.php
index f34bcfb930f912ea70e6b4592324924ec62fd4a7..70c92db226f885958efe0d5c9c3bd9a4a2b2388d 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -182,7 +182,9 @@ $dispatcher = patterns('',
         url_get('^(?P<tid>\d+)/delete', 'delete'),
         url_post('^(?P<tid>\d+)/delete$', 'delete'),
         url_get('^(?P<tid>\d+)/view$', 'task'),
-        url_post('^(?P<tid>\d+)$', 'task')
+        url_post('^(?P<tid>\d+)$', 'task'),
+        url_get('^mass/(?P<action>[\w.]+)', 'massProcess'),
+        url_post('^mass/(?P<action>[\w.]+)', 'massProcess')
     )),
     url('^/collaborators/', patterns('ajax.tickets.php:TicketsAjaxAPI',
         url_get('^(?P<cid>\d+)/view$', 'viewCollaborator'),
diff --git a/scp/tasks.php b/scp/tasks.php
new file mode 100644
index 0000000000000000000000000000000000000000..21ec96fd162769e56f63216bdb26f74d397b2fc3
--- /dev/null
+++ b/scp/tasks.php
@@ -0,0 +1,197 @@
+<?php
+/*************************************************************************
+    tasks.php
+
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+
+require('staff.inc.php');
+require_once(INCLUDE_DIR.'class.task.php');
+
+$page = '';
+$task = null; //clean start.
+if ($_REQUEST['id']) {
+    if (!($task=Task::lookup($_REQUEST['id'])))
+         $errors['err'] = sprintf(__('%s: Unknown or invalid ID.'), __('task'));
+    elseif (!$task->checkStaffPerm($thisstaff)) {
+        $errors['err'] = __('Access denied. Contact admin if you believe this is in error');
+        $task = null;
+    }
+}
+
+// Configure form for file uploads
+$note_form = new Form(array(
+    'attachments' => new FileUploadField(array('id'=>'attach',
+        'name'=>'attach:note',
+        'configuration' => array('extensions'=>'')))
+));
+
+//At this stage we know the access status. we can process the post.
+if($_POST && !$errors):
+
+    if ($task) {
+        //More coffee please.
+        $errors=array();
+        $role = $thisstaff->getRole($task->getDeptId());
+        switch(strtolower($_POST['a'])):
+        case 'postnote': /* Post Internal Note */
+            $vars = $_POST;
+            $attachments = $note_form->getField('attachments')->getClean();
+            $vars['cannedattachments'] = array_merge(
+                $vars['cannedattachments'] ?: array(), $attachments);
+
+            $wasOpen = ($task->isOpen());
+            if(($note=$task->postNote($vars, $errors, $thisstaff))) {
+
+                $msg=__('Internal note posted successfully');
+                // Clear attachment list
+                $note_form->setSource(array());
+                $note_form->getField('attachments')->reset();
+
+                if($wasOpen && $task->isClosed())
+                    $task = null; //Going back to main listing.
+                else
+                    // Ticket is still open -- clear draft for the note
+                    Draft::deleteForNamespace('task.note.'.$task->getId(),
+                        $thisstaff->getId());
+
+            } else {
+
+                if(!$errors['err'])
+                    $errors['err'] = __('Unable to post internal note - missing or invalid data.');
+
+                $errors['postnote'] = __('Unable to post the note. Correct the error(s) below and try again!');
+            }
+            break;
+        default:
+            $errors['err']=__('Unknown action');
+        endswitch;
+    }
+    if(!$errors)
+        $thisstaff->resetStats(); //We'll need to reflect any changes just made!
+endif;
+
+/*... Quick stats ...*/
+$stats= $thisstaff->getTasksStats();
+
+// Clear advanced search upon request
+if (isset($_GET['clear_filter']))
+    unset($_SESSION['advsearch']);
+
+//Navigation
+$nav->setTabActive('tasks');
+$open_name = _P('queue-name',
+    /* This is the name of the open tasks queue */
+    'Open');
+
+$nav->addSubMenu(array('desc'=>$open_name.' ('.number_format($stats['open']).')',
+                       'title'=>__('Open Tasks'),
+                       'href'=>'tasks.php?status=open',
+                       'iconclass'=>'Ticket'),
+                    ((!$_REQUEST['status'] && !isset($_SESSION['advsearch'])) || $_REQUEST['status']=='open'));
+
+if ($stats['assigned']) {
+
+    $nav->addSubMenu(array('desc'=>__('My Tasks').' ('.number_format($stats['assigned']).')',
+                           'title'=>__('Assigned Tasks'),
+                           'href'=>'tasks.php?status=assigned',
+                           'iconclass'=>'assignedTickets'),
+                        ($_REQUEST['status']=='assigned'));
+}
+
+if ($stats['overdue']) {
+    $nav->addSubMenu(array('desc'=>__('Overdue').' ('.number_format($stats['overdue']).')',
+                           'title'=>__('Stale Tasks'),
+                           'href'=>'tasks.php?status=overdue',
+                           'iconclass'=>'overdueTickets'),
+                        ($_REQUEST['status']=='overdue'));
+
+    if(!$sysnotice && $stats['overdue']>10)
+        $sysnotice=sprintf(__('%d overdue tasks!'), $stats['overdue']);
+}
+
+if ($stats['closed']) {
+    $nav->addSubMenu(array('desc' => __('Closed').' ('.number_format($stats['closed']).')',
+                           'title'=>__('Closed Tasks'),
+                           'href'=>'tasks.php?status=closed',
+                           'iconclass'=>'closedTickets'),
+                        ($_REQUEST['status']=='closed'));
+}
+
+if (isset($_SESSION['advsearch'])) {
+    // XXX: De-duplicate and simplify this code
+    $search = SavedSearch::create();
+    $form = $search->getFormFromSession('advsearch');
+    $form->loadState($_SESSION['advsearch']);
+    $tickets = TicketModel::objects();
+    $tickets = $search->mangleQuerySet($tickets, $form);
+    $count = $tickets->count();
+    $nav->addSubMenu(array('desc' => __('Search').' ('.number_format($count).')',
+                           'title'=>__('Advanced Ticket Search'),
+                           'href'=>'tickets.php?status=search',
+                           'iconclass'=>'Ticket'),
+                        (!$_REQUEST['status'] || $_REQUEST['status']=='search'));
+}
+
+if ($thisstaff->hasPerm(TaskModel::PERM_CREATE)) {
+    $nav->addSubMenu(array('desc'=>__('New Task'),
+                           'title'=> __('Open a New Task'),
+                           'href'=>'tasks.php?a=open',
+                           'iconclass'=>'newTicket',
+                           'id' => 'new-task'),
+                        ($_REQUEST['a']=='open'));
+}
+
+
+$ost->addExtraHeader('<script type="text/javascript" src="js/ticket.js"></script>');
+$ost->addExtraHeader('<meta name="tip-namespace" content="tasks.queue" />',
+    "$('#content').data('tipNamespace', 'tasks.queue');");
+
+if($task) {
+    $ost->setPageTitle(sprintf(__('Task #%s'),$task->getNumber()));
+    $nav->setActiveSubMenu(-1);
+    $inc = 'templates/task-view.tmpl.php';
+    if ($_REQUEST['a']=='edit'
+            && $task->checkStaffPerm($thisstaff, TaskModel::PERM_EDIT)) {
+        $inc = 'task-edit.inc.php';
+        if (!$forms) $forms=DynamicFormEntry::forObject($task->getId(), 'A');
+        // Auto add new fields to the entries
+        foreach ($forms as $f) $f->addMissingFields();
+    } elseif($_REQUEST['a'] == 'print' && !$task->pdfExport($_REQUEST['psize']))
+        $errors['err'] = __('Internal error: Unable to export the task to PDF for print.');
+} else {
+	$inc = 'tasks.inc.php';
+    if ($_REQUEST['a']=='open' &&
+            $thisstaff->hasPerm(Task::PERM_CREATE))
+        $inc = 'task-open.inc.php';
+    elseif($_REQUEST['a'] == 'export') {
+        $ts = strftime('%Y%m%d');
+        if (!($query=$_SESSION[':Q:tasks']))
+            $errors['err'] = __('Query token not found');
+        elseif (!Export::saveTasks($query, "tasks-$ts.csv", 'csv'))
+            $errors['err'] = __('Internal error: Unable to dump query results');
+    }
+
+    //Clear active submenu on search with no status
+    if($_REQUEST['a']=='search' && !$_REQUEST['status'])
+        $nav->setActiveSubMenu(-1);
+
+    //set refresh rate if the user has it configured
+    if(!$_POST && !$_REQUEST['a'] && ($min=$thisstaff->getRefreshRate())) {
+        $js = "clearTimeout(window.task_refresh);
+               window.task_refresh = setTimeout($.refreshTaskView,"
+            .($min*60000).");";
+        $ost->addExtraHeader('<script type="text/javascript">'.$js.'</script>',
+            $js);
+    }
+}
+
+require_once(STAFFINC_DIR.'header.inc.php');
+require_once(STAFFINC_DIR.$inc);
+require_once(STAFFINC_DIR.'footer.inc.php');