Do not refresh the whole page when changing subtask status (work in progress)
This commit is contained in:
@@ -22,6 +22,7 @@ New features:
|
|||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
|
||||||
|
* Do not refresh the whole page when changing subtask status (work in progress)
|
||||||
* Add dropdown menu with inline popup for all task actions
|
* Add dropdown menu with inline popup for all task actions
|
||||||
* Change sidebar style
|
* Change sidebar style
|
||||||
* Change task summary layout
|
* Change task summary layout
|
||||||
|
|||||||
@@ -214,8 +214,7 @@ abstract class Base extends \Kanboard\Core\Base
|
|||||||
$project = $this->project->getByIdWithOwner($project_id);
|
$project = $this->project->getByIdWithOwner($project_id);
|
||||||
|
|
||||||
if (empty($project)) {
|
if (empty($project)) {
|
||||||
$this->flash->failure(t('Project not found.'));
|
$this->notfound();
|
||||||
$this->response->redirect($this->helper->url->to('project', 'index'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $project;
|
return $project;
|
||||||
@@ -242,6 +241,23 @@ abstract class Base extends \Kanboard\Core\Base
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current subtask
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getSubtask()
|
||||||
|
{
|
||||||
|
$subtask = $this->subtask->getById($this->request->getIntegerParam('subtask_id'));
|
||||||
|
|
||||||
|
if (empty($subtask)) {
|
||||||
|
$this->notfound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $subtask;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common method to get project filters
|
* Common method to get project filters
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class Comment extends Base
|
|||||||
public function update()
|
public function update()
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
$comment = $this->getComment();
|
$this->getComment();
|
||||||
|
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
list($valid, $errors) = $this->commentValidator->validateModification($values);
|
list($valid, $errors) = $this->commentValidator->validateModification($values);
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
use Kanboard\Model\Subtask as SubtaskModel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtask controller
|
* Subtask controller
|
||||||
*
|
*
|
||||||
@@ -12,23 +10,6 @@ use Kanboard\Model\Subtask as SubtaskModel;
|
|||||||
*/
|
*/
|
||||||
class Subtask extends Base
|
class Subtask extends Base
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Get the current subtask
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getSubtask()
|
|
||||||
{
|
|
||||||
$subtask = $this->subtask->getById($this->request->getIntegerParam('subtask_id'));
|
|
||||||
|
|
||||||
if (empty($subtask)) {
|
|
||||||
$this->notfound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $subtask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show list of subtasks
|
* Show list of subtasks
|
||||||
*/
|
*/
|
||||||
@@ -181,98 +162,6 @@ class Subtask extends Base
|
|||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Change status to the next status: Toto -> In Progress -> Done
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function toggleStatus()
|
|
||||||
{
|
|
||||||
$task = $this->getTask();
|
|
||||||
$subtask = $this->getSubtask();
|
|
||||||
$redirect = $this->request->getStringParam('redirect', 'task');
|
|
||||||
|
|
||||||
$this->subtask->toggleStatus($subtask['id']);
|
|
||||||
|
|
||||||
if ($redirect === 'board') {
|
|
||||||
$this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
|
||||||
|
|
||||||
$this->response->html($this->template->render('board/tooltip_subtasks', array(
|
|
||||||
'subtasks' => $this->subtask->getAll($task['id']),
|
|
||||||
'task' => $task,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->toggleRedirect($task, $redirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle subtask restriction (popover)
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function subtaskRestriction()
|
|
||||||
{
|
|
||||||
$task = $this->getTask();
|
|
||||||
$subtask = $this->getSubtask();
|
|
||||||
|
|
||||||
$this->response->html($this->template->render('subtask/restriction_change_status', array(
|
|
||||||
'status_list' => array(
|
|
||||||
SubtaskModel::STATUS_TODO => t('Todo'),
|
|
||||||
SubtaskModel::STATUS_DONE => t('Done'),
|
|
||||||
),
|
|
||||||
'subtask_inprogress' => $this->subtask->getSubtaskInProgress($this->userSession->getId()),
|
|
||||||
'subtask' => $subtask,
|
|
||||||
'task' => $task,
|
|
||||||
'redirect' => $this->request->getStringParam('redirect'),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change status of the in progress subtask and the other subtask
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function changeRestrictionStatus()
|
|
||||||
{
|
|
||||||
$task = $this->getTask();
|
|
||||||
$subtask = $this->getSubtask();
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
|
|
||||||
// Change status of the previous in progress subtask
|
|
||||||
$this->subtask->update(array(
|
|
||||||
'id' => $values['id'],
|
|
||||||
'status' => $values['status'],
|
|
||||||
));
|
|
||||||
|
|
||||||
// Set the current subtask to in pogress
|
|
||||||
$this->subtask->update(array(
|
|
||||||
'id' => $subtask['id'],
|
|
||||||
'status' => SubtaskModel::STATUS_INPROGRESS,
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->toggleRedirect($task, $values['redirect']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect to the right page
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private function toggleRedirect(array $task, $redirect)
|
|
||||||
{
|
|
||||||
switch ($redirect) {
|
|
||||||
case 'board':
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
|
||||||
case 'dashboard':
|
|
||||||
$this->response->redirect($this->helper->url->to('app', 'index'));
|
|
||||||
case 'subtask':
|
|
||||||
$this->response->redirect($this->helper->url->to('subtask', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
|
||||||
default:
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'subtasks'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move subtask position
|
* Move subtask position
|
||||||
*
|
*
|
||||||
|
|||||||
61
app/Controller/SubtaskRestriction.php
Normal file
61
app/Controller/SubtaskRestriction.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Model\Subtask as SubtaskModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtask Restriction
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class SubtaskRestriction extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Show popup
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function popover()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$subtask = $this->getSubtask();
|
||||||
|
|
||||||
|
$this->response->html($this->template->render('subtask_restriction/popover', array(
|
||||||
|
'status_list' => array(
|
||||||
|
SubtaskModel::STATUS_TODO => t('Todo'),
|
||||||
|
SubtaskModel::STATUS_DONE => t('Done'),
|
||||||
|
),
|
||||||
|
'subtask_inprogress' => $this->subtask->getSubtaskInProgress($this->userSession->getId()),
|
||||||
|
'subtask' => $subtask,
|
||||||
|
'task' => $task,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change status of the in progress subtask and the other subtask
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$subtask = $this->getSubtask();
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
// Change status of the previous "in progress" subtask
|
||||||
|
$this->subtask->update(array(
|
||||||
|
'id' => $values['id'],
|
||||||
|
'status' => $values['status'],
|
||||||
|
));
|
||||||
|
|
||||||
|
// Set the current subtask to "in progress"
|
||||||
|
$this->subtask->update(array(
|
||||||
|
'id' => $subtask['id'],
|
||||||
|
'status' => SubtaskModel::STATUS_INPROGRESS,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
app/Controller/SubtaskStatus.php
Normal file
28
app/Controller/SubtaskStatus.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtask Status
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class SubtaskStatus extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Change status to the next status: Toto -> In Progress -> Done
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function change()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$subtask = $this->getSubtask();
|
||||||
|
|
||||||
|
$status = $this->subtask->toggleStatus($subtask['id']);
|
||||||
|
$subtask['status'] = $status;
|
||||||
|
|
||||||
|
$this->response->html($this->helper->subtask->toggleStatus($subtask, $task['project_id']));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,38 +10,40 @@ namespace Kanboard\Helper;
|
|||||||
*/
|
*/
|
||||||
class Subtask extends \Kanboard\Core\Base
|
class Subtask extends \Kanboard\Core\Base
|
||||||
{
|
{
|
||||||
|
public function getTitle(array $subtask)
|
||||||
|
{
|
||||||
|
if ($subtask['status'] == 0) {
|
||||||
|
$html = '<i class="fa fa-square-o fa-fw"></i>';
|
||||||
|
} elseif ($subtask['status'] == 1) {
|
||||||
|
$html = '<i class="fa fa-gears fa-fw"></i>';
|
||||||
|
} else {
|
||||||
|
$html = '<i class="fa fa-check-square-o fa-fw"></i>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html.$this->helper->e($subtask['title']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the link to toggle subtask status
|
* Get the link to toggle subtask status
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $subtask
|
* @param array $subtask
|
||||||
* @param string $redirect
|
|
||||||
* @param integer $project_id
|
* @param integer $project_id
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function toggleStatus(array $subtask, $redirect, $project_id = 0)
|
public function toggleStatus(array $subtask, $project_id)
|
||||||
{
|
{
|
||||||
if ($project_id > 0 && ! $this->helper->user->hasProjectAccess('subtask', 'edit', $project_id)) {
|
if (! $this->helper->user->hasProjectAccess('subtask', 'edit', $project_id)) {
|
||||||
return trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']);
|
return $this->getTitle($subtask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$params = array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id']);
|
||||||
|
|
||||||
if ($subtask['status'] == 0 && isset($this->sessionStorage->hasSubtaskInProgress) && $this->sessionStorage->hasSubtaskInProgress) {
|
if ($subtask['status'] == 0 && isset($this->sessionStorage->hasSubtaskInProgress) && $this->sessionStorage->hasSubtaskInProgress) {
|
||||||
return $this->helper->url->link(
|
return $this->helper->url->link($this->getTitle($subtask), 'SubtaskRestriction', 'popover', $params, false, 'popover');
|
||||||
trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']),
|
|
||||||
'subtask',
|
|
||||||
'subtaskRestriction',
|
|
||||||
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect),
|
|
||||||
false,
|
|
||||||
'popover task-board-popover'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->helper->url->link(
|
return $this->helper->url->link($this->getTitle($subtask), 'SubtaskStatus', 'change', $params, false, 'ajax-replace');
|
||||||
trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']),
|
|
||||||
'subtask',
|
|
||||||
'toggleStatus',
|
|
||||||
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function selectTitle(array $values, array $errors = array(), array $attributes = array())
|
public function selectTitle(array $values, array $errors = array(), array $attributes = array())
|
||||||
|
|||||||
@@ -353,15 +353,16 @@ class Subtask extends Base
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $subtask_id
|
* @param integer $subtask_id
|
||||||
* @return bool
|
* @return boolean|integer
|
||||||
*/
|
*/
|
||||||
public function toggleStatus($subtask_id)
|
public function toggleStatus($subtask_id)
|
||||||
{
|
{
|
||||||
$subtask = $this->getById($subtask_id);
|
$subtask = $this->getById($subtask_id);
|
||||||
|
$status = ($subtask['status'] + 1) % 3;
|
||||||
|
|
||||||
$values = array(
|
$values = array(
|
||||||
'id' => $subtask['id'],
|
'id' => $subtask['id'],
|
||||||
'status' => ($subtask['status'] + 1) % 3,
|
'status' => $status,
|
||||||
'task_id' => $subtask['task_id'],
|
'task_id' => $subtask['task_id'],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -369,7 +370,7 @@ class Subtask extends Base
|
|||||||
$values['user_id'] = $this->userSession->getId();
|
$values['user_id'] = $this->userSession->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->update($values);
|
return $this->update($values) ? $status : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ class AuthenticationProvider implements ServiceProviderInterface
|
|||||||
$acl->add('ProjectEdit', '*', Role::PROJECT_MANAGER);
|
$acl->add('ProjectEdit', '*', Role::PROJECT_MANAGER);
|
||||||
$acl->add('Projectuser', '*', Role::PROJECT_MANAGER);
|
$acl->add('Projectuser', '*', Role::PROJECT_MANAGER);
|
||||||
$acl->add('Subtask', '*', Role::PROJECT_MEMBER);
|
$acl->add('Subtask', '*', Role::PROJECT_MEMBER);
|
||||||
|
$acl->add('SubtaskRestriction', '*', Role::PROJECT_MEMBER);
|
||||||
|
$acl->add('SubtaskStatus', '*', Role::PROJECT_MEMBER);
|
||||||
$acl->add('Swimlane', '*', Role::PROJECT_MANAGER);
|
$acl->add('Swimlane', '*', Role::PROJECT_MANAGER);
|
||||||
$acl->add('Task', 'remove', Role::PROJECT_MEMBER);
|
$acl->add('Task', 'remove', Role::PROJECT_MEMBER);
|
||||||
$acl->add('Taskcreation', '*', Role::PROJECT_MEMBER);
|
$acl->add('Taskcreation', '*', Role::PROJECT_MEMBER);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<?= $this->url->link($this->e($subtask['task_name']), 'task', 'show', array('task_id' => $subtask['task_id'], 'project_id' => $subtask['project_id'])) ?>
|
<?= $this->url->link($this->e($subtask['task_name']), 'task', 'show', array('task_id' => $subtask['task_id'], 'project_id' => $subtask['project_id'])) ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<?= $this->subtask->toggleStatus($subtask, 'dashboard') ?>
|
<?= $this->subtask->toggleStatus($subtask, $subtask['project_id']) ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<?php if (! empty($subtask['time_spent'])): ?>
|
<?php if (! empty($subtask['time_spent'])): ?>
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
<section id="tooltip-subtasks">
|
<table class="table-stripped">
|
||||||
<?php foreach ($subtasks as $subtask): ?>
|
<?php foreach ($subtasks as $subtask): ?>
|
||||||
<?= $this->subtask->toggleStatus($subtask, 'board', $task['project_id']) ?>
|
<tr>
|
||||||
<?= $this->e(empty($subtask['username']) ? '' : ' ['.$this->user->getFullname($subtask).']') ?>
|
<td class="column-80">
|
||||||
<br>
|
<?= $this->subtask->toggleStatus($subtask, $task['project_id']) ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?= $this->e($subtask['username'] ?: $this->user->getFullname($subtask)) ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</section>
|
</table>
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
<?php if ($subtask['status'] == 0): ?>
|
|
||||||
<i class="fa fa-square-o fa-fw"></i>
|
|
||||||
<?php elseif ($subtask['status'] == 1): ?>
|
|
||||||
<i class="fa fa-gears fa-fw"></i>
|
|
||||||
<?php else: ?>
|
|
||||||
<i class="fa fa-check-square-o fa-fw"></i>
|
|
||||||
<?php endif ?>
|
|
||||||
@@ -3,12 +3,12 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<?php if ($subtask['position'] != $first_position): ?>
|
<?php if ($subtask['position'] != $first_position): ?>
|
||||||
<li>
|
<li>
|
||||||
<?= $this->url->link(t('Move Up'), 'subtask', 'movePosition', array('project_id' => $project['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'up', 'redirect' => $redirect), true) ?>
|
<?= $this->url->link(t('Move Up'), 'subtask', 'movePosition', array('project_id' => $task['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'up'), true) ?>
|
||||||
</li>
|
</li>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php if ($subtask['position'] != $last_position): ?>
|
<?php if ($subtask['position'] != $last_position): ?>
|
||||||
<li>
|
<li>
|
||||||
<?= $this->url->link(t('Move Down'), 'subtask', 'movePosition', array('project_id' => $project['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'down', 'redirect' => $redirect), true) ?>
|
<?= $this->url->link(t('Move Down'), 'subtask', 'movePosition', array('project_id' => $task['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'down'), true) ?>
|
||||||
</li>
|
</li>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -2,82 +2,9 @@
|
|||||||
<h2><?= t('Sub-Tasks') ?></h2>
|
<h2><?= t('Sub-Tasks') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="subtasks" class="task-show-section">
|
<div id="subtasks">
|
||||||
|
|
||||||
<?php if (! empty($subtasks)): ?>
|
<?= $this->render('subtask/table', array('subtasks' => $subtasks, 'task' => $task, 'editable' => $editable)) ?>
|
||||||
|
|
||||||
<?php $first_position = $subtasks[0]['position']; ?>
|
|
||||||
<?php $last_position = $subtasks[count($subtasks) - 1]['position']; ?>
|
|
||||||
<table class="subtasks-table">
|
|
||||||
<tr>
|
|
||||||
<th class="column-40"><?= t('Title') ?></th>
|
|
||||||
<th><?= t('Assignee') ?></th>
|
|
||||||
<th><?= t('Time tracking') ?></th>
|
|
||||||
<?php if ($editable): ?>
|
|
||||||
<th class="column-5"></th>
|
|
||||||
<?php endif ?>
|
|
||||||
</tr>
|
|
||||||
<?php foreach ($subtasks as $subtask): ?>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<?php if ($editable): ?>
|
|
||||||
<?= $this->subtask->toggleStatus($subtask, $redirect) ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<?= $this->render('subtask/icons', array('subtask' => $subtask)) . $this->e($subtask['title']) ?>
|
|
||||||
<?php endif ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if (! empty($subtask['username'])): ?>
|
|
||||||
<?php if ($editable): ?>
|
|
||||||
<?= $this->url->link($this->e($subtask['name'] ?: $subtask['username']), 'user', 'show', array('user_id' => $subtask['user_id'])) ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<?= $this->e($subtask['name'] ?: $subtask['username']) ?>
|
|
||||||
<?php endif ?>
|
|
||||||
<?php endif ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul class="no-bullet">
|
|
||||||
<li>
|
|
||||||
<?php if (! empty($subtask['time_spent'])): ?>
|
|
||||||
<strong><?= $this->e($subtask['time_spent']).'h' ?></strong> <?= t('spent') ?>
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<?php if (! empty($subtask['time_estimated'])): ?>
|
|
||||||
<strong><?= $this->e($subtask['time_estimated']).'h' ?></strong> <?= t('estimated') ?>
|
|
||||||
<?php endif ?>
|
|
||||||
</li>
|
|
||||||
<?php if ($editable && $subtask['user_id'] == $this->user->getId()): ?>
|
|
||||||
<li>
|
|
||||||
<?php if ($subtask['is_timer_started']): ?>
|
|
||||||
<i class="fa fa-pause"></i>
|
|
||||||
<?= $this->url->link(t('Stop timer'), 'timer', 'subtask', array('timer' => 'stop', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?>
|
|
||||||
(<?= $this->dt->age($subtask['timer_start_date']) ?>)
|
|
||||||
<?php else: ?>
|
|
||||||
<i class="fa fa-play-circle-o"></i>
|
|
||||||
<?= $this->url->link(t('Start timer'), 'timer', 'subtask', array('timer' => 'start', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?>
|
|
||||||
<?php endif ?>
|
|
||||||
</li>
|
|
||||||
<?php endif ?>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<?php if ($editable): ?>
|
|
||||||
<td>
|
|
||||||
<?= $this->render('subtask/menu', array(
|
|
||||||
'project' => $project,
|
|
||||||
'task' => $task,
|
|
||||||
'subtask' => $subtask,
|
|
||||||
'redirect' => $redirect,
|
|
||||||
'first_position' => $first_position,
|
|
||||||
'last_position' => $last_position,
|
|
||||||
)) ?>
|
|
||||||
</td>
|
|
||||||
<?php endif ?>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach ?>
|
|
||||||
</table>
|
|
||||||
<?php else: ?>
|
|
||||||
<p class="alert"><?= t('There is no subtask at the moment.') ?></p>
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<?php if ($editable && $this->user->hasProjectAccess('subtask', 'save', $task['project_id'])): ?>
|
<?php if ($editable && $this->user->hasProjectAccess('subtask', 'save', $task['project_id'])): ?>
|
||||||
<form method="post" action="<?= $this->url->href('subtask', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>" autocomplete="off">
|
<form method="post" action="<?= $this->url->href('subtask', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>" autocomplete="off">
|
||||||
|
|||||||
69
app/Template/subtask/table.php
Normal file
69
app/Template/subtask/table.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?php if (! empty($subtasks)): ?>
|
||||||
|
|
||||||
|
<?php $first_position = $subtasks[0]['position']; ?>
|
||||||
|
<?php $last_position = $subtasks[count($subtasks) - 1]['position']; ?>
|
||||||
|
|
||||||
|
<table class="subtasks-table">
|
||||||
|
<tr>
|
||||||
|
<th class="column-40"><?= t('Title') ?></th>
|
||||||
|
<th><?= t('Assignee') ?></th>
|
||||||
|
<th><?= t('Time tracking') ?></th>
|
||||||
|
<?php if ($editable): ?>
|
||||||
|
<th class="column-5"></th>
|
||||||
|
<?php endif ?>
|
||||||
|
</tr>
|
||||||
|
<?php foreach ($subtasks as $subtask): ?>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<?php if ($editable): ?>
|
||||||
|
<?= $this->subtask->toggleStatus($subtask, $task['project_id']) ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<?= $this->subtask->getTitle($subtask) ?>
|
||||||
|
<?php endif ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?php if (! empty($subtask['username'])): ?>
|
||||||
|
<?= $this->e($subtask['name'] ?: $subtask['username']) ?>
|
||||||
|
<?php endif ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul class="no-bullet">
|
||||||
|
<li>
|
||||||
|
<?php if (! empty($subtask['time_spent'])): ?>
|
||||||
|
<strong><?= $this->e($subtask['time_spent']).'h' ?></strong> <?= t('spent') ?>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<?php if (! empty($subtask['time_estimated'])): ?>
|
||||||
|
<strong><?= $this->e($subtask['time_estimated']).'h' ?></strong> <?= t('estimated') ?>
|
||||||
|
<?php endif ?>
|
||||||
|
</li>
|
||||||
|
<?php if ($editable && $subtask['user_id'] == $this->user->getId()): ?>
|
||||||
|
<li>
|
||||||
|
<?php if ($subtask['is_timer_started']): ?>
|
||||||
|
<i class="fa fa-pause"></i>
|
||||||
|
<?= $this->url->link(t('Stop timer'), 'timer', 'subtask', array('timer' => 'stop', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?>
|
||||||
|
(<?= $this->dt->age($subtask['timer_start_date']) ?>)
|
||||||
|
<?php else: ?>
|
||||||
|
<i class="fa fa-play-circle-o"></i>
|
||||||
|
<?= $this->url->link(t('Start timer'), 'timer', 'subtask', array('timer' => 'start', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?>
|
||||||
|
<?php endif ?>
|
||||||
|
</li>
|
||||||
|
<?php endif ?>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<?php if ($editable): ?>
|
||||||
|
<td>
|
||||||
|
<?= $this->render('subtask/menu', array(
|
||||||
|
'task' => $task,
|
||||||
|
'subtask' => $subtask,
|
||||||
|
'first_position' => $first_position,
|
||||||
|
'last_position' => $last_position,
|
||||||
|
)) ?>
|
||||||
|
</td>
|
||||||
|
<?php endif ?>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</table>
|
||||||
|
<?php else: ?>
|
||||||
|
<p class="alert"><?= t('There is no subtask at the moment.') ?></p>
|
||||||
|
<?php endif ?>
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= t('You already have one subtask in progress') ?></h2>
|
<h2><?= t('You already have one subtask in progress') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
|
<form class="popover-form" action="<?= $this->url->href('SubtaskRestriction', 'update', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'subtask_id' => $subtask['id'])) ?>" method="post">
|
||||||
<form action="<?= $this->url->href('subtask', 'changeRestrictionStatus', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'subtask_id' => $subtask['id'])) ?>" method="post">
|
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
<?= $this->form->hidden('redirect', array('redirect' => $redirect)) ?>
|
|
||||||
|
|
||||||
<p><?= t('Select the new status of the subtask: "%s"', $subtask_inprogress['title']) ?></p>
|
<p><?= t('Select the new status of the subtask: "%s"', $subtask_inprogress['title']) ?></p>
|
||||||
<?= $this->form->radios('status', $status_list) ?>
|
<?= $this->form->radios('status', $status_list) ?>
|
||||||
<?= $this->form->hidden('id', $subtask_inprogress) ?>
|
<?= $this->form->hidden('id', $subtask_inprogress) ?>
|
||||||
|
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<input type="submit" value="<?= t('Save') ?>" class="btn btn-red"/>
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-red">
|
||||||
<?= t('or') ?>
|
<?= t('or') ?>
|
||||||
<a href="#" class="close-popover"><?= t('cancel') ?></a>
|
<a href="#" class="close-popover"><?= t('cancel') ?></a>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,15 +18,14 @@
|
|||||||
'subtasks' => $subtasks,
|
'subtasks' => $subtasks,
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'users_list' => isset($users_list) ? $users_list : array(),
|
'users_list' => isset($users_list) ? $users_list : array(),
|
||||||
'editable' => $this->user->hasProjectAccess('subtask', 'edit', $project['id']),
|
'editable' => true,
|
||||||
'redirect' => 'task',
|
|
||||||
)) ?>
|
)) ?>
|
||||||
|
|
||||||
<?= $this->render('tasklink/show', array(
|
<?= $this->render('tasklink/show', array(
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
'links' => $links,
|
'links' => $links,
|
||||||
'link_label_list' => $link_label_list,
|
'link_label_list' => $link_label_list,
|
||||||
'editable' => $this->user->hasProjectAccess('tasklink', 'edit', $project['id']),
|
'editable' => true,
|
||||||
'is_public' => false,
|
'is_public' => false,
|
||||||
)) ?>
|
)) ?>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -41,6 +41,19 @@ App.prototype.listen = function() {
|
|||||||
this.autoComplete();
|
this.autoComplete();
|
||||||
this.datePicker();
|
this.datePicker();
|
||||||
this.focus();
|
this.focus();
|
||||||
|
|
||||||
|
$(document).on("click", ".ajax-replace", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var el = $(this);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
cache: false,
|
||||||
|
url: el.attr("href"),
|
||||||
|
success: function(data) {
|
||||||
|
el.replaceWith(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.refresh = function() {
|
App.prototype.refresh = function() {
|
||||||
|
|||||||
@@ -48,21 +48,6 @@ Tooltip.prototype.listen = function() {
|
|||||||
var position = $(_this).tooltip("option", "position");
|
var position = $(_this).tooltip("option", "position");
|
||||||
position.of = $(_this);
|
position.of = $(_this);
|
||||||
tooltip.position(position);
|
tooltip.position(position);
|
||||||
|
|
||||||
// Toggle subtasks status
|
|
||||||
$('#tooltip-subtasks a').not(".popover").click(function(e) {
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
if ($(this).hasClass("popover-subtask-restriction")) {
|
|
||||||
self.app.popover.open($(this).attr('href'));
|
|
||||||
$(_this).tooltip('close');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$.get($(this).attr('href'), setTooltipContent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return '<i class="fa fa-spinner fa-spin"></i>';
|
return '<i class="fa fa-spinner fa-spin"></i>';
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class SubtaskTest extends Base
|
|||||||
$this->assertEquals(0, $subtask['user_id']);
|
$this->assertEquals(0, $subtask['user_id']);
|
||||||
$this->assertEquals(1, $subtask['task_id']);
|
$this->assertEquals(1, $subtask['task_id']);
|
||||||
|
|
||||||
$this->assertTrue($s->toggleStatus(1));
|
$this->assertEquals(Subtask::STATUS_INPROGRESS, $s->toggleStatus(1));
|
||||||
|
|
||||||
$subtask = $s->getById(1);
|
$subtask = $s->getById(1);
|
||||||
$this->assertNotEmpty($subtask);
|
$this->assertNotEmpty($subtask);
|
||||||
@@ -167,7 +167,7 @@ class SubtaskTest extends Base
|
|||||||
$this->assertEquals(0, $subtask['user_id']);
|
$this->assertEquals(0, $subtask['user_id']);
|
||||||
$this->assertEquals(1, $subtask['task_id']);
|
$this->assertEquals(1, $subtask['task_id']);
|
||||||
|
|
||||||
$this->assertTrue($s->toggleStatus(1));
|
$this->assertEquals(Subtask::STATUS_DONE, $s->toggleStatus(1));
|
||||||
|
|
||||||
$subtask = $s->getById(1);
|
$subtask = $s->getById(1);
|
||||||
$this->assertNotEmpty($subtask);
|
$this->assertNotEmpty($subtask);
|
||||||
@@ -175,7 +175,7 @@ class SubtaskTest extends Base
|
|||||||
$this->assertEquals(0, $subtask['user_id']);
|
$this->assertEquals(0, $subtask['user_id']);
|
||||||
$this->assertEquals(1, $subtask['task_id']);
|
$this->assertEquals(1, $subtask['task_id']);
|
||||||
|
|
||||||
$this->assertTrue($s->toggleStatus(1));
|
$this->assertEquals(Subtask::STATUS_TODO, $s->toggleStatus(1));
|
||||||
|
|
||||||
$subtask = $s->getById(1);
|
$subtask = $s->getById(1);
|
||||||
$this->assertNotEmpty($subtask);
|
$this->assertNotEmpty($subtask);
|
||||||
@@ -205,7 +205,7 @@ class SubtaskTest extends Base
|
|||||||
// Set the current logged user
|
// Set the current logged user
|
||||||
$this->container['sessionStorage']->user = array('id' => 1);
|
$this->container['sessionStorage']->user = array('id' => 1);
|
||||||
|
|
||||||
$this->assertTrue($s->toggleStatus(1));
|
$this->assertEquals(Subtask::STATUS_INPROGRESS, $s->toggleStatus(1));
|
||||||
|
|
||||||
$subtask = $s->getById(1);
|
$subtask = $s->getById(1);
|
||||||
$this->assertNotEmpty($subtask);
|
$this->assertNotEmpty($subtask);
|
||||||
@@ -213,7 +213,7 @@ class SubtaskTest extends Base
|
|||||||
$this->assertEquals(1, $subtask['user_id']);
|
$this->assertEquals(1, $subtask['user_id']);
|
||||||
$this->assertEquals(1, $subtask['task_id']);
|
$this->assertEquals(1, $subtask['task_id']);
|
||||||
|
|
||||||
$this->assertTrue($s->toggleStatus(1));
|
$this->assertEquals(Subtask::STATUS_DONE, $s->toggleStatus(1));
|
||||||
|
|
||||||
$subtask = $s->getById(1);
|
$subtask = $s->getById(1);
|
||||||
$this->assertNotEmpty($subtask);
|
$this->assertNotEmpty($subtask);
|
||||||
@@ -221,7 +221,7 @@ class SubtaskTest extends Base
|
|||||||
$this->assertEquals(1, $subtask['user_id']);
|
$this->assertEquals(1, $subtask['user_id']);
|
||||||
$this->assertEquals(1, $subtask['task_id']);
|
$this->assertEquals(1, $subtask['task_id']);
|
||||||
|
|
||||||
$this->assertTrue($s->toggleStatus(1));
|
$this->assertEquals(Subtask::STATUS_TODO, $s->toggleStatus(1));
|
||||||
|
|
||||||
$subtask = $s->getById(1);
|
$subtask = $s->getById(1);
|
||||||
$this->assertNotEmpty($subtask);
|
$this->assertNotEmpty($subtask);
|
||||||
|
|||||||
Reference in New Issue
Block a user