Add tasks in bulk from the board

This commit is contained in:
Frederic Guillot 2016-05-13 21:44:31 -04:00
parent a1a48b8374
commit 10f662ce07
8 changed files with 167 additions and 9 deletions

View File

@ -1,3 +1,11 @@
Version 1.0.29 (unreleased)
--------------
New features:
* Add tasks in bulk from the board
Version 1.0.28
--------------

View File

@ -0,0 +1,88 @@
<?php
namespace Kanboard\Controller;
/**
* Class TaskBulk
*
* @package Kanboard\Controller
*/
class TaskBulk extends Base
{
/**
* Show the form
*
* @param array $values
* @param array $errors
*/
public function show(array $values = array(), array $errors = array())
{
$project = $this->getProject();
if (empty($values)) {
$values = array(
'swimlane_id' => $this->request->getIntegerParam('swimlane_id'),
'column_id' => $this->request->getIntegerParam('column_id'),
'project_id' => $project['id'],
);
}
$this->response->html($this->template->render('task_bulk/show', array(
'project' => $project,
'values' => $values,
'errors' => $errors,
'users_list' => $this->projectUserRole->getAssignableUsersList($project['id'], true, false, true),
'colors_list' => $this->color->getList(),
'categories_list' => $this->category->getList($project['id']),
)));
}
/**
* Save all tasks in the database
*/
public function save()
{
$project = $this->getProject();
$values = $this->request->getValues();
list($valid, $errors) = $this->taskValidator->validateBulkCreation($values);
if ($valid) {
$this->createTasks($project, $values);
$this->response->redirect($this->helper->url->to(
'Board',
'show',
array('project_id' => $project['id']),
'swimlane-'. $values['swimlane_id']
), true);
} else {
$this->show($values, $errors);
}
}
/**
* Create all tasks
*
* @param array $project
* @param array $values
*/
protected function createTasks(array $project, array $values)
{
$tasks = preg_split('/\r\n|[\r\n]/', $values['tasks']);
foreach ($tasks as $title) {
$title = trim($title);
if (! empty($title)) {
$this->taskCreation->create(array(
'title' => $title,
'column_id' => $values['column_id'],
'swimlane_id' => $values['swimlane_id'],
'category_id' => empty($values['category_id']) ? 0 : $values['category_id'],
'owner_id' => empty($values['owner_id']) ? 0 : $values['owner_id'],
'color_id' => $values['color_id'],
'project_id' => $project['id'],
));
}
}
}
}

View File

@ -79,6 +79,6 @@ class Taskcreation extends Base
));
}
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])));
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])), true);
}
}

View File

@ -35,11 +35,17 @@
<i class="fa fa-minus-square fa-fw"></i>
<a href="#" class="board-toggle-column-view" data-column-id="<?= $column['id'] ?>"><?= t('Hide this column') ?></a>
</li>
<?php if ($this->user->hasProjectAccess('BoardPopover', 'closeColumnTasks', $column['project_id']) && $column['nb_tasks'] > 0): ?>
<?php if ($this->user->hasProjectAccess('Taskcreation', 'create', $column['project_id'])): ?>
<li>
<i class="fa fa-close fa-fw"></i>
<?= $this->url->link(t('Close all tasks of this column'), 'BoardPopover', 'confirmCloseColumnTasks', array('project_id' => $column['project_id'], 'column_id' => $column['id'], 'swimlane_id' => $swimlane['id']), false, 'popover') ?>
<i class="fa fa-align-justify" aria-hidden="true"></i>
<?= $this->url->link(t('Create tasks in bulk'), 'TaskBulk', 'show', array('project_id' => $column['project_id'], 'column_id' => $column['id'], 'swimlane_id' => $swimlane['id']), false, 'popover') ?>
</li>
<?php if ($column['nb_tasks'] > 0): ?>
<li>
<i class="fa fa-close fa-fw"></i>
<?= $this->url->link(t('Close all tasks of this column'), 'BoardPopover', 'confirmCloseColumnTasks', array('project_id' => $column['project_id'], 'column_id' => $column['id'], 'swimlane_id' => $swimlane['id']), false, 'popover') ?>
</li>
<?php endif ?>
<?php endif ?>
</ul>
</span>

View File

@ -0,0 +1,27 @@
<div class="page-header">
<h2><?= t('Create tasks in bulk') ?></h2>
</div>
<form class="popover-form" method="post" action="<?= $this->url->href('TaskBulk', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
<?= $this->form->csrf() ?>
<?= $this->form->hidden('column_id', $values) ?>
<?= $this->form->hidden('swimlane_id', $values) ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->task->selectAssignee($users_list, $values, $errors) ?>
<?= $this->task->selectCategory($categories_list, $values, $errors) ?>
<?= $this->form->label(t('Tasks'), 'tasks') ?>
<?= $this->form->textarea('tasks', $values, $errors, array(
'placeholder="'.implode("\r\n", array(t('My task title'), t('My task title'), t('My task title'))).'"')
) ?>
<p class="form-help"><?= t('Enter one task by line.') ?></p>
<?= $this->render('task/color_picker', array('colors_list' => $colors_list, 'values' => $values)) ?>
<div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
<?= t('or') ?> <?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
</div>
</form>

View File

@ -69,6 +69,32 @@ class TaskValidator extends Base
);
}
/**
* Validate task creation
*
* @access public
* @param array $values Form values
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
*/
public function validateBulkCreation(array $values)
{
$rules = array(
new Validators\Required('project_id', t('The project is required')),
new Validators\Required('tasks', t('Field required')),
new Validators\Required('column_id', t('Field required')),
new Validators\Required('swimlane_id', t('Field required')),
new Validators\Integer('category_id', t('This value must be an integer')),
new Validators\Integer('swimlane_id', t('This value must be an integer')),
);
$v = new Validator($values, array_merge($rules, $this->commonValidationRules()));
return array(
$v->execute(),
$v->getErrors()
);
}
/**
* Validate description creation
*

File diff suppressed because one or more lines are too long

View File

@ -67,10 +67,13 @@ Kanboard.Popover.prototype.close = function(e) {
Kanboard.Popover.prototype.ajaxReload = function(data, request, self) {
var redirect = request.getResponseHeader("X-Ajax-Redirect");
if (redirect) {
window.location = redirect === 'self' ? window.location.href.split("#")[0] : redirect;
}
else {
if (redirect === 'self') {
window.location.reload();
} else if (redirect && redirect.indexOf('#') > -1) {
window.location = redirect.split('#')[0];
} else if (redirect) {
window.location = redirect;
} else {
$("#popover-content").html(data);
$("#popover-content input[autofocus]").focus();
self.executeOnOpenedListeners();