diff --git a/include/ajax.tasks.php b/include/ajax.tasks.php
new file mode 100644
index 0000000000000000000000000000000000000000..e58507401e859115a20cc05458781227982f7454
--- /dev/null
+++ b/include/ajax.tasks.php
@@ -0,0 +1,78 @@
+<?php
+/*********************************************************************
+    ajax.tasks.php
+
+    AJAX interface for tasks
+
+    Peter Rotich <peter@osticket.com>
+    Copyright (c)  20014 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:
+**********************************************************************/
+
+if(!defined('INCLUDE_DIR')) die('403');
+
+include_once(INCLUDE_DIR.'class.ticket.php');
+require_once(INCLUDE_DIR.'class.ajax.php');
+require_once(INCLUDE_DIR.'class.task.php');
+
+class TasksAjaxAPI extends AjaxController {
+
+    function preview($tid) {
+        global $thisstaff;
+
+        // TODO: check staff's access.
+        if(!$thisstaff || !($task=Task::lookup($tid)))
+            Http::response(404, __('No such task'));
+
+        include STAFFINC_DIR . 'templates/task-preview.tmpl.php';
+    }
+
+    function task($tid) {
+        global $thisstaff;
+
+        // TODO: check staff's access.
+        if (!$thisstaff || !($task=Task::lookup($tid)))
+            Http::response(404, __('No such task'));
+
+        $info=$errors=array();
+        $task_note_form = new Form(array(
+            'attachments' => new FileUploadField(array('id'=>'attach',
+            'name'=>'attach:note',
+            'configuration' => array('extensions'=>'')))
+            ));
+
+        if ($_POST) {
+
+            switch ($_POST['a']) {
+            case 'postnote':
+                $vars = $_POST;
+                $attachments = $task_note_form->getField('attachments')->getClean();
+                $vars['cannedattachments'] = array_merge(
+                    $vars['cannedattachments'] ?: array(), $attachments);
+
+                if(($note=$task->postNote($vars, $errors, $thisstaff))) {
+                    $msg=__('Note posted successfully');
+                    // Clear attachment list
+                    $task_note_form->setSource(array());
+                    $task_note_form->getField('attachments')->reset();
+                    Draft::deleteForNamespace('task.note.'.$task->getId(),
+                            $thisstaff->getId());
+                } else {
+                    if(!$errors['err'])
+                        $errors['err'] = __('Unable to post the note - missing or invalid data.');
+                }
+                break;
+            default:
+                $errors['err'] = __('Unknown action');
+            }
+        }
+
+        include STAFFINC_DIR . 'templates/task-view.tmpl.php';
+    }
+}
+?>
diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 196bcc390e7147479bc5fd073dfaef3ec25e331b..28c97eaf8c777348649cce147f44c9bc3d14e65c 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -854,5 +854,47 @@ class TicketsAjaxAPI extends AjaxController {
 
         include(STAFFINC_DIR . 'templates/ticket-status.tmpl.php');
     }
+
+    function tasks($tid) {
+        global $thisstaff;
+
+        if (!($ticket=Ticket::lookup($tid))
+                || !$ticket->checkStaffAccess($thisstaff))
+            Http::response(404, 'Unknown ticket');
+
+         include STAFFINC_DIR . 'ticket-tasks.inc.php';
+    }
+
+    function addTask($tid) {
+        global $thisstaff;
+
+        if (!($ticket=Ticket::lookup($tid))
+                || !$ticket->checkStaffAccess($thisstaff))
+            Http::response(404, 'Unknown ticket');
+
+        $info = array();
+
+        if ($_POST) {
+            /*
+            Draft::deleteForNamespace(
+                    sprintf('ticket.%d.task', $ticket->getId()),
+                    $thisstaff->getId());
+            */
+            $form = TaskForm::getDefaultForm()->getForm($_POST);
+            if ($form && ($task = Task::create($form, $ticket)))
+                Http::response(201, $task->to_json());
+
+            $info['error'] = __('Error adding task - try again!');
+        }
+
+        $info['action'] = sprintf('#tickets/%d/add-task', $ticket->getId());
+        $info['title'] = sprintf(
+                __( 'Ticket #%1$s: %2$s'),
+                $ticket->getNumber(),
+                _('Add New Task')
+                );
+
+         include STAFFINC_DIR . 'templates/task.tmpl.php';
+    }
 }
 ?>
diff --git a/include/staff/dynamic-forms.inc.php b/include/staff/dynamic-forms.inc.php
index bfa399490f858aebbc46bdf25354d010be718a2e..55f1fc04fb0404c63618a19da932994774ef4f1c 100644
--- a/include/staff/dynamic-forms.inc.php
+++ b/include/staff/dynamic-forms.inc.php
@@ -31,6 +31,7 @@ $showing=$pageNav->showing().' '._N('form','forms',$count);
     $forms = array(
         'U' => 'icon-user',
         'T' => 'icon-ticket',
+        'A' => 'icon-tasks',
         'C' => 'icon-building',
         'O' => 'icon-group',
     );
diff --git a/include/staff/templates/task-preview.tmpl.php b/include/staff/templates/task-preview.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab2b9f90cac48499b6dd01bfe20c07ee66d13d26
--- /dev/null
+++ b/include/staff/templates/task-preview.tmpl.php
@@ -0,0 +1,137 @@
+<?php
+$error=$msg=$warn=null;
+
+if($lock && $lock->getStaffId()==$thisstaff->getId())
+    $warn.='&nbsp;<span class="Icon lockedTicket">'
+    .sprintf(__('Ticket is locked by %s'), $lock->getStaffName()).'</span>';
+elseif($task->isOverdue())
+    $warn.='&nbsp;<span class="Icon overdueTicket">'.__('Marked overdue!').'</span>';
+
+echo sprintf(
+        '<div style="width:600px; padding: 2px 2px 0 5px;" id="t%s">
+         <h2>'.__('Task #%s').': %s</h2><br>',
+         $task->getNumber(),
+         $task->getNumber(),
+         Format::htmlchars($task->getTitle()));
+
+if($error)
+    echo sprintf('<div id="msg_error">%s</div>',$error);
+elseif($msg)
+    echo sprintf('<div id="msg_notice">%s</div>',$msg);
+elseif($warn)
+    echo sprintf('<div id="msg_warning">%s</div>',$warn);
+
+echo '<ul class="tabs" id="ticket-preview">';
+
+echo '
+        <li><a id="preview_tab" href="#preview" class="active"
+            ><i class="icon-list-alt"></i>&nbsp;'.__('Task Summary').'</a></li>';
+if (0 && $task->getNumCollaborators()) {
+echo sprintf('
+        <li><a id="collab_tab" href="#collab"
+            ><i class="icon-fixed-width icon-group
+            faded"></i>&nbsp;'.__('Collaborators (%d)').'</a></li>',
+            $task->getNumCollaborators());
+}
+echo '</ul>';
+echo '<div id="ticket-preview_container">';
+echo '<div class="tab_content" id="preview_tab_content">';
+echo '<table border="0" cellspacing="" cellpadding="1" width="100%" class="ticket_info">';
+$status=sprintf('<span>%s</span>',ucfirst($task->getStatus()));
+echo sprintf('
+        <tr>
+            <th width="100">'.__('Status').':</th>
+            <td>%s</td>
+        </tr>
+        <tr>
+            <th>'.__('Created').':</th>
+            <td>%s</td>
+        </tr>',$status,
+        Format::db_datetime($task->getCreateDate()));
+
+if (0 && $task->isOpen() && $task->getEstDueDate()) {
+    echo sprintf('
+            <tr>
+                <th>'.__('Due Date').':</th>
+                <td>%s</td>
+            </tr>',
+            Format::db_datetime($task->getEstDueDate()));
+}
+echo '</table>';
+
+
+echo '<hr>
+    <table border="0" cellspacing="" cellpadding="1" width="100%" class="ticket_info">';
+if(0 && $ticket->isOpen()) {
+    echo sprintf('
+            <tr>
+                <th width="100">'.__('Assigned To').':</th>
+                <td>%s</td>
+            </tr>',$ticket->isAssigned()?implode('/', $ticket->getAssignees()):' <span class="faded">&mdash; '.__('Unassigned').' &mdash;</span>');
+}
+echo sprintf(
+    '
+        <tr>
+            <th width="100">'.__('Department').':</th>
+            <td>%s</td>
+        </tr>',
+    Format::htmlchars('Dept. HERE')
+    );
+
+echo '
+    </table>';
+echo '</div>';
+?>
+<div class="tab_content" id="collab_tab_content" style="display:none;">
+    <table border="0" cellspacing="" cellpadding="1">
+        <colgroup><col style="min-width: 250px;"></col></colgroup>
+        <?php
+        if (0 && ($collabs=$task->getCollaborators())) {?>
+        <?php
+            foreach($collabs as $collab) {
+                echo sprintf('<tr><td %s><i class="icon-%s"></i>
+                        <a href="users.php?id=%d" class="no-pjax">%s</a> <em>&lt;%s&gt;</em></td></tr>',
+                        ($collab->isActive()? '' : 'class="faded"'),
+                        ($collab->isActive()? 'comments' :  'comment-alt'),
+                        $collab->getUserId(),
+                        $collab->getName(),
+                        $collab->getEmail());
+            }
+        }  else {
+            echo __("Task doesn't have any collaborators.");
+        }?>
+    </table>
+    <br>
+    <?php
+    echo sprintf('<span><a class="collaborators"
+                            href="#tasks/%d/collaborators">%s</a></span>',
+                            $task->getId(),
+                            0
+                                ? __('Manage Collaborators') : __('Add Collaborator')
+                                );
+    ?>
+</div>
+</div>
+<?php
+$options = array();
+$options[]=array('action'=>sprintf(__('Thread (%d)'),
+            $task->getThread()->getNumEntries()),
+        'url'=>"tickets.php?id=$tid");
+if ($thisstaff->canAssignTickets())
+    $options[]=array('action'=>($task->isAssigned()?__('Reassign'):__('Assign')),'url'=>"tickets.php?id=$tid#assign");
+
+if ($thisstaff->canTransferTickets())
+    $options[]=array('action'=>'Transfer','url'=>"tickets.php?id=$tid#transfer");
+
+if ($thisstaff->canEditTickets())
+    $options[]=array('action'=>'Edit Task','url'=>"tickets.php?id=$tid&a=edit");
+
+if ($options) {
+    echo '<ul class="tip_menu">';
+    foreach($options as $option)
+        echo sprintf('<li><a href="%s">%s</a></li>',$option['url'],$option['action']);
+    echo '</ul>';
+}
+
+echo '</div>';
+?>
diff --git a/include/staff/templates/task-view.tmpl.php b/include/staff/templates/task-view.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..686ffa6fe3f4ee3fcca96629e220843ec36e22de
--- /dev/null
+++ b/include/staff/templates/task-view.tmpl.php
@@ -0,0 +1,311 @@
+<?php
+if (!defined('OSTSCPINC') || !$thisstaff || !is_object($task))
+    die('Invalid path');
+
+//Make sure the staff is allowed to access this task
+/*
+ if (!@$thisstaff->isStaff() || !$task->checkStaffAccess($thisstaff))
+    die('Access Denied');
+*/
+
+//Re-use the post info on error...savekeyboards.org (Why keyboard? -> some people care about objects than users!!)
+$info=($_POST && $errors)?Format::input($_POST):array();
+
+/*
+$dept  = $task->getDept();  //Dept
+$staff = $task->getStaff(); //Assigned or closed by..
+$team  = $task->getTeam();  //Assigned team.
+*/
+$id    = $task->getId();    //Ticket ID.
+if ($task->isOverdue())
+    $warn.='&nbsp;&nbsp;<span class="Icon overdueTicket">'.__('Marked overdue!').'</span>';
+
+?>
+<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
+                echo sprintf(__('Task #%s'), $task->getNumber()); ?></a>
+            </h3>
+        </td>
+        <td width="auto" class="flush-right has_bottom_border">
+            <span>
+                <i class="icon-list"></i>
+                <select name="task-action">
+                    <option value="" selected="selected">
+                    <?php echo _('Task Options'); ?>
+                    </option>
+                </select>
+            </span>
+        </td>
+    </tr>
+</table>
+<table class="ticket_info" cellspacing="0" cellpadding="0" width="940" border="0">
+    <tr>
+        <td width="50%">
+            <table border="0" cellspacing="" cellpadding="4" width="100%">
+                <tr>
+                    <th width="100"><?php echo __('Status');?>:</th>
+                    <td><?php echo $task->getStatus(); ?></td>
+                </tr>
+                <tr>
+                    <th><?php echo __('Department');?>:</th>
+                    <td><?php echo Format::htmlchars( (string) $task->getDept()); ?></td>
+                </tr>
+                <tr>
+                    <th><?php echo __('Create Date');?>:</th>
+                    <td><?php echo Format::db_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>
+                    <th width="100"><?php echo __('Assigned To');?>:</th>
+                    <td>
+                        <?php
+                        if ( 0 && $ticket->isAssigned())
+                            echo Format::htmlchars(implode('/', $ticket->getAssignees()));
+                        else
+                            echo '<span class="faded">&mdash; '.__('Unassigned').' &mdash;</span>';
+                        ?>
+                    </td>
+                </tr>
+                <?php
+                } else { ?>
+                <tr>
+                    <th width="100"><?php echo __('Closed By');?>:</th>
+                    <td>
+                        <?php
+                        if (0 && ($staff = $task->getStaff()))
+                            echo Format::htmlchars($staff->getName());
+                        else
+                            echo '<span class="faded">&mdash; '.__('Unknown').' &mdash;</span>';
+                        ?>
+                    </td>
+                </tr>
+                <?php
+                } ?>
+                <tr>
+                    <th><?php echo __('SLA Plan');?>:</th>
+                    <td><?php echo $sla?Format::htmlchars($sla->getName()):'<span class="faded">&mdash; '.__('None').' &mdash;</span>'; ?></td>
+                </tr>
+                <?php
+                if($task->isOpen()){ ?>
+                <tr>
+                    <th><?php echo __('Due Date');?>:</th>
+                    <td><?php echo 'here'; //Format::db_datetime($ticket->getEstDueDate()); ?></td>
+                </tr>
+                <?php
+                }else { ?>
+                <tr>
+                    <th><?php echo __('Close Date');?>:</th>
+                    <td><?php echo 0 ?
+                    Format::db_datetime($task->getCloseDate()) : ' recently! '; ?></td>
+                </tr>
+                <?php
+                }
+                ?>
+            </table>
+        </td>
+    </tr>
+</table>
+<br>
+<br>
+<table class="ticket_info" cellspacing="0" cellpadding="0" width="940" border="0">
+<?php
+$idx = 0;
+foreach (DynamicFormEntry::forObject($task->getId(),
+            ObjectModel::OBJECT_TYPE_TASK) as $form) {
+    $answers = array_filter($form->getAnswers(), function ($a) {
+            return $a->getField()->isStorable();
+        });
+    if (count($answers) == 0)
+        continue;
+    ?>
+        <tr>
+        <td colspan="2">
+            <table cellspacing="0" cellpadding="4" width="100%" border="0">
+            <?php foreach($answers as $a) {
+                if (!($v = $a->display())) continue; ?>
+                <tr>
+                    <th width="100"><?php
+                        echo $a->getField()->get('label');
+                    ?>:</th>
+                    <td><?php
+                        echo $v;
+                    ?></td>
+                </tr>
+                <?php
+            } ?>
+            </table>
+        </td>
+        </tr>
+    <?php
+    $idx++;
+} ?>
+</table>
+<div class="clear"></div>
+<div id="task_thread_container">
+    <div id="task_thread_content">
+    <?php
+    $threadTypes=array('M'=>'message','R'=>'response', 'N'=>'note');
+    /* -------- Messages & Responses & Notes (if inline)-------------*/
+    $types = array('M', 'R', 'N');
+    if(($thread=$task->getThreadEntries($types))) {
+       foreach($thread as $entry) { ?>
+        <table class="thread-entry <?php echo $threadTypes[$entry['type']]; ?>" cellspacing="0" cellpadding="1" width="940" border="0">
+            <tr>
+                <th colspan="4" width="100%">
+                <div>
+                    <span class="pull-left">
+                    <span style="display:inline-block"><?php
+                        echo Format::db_datetime($entry['created']);?></span>
+                    <span style="display:inline-block;padding:0 1em" class="faded title"><?php
+                        echo Format::truncate($entry['title'], 100); ?></span>
+                    </span>
+                    <span class="pull-right" style="white-space:no-wrap;display:inline-block">
+                        <span style="vertical-align:middle;" class="textra"></span>
+                        <span style="vertical-align:middle;"
+                            class="tmeta faded title"><?php
+                            echo Format::htmlchars($entry['name'] ?: $entry['poster']); ?></span>
+                    </span>
+                </div>
+                </th>
+            </tr>
+            <tr><td colspan="4" class="thread-body" id="thread-id-<?php
+                echo $entry['id']; ?>"><div><?php
+                echo $entry['body']->toHtml(); ?></div></td></tr>
+            <?php
+            $urls = null;
+            if($entry['attachments']
+                    && ($tentry = $task->getThreadEntry($entry['id']))
+                    && ($urls = $tentry->getAttachmentUrls())
+                    && ($links = $tentry->getAttachmentsLinks())) {?>
+            <tr>
+                <td class="info" colspan="4"><?php echo $links; ?></td>
+            </tr> <?php
+            }
+            if ($urls) { ?>
+                <script type="text/javascript">
+                    $('#thread-id-<?php echo $entry['id']; ?>')
+                        .data('urls', <?php
+                            echo JsonDataEncoder::encode($urls); ?>)
+                        .data('id', <?php echo $entry['id']; ?>);
+                </script>
+<?php
+            } ?>
+        </table>
+        <?php
+        if ($entry['type'] == 'M')
+            $msgId = $entry['id'];
+       }
+    } else {
+        echo '<p>'.__('Error fetching thread - get technical help.').'</p>';
+    }?>
+   </div>
+</div>
+<div class="clear" style="padding-bottom:10px;"></div>
+<?php if($errors['err']) { ?>
+    <div id="msg_error"><?php echo $errors['err']; ?></div>
+<?php }elseif($msg) { ?>
+    <div id="msg_notice"><?php echo $msg; ?></div>
+<?php }elseif($warn) { ?>
+    <div id="msg_warning"><?php echo $warn; ?></div>
+<?php } ?>
+<div id="response_options">
+    <ul class="tabs"></ul>
+    <form id="task_note"
+        action="#tasks/<? echo $task->getId(); ?>"
+        name="task_note"
+        method="post" enctype="multipart/form-data">
+        <?php csrf_token(); ?>
+        <input type="hidden" name="id" value="<?php echo $task->getId(); ?>">
+        <input type="hidden" name="a" value="postnote">
+        <table width="100%" border="0" cellspacing="0" cellpadding="3">
+            <tr>
+                <td>
+                    <div>
+                        <div class="faded" style="padding-left:0.15em"><?php
+                        echo __('Note title - summary of the note (optional)'); ?></div>
+                        <input type="text" name="title" id="title" size="60" value="<?php echo $info['title']; ?>" >
+                        <br/>
+                        <span class="error">&nbsp;<?php echo $errors['title']; ?></span>
+                    </div>
+                    <div>
+                        <label><strong><?php echo __('Internal Note'); ?></strong><span class='error'>&nbsp;* <?php echo $errors['note']; ?></span></label>
+                    </div>
+                    <textarea name="note" id="internal_note" cols="80"
+                        placeholder="<?php echo __('Note details'); ?>"
+                        rows="9" wrap="soft" data-draft-namespace="task.note"
+                        data-draft-object-id="<?php echo $task->getId(); ?>"
+                        class="richtext ifhtml draft draft-delete"><?php
+                        echo $info['note'];
+                        ?></textarea>
+                    <div class="attachments">
+                    <?php
+                        if ($task_note_form)
+                            print $task_note_form->getField('attachments')->render();
+                    ?>
+                    </div>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    <div><?php echo __('Task Status');?>
+                        <span class="faded"> - </span>
+                        <select  name="task_status">
+                            <option value="1" <?php
+                                echo $task->isOpen() ?
+                                'selected="selected"': ''; ?>> <?php
+                                echo _('Open'); ?></option>
+                            <option value="0" <?php
+                                echo $task->isClosed() ?
+                                'selected="selected"': ''; ?>> <?php
+                                echo _('Closed'); ?></option>
+                        </select>
+                        &nbsp;<span class='error'><?php echo
+                        $errors['task_status']; ?></span>
+                    </div>
+                </td>
+            </tr>
+        </table>
+       <p  style="padding-left:165px;">
+           <input class="btn_sm" type="submit" value="<?php echo __('Post Note');?>">
+           <input class="btn_sm" type="reset" value="<?php echo __('Reset');?>">
+       </p>
+    </form>
+ </div>
+<script type="text/javascript">
+$(function() {
+    $(document).on('click', 'a.active#ticket_tasks', function(e) {
+        e.preventDefault();
+        $('div#task_content').hide().empty();
+        $('div#tasks_content').show();
+        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/templates/task.tmpl.php b/include/staff/templates/task.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..959a80c73a8d52055b8954b9cbf9f6f96a973ba9
--- /dev/null
+++ b/include/staff/templates/task.tmpl.php
@@ -0,0 +1,46 @@
+<?php
+
+if (!$info['title'])
+    $info['title'] = __('New Task');
+
+?>
+<div id="task-form">
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<hr/>
+<?php
+
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['warning']) {
+    echo sprintf('<p id="msg_warning">%s</p>', $info['warning']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} ?>
+<div id="new-task-form" style="display:block;">
+<form method="post" class="org" action="<?php echo $info['action'] ?: '#tasks/add'; ?>">
+    <table width="100%" class="fixed">
+    <?php
+        if (!$form) $form = TaskForm::getInstance();
+        $form->render(true,
+                __('Create New Task'),
+                array(
+                    'draft-namespace' => sprintf('ticket.%d.task',
+                        $ticket->getId()))
+                ); ?>
+    </table>
+    <hr>
+    <p class="full-width">
+        <span class="buttons pull-left">
+            <input type="reset" value="<?php echo __('Reset'); ?>">
+            <input type="button" name="cancel" class="close"
+                value="<?php echo __('Cancel'); ?>">
+        </span>
+        <span class="buttons pull-right">
+            <input type="submit" value="<?php echo __('Create Task'); ?>">
+        </span>
+     </p>
+</form>
+</div>
+<div class="clear"></div>
+</div>
diff --git a/include/staff/ticket-tasks.inc.php b/include/staff/ticket-tasks.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..24f111be56f2e238d055182b4e4ec2e092352b2e
--- /dev/null
+++ b/include/staff/ticket-tasks.inc.php
@@ -0,0 +1,161 @@
+<?php
+
+//TODO: Make it ORM based once we marge other models.
+$select ='SELECT task.*, dept.dept_name '
+        .' ,CONCAT_WS(" ", staff.firstname, staff.lastname) as staff, team.name as team '
+        .' ,IF(staff.staff_id IS NULL,team.name,CONCAT_WS(" ", staff.lastname, staff.firstname)) as assigned ';
+
+$from =' FROM '.TASK_TABLE.' task '
+      .' LEFT JOIN '.DEPT_TABLE.' dept ON task.dept_id=dept.dept_id '
+      .' LEFT JOIN '.STAFF_TABLE.' staff ON (task.staff_id=staff.staff_id) '
+      .' LEFT JOIN '.TEAM_TABLE.' team ON (task.team_id=team.team_id) ';
+
+if ($ticket)
+    $where = 'WHERE task.object_type="T" AND task.object_id = '.db_input($ticket->getId());
+
+$query ="$select $from $where ORDER BY task.created DESC";
+
+// Fetch the results
+$results = array();
+$res = db_query($query);
+while ($row = db_fetch_array($res))
+    $results[$row['id']] = $row;
+
+?>
+
+<div id="tasks_content" style="display:block;">
+<div style="width:700px; float:left;">
+   <?php
+    if ($results) {
+        echo '<strong>'.sprintf(_N('Showing %d Task', 'Showing %d Tasks',
+            count($results)), count($results)).'</strong>';
+    } else {
+        echo sprintf(__('%s does not have any tasks'), $ticket? 'Ticket' :
+                'System');
+    }
+   ?>
+</div>
+<div style="float:right;text-align:right;padding-right:5px;">
+    <?php
+    if ($ticket) { ?>
+        <a
+        class="Icon newTicket ticket-action"
+        data-dialog='{"size":"large"}'
+        href="#tickets/<?php
+            echo $ticket->getId(); ?>/add-task"> <?php
+            print __('Add New Task'); ?></a>
+    <?php
+    } ?>
+</div>
+<br/>
+<div>
+<?php
+if ($results) { ?>
+<form action="tickets.php?id=<?php echo $ticket->getId(); ?>" method="POST" name='tasks' style="padding-top:10px;">
+<?php csrf_token(); ?>
+ <input type="hidden" name="a" value="mass_process" >
+ <input type="hidden" name="do" id="action" value="" >
+ <table class="list" border="0" cellspacing="1" cellpadding="2" width="940">
+    <thead>
+        <tr>
+            <?php
+            if (0) {?>
+            <th width="8px">&nbsp;</th>
+            <?php
+            } ?>
+            <th width="70"><?php echo __('Number'); ?></th>
+            <th width="100"><?php echo __('Date'); ?></th>
+            <th width="100"><?php echo __('Status'); ?></th>
+            <th width="300"><?php echo __('Title'); ?></th>
+            <th width="200"><?php echo __('Department'); ?></th>
+            <th width="200"><?php echo __('Assignee'); ?></th>
+        </tr>
+    </thead>
+    <tbody class="tasks">
+    <?php
+    foreach($results as $row) {
+        if (!($task = Task::lookup($row['id'])))
+            continue;
+
+        $flag=null;
+        if ($row['lock_id'])
+            $flag='locked';
+        elseif ($row['isoverdue'])
+            $flag='overdue';
+
+        $assigned='';
+        if ($row['staff_id'])
+            $assigned=sprintf('<span class="Icon staffAssigned">%s</span>',Format::truncate($row['staff'],40));
+        elseif ($row['team_id'])
+            $assigned=sprintf('<span class="Icon teamAssigned">%s</span>',Format::truncate($row['team'],40));
+        else
+            $assigned=' ';
+
+        $status = $task->isOpen() ? '<strong>open</strong>': 'closed';
+
+        $tid=$row['number'];
+        $title = Format::htmlchars(Format::truncate($task->getTitle(),40));
+        $threadcount= $task->getThread()->getNumEntries();
+        ?>
+        <tr id="<?php echo $row['id']; ?>">
+            <?php
+            //Implement mass  action....if need be.
+            if (0) { ?>
+            <td align="center" class="nohover">
+                <input class="ckb" type="checkbox" name="tids[]"
+                value="<?php echo $row['id']; ?>" <?php echo $sel?'checked="checked"':''; ?>>
+            </td>
+            <?php
+            } ?>
+            <td align="center" nowrap>
+              <a class="Icon no-pjax preview"
+                title="<?php echo __('Preview Task'); ?>"
+                href="#tasks/<?php echo $task->getId(); ?>/view"
+                data-preview="#tasks/<?php echo $task->getId(); ?>/preview"
+                ><?php echo $task->getNumber(); ?></a></td>
+            <td align="center" nowrap><?php echo
+            Format::db_datetime($row['created']); ?></td>
+            <td><?php echo $status; ?></td>
+            <td><a <?php if ($flag) { ?> class="no-pjax"
+                    title="<?php echo ucfirst($flag); ?> Task" <?php } ?>
+                    href="#tasks/<?php echo $task->getId(); ?>/view"><?php
+                echo $title; ?></a>
+                 <?php
+                    if ($threadcount>1)
+                        echo "<small>($threadcount)</small>&nbsp;".'<i
+                            class="icon-fixed-width icon-comments-alt"></i>&nbsp;';
+                    if ($row['collaborators'])
+                        echo '<i class="icon-fixed-width icon-group faded"></i>&nbsp;';
+                    if ($row['attachments'])
+                        echo '<i class="icon-fixed-width icon-paperclip"></i>&nbsp;';
+                ?>
+            </td>
+            <td><?php echo Format::truncate($row['dept_name'], 40); ?></td>
+            <td>&nbsp;<?php echo $assigned; ?></td>
+        </tr>
+   <?php
+    }
+    ?>
+    </tbody>
+</table>
+</form>
+<?php
+ } ?>
+</div>
+</div>
+<div id="task_content" style="display:none;">
+</div>
+<script type="text/javascript">
+$(function() {
+    $(document).on('click.tasks', 'tbody.tasks a, a#reload-task', function(e) {
+        e.preventDefault();
+        var url = 'ajax.php/'+$(this).attr('href').substr(1);
+        var $container = $('div#task_content');
+        $container.load(url, function () {
+            $('.tip_box').remove();
+            $('div#tasks_content').hide();
+        }).show();
+        return false;
+     });
+});
+</script>
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 54095699b6015dee25b897cf47df82cb2b4ab717..d8d0e5b43b180dcb604540424e698344848c8daa 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -378,6 +378,12 @@ $tcount+= $ticket->getNumNotes();
 ?>
 <ul  class="tabs threads" id="ticket_tabs" >
     <li><a class="active" href="#ticket_thread"><?php echo sprintf(__('Ticket Thread (%d)'), $tcount); ?></a></li>
+    <li><a id="ticket_tasks" href="<?php
+        echo sprintf('#tickets/%d/tasks', $ticket->getId()); ?>"><?php
+        echo __('Tasks');
+        if ($ticket->getNumTasks())
+            echo sprintf('&nbsp;(%d)', $ticket->getNumTasks());
+        ?></a></li>
 </ul>
 <div id="ticket_tabs_container">
     <div id="ticket_thread" class="tab_content">
diff --git a/scp/ajax.php b/scp/ajax.php
index dc0d35e34821a50a57ff886ff52377c806781846..d0d6f409f4628e114db3833635b848e993dd570a 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -144,6 +144,8 @@ $dispatcher = patterns('',
         url_post('^(?P<tid>\d+)/status$', 'setTicketStatus'),
         url_get('^status/(?P<status>\w+)(?:/(?P<sid>\d+))?$', 'changeSelectedTicketsStatus'),
         url_post('^status/(?P<state>\w+)$', 'setSelectedTicketsStatus'),
+        url_get('^(?P<tid>\d+)/tasks$', 'tasks'),
+        url('^(?P<tid>\d+)/add-task$', 'addTask'),
         url_get('^lookup', 'lookup'),
         url('^search', patterns('ajax.search.php:SearchAjaxAPI',
             url_get('^$', 'getAdvancedSearchDialog'),
@@ -156,6 +158,11 @@ $dispatcher = patterns('',
             url_get('^/field/(?P<id>[\w_!:]+)$', 'addField')
         ))
     )),
+    url('^/tasks/', patterns('ajax.tasks.php:TasksAjaxAPI',
+        url_get('^(?P<tid>\d+)/preview$', 'preview'),
+        url_get('^(?P<tid>\d+)/view$', 'task'),
+        url_post('^(?P<tid>\d+)$', 'task')
+    )),
     url('^/collaborators/', patterns('ajax.tickets.php:TicketsAjaxAPI',
         url_get('^(?P<cid>\d+)/view$', 'viewCollaborator'),
         url_post('^(?P<cid>\d+)$', 'updateCollaborator')
diff --git a/scp/css/scp.css b/scp/css/scp.css
index e797c6083c7d134b349d94b230960d02ade136d2..0d76bf2ba467afd9ff21f10e99c9f039bdc3fb2e 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -459,7 +459,7 @@ table.list thead th {
     color:#000;
     text-align:left;
     vertical-align:top;
-    padding: 2px 4px;
+    padding: 4px 5px;
 }
 
 table.list th a {
@@ -468,7 +468,7 @@ table.list th a {
     color:#000;
 }
 
-table.list thead th a { padding: 3px; padding-right: 15px; display: block; white-space: nowrap; color: #000; background: url('../images/asc_desc.gif') 100% 50% no-repeat; }
+table.list thead th a { padding-right: 15px; display: block; white-space: nowrap; color: #000; background: url('../images/asc_desc.gif') 100% 50% no-repeat; }
 
 table.list thead th a.asc { background: url('../images/asc.gif') 100% 50% no-repeat #cfe6ff; }
 table.list thead th a.desc { background: url('../images/desc.gif') 100% 50% no-repeat #cfe6ff; }