diff --git a/include/ajax.tasks.php b/include/ajax.tasks.php index 638f6982d8a1dcf14a3c4686490a347a5c00c086..15a623c4d7d45e324540e9d0426f37b35205ed85 100644 --- a/include/ajax.tasks.php +++ b/include/ajax.tasks.php @@ -19,6 +19,7 @@ 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'); +include_once INCLUDE_DIR . 'class.thread_actions.php'; class TasksAjaxAPI extends AjaxController { @@ -57,9 +58,35 @@ class TasksAjaxAPI extends AjaxController { return $this->json_encode($tasks); } - function add() { + function triggerThreadAction($task_id, $thread_id, $action) { + $thread = ThreadEntry::lookup($thread_id); + if (!$thread) + Http::response(404, 'No such task thread entry'); + if ($thread->getThread()->getObjectId() != $task_id) + Http::response(404, 'No such task thread entry'); + + $valid = false; + foreach ($thread->getActions() as $group=>$list) { + foreach ($list as $name=>$A) { + if ($A->getId() == $action) { + $valid = true; break; + } + } + } + + if (!$valid) + Http::response(400, 'Not a valid action for this thread'); + + + $thread->triggerAction($action); + } + + function add($tid=0, $vars=array()) { global $thisstaff; + if ($tid) + $originalTask = Task::lookup($tid); + $info=$errors=array(); if ($_POST) { Draft::deleteForNamespace('task.add', $thisstaff->getId()); @@ -86,11 +113,53 @@ class TasksAjaxAPI extends AjaxController { $vars['staffId'] = $thisstaff->getId(); $vars['poster'] = $thisstaff; $vars['ip_address'] = $_SERVER['REMOTE_ADDR']; - if (($task=Task::create($vars, $errors))) - Http::response(201, $task->getId()); + if (($task=Task::create($vars, $errors))) { + if ($_SESSION[':form-data']['eid']) { + //add internal note to original task: + $taskLink = sprintf('<a href="tasks.php?id=%d"><b>#%d</b></a>', + $task->getId(), + $task->getId()); + + $entryLink = sprintf('<a href="#entry-%d"><b>%d</b></a> (%s)', + $_SESSION[':form-data']['eid'], + $_SESSION[':form-data']['eid'], + Format::datetime($_SESSION[':form-data']['timestamp'])); + + $note = array( + 'title' => __('Task Created From Thread'), + 'note' => __('Task ' . $taskLink . + '<br /> Thread Entry ID: ' . $entryLink) + ); + + $originalTask->postNote($note, $errors, $thisstaff); + + //add internal note to new task: + $taskLink = sprintf('<a href="tasks.php?id=%d"><b>#%s</b></a>', + $originalTask->getId(), + $originalTask->getNumber()); + + $note = array( + 'title' => __('Task Created From Thread'), + 'note' => __('This Task was created from Task ' . $taskLink)); + + $task->postNote($note, $errors, $thisstaff); + + unset($_SESSION[':form-data']); + } + + Http::response(201, $task->getId()); + } + } + $info['error'] = sprintf('%s - %s', __('Error adding task'), __('Please try again!')); } - $info['error'] = sprintf('%s - %s', __('Error adding task'), __('Please try again!')); + if ($originalTask) { + $info['action'] = sprintf('#tasks/%d/add', $originalTask->getId()); + $info['title'] = sprintf( + __( 'Task #%1$s: %2$s'), + $originalTask->getNumber(), + __('Add New Task') + ); } include STAFFINC_DIR . 'templates/task.tmpl.php'; diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 91f12f895d7945e804bbc05ac72e3837bb6f9e64..5377996c628c55c498a78e8d50650dd10815a713 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -1348,8 +1348,42 @@ function refer($tid, $target=null) { $vars['staffId'] = $thisstaff->getId(); $vars['poster'] = $thisstaff; $vars['ip_address'] = $_SERVER['REMOTE_ADDR']; - if (($task=Task::create($vars, $errors))) - Http::response(201, $task->getId()); + if (($task=Task::create($vars, $errors))) { + + if ($_SESSION[':form-data']['eid']) { + //add internal note to ticket: + $taskLink = sprintf('<a href="tasks.php?id=%d"><b>#%d</b></a>', + $task->getId(), + $task->getId()); + + $entryLink = sprintf('<a href="#entry-%d"><b>%d</b></a> (%s)', + $_SESSION[':form-data']['eid'], + $_SESSION[':form-data']['eid'], + Format::datetime($_SESSION[':form-data']['timestamp'])); + + $note = array( + 'title' => __('Task Created From Thread'), + 'body' => __('Task ' . $taskLink . + '<br /> Thread Entry ID: ' . $entryLink) + ); + + $ticket->logNote($note['title'], $note['body'], $thisstaff); + + //add internal note to task: + $ticketLink = sprintf('<a href="tickets.php?id=%d"><b>#%s</b></a>', + $ticket->getId(), + $ticket->getNumber()); + + $note = array( + 'title' => __('Task Created From Thread'), + 'note' => __('This Task was created from Ticket ' . $ticketLink)); + + $task->postNote($note, $errors, $thisstaff); + } + unset($_SESSION[':form-data']); + } + + Http::response(201, $task->getId()); } $info['error'] = sprintf('%s - %s', __('Error adding task'), __('Please try again!')); diff --git a/include/class.thread.php b/include/class.thread.php index 017d7db353c3fbd5740935138f2fc26222a03dcb..353ce11b5ed6f38bf7651f974d3aa9b07b1e1c16 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -3007,8 +3007,9 @@ abstract class ThreadEntryAction { * `#` in the url */ function getAjaxUrl($dialog=false) { - return sprintf('%stickets/%d/thread/%d/%s', + return sprintf('%s%s/%d/thread/%d/%s', $dialog ? '#' : 'ajax.php/', + $this->entry->getThread()->getObjectType() == 'T' ? 'tickets' : 'tasks', $this->entry->getThread()->getObjectId(), $this->entry->getId(), static::getId() @@ -3018,6 +3019,10 @@ abstract class ThreadEntryAction { function getTicketsAPI() { return new TicketsAjaxAPI(); } + + function getTasksAPI() { + return new TasksAjaxAPI(); + } } interface Threadable { diff --git a/include/class.thread_actions.php b/include/class.thread_actions.php index 08e83dccef789b4cfc8aaf1f4ca3a8833b0f21a5..a2c67788c5ba397585a459b42b8ed786a88d4d63 100644 --- a/include/class.thread_actions.php +++ b/include/class.thread_actions.php @@ -489,10 +489,11 @@ $.dialog(url, [201], function(xhr, resp) { if (!!redirect) $.pjax({url: redirect, container: '#pjax-container'}); else - $.pjax({url: 'tickets.php?id=%d#tasks', container: '#pjax-container'}); + $.pjax({url: '%s.php?id=%d#tasks', container: '#pjax-container'}); }); JS , $this->getAjaxUrl(), + $this->entry->getThread()->getObjectType() == 'T' ? 'tickets' : 'tasks', $this->entry->getThread()->getObjectId() ); } @@ -507,9 +508,14 @@ JS } private function trigger__get() { - $vars = array( 'description' => Format::htmlchars($this->entry->getBody())); + + $_SESSION[':form-data']['tid'] = $this->entry->getThread()->getObJectId(); + $_SESSION[':form-data']['eid'] = $this->entry->getId(); + $_SESSION[':form-data']['timestamp'] = $this->entry->getCreateDate(); + $_SESSION[':form-data']['type'] = $this->entry->getThread()->object_type; + if (($f= TaskForm::getInstance()->getField('description'))) { $k = 'attach:'.$f->getId(); unset($_SESSION[':form-data'][$k]); @@ -519,11 +525,18 @@ JS } } - return $this->getTicketsAPI()->addTask($this->getObjectId(), $vars); + if ($this->entry->getThread()->getObjectType() == 'T') + return $this->getTicketsAPI()->addTask($this->getObjectId(), $vars); //TasksAjaxAPI + else + return $this->getTasksAPI()->add($this->getObjectId(), $vars); + } private function trigger__post() { - return $this->getTicketsAPI()->addTask($this->getObjectId()); + if ($this->entry->getThread()->getObjectType() == 'T') + return $this->getTicketsAPI()->addTask($this->getObjectId(), $vars); + else + return $this->getTasksAPI()->add($this->getObjectId(), $vars); } } diff --git a/include/class.ticket.php b/include/class.ticket.php index 167703aaf49e2d1ae32d405f33210892b29b548c..f28f4e8e1d670bfec09aeeca9dcea6a2f7a5f9c2 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -3886,6 +3886,56 @@ implements RestrictedAccess, Threadable, Searchable { $message->save(); } + //check to see if ticket was created from a thread + if ($_SESSION[':form-data']['ticket'] || $_SESSION[':form-data']['task']) { + $oldTicket = $_SESSION[':form-data']['ticket']; + $oldTask = $_SESSION[':form-data']['task']; + + //add internal note to new ticket. + //New ticket should have link to old task/ticket: + $link = sprintf('<a href="%s.php?id=%d#entry-%d"><b>#%s</b></a>', + $oldTicket ? 'tickets' : 'tasks', + $oldTicket ? $oldTicket->getId() : $oldTask->getId(), + $_SESSION[':form-data']['eid'], + $oldTicket ? $oldTicket->getNumber() : $oldTask->getNumber()); + + $note = array( + 'title' => __('Ticket Created From Thread'), + 'body' => sprintf(__('This Ticket was created from %s '. $link), + $oldTicket ? 'Ticket' : 'Task') + ); + + $ticket->logNote($note['title'], $note['body'], $thisstaff); + + //add internal note to referenced ticket/task + // Old ticket/task should have link to new ticket + $ticketLink = sprintf('<a href="tickets.php?id=%d"><b>#%s</b></a>', + $ticket->getId(), + $ticket->getNumber()); + + $entryLink = sprintf('<a href="#entry-%d"><b>%d</b></a> (%s)', + $_SESSION[':form-data']['eid'], + $_SESSION[':form-data']['eid'], + Format::datetime($_SESSION[':form-data']['timestamp'])); + + $ticketNote = array( + 'title' => __('Ticket Created From Thread'), + 'body' => __('Ticket ' . $ticketLink). + '<br /> Thread Entry ID: ' . $entryLink); + + $taskNote = array( + 'title' => __('Ticket Created From Thread'), + 'note' => __('Ticket ' . $ticketLink). + '<br /> Thread Entry ID: ' . $entryLink); + + if ($oldTicket) + $oldTicket->logNote($ticketNote['title'], $ticketNote['body'], $thisstaff); + elseif ($oldTask) + $oldTask->postNote($taskNote, $errors, $thisstaff); + + unset($_SESSION[':form-data']); + } + // Configure service-level-agreement for this ticket $ticket->selectSLAId($vars['slaId']); diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php index 5185c11d7549f4f66e83be8456c42fb877dc22e1..277714d5b701b9bfb22ecc8a83c5a2c5fceceaea 100644 --- a/include/staff/ticket-open.inc.php +++ b/include/staff/ticket-open.inc.php @@ -9,7 +9,17 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); // Use thread entry to seed the ticket if (!$user && $_GET['tid'] && ($entry = ThreadEntry::lookup($_GET['tid']))) { + if ($entry->getThread()->getObjectType() == 'T') + $oldTicket = Ticket::lookup($entry->getThread()->getObjectId()); + if ($entry->getThread()->getObjectType() == 'A') + $oldTask = Task::lookup($entry->getThread()->getObjectId()); + $_SESSION[':form-data']['message'] = Format::htmlchars($entry->getBody()); + $_SESSION[':form-data']['ticket'] = $oldTicket; + $_SESSION[':form-data']['task'] = $oldTask; + $_SESSION[':form-data']['eid'] = $entry->getId(); + $_SESSION[':form-data']['timestamp'] = $entry->getCreateDate(); + if ($entry->user_id) $user = User::lookup($entry->user_id); diff --git a/scp/ajax.php b/scp/ajax.php index 85d010e92b48b47d39643715bd8d9884c4c040c8..7dc4a56a2a9c690add163d05fed948045ad7cd2a 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -203,7 +203,9 @@ $dispatcher = patterns('', url('^(?P<tid>\d+)/reopen', 'reopen'), url_get('^(?P<tid>\d+)/view$', 'task'), url_post('^(?P<tid>\d+)$', 'task'), + url('^(?P<tid>\d+)/thread/(?P<thread_id>\d+)/(?P<action>\w+)$', 'triggerThreadAction'), url('^add$', 'add'), + url('^(?P<tid>\d+)/add', 'add'), url('^lookup', 'lookup'), url('^mass/(?P<action>\w+)(?:/(?P<what>\w+))?', 'massProcess') )),