Add task transitions history
This commit is contained in:
@@ -526,4 +526,19 @@ class Task extends Base
|
||||
'subtask_paginator' => $subtask_paginator,
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the task transitions
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function transitions()
|
||||
{
|
||||
$task = $this->getTask();
|
||||
|
||||
$this->response->html($this->taskLayout('task/transitions', array(
|
||||
'task' => $task,
|
||||
'transitions' => $this->transition->getAllByTask($task['id']),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -811,4 +811,7 @@ return array(
|
||||
'Move the task to another column when assignee is cleared' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci n\'est plus assignée',
|
||||
'Source column' => 'Colonne d\'origine',
|
||||
'Show subtask estimates in the user calendar' => 'Afficher le temps estimé des sous-tâches dans le calendrier utilisateur',
|
||||
'Transitions' => 'Transitions',
|
||||
'Executer' => 'Exécutant',
|
||||
'Time spent in the column' => 'Temps passé dans la colonne',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
'Move the task to another column when assignee is cleared' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés törlésekor',
|
||||
'Source column' => 'Forrás oszlop',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -809,4 +809,7 @@ return array(
|
||||
// 'Move the task to another column when assignee is cleared' => '',
|
||||
// 'Source column' => '',
|
||||
// 'Show subtask estimates in the user calendar' => '',
|
||||
// 'Transitions' => '',
|
||||
// 'Executer' => '',
|
||||
// 'Time spent in the column' => '',
|
||||
);
|
||||
|
||||
@@ -143,6 +143,9 @@ class TaskPosition extends Base
|
||||
'position' => $new_position,
|
||||
'column_id' => $new_column_id,
|
||||
'swimlane_id' => $new_swimlane_id,
|
||||
'src_column_id' => $task['column_id'],
|
||||
'dst_column_id' => $new_column_id,
|
||||
'date_moved' => $task['date_moved'],
|
||||
);
|
||||
|
||||
if ($task['swimlane_id'] != $new_swimlane_id) {
|
||||
|
||||
67
app/Model/Transition.php
Normal file
67
app/Model/Transition.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
/**
|
||||
* Transition model
|
||||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Transition extends Base
|
||||
{
|
||||
/**
|
||||
* SQL table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TABLE = 'transitions';
|
||||
|
||||
/**
|
||||
* Save transition event
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id
|
||||
* @param array $task
|
||||
* @return boolean
|
||||
*/
|
||||
public function save($user_id, array $task)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->insert(array(
|
||||
'user_id' => $user_id,
|
||||
'project_id' => $task['project_id'],
|
||||
'task_id' => $task['task_id'],
|
||||
'src_column_id' => $task['src_column_id'],
|
||||
'dst_column_id' => $task['dst_column_id'],
|
||||
'date' => time(),
|
||||
'time_spent' => time() - $task['date_moved']
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all transitions by task
|
||||
*
|
||||
* @access public
|
||||
* @param integer $task_id
|
||||
* @return array
|
||||
*/
|
||||
public function getAllByTask($task_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)
|
||||
->columns(
|
||||
'src.title as src_column',
|
||||
'dst.title as dst_column',
|
||||
User::TABLE.'.name',
|
||||
User::TABLE.'.username',
|
||||
self::TABLE.'.user_id',
|
||||
self::TABLE.'.date',
|
||||
self::TABLE.'.time_spent'
|
||||
)
|
||||
->eq('task_id', $task_id)
|
||||
->desc('date')
|
||||
->join(User::TABLE, 'id', 'user_id')
|
||||
->join(Board::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src')
|
||||
->join(Board::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst')
|
||||
->findAll();
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,31 @@ use PDO;
|
||||
use Core\Security;
|
||||
use Model\Link;
|
||||
|
||||
const VERSION = 55;
|
||||
const VERSION = 56;
|
||||
|
||||
function version_56($pdo)
|
||||
{
|
||||
$pdo->exec('CREATE TABLE transitions (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`user_id` INT NOT NULL,
|
||||
`project_id` INT NOT NULL,
|
||||
`task_id` INT NOT NULL,
|
||||
`src_column_id` INT NOT NULL,
|
||||
`dst_column_id` INT NOT NULL,
|
||||
`date` INT NOT NULL,
|
||||
`time_spent` INT DEFAULT 0,
|
||||
FOREIGN KEY(src_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(dst_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY(id)
|
||||
) ENGINE=InnoDB CHARSET=utf8');
|
||||
|
||||
$pdo->exec("CREATE INDEX transitions_task_index ON transitions(task_id)");
|
||||
$pdo->exec("CREATE INDEX transitions_project_index ON transitions(project_id)");
|
||||
$pdo->exec("CREATE INDEX transitions_user_index ON transitions(user_id)");
|
||||
}
|
||||
|
||||
function version_55($pdo)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,30 @@ use PDO;
|
||||
use Core\Security;
|
||||
use Model\Link;
|
||||
|
||||
const VERSION = 36;
|
||||
const VERSION = 37;
|
||||
|
||||
function version_37($pdo)
|
||||
{
|
||||
$pdo->exec('CREATE TABLE transitions (
|
||||
"id" SERIAL PRIMARY KEY,
|
||||
"user_id" INTEGER NOT NULL,
|
||||
"project_id" INTEGER NOT NULL,
|
||||
"task_id" INTEGER NOT NULL,
|
||||
"src_column_id" INTEGER NOT NULL,
|
||||
"dst_column_id" INTEGER NOT NULL,
|
||||
"date" INTEGER NOT NULL,
|
||||
"time_spent" INTEGER DEFAULT 0,
|
||||
FOREIGN KEY(src_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(dst_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||
)');
|
||||
|
||||
$pdo->exec("CREATE INDEX transitions_task_index ON transitions(task_id)");
|
||||
$pdo->exec("CREATE INDEX transitions_project_index ON transitions(project_id)");
|
||||
$pdo->exec("CREATE INDEX transitions_user_index ON transitions(user_id)");
|
||||
}
|
||||
|
||||
function version_36($pdo)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,30 @@ use Core\Security;
|
||||
use PDO;
|
||||
use Model\Link;
|
||||
|
||||
const VERSION = 54;
|
||||
const VERSION = 55;
|
||||
|
||||
function version_55($pdo)
|
||||
{
|
||||
$pdo->exec('CREATE TABLE transitions (
|
||||
"id" INTEGER PRIMARY KEY,
|
||||
"user_id" INTEGER NOT NULL,
|
||||
"project_id" INTEGER NOT NULL,
|
||||
"task_id" INTEGER NOT NULL,
|
||||
"src_column_id" INTEGER NOT NULL,
|
||||
"dst_column_id" INTEGER NOT NULL,
|
||||
"date" INTEGER NOT NULL,
|
||||
"time_spent" INTEGER DEFAULT 0,
|
||||
FOREIGN KEY(src_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(dst_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||
)');
|
||||
|
||||
$pdo->exec("CREATE INDEX transitions_task_index ON transitions(task_id)");
|
||||
$pdo->exec("CREATE INDEX transitions_project_index ON transitions(project_id)");
|
||||
$pdo->exec("CREATE INDEX transitions_user_index ON transitions(user_id)");
|
||||
}
|
||||
|
||||
function version_54($pdo)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||
'TimetableWeek',
|
||||
'TimetableOff',
|
||||
'TimetableExtra',
|
||||
'Transition',
|
||||
'User',
|
||||
'UserSession',
|
||||
'Webhook',
|
||||
|
||||
@@ -14,6 +14,7 @@ use Subscriber\ProjectModificationDateSubscriber;
|
||||
use Subscriber\WebhookSubscriber;
|
||||
use Subscriber\SubtaskTimesheetSubscriber;
|
||||
use Subscriber\TaskMovedDateSubscriber;
|
||||
use Subscriber\TransitionSubscriber;
|
||||
|
||||
class EventDispatcherProvider implements ServiceProviderInterface
|
||||
{
|
||||
@@ -29,6 +30,7 @@ class EventDispatcherProvider implements ServiceProviderInterface
|
||||
$container['dispatcher']->addSubscriber(new NotificationSubscriber($container));
|
||||
$container['dispatcher']->addSubscriber(new SubtaskTimesheetSubscriber($container));
|
||||
$container['dispatcher']->addSubscriber(new TaskMovedDateSubscriber($container));
|
||||
$container['dispatcher']->addSubscriber(new TransitionSubscriber($container));
|
||||
|
||||
// Automatic actions
|
||||
$container['action']->attachEvents();
|
||||
|
||||
26
app/Subscriber/TransitionSubscriber.php
Normal file
26
app/Subscriber/TransitionSubscriber.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Subscriber;
|
||||
|
||||
use Event\TaskEvent;
|
||||
use Model\Task;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class TransitionSubscriber extends Base implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
Task::EVENT_MOVE_COLUMN => array('execute', 0),
|
||||
);
|
||||
}
|
||||
|
||||
public function execute(TaskEvent $event)
|
||||
{
|
||||
$user_id = $this->userSession->getId();
|
||||
|
||||
if (! empty($user_id)) {
|
||||
$this->transition->save($user_id, $event->getAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@
|
||||
<li>
|
||||
<?= $this->a(t('Summary'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||
</li>
|
||||
<li>
|
||||
<?= $this->a(t('Transitions'), 'task', 'transitions', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||
</li>
|
||||
<?php if ($task['time_estimated'] > 0 || $task['time_spent'] > 0): ?>
|
||||
<li>
|
||||
<?= $this->a(t('Time tracking'), 'task', 'timesheet', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||
|
||||
26
app/Template/task/transitions.php
Normal file
26
app/Template/task/transitions.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<div class="page-header">
|
||||
<h2><?= t('Transitions') ?></h2>
|
||||
</div>
|
||||
|
||||
<?php if (empty($transitions)): ?>
|
||||
<p class="alert"><?= t('There is nothing to show.') ?></p>
|
||||
<?php else: ?>
|
||||
<table class="table-stripped">
|
||||
<tr>
|
||||
<th><?= t('Date') ?></th>
|
||||
<th><?= t('Source column') ?></th>
|
||||
<th><?= t('Destination column') ?></th>
|
||||
<th><?= t('Executer') ?></th>
|
||||
<th><?= t('Time spent in the column') ?></th>
|
||||
</tr>
|
||||
<?php foreach ($transitions as $transition): ?>
|
||||
<tr>
|
||||
<td><?= dt('%B %e, %Y at %k:%M %p', $transition['date']) ?></td>
|
||||
<td><?= $this->e($transition['src_column']) ?></td>
|
||||
<td><?= $this->e($transition['dst_column']) ?></td>
|
||||
<td><?= $this->a($this->e($transition['name'] ?: $transition['username']), 'user', 'show', array('user_id' => $transition['user_id'])) ?></td>
|
||||
<td><?= n(round($transition['time_spent'] / 3600, 2)).' '.t('hours') ?></td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
<?php endif ?>
|
||||
Reference in New Issue
Block a user