Add checkboxes in list view to move tasks to another column at once
This commit is contained in:
44
app/Controller/TaskBulkMoveColumnController.php
Normal file
44
app/Controller/TaskBulkMoveColumnController.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Controller;
|
||||
|
||||
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||
|
||||
class TaskBulkMoveColumnController extends BaseController
|
||||
{
|
||||
public function show(array $values = [], array $errors = [])
|
||||
{
|
||||
$project = $this->getProject();
|
||||
|
||||
if (empty($values)) {
|
||||
$values['task_ids'] = $this->request->getStringParam('task_ids');
|
||||
}
|
||||
|
||||
$this->response->html($this->template->render('task_bulk_move_column/show', [
|
||||
'project' => $project,
|
||||
'values' => $values,
|
||||
'errors' => $errors,
|
||||
'columns' => $this->columnModel->getList($project['id']),
|
||||
'swimlanes' => $this->swimlaneModel->getList($project['id'], false, true),
|
||||
]));
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
$values = $this->request->getValues();
|
||||
$taskIDs = explode(',', $values['task_ids']);
|
||||
|
||||
foreach ($taskIDs as $taskID) {
|
||||
$task = $this->taskFinderModel->getById($taskID);
|
||||
|
||||
if (! $this->helper->projectRole->canMoveTask($task['project_id'], $task['column_id'], $values['column_id'])) {
|
||||
throw new AccessForbiddenException(e('You are not allowed to move this task.'));
|
||||
}
|
||||
|
||||
$this->taskPositionModel->moveBottom($project['id'], $taskID, $values['swimlane_id'], $values['column_id']);
|
||||
}
|
||||
|
||||
$this->response->redirect($this->helper->url->to('TaskListController', 'show', ['project_id' => $project['id']]), true);
|
||||
}
|
||||
}
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
'%s moved the task #%d to the swimlane "%s"' => '%s flyttet opgave #%d til spor "%s"',
|
||||
'%sh spent' => '%sh brugt',
|
||||
'%sh estimated' => '%sh anslået',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
'%s moved the task #%d to the swimlane "%s"' => '%s a déplacé la tâche #%d vers la swimlane « %s »',
|
||||
'%sh spent' => '%sh passé',
|
||||
'%sh estimated' => '%sh estimé',
|
||||
'Select All' => 'Tout sélectionner',
|
||||
'Unselect All' => 'Tout désélectionner',
|
||||
'Apply action' => 'Appliquer une action',
|
||||
'Move selected tasks to another column' => 'Déplaçer les tâches sélectionnées vers une autre colonne',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
'%s moved the task #%d to the swimlane "%s"' => '%s перенёс задачу #%d на дорожку "%s"',
|
||||
'%sh spent' => '%sч затрачено',
|
||||
'%sh estimated' => '%sч запланировано',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
'%s moved the task #%d to the swimlane "%s"' => '%s , #%d görevini "%s" kulvarına taşıdı',
|
||||
'%sh spent' => '%sh harcandı',
|
||||
'%sh estimated' => '%sh tahmin edildi',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
'%s moved the task #%d to the swimlane "%s"' => '%s перемістив задачу #%d на доріжку "%s"',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
'%s moved the task #%d to the swimlane "%s"' => '%s将任务 #%d 移动到了里程碑 "%s" 下',
|
||||
'%sh spent' => '花费%s小时',
|
||||
'%sh estimated' => '预估%s小时',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -1377,4 +1377,8 @@ return array(
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// '%sh spent' => '',
|
||||
// '%sh estimated' => '',
|
||||
// 'Select All' => '',
|
||||
// 'Unselect All' => '',
|
||||
// 'Apply action' => '',
|
||||
// 'Move selected tasks to another column' => '',
|
||||
);
|
||||
|
||||
@@ -12,6 +12,42 @@ use Kanboard\Core\Base;
|
||||
*/
|
||||
class TaskPositionModel extends Base
|
||||
{
|
||||
public function moveBottom($project_id, $task_id, $swimlane_id, $column_id)
|
||||
{
|
||||
$this->db->startTransaction();
|
||||
|
||||
$task = $this->taskFinderModel->getById($task_id);
|
||||
|
||||
$result = $this->db->table(TaskModel::TABLE)
|
||||
->eq('project_id', $project_id)
|
||||
->eq('swimlane_id', $swimlane_id)
|
||||
->eq('column_id', $column_id)
|
||||
->columns('MAX(position) AS pos')
|
||||
->findOne();
|
||||
|
||||
$position = 1;
|
||||
if (! empty($result)) {
|
||||
$position = $result['pos'] + 1;
|
||||
}
|
||||
|
||||
$result = $this->db->table(TaskModel::TABLE)
|
||||
->eq('id', $task_id)
|
||||
->eq('project_id', $project_id)
|
||||
->update([
|
||||
'swimlane_id' => $swimlane_id,
|
||||
'column_id' => $column_id,
|
||||
'position' => $position
|
||||
]);
|
||||
|
||||
$this->db->closeTransaction();
|
||||
|
||||
if ($result) {
|
||||
$this->fireEvents($task, $column_id, $position, $swimlane_id);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a task to another column or to another position
|
||||
*
|
||||
|
||||
@@ -106,6 +106,7 @@ class AuthenticationProvider implements ServiceProviderInterface
|
||||
$acl->add('TaskSuppressionController', '*', Role::PROJECT_MEMBER);
|
||||
$acl->add('TaskCreationController', '*', Role::PROJECT_MEMBER);
|
||||
$acl->add('TaskBulkController', '*', Role::PROJECT_MEMBER);
|
||||
$acl->add('TaskBulkMoveColumnController', '*', Role::PROJECT_MEMBER);
|
||||
$acl->add('TaskDuplicationController', '*', Role::PROJECT_MEMBER);
|
||||
$acl->add('TaskRecurrenceController', '*', Role::PROJECT_MEMBER);
|
||||
$acl->add('TaskImportController', '*', Role::PROJECT_MANAGER);
|
||||
|
||||
16
app/Template/task_bulk_move_column/show.php
Normal file
16
app/Template/task_bulk_move_column/show.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<div class="page-header">
|
||||
<h2><?= t('Move selected tasks to another column') ?></h2>
|
||||
</div>
|
||||
|
||||
<form action="<?= $this->url->href('TaskBulkMoveColumnController', 'save', ['project_id' => $project['id']]) ?>" method="post">
|
||||
<?= $this->form->csrf() ?>
|
||||
<?= $this->form->hidden('task_ids', $values) ?>
|
||||
|
||||
<?= $this->form->label(t('Swimlane'), 'swimlane_id') ?>
|
||||
<?= $this->form->select('swimlane_id', $swimlanes, $values) ?>
|
||||
|
||||
<?= $this->form->label(t('Column'), 'column_id') ?>
|
||||
<?= $this->form->select('column_id', $columns, $values) ?>
|
||||
|
||||
<?= $this->modal->submitButtons() ?>
|
||||
</form>
|
||||
@@ -6,6 +6,24 @@
|
||||
<?= t('%d task', $paginator->getTotal()) ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php if (isset($show_items_selection)): ?>
|
||||
<?php if ($this->user->hasProjectAccess('TaskModificationController', 'save', $project['id'])): ?>
|
||||
<div class="list-item-links">
|
||||
<a href="#" data-list-item-selection="all"><?= t('Select All') ?></a> / <a href="#" data-list-item-selection="none"><?= t('Unselect All') ?></a>
|
||||
</div>
|
||||
<div class="list-item-actions list-item-action-hidden">
|
||||
-
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-menu dropdown-menu-link-icon"><strong><?= t('Apply action') ?> <i class="fa fa-caret-down"></i></strong></a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="<?= $this->url->href('TaskBulkMoveColumnController', 'show', ['project_id' => $project['id']]) ?>" data-list-item-action="modal"><?= t('Move selected tasks to another column') ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
<div class="table-list-header-menu">
|
||||
<?php if (isset($project)): ?>
|
||||
<?php if ($this->user->hasSubtaskListActivated()): ?>
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
<?= $this->render('task_list/header', array(
|
||||
'paginator' => $paginator,
|
||||
'project' => $project,
|
||||
'show_items_selection' => true,
|
||||
)) ?>
|
||||
|
||||
<?php foreach ($paginator->getCollection() as $task): ?>
|
||||
<div class="table-list-row color-<?= $task['color_id'] ?>">
|
||||
<?= $this->render('task_list/task_title', array(
|
||||
'task' => $task,
|
||||
'show_items_selection' => true,
|
||||
)) ?>
|
||||
|
||||
<?= $this->render('task_list/task_details', array(
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<div>
|
||||
<?php if ($this->user->hasProjectAccess('TaskModificationController', 'edit', $task['project_id'])): ?>
|
||||
<?php if (isset($show_items_selection)): ?>
|
||||
<input type="checkbox" data-list-item="selectable" name="tasks[]" value="<?= $task['id'] ?>">
|
||||
<?php endif ?>
|
||||
<?= $this->render('task/dropdown', array('task' => $task)) ?>
|
||||
<?php else: ?>
|
||||
<strong><?= '#'.$task['id'] ?></strong>
|
||||
|
||||
Reference in New Issue
Block a user