diff --git a/include/ajax.tasks.php b/include/ajax.tasks.php index e58507401e859115a20cc05458781227982f7454..ab8bce914e6b87629fc43d12ff14deaaaf137cc5 100644 --- a/include/ajax.tasks.php +++ b/include/ajax.tasks.php @@ -32,6 +32,98 @@ class TasksAjaxAPI extends AjaxController { include STAFFINC_DIR . 'templates/task-preview.tmpl.php'; } + function edit($tid) { + global $thisstaff; + + // TODO: check staff's access. + if(!$thisstaff || !($task=Task::lookup($tid))) + Http::response(404, __('No such task')); + + $info = $errors = array(); + $forms = DynamicFormEntry::forObject($task->getId(), + ObjectModel::OBJECT_TYPE_TASK); + + if ($_POST) { + $info = Format::htmlchars($_POST); + $info['error'] = $errors['err'] ?: __('Coming soon!'); + } + + include STAFFINC_DIR . 'templates/task-edit.tmpl.php'; + } + + function transfer($tid) { + global $thisstaff; + + // TODO: check staff's access. + if(!$thisstaff || !($task=Task::lookup($tid))) + Http::response(404, __('No such task')); + + $info = $errors = array(); + if ($_POST) { + if ($task->transfer($_POST, $errors)) { + Http::response(201, $task->getId()); + + } + + $info = Format::htmlchars($_POST); + $info['error'] = $errors['err'] ?: __('Unable to transfer task'); + } + + include STAFFINC_DIR . 'templates/task-transfer.tmpl.php'; + } + + function assign($tid) { + global $thisstaff; + + // TODO: check staff's access. + if(!$thisstaff || !($task=Task::lookup($tid))) + Http::response(404, __('No such task')); + + $info = $errors = array(); + if ($_POST) { + if ($task->assign($_POST, $errors)) { + Http::response(201, $task->getId()); + + } + + $info = Format::htmlchars($_POST); + $info['error'] = $errors['err'] ?: __('Unable to assign task'); + } + + include STAFFINC_DIR . 'templates/task-assign.tmpl.php'; + } + + function delete($tid) { + global $thisstaff; + + // TODO: check staff's access. + if(!$thisstaff || !($task=Task::lookup($tid))) + Http::response(404, __('No such task')); + + $info = $errors = array(); + if ($_POST) { + if ($task->delete($_POST, $errors)) { + Http::response(201, 0); + + } + + $info = Format::htmlchars($_POST); + $info['error'] = $errors['err'] ?: __('Unable to delete task'); + } + $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>', + __('Deleted tasks CANNOT be recovered, including any associated attachments.') + ); + + include STAFFINC_DIR . 'templates/task-delete.tmpl.php'; + } + + function task($tid) { global $thisstaff; @@ -54,7 +146,6 @@ class TasksAjaxAPI extends AjaxController { $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 diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 28c97eaf8c777348649cce147f44c9bc3d14e65c..6cd63e98ad71c3603754b88e25cc78ee61d1bf4b 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -872,17 +872,39 @@ class TicketsAjaxAPI extends AjaxController { || !$ticket->checkStaffAccess($thisstaff)) Http::response(404, 'Unknown ticket'); - $info = array(); + $info=$errors=array(); if ($_POST) { - /* Draft::deleteForNamespace( sprintf('ticket.%d.task', $ticket->getId()), $thisstaff->getId()); - */ + // Default form $form = TaskForm::getDefaultForm()->getForm($_POST); - if ($form && ($task = Task::create($form, $ticket))) - Http::response(201, $task->to_json()); + // Internal form + $iform = TaskForm::getInternalForm($_POST); + $isvalid = true; + if (!$iform->isValid()) + $isvalid = false; + if (!$form->isValid()) + $isvalid = false; + + if ($isvalid) { + $vars = $_POST; + $vars['object_id'] = $ticket->getId(); + $vars['object_type'] = ObjectModel::OBJECT_TYPE_TICKET; + $vars['default_formdata'] = $form->getClean(); + $vars['internal_formdata'] = $iform->getClean(); + $desc = $form->getField('description'); + if ($desc + && $desc->isAttachmentsEnabled() + && ($attachments=$desc->getWidget()->getAttachments())) + $vars['cannedattachments'] = $attachments->getClean(); + $vars['staffId'] = $thisstaff->getId(); + $vars['poster'] = $thisstaff; + $vars['ip_address'] = $_SERVER['REMOTE_ADDR']; + if (($task=Task::create($vars, $errors))) + Http::response(201, $task->getId()); + } $info['error'] = __('Error adding task - try again!'); } diff --git a/include/class.forms.php b/include/class.forms.php index 25ee52ce1a427caa6f514abf57dcd65daf710362..4188797bddf25a7496b4e6a382224c1651b8e296 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -1547,6 +1547,139 @@ FormField::addFieldTypes(/*@trans*/ 'Dynamic Fields', function() { }); +class DepartmentField extends ChoiceField { + function getWidget() { + $widget = parent::getWidget(); + if ($widget->value instanceof Dept) + $widget->value = $widget->value->getId(); + return $widget; + } + + function hasIdValue() { + return true; + } + + function getChoices() { + global $cfg; + + $choices = array(); + if (($depts = Dept::getDepartments())) + foreach ($depts as $id => $name) + $choices[$id] = $name; + + return $choices; + } + + function parse($id) { + return $this->to_php(null, $id); + } + + function to_php($value, $id=false) { + if (is_array($id)) { + reset($id); + $id = key($id); + } + return $id; + } + + function to_database($dept) { + return ($dept instanceof Dept) + ? array($dept->getName(), $dept->getId()) + : $dept; + } + + function toString($value) { + return (string) $value; + } + + function searchable($value) { + return null; + } + + function getConfigurationOptions() { + return array( + 'prompt' => new TextboxField(array( + 'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'', + 'hint'=>__('Leading text shown before a value is selected'), + 'configuration'=>array('size'=>40, 'length'=>40), + )), + ); + } +} +FormField::addFieldTypes(/*@trans*/ 'Dynamic Fields', function() { + return array( + 'department' => array(__('Department'), DepartmentField), + ); +}); + + +class AssigneeField extends ChoiceField { + function getWidget() { + $widget = parent::getWidget(); + if (is_object($widget->value)) + $widget->value = $widget->value->getId(); + return $widget; + } + + function hasIdValue() { + return true; + } + + function getChoices() { + global $cfg; + $choices = array(); + if (($agents = Staff::getAvailableStaffMembers())) + foreach ($agents as $id => $name) + $choices[$id] = $name; + + return $choices; + } + + function parse($id) { + return $this->to_php(null, $id); + } + + function to_php($value, $id=false) { + if (is_array($id)) { + reset($id); + $id = key($id); + } + + return $id; + } + + + function to_database($value) { + return (is_object($value)) + ? array($value->getName(), $value->getId()) + : $value; + } + + function toString($value) { + return (string) $value; + } + + function searchable($value) { + return null; + } + + function getConfigurationOptions() { + return array( + 'prompt' => new TextboxField(array( + 'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'', + 'hint'=>__('Leading text shown before a value is selected'), + 'configuration'=>array('size'=>40, 'length'=>40), + )), + ); + } +} +FormField::addFieldTypes(/*@trans*/ 'Dynamic Fields', function() { + return array( + 'assignee' => array(__('Assignee'), AssigneeField), + ); +}); + + class TicketStateField extends ChoiceField { static $_states = array( diff --git a/include/class.role.php b/include/class.role.php index 1f2ab4d8cda60f1f16130a1a1dba505e0823cc34..38fbc68a93465250611c7165a9c7e842ca5b207e 100644 --- a/include/class.role.php +++ b/include/class.role.php @@ -297,7 +297,7 @@ class RolePermission { 'task.close' => array( /* @trans */ 'Close', /* @trans */ 'Ability to close tasks'), - 'tasks.delete' => array( + 'task.delete' => array( /* @trans */ 'Delete', /* @trans */ 'Ability to delete tasks'), ), @@ -373,7 +373,7 @@ class RolePermission { return ($this->has('ticket.transfer')); } - function canPostReply() { + function canPostTicketReply() { return ($this->has('ticket.reply')); } @@ -385,6 +385,35 @@ class RolePermission { return ($this->has('ticket.delete')); } + /* tasks */ + function canCreateTasks() { + return ($this->get('task.create')); + } + + function canEditTasks() { + return ($this->get('task.edit')); + } + + function canAssignTasks() { + return ($this->get('task.assign')); + } + + function canTransferTasks() { + return ($this->get('task.transfer')); + } + + function canPostTaskReply() { + return ($this->get('task.reply')); + } + + function canCloseTasks() { + return ($this->get('task.close')); + } + + function canDeleteTasks() { + return ($this->get('task.delete')); + } + /* Knowledge base */ function canManagePremade() { return ($this->has('kb.premade')); diff --git a/include/class.task.php b/include/class.task.php index 57767a41f1d17db7922446c8b056ad1dccdd25a8..9b155e249a94b9b20ebf89295b76b23e26d05485 100644 --- a/include/class.task.php +++ b/include/class.task.php @@ -5,10 +5,14 @@ class TaskModel extends VerySimpleModel { 'table' => TASK_TABLE, 'pk' => array('id'), 'joins' => array( - 'thread' => array( - 'reverse' => 'ThreadModel.object', + 'dept' => array( + 'constraint' => array('dept_id' => 'Dept.id'), ), - ) + 'staff' => array( + 'constraint' => array('staff_id' => 'Staff.staff_id'), + 'null' => true, + ), + ), ); const ISOPEN = 0x0001; @@ -86,6 +90,8 @@ class Task extends TaskModel { var $entry; var $thread; + var $_entries; + function getStatus() { return $this->isOpen() ? _('Open') : _('Closed'); @@ -95,9 +101,23 @@ class Task extends TaskModel { return $this->__cdata('title', ObjectModel::OBJECT_TYPE_TASK); } + function getAssignees() { + + $assignees=array(); + if ($this->staff) + $assignees[] = $this->staff->getName(); + + //Add team assignment + if (isset($this->team)) + $assignees[] = $this->team->getName(); + + return $assignees; + } + + function getAssigned($glue='/') { + $assignees = $this->getAssignees(); - function getDept() { - return "Dept Object"; + return $assignees ? implode($glue, $assignees):''; } function getThread() { @@ -199,6 +219,68 @@ class Task extends TaskModel { } /* util routines */ + function assign($vars, &$errors) { + global $thisstaff; + + if (!isset($vars['staff_id']) || !($staff=Staff::lookup($vars['staff_id']))) + $errors['staff_id'] = __('Agent selection required'); + elseif ($staff->getid() == $this->getStaffId()) + $errors['dept_id'] = __('Task already assigned to agent'); + else + $this->staff_id = $staff->getId(); + + if ($errors || !$this->save()) + return false; + + // Transfer completed... post internal note. + $title = sprintf(__('Task assigned to %s'), + $staff->getName()); + if ($vars['comments']) { + $note = $vars['comments']; + } else { + $note = $title; + $title = ''; + } + + $this->postNote( + array('note' => $note, 'title' => $title), + $errors, + $thisstaff); + + return true; + } + + function transfer($vars, &$errors) { + global $thisstaff; + + if (!isset($vars['dept_id']) || !($dept=Dept::lookup($vars['dept_id']))) + $errors['dept_id'] = __('Department selection required'); + elseif ($dept->getid() == $this->getDeptId()) + $errors['dept_id'] = __('Task already in the department'); + else + $this->dept_id = $dept->getId(); + + if ($errors || !$this->save()) + return false; + + // Transfer completed... post internal note. + $title = sprintf(__('Task transfered to %s department'), + $dept->getName()); + if ($vars['comments']) { + $note = $vars['comments']; + } else { + $note = $title; + $title = ''; + } + + $this->postNote( + array('note' => $note, 'title' => $title), + $errors, + $thisstaff); + + return true; + } + function postNote($vars, &$errors, $poster='', $alert=true) { global $cfg, $thisstaff; @@ -216,7 +298,7 @@ class Task extends TaskModel { if (isset($vars['task_status'])) { if ($vars['task_status']) - $this->open(); + $this->reopen(); else $this->close(); @@ -238,55 +320,69 @@ class Task extends TaskModel { return !self::lookupIdByNumber($number); } - static function create($form, $object) { - global $cfg, $thisstaff; + static function create($vars) { + global $cfg; - if (!$thisstaff - || !$form - // TODO: Make sure it's an instance of ORM Model - || !$object) - return null; + $task = parent::create(array( + 'flags' => self::ISOPEN, + 'object_id' => $vars['object_id'], + 'object_type' => $vars['object_type'], + 'number' => $cfg->getNewTaskNumber(), + 'created' => new SqlFunction('NOW'), + 'updated' => new SqlFunction('NOW'), + )); + // Save internal fields. + if ($vars['internal_formdata']['staff_id']) + $task->staff_id = $vars['internal_formdata']['staff_id']; + if ($vars['internal_formdata']['dept_id']) + $task->dept_id = $vars['internal_formdata']['dept_id']; + if ($vars['internal_formdata']['duedate']) + $task->duedate = $vars['internal_formdata']['duedate']; - if (!$form->isValid()) - return false; + $task->save(true); - try { - - $task = parent::create(array( - 'flags' => 1, - 'object_id' => $object->getId(), - 'object_type' => $object->getObjectType(), - 'number' => $cfg->getNewTaskNumber(), - 'created' => new SqlFunction('NOW'), - 'updated' => new SqlFunction('NOW'), - )); - $task->save(true); - } catch(OrmException $e) { - return null; - } + // Add dynamic data + $task->addDynamicData($vars['default_formdata']); - $vars = $form->getClean(); - $task->addDynamicData($vars); // Create a thread + message. $thread = TaskThread::create($task); - $desc = $form->getField('description'); - if ($desc - && $desc->isAttachmentsEnabled() - && ($attachments=$desc->getWidget()->getAttachments())) - $vars['cannedattachments'] = $attachments->getClean(); - - $vars['staffId'] = $thisstaff->getId(); - $vars['poster'] = $thisstaff; - if (!$vars['ip_address'] && $_SERVER['REMOTE_ADDR']) - $vars['ip_address'] = $_SERVER['REMOTE_ADDR']; - $thread->addDescription($vars); - Signal::send('model.created', $task); return $task; } + function delete($comments='') { + global $ost, $thisstaff; + + $thread = $this->getThread(); + + if (!parent::delete()) + return false; + + $thread->delete(); + + Draft::deleteForNamespace('task.%.' . $this->getId()); + + foreach (DynamicFormEntry::forObject($this->getId(), ObjectModel::OBJECT_TYPE_TASK) as $form) + $form->delete(); + + // Log delete + $log = sprintf(__('Task #%1$s deleted by %2$s'), + $this->getNumber(), + $thisstaff ? $thisstaff->getName() : __('SYSTEM')); + + if ($comments) + $log .= sprintf('<hr>%s', $comments); + + $ost->logDebug( + sprintf( __('Task #%s deleted'), $this->getNumber()), + $log); + + return true; + + } + static function __loadDefaultForm() { require_once INCLUDE_DIR.'class.i18n.php'; @@ -305,7 +401,10 @@ class Task extends TaskModel { class TaskForm extends DynamicForm { static $instance; - static $form; + static $defaultForm; + static $internalForm; + + static $forms; static function objects() { $os = parent::objects(); @@ -313,12 +412,12 @@ class TaskForm extends DynamicForm { } static function getDefaultForm() { - if (!isset(static::$form)) { + if (!isset(static::$defaultForm)) { if (($o = static::objects()) && $o[0]) - static::$form = $o[0]; + static::$defaultForm = $o[0]; } - return static::$form; + return static::$defaultForm; } static function getInstance($object_id=0, $new=false) { @@ -332,6 +431,43 @@ class TaskForm extends DynamicForm { return static::$instance; } + + static function getInternalForm($source=null) { + if (!isset(static::$internalForm)) + static::$internalForm = new Form(self::getInternalFields(), $source); + + return static::$internalForm; + } + + static function getInternalFields() { + return array( + 'dept_id' => new DepartmentField(array( + 'id'=>1, + 'label' => __('Department'), + 'flags' => hexdec(0X450F3), + 'required' => true, + )), + 'staff_id' => new AssigneeField(array( + 'id'=>2, + 'label' => __('Assignee'), + 'flags' => hexdec(0X450F3), + 'required' => false, + )), + 'duedate' => new DatetimeField(array( + 'id' => 3, + 'label' => __('Due Date'), + 'flags' => hexdec(0X450B3), + 'required' => false, + 'configuration' => array( + 'min' => Misc::gmtime(), + 'time' => true, + 'gmt' => true, + 'future' => true, + ), + )), + + ); + } } // Task thread class diff --git a/include/class.ticket.php b/include/class.ticket.php index 64fb7dcb00cae7542ec497b54281e405951bd2fd..eb46e86c4278659806e2f54349063885b08c7964 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -3031,7 +3031,7 @@ class Ticket { // post response - if any $response = null; - if($vars['response'] && $role->canPostReply()) { + if($vars['response'] && $role->canPostTicketReply()) { $vars['response'] = $ticket->replaceVars($vars['response']); // $vars['cannedatachments'] contains the attachments placed on diff --git a/include/i18n/en_US/form.yaml b/include/i18n/en_US/form.yaml index 6e3d4c9e99e0df2309f129af394b292a11eb1f2c..7d1eb9aa2f5303d1c35b2c04c9a9b15102b1e9de 100644 --- a/include/i18n/en_US/form.yaml +++ b/include/i18n/en_US/form.yaml @@ -185,35 +185,20 @@ title: Task Details instructions: Please Describe The Issue notes: | - This form is used to create tasks. + This form is used to create a task. deletable: false fields: - type: text # notrans name: title # notrans - label: Title - required: true - edit_mask: 15 - flags: 1 + flags: 0x470B1 sort: 1 + label: Title configuration: size: 40 length: 50 - type: thread # notrans name: description # notrans + flags: 0x450B3 + sort: 2 label: Description hint: Details on the reason(s) for creating the task. - required: true - edit_mask: 15 - flags: 3 - sort: 2 - - type: datetime # notrans - name: duedate # notrans - label: Due Date - required: false - edit_mask: 15 - flags: 3 - sort: 3 - configuration: - time: true - gmt: true - future: true diff --git a/include/staff/templates/task-assign.tmpl.php b/include/staff/templates/task-assign.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..0c5dd7a5eac411e9f78ab99e0096a0dd671187a8 --- /dev/null +++ b/include/staff/templates/task-assign.tmpl.php @@ -0,0 +1,95 @@ +<?php +global $cfg; + +if (!$info['title']) + $info['title'] = sprintf(__('%s Tasks #%s'), + $task->isAssigned() ? __('Reassign') : __('Assign'), + $task->getNumber() + ); + +?> +<h3><?php echo $info['title']; ?></h3> +<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> +<div class="clear"></div> +<hr/> +<?php +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['warn']) { + echo sprintf('<p id="msg_warning">%s</p>', $info['warn']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} elseif ($info['notice']) { + echo sprintf('<p id="msg_info"><i class="icon-info-sign"></i> %s</p>', + $info['notice']); +} + + +$action = $info['action'] ?: ('#tasks/'.$task->getId().'/assign'); +?> +<div id="ticket-status" style="display:block; margin:5px;"> +<form method="post" name="transfer" id="transfer" + action="<?php echo $action; ?>"> + <table width="100%"> + <?php + if ($info['extra']) { + ?> + <tbody> + <tr><td colspan="2"><strong><?php echo $info['extra']; + ?></strong></td> </tr> + </tbody> + <?php + } + ?> + <tbody> + <tr><td colspan=2> + <span> + <strong><?php echo __('Agent') ?>: </strong> + <select name="staff_id"> + <?php + foreach (Staff::getAvailableStaffMembers() as $id => $name) { + echo sprintf('<option value="%d" %s>%s</option>', + $id, + ($info['staff_id'] == $id) + ? 'selected="selected"' : '', + $name + ); + } + ?> + </select> + <font class="error">* <?php echo + $errors['dept_id']; ?></font> + </span> + </td> </tr> + </tbody> + <tbody> + <tr> + <td colspan="2"> + <?php + $placeholder = $info['placeholder'] ?: __('Optional reason for the assignment'); + ?> + <textarea name="comments" id="comments" + cols="50" rows="3" wrap="soft" style="width:100%" + class="<?php if ($cfg->isHtmlThreadEnabled()) echo 'richtext'; + ?> no-bar" + placeholder="<?php echo $placeholder; ?>"><?php + echo $info['comments']; ?></textarea> + </td> + </tr> + </tbody> + </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 $verb ?: __('Submit'); ?>"> + </span> + </p> +</form> +</div> +<div class="clear"></div> diff --git a/include/staff/templates/task-delete.tmpl.php b/include/staff/templates/task-delete.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..6014bd88aa6be37d1027d01cbb083ba6b4d03b1b --- /dev/null +++ b/include/staff/templates/task-delete.tmpl.php @@ -0,0 +1,74 @@ +<?php +global $cfg; + +if (!$info['title']) + $info['title'] = sprintf(__('%s Tasks #%s'), + __('Delete'), + $task->getNumber() + ); + +?> +<h3><?php echo $info['title']; ?></h3> +<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> +<div class="clear"></div> +<hr/> +<?php +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['warn']) { + echo sprintf('<p id="msg_warning">%s</p>', $info['warn']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} elseif ($info['notice']) { + echo sprintf('<p id="msg_info"><i class="icon-info-sign"></i> %s</p>', + $info['notice']); +} + + +$action = $info['action'] ?: ('#tasks/'.$task->getId().'/delete'); +?> +<div id="ticket-status" style="display:block; margin:5px;"> +<form method="post" name="delete" id="delete" + action="<?php echo $action; ?>"> + <table width="100%"> + <?php + if ($info['extra']) { + ?> + <tbody> + <tr><td colspan="2"><strong><?php echo $info['extra']; + ?></strong></td> </tr> + </tbody> + <?php + } + ?> + <tbody> + <tr> + <td colspan="2"> + <?php + $placeholder = $info['placeholder'] ?: __('Optional reason for the deletion'); + ?> + <textarea name="comments" id="comments" + cols="50" rows="3" wrap="soft" style="width:100%" + class="<?php if ($cfg->isHtmlThreadEnabled()) echo 'richtext'; + ?> no-bar" + placeholder="<?php echo $placeholder; ?>"><?php + echo $info['comments']; ?></textarea> + </td> + </tr> + </tbody> + </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 $verb ?: __('Submit'); ?>"> + </span> + </p> +</form> +</div> +<div class="clear"></div> diff --git a/include/staff/templates/task-edit.tmpl.php b/include/staff/templates/task-edit.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..a77079e251be82ab85d584083a05a540fe2eb977 --- /dev/null +++ b/include/staff/templates/task-edit.tmpl.php @@ -0,0 +1,96 @@ +<?php +global $cfg; + +if (!$info['title']) + $info['title'] = sprintf(__('%s Tasks #%s'), + __('Edit'), $task->getNumber() + ); + +$action = $info['action'] ?: ('#tasks/'.$task->getId().'/edit'); + +?> +<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="edit-task-form" style="display:block;"> +<form method="post" class="task" action="<?php echo $action; ?>"> + + <table class="form_table dynamic-forms" width="100%" border="0" cellspacing="0" cellpadding="2"> + <?php if ($forms) + foreach ($forms as $form) { + $form->render(true, false, array('mode'=>'edit','width'=>160,'entry'=>$form)); + print $form->getForm()->getMedia(); + } ?> + </table> + <table class="form_table dynamic-forms" width="100%" border="0" cellspacing="0" cellpadding="2"> + <tr><th colspan=2><em><?php + echo __('Task Visibility & Assignment'); ?></em></th></tr> + <?php + $iform = $iform ?: TaskForm::getInternalForm(); + foreach ($iform->getFields() as $name=>$field) { + if (!$field->isEditable()) continue; + ?> + <tr> + <td class="multi-line <?php if ($field->get('required')) echo 'required'; + ?>" style="min-width:120px;" width="160"> + <?php echo Format::htmlchars($field->get('label')); ?>:</td> + <td> + <fieldset id="field<?php echo $field->getWidget()->id; + ?>" <?php if (!$field->isVisible()) echo 'style="display:none;"'; ?>> + <?php echo $field->render(); ?> + <?php if ($field->get('required')) { ?> + <span class="error">*</span> + <?php + } + foreach ($field->errors() as $E) { + ?><div class="error"><?php echo $E; ?></div><?php + } ?> + </fieldset> + </td> + </tr> + <?php + } + ?> + </table> + <table class="form_table" width="100%" border="0" cellspacing="0" cellpadding="2"> + <tbody> + <tr> + <th colspan="2"> + <em><strong><?php echo __('Internal Note');?></strong>: <?php + echo __('Reason for editing the task (optional');?> <font class="error"> <?php echo $errors['note'];?></font></em> + </th> + </tr> + <tr> + <td colspan="2"> + <textarea class="richtext no-bar" name="note" cols="21" + rows="6" style="width:80%;"><?php echo $info['note']; + ?></textarea> + </td> + </tr> + </tbody> + </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 __('Update'); ?>"> + </span> + </p> +</form> +</div> +<div class="clear"></div> +</div> diff --git a/include/staff/templates/task-preview.tmpl.php b/include/staff/templates/task-preview.tmpl.php index ab2b9f90cac48499b6dd01bfe20c07ee66d13d26..d6968f49a42da80daa6ccc8f730d548edbd519b0 100644 --- a/include/staff/templates/task-preview.tmpl.php +++ b/include/staff/templates/task-preview.tmpl.php @@ -1,10 +1,7 @@ <?php $error=$msg=$warn=null; -if($lock && $lock->getStaffId()==$thisstaff->getId()) - $warn.=' <span class="Icon lockedTicket">' - .sprintf(__('Ticket is locked by %s'), $lock->getStaffName()).'</span>'; -elseif($task->isOverdue()) +if($task->isOverdue()) $warn.=' <span class="Icon overdueTicket">'.__('Marked overdue!').'</span>'; echo sprintf( @@ -21,21 +18,14 @@ elseif($msg) elseif($warn) echo sprintf('<div id="msg_warning">%s</div>',$warn); -echo '<ul class="tabs" id="ticket-preview">'; +echo '<ul class="tabs" id="task-preview">'; echo ' - <li><a id="preview_tab" href="#preview" class="active" + <li class="active"><a href="#summary" ><i class="icon-list-alt"></i> '.__('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> '.__('Collaborators (%d)').'</a></li>', - $task->getNumCollaborators()); -} echo '</ul>'; -echo '<div id="ticket-preview_container">'; -echo '<div class="tab_content" id="preview_tab_content">'; +echo '<div id="task-preview_container">'; +echo '<div class="tab_content" id="summary">'; echo '<table border="0" cellspacing="" cellpadding="1" width="100%" class="ticket_info">'; $status=sprintf('<span>%s</span>',ucfirst($task->getStatus())); echo sprintf(' @@ -47,27 +37,27 @@ echo sprintf(' <th>'.__('Created').':</th> <td>%s</td> </tr>',$status, - Format::db_datetime($task->getCreateDate())); + Format::datetime($task->getCreateDate())); -if (0 && $task->isOpen() && $task->getEstDueDate()) { +if ($task->isOpen() && $task->duedate) { echo sprintf(' <tr> <th>'.__('Due Date').':</th> <td>%s</td> </tr>', - Format::db_datetime($task->getEstDueDate())); + Format::datetime($task->duedate)); } echo '</table>'; echo '<hr> <table border="0" cellspacing="" cellpadding="1" width="100%" class="ticket_info">'; -if(0 && $ticket->isOpen()) { +if ($task->isOpen()) { echo sprintf(' <tr> <th width="100">'.__('Assigned To').':</th> <td>%s</td> - </tr>',$ticket->isAssigned()?implode('/', $ticket->getAssignees()):' <span class="faded">— '.__('Unassigned').' —</span>'); + </tr>', $task->getAssigned() ?: ' <span class="faded">— '.__('Unassigned').' —</span>'); } echo sprintf( ' @@ -75,63 +65,16 @@ echo sprintf( <th width="100">'.__('Department').':</th> <td>%s</td> </tr>', - Format::htmlchars('Dept. HERE') + Format::htmlchars($task->dept->getName()) ); 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><%s></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>'; -} +//TODO: add link to view if the user has permission echo '</div>'; ?> diff --git a/include/staff/templates/task-transfer.tmpl.php b/include/staff/templates/task-transfer.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..8a872f43845ec328c92554f32125e10682173b89 --- /dev/null +++ b/include/staff/templates/task-transfer.tmpl.php @@ -0,0 +1,93 @@ +<?php +global $cfg; + +if (!$info['title']) + $info['title'] = sprintf(__('%s Tasks #%s'), + __('Tranfer'), $task->getNumber()); + +?> +<h3><?php echo $info['title']; ?></h3> +<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> +<div class="clear"></div> +<hr/> +<?php +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['warn']) { + echo sprintf('<p id="msg_warning">%s</p>', $info['warn']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} elseif ($info['notice']) { + echo sprintf('<p id="msg_info"><i class="icon-info-sign"></i> %s</p>', + $info['notice']); +} + + +$action = $info['action'] ?: ('#tasks/'.$task->getId().'/transfer'); +?> +<div style="display:block; margin:5px;"> +<form method="post" name="transfer" id="transfer" + action="<?php echo $action; ?>"> + <table width="100%"> + <?php + if ($info['extra']) { + ?> + <tbody> + <tr><td colspan="2"><strong><?php echo $info['extra']; + ?></strong></td> </tr> + </tbody> + <?php + } + ?> + <tbody> + <tr><td colspan=2> + <span> + <strong><?php echo __('Department') ?>: </strong> + <select name="dept_id"> + <?php + foreach (Dept::getDepartments() as $id => $name) { + echo sprintf('<option value="%d" %s>%s</option>', + $id, + ($info['dept_id'] == $id) + ? 'selected="selected"' : '', + $name + ); + } + ?> + </select> + <font class="error">* <?php echo + $errors['dept_id']; ?></font> + </span> + </td> </tr> + </tbody> + <tbody> + <tr> + <td colspan="2"> + <?php + $placeholder = $info['placeholder'] ?: __('Optional reason for the transfer'); + ?> + <textarea name="comments" id="comments" + cols="50" rows="3" wrap="soft" style="width:100%" + class="<?php if ($cfg->isHtmlThreadEnabled()) echo 'richtext'; + ?> no-bar" + placeholder="<?php echo $placeholder; ?>"><?php + echo $info['comments']; ?></textarea> + </td> + </tr> + </tbody> + </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 $verb ?: __('Submit'); ?>"> + </span> + </p> +</form> +</div> +<div class="clear"></div> diff --git a/include/staff/templates/task-view.tmpl.php b/include/staff/templates/task-view.tmpl.php index 686ffa6fe3f4ee3fcca96629e220843ec36e22de..217afdc8c20edd5e7652d7d1b5f9be75fd2db96d 100644 --- a/include/staff/templates/task-view.tmpl.php +++ b/include/staff/templates/task-view.tmpl.php @@ -8,14 +8,32 @@ if (!defined('OSTSCPINC') || !$thisstaff || !is_object($task)) die('Access Denied'); */ -//Re-use the post info on error...savekeyboards.org (Why keyboard? -> some people care about objects than users!!) +$actions = array(); +$actions += array( + 'edit' => array( + 'icon' => 'icon-edit', + 'dialog' => '{"size":"large"}', + 'action' => __('Edit') + )); +$actions += array( + 'assign' => array( + 'icon' => 'icon-user', + 'action' => $task->isAssigned() ? __('Reassign') : __('Assign') + )); +$actions += array( + 'transfer' => array( + 'icon' => 'icon-share', + 'action' => __('Transfer') + )); +$actions += array( + 'delete' => array( + 'icon' => 'icon-trash', + 'action' => __('Delete') + )); + + $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.=' <span class="Icon overdueTicket">'.__('Marked overdue!').'</span>'; @@ -30,14 +48,39 @@ if ($task->isOverdue()) </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> + <?php + if ($actions) { ?> + <span + class="action-button" + data-dropdown="#action-dropdown-taskoptions"> + <i class="icon-caret-down pull-right"></i> + <a class="task-action" + href="#taskoptions"><i + class="icon-reorder"></i> <?php + echo __('Task Options'); ?></a> </span> + <div id="action-dropdown-taskoptions" + class="action-dropdown anchor-right"> + <ul> + <?php foreach ($actions as $a => $action) { ?> + <li> + <a class="no-pjax task-action" + <?php + if ($action['dialog']) + echo sprintf("data-dialog='%s'", $action['dialog']); + ?> + href="<?php + echo sprintf('#tasks/%d/%s', $task->getId(), $a); ?>" + ><i class="<?php + echo $action['icon'] ?: 'icon-tag'; ?>"></i> <?php + echo $action['action']; ?></a> + </li> + <?php + } ?> + </ul> + </div> + <?php + } ?> </td> </tr> </table> @@ -51,11 +94,11 @@ if ($task->isOverdue()) </tr> <tr> <th><?php echo __('Department');?>:</th> - <td><?php echo Format::htmlchars( (string) $task->getDept()); ?></td> + <td><?php echo Format::htmlchars($task->dept->getName()); ?></td> </tr> <tr> <th><?php echo __('Create Date');?>:</th> - <td><?php echo Format::db_datetime($task->getCreateDate()); ?></td> + <td><?php echo Format::datetime($task->getCreateDate()); ?></td> </tr> </table> </td> @@ -67,8 +110,8 @@ if ($task->isOverdue()) <th width="100"><?php echo __('Assigned To');?>:</th> <td> <?php - if ( 0 && $ticket->isAssigned()) - echo Format::htmlchars(implode('/', $ticket->getAssignees())); + if ($assigned=$task->getAssigned()) + echo Format::htmlchars($assigned); else echo '<span class="faded">— '.__('Unassigned').' —</span>'; ?> @@ -97,14 +140,16 @@ if ($task->isOverdue()) if($task->isOpen()){ ?> <tr> <th><?php echo __('Due Date');?>:</th> - <td><?php echo 'here'; //Format::db_datetime($ticket->getEstDueDate()); ?></td> + <td><?php echo $task->duedate ? + Format::datetime($task->duedate) : '<span + class="faded">— '.__('None').' —</span>'; ?></td> </tr> <?php }else { ?> <tr> <th><?php echo __('Close Date');?>:</th> <td><?php echo 0 ? - Format::db_datetime($task->getCloseDate()) : ' recently! '; ?></td> + Format::datetime($task->getCloseDate()) : ''; ?></td> </tr> <?php } @@ -163,7 +208,7 @@ foreach (DynamicFormEntry::forObject($task->getId(), <div> <span class="pull-left"> <span style="display:inline-block"><?php - echo Format::db_datetime($entry['created']);?></span> + echo Format::datetime($entry['created']);?></span> <span style="display:inline-block;padding:0 1em" class="faded title"><?php echo Format::truncate($entry['title'], 100); ?></span> </span> @@ -219,7 +264,7 @@ foreach (DynamicFormEntry::forObject($task->getId(), <div id="response_options"> <ul class="tabs"></ul> <form id="task_note" - action="#tasks/<? echo $task->getId(); ?>" + action="#tasks/<?php echo $task->getId(); ?>" name="task_note" method="post" enctype="multipart/form-data"> <?php csrf_token(); ?> @@ -281,7 +326,7 @@ foreach (DynamicFormEntry::forObject($task->getId(), </div> <script type="text/javascript"> $(function() { - $(document).on('click', 'a.active#ticket_tasks', function(e) { + $(document).on('click', 'li.active a#ticket_tasks', function(e) { e.preventDefault(); $('div#task_content').hide().empty(); $('div#tasks_content').show(); diff --git a/include/staff/templates/task.tmpl.php b/include/staff/templates/task.tmpl.php index 959a80c73a8d52055b8954b9cbf9f6f96a973ba9..bf1355bc0ac77b94c672f322eee7e1389674ccf4 100644 --- a/include/staff/templates/task.tmpl.php +++ b/include/staff/templates/task.tmpl.php @@ -21,13 +21,40 @@ if ($info['error']) { <form method="post" class="org" action="<?php echo $info['action'] ?: '#tasks/add'; ?>"> <table width="100%" class="fixed"> <?php - if (!$form) $form = TaskForm::getInstance(); + $form = $form ?: TaskForm::getInstance(); $form->render(true, __('Create New Task'), array( 'draft-namespace' => sprintf('ticket.%d.task', $ticket->getId())) - ); ?> + ); + ?> + <tr><th colspan=2><em><?php + echo __('Task Visibility & Assignment'); ?></em></th></tr> + <?php + $iform = $iform ?: TaskForm::getInternalForm(); + foreach ($iform->getFields() as $name=>$field) { ?> + <tr> + <td class="multi-line <?php if ($field->get('required')) echo 'required'; + ?>" style="min-width:120px;" > + <?php echo Format::htmlchars($field->get('label')); ?>:</td> + <td> + <fieldset id="field<?php echo $field->getWidget()->id; + ?>" <?php if (!$field->isVisible()) echo 'style="display:none;"'; ?>> + <?php echo $field->render(); ?> + <?php if ($field->get('required')) { ?> + <span class="error">*</span> + <?php + } + foreach ($field->errors() as $E) { + ?><div class="error"><?php echo $E; ?></div><?php + } ?> + </fieldset> + </td> + </tr> + <?php + } + ?> </table> <hr> <p class="full-width"> diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php index 7ec099aff6b315bbc6180c6f2f88b5f8841e0b40..642808356b95b644a5a0b9a99921c601cd57f714 100644 --- a/include/staff/ticket-open.inc.php +++ b/include/staff/ticket-open.inc.php @@ -272,7 +272,7 @@ if ($_POST) <tbody> <?php //is the user allowed to post replies?? - if($thisstaff->getRole()->canPostReply()) { ?> + if($thisstaff->getRole()->canPostTicketReply()) { ?> <tr> <th colspan="2"> <em><strong><?php echo __('Response');?></strong>: <?php echo __('Optional response to the above issue.');?></em> diff --git a/include/staff/ticket-tasks.inc.php b/include/staff/ticket-tasks.inc.php index 24f111be56f2e238d055182b4e4ec2e092352b2e..d4cf59e5f133cd06dc5d243872752fa6e61c6429 100644 --- a/include/staff/ticket-tasks.inc.php +++ b/include/staff/ticket-tasks.inc.php @@ -1,36 +1,22 @@ <?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 '; +$tasks = Task::objects() + ->select_related('dept', 'staff') + ->order_by('-created'); -$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; +$count = $tasks->count(); +$pageNav = new Pagenate($count,1, 100000); //TODO: support ajax based pages +$showing = $pageNav->showing().' '._N('task', 'tasks', $count); ?> - <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>'; + if ($count) { + echo '<strong>'.$showing.'</strong>'; } else { - echo sprintf(__('%s does not have any tasks'), $ticket? 'Ticket' : + echo sprintf(__('%s does not have any tasks'), $ticket? 'This ticket' : 'System'); } ?> @@ -39,7 +25,8 @@ while ($row = db_fetch_array($res)) <?php if ($ticket) { ?> <a - class="Icon newTicket ticket-action" + class="Icon newTicket task-action" + data-url="tickets.php?id=<?php echo $ticket->getId(); ?>#tasks" data-dialog='{"size":"large"}' href="#tickets/<?php echo $ticket->getId(); ?>/add-task"> <?php @@ -50,8 +37,8 @@ while ($row = db_fetch_array($res)) <br/> <div> <?php -if ($results) { ?> -<form action="tickets.php?id=<?php echo $ticket->getId(); ?>" method="POST" name='tasks' style="padding-top:10px;"> +if ($count) { ?> +<form action="#tickets/<?php echo $ticket->getId(); ?>/tasks" 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="" > @@ -59,6 +46,7 @@ if ($results) { ?> <thead> <tr> <?php + //TODO: support mass actions. if (0) {?> <th width="8px"> </th> <?php @@ -73,52 +61,41 @@ if ($results) { ?> </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'; - + foreach($tasks as $task) { + $id = $task->getId(); $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=' '; + if ($task->staff) + $assigned=sprintf('<span class="Icon staffAssigned">%s</span>', + Format::truncate($task->staff->getName(),40)); $status = $task->isOpen() ? '<strong>open</strong>': 'closed'; - $tid=$row['number']; $title = Format::htmlchars(Format::truncate($task->getTitle(),40)); - $threadcount= $task->getThread()->getNumEntries(); + $threadcount = $task->getThread() ? + $task->getThread()->getNumEntries() : 0; ?> - <tr id="<?php echo $row['id']; ?>"> + <tr id="<?php echo $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"':''; ?>> + value="<?php echo $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" + href="#tasks/<?php echo $id; ?>/view" + data-preview="#tasks/<?php echo $id; ?>/preview" ><?php echo $task->getNumber(); ?></a></td> <td align="center" nowrap><?php echo - Format::db_datetime($row['created']); ?></td> + Format::datetime($task->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 + href="#tasks/<?php echo $id; ?>/view"><?php echo $title; ?></a> <?php if ($threadcount>1) @@ -130,7 +107,7 @@ if ($results) { ?> echo '<i class="icon-fixed-width icon-paperclip"></i> '; ?> </td> - <td><?php echo Format::truncate($row['dept_name'], 40); ?></td> + <td><?php echo Format::truncate($task->dept->getName(), 40); ?></td> <td> <?php echo $assigned; ?></td> </tr> <?php @@ -157,5 +134,30 @@ $(function() { }).show(); return false; }); + $(document).off('.task-action'); + $(document).on('click.task-action', 'a.task-action', function(e) { + e.preventDefault(); + var url = 'ajax.php/' + +$(this).attr('href').substr(1) + +'?_uid='+new Date().getTime(); + var $redirect = $(this).data('href'); + var $options = $(this).data('dialog'); + $.dialog(url, [201], function (xhr) { + var tid = parseInt(xhr.responseText); + if (tid) { + var url = 'ajax.php/tasks/'+tid+'/view'; + var $container = $('div#task_content'); + $container.load(url, function () { + $('.tip_box').remove(); + $('div#tasks_content').hide(); + }).show(); + } else { + window.location.href = $redirect ? $redirect : window.location.href; + } + }, $options); + return false; + }); + + }); </script> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index d8d0e5b43b180dcb604540424e698344848c8daa..e6522e7dee47fbb44e6a87aeb10e35379828b5e3 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -377,8 +377,9 @@ $tcount = $ticket->getThreadCount(); $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 + <li class="active"><a href="#ticket_thread"><?php echo sprintf(__('Ticket Thread (%d)'), $tcount); ?></a></li> + <li><a id="ticket_tasks" href="#tasks" + data-url="<?php echo sprintf('#tickets/%d/tasks', $ticket->getId()); ?>"><?php echo __('Tasks'); if ($ticket->getNumTasks()) @@ -454,7 +455,7 @@ $tcount+= $ticket->getNumNotes(); <div id="response_options"> <ul class="tabs"> <?php - if ($role->canPostReply()) { ?> + if ($role->canPostTicketReply()) { ?> <li class="active"><a href="#reply"><?php echo __('Post Reply');?></a></li> <?php } ?> @@ -472,7 +473,7 @@ $tcount+= $ticket->getNumNotes(); } ?> </ul> <?php - if ($role->canPostReply()) { ?> + if ($role->canPostTicketReply()) { ?> <form id="reply" class="tab_content" action="tickets.php?id=<?php echo $ticket->getId(); ?>" name="reply" method="post" enctype="multipart/form-data"> <?php csrf_token(); ?> diff --git a/scp/ajax.php b/scp/ajax.php index d0d6f409f4628e114db3833635b848e993dd570a..1c313c18c4afab80c58cbb3579de2cf254a34c76 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -160,6 +160,14 @@ $dispatcher = patterns('', )), url('^/tasks/', patterns('ajax.tasks.php:TasksAjaxAPI', url_get('^(?P<tid>\d+)/preview$', 'preview'), + url_get('^(?P<tid>\d+)/edit', 'edit'), + url_post('^(?P<tid>\d+)/edit$', 'edit'), + url_get('^(?P<tid>\d+)/transfer', 'transfer'), + url_post('^(?P<tid>\d+)/transfer$', 'transfer'), + url_get('^(?P<tid>\d+)/assign', 'assign'), + url_post('^(?P<tid>\d+)/assign$', 'assign'), + 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') )),