Add the possibility to create external tasks

This commit is contained in:
Frederic Guillot 2016-11-05 22:26:58 -04:00
parent ae5d31e4c2
commit 3f7840c4db
No known key found for this signature in database
GPG Key ID: 92D77191BA7FBC99
19 changed files with 269 additions and 35 deletions

View File

@ -0,0 +1,97 @@
<?php
namespace Kanboard\Controller;
use Kanboard\Core\ExternalTask\ExternalTaskException;
/**
* External Task Creation Controller
*
* @package Kanboard\Controller
* @author Frederic Guillot
*/
class ExternalTaskCreationController extends BaseController
{
public function step1(array $values = array(), $errorMessage = '')
{
$project = $this->getProject();
$providerName = $this->request->getStringParam('provider_name');
$taskProvider = $this->externalTaskManager->getProvider($providerName);
if (empty($values)) {
$values = array(
'swimlane_id' => $this->request->getIntegerParam('swimlane_id'),
'column_id' => $this->request->getIntegerParam('column_id'),
);
}
$this->response->html($this->template->render('external_task_creation/step1', array(
'project' => $project,
'values' => $values,
'error_message' => $errorMessage,
'provider_name' => $providerName,
'template' => $taskProvider->getImportFormTemplate(),
)));
}
public function step2(array $values = array(), array $errors = array())
{
$project = $this->getProject();
$providerName = $this->request->getStringParam('provider_name');
try {
$taskProvider = $this->externalTaskManager->getProvider($providerName);
if (empty($values)) {
$values = $this->request->getValues();
$externalTask = $taskProvider->retrieve($taskProvider->buildTaskUri($values));
$values = $externalTask->getFormValues() + array(
'external_uri' => $externalTask->getUri(),
'external_provider' => $providerName,
'project_id' => $project['id'],
'swimlane_id' => $values['swimlane_id'],
'column_id' => $values['column_id'],
'color_id' => $this->colorModel->getDefaultColor(),
'owner_id' => $this->userSession->getId(),
);
} else {
$externalTask = $taskProvider->retrieve($values['external_uri']);
}
$this->response->html($this->template->render('external_task_creation/step2', array(
'project' => $project,
'external_task' => $externalTask,
'provider_name' => $providerName,
'values' => $values,
'errors' => $errors,
'template' => $taskProvider->getCreationFormTemplate(),
'columns_list' => $this->columnModel->getList($project['id']),
'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id'], true, false, true),
'categories_list' => $this->categoryModel->getList($project['id']),
'swimlanes_list' => $this->swimlaneModel->getList($project['id'], false, true),
)));
} catch (ExternalTaskException $e) {
$this->step1($values, $e->getMessage());
}
}
public function step3()
{
$project = $this->getProject();
$values = $this->request->getValues();
list($valid, $errors) = $this->taskValidator->validateCreation($values);
if (! $valid) {
$this->step2($values, $errors);
} else if (! $this->helper->projectRole->canCreateTaskInColumn($project['id'], $values['column_id'])) {
$this->flash->failure(t('You cannot create tasks in this column.'));
$this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id'])), true);
} else {
$taskId = $this->taskCreationModel->create($values);
$this->flash->success(t('Task created successfully.'));
$this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $project['id'], 'task_id' => $taskId)), true);
}
}
}

View File

@ -2,13 +2,12 @@
namespace Kanboard\Core\ExternalTask;
use Exception;
/**
* Class AccessForbiddenException
*
* @package Kanboard\Core\ExternalTask
* @author Frederic Guillot
*/
class AccessForbiddenException extends Exception
class AccessForbiddenException extends ExternalTaskException
{
}

View File

@ -0,0 +1,15 @@
<?php
namespace Kanboard\Core\ExternalTask;
use Exception;
/**
* Class NotFoundException
*
* @package Kanboard\Core\ExternalTask
* @author Frederic Guillot
*/
class ExternalTaskException extends Exception
{
}

View File

@ -0,0 +1,26 @@
<?php
namespace Kanboard\Core\ExternalTask;
/**
* Interface ExternalTaskInterface
*
* @package Kanboard\Core\ExternalTask
* @author Frederic Guillot
*/
interface ExternalTaskInterface
{
/**
* Return Uniform Resource Identifier for the task
*
* @return string
*/
public function getUri();
/**
* Return a dict to populate the task form
*
* @return array
*/
public function getFormValues();
}

View File

@ -10,15 +10,6 @@ namespace Kanboard\Core\ExternalTask;
*/
interface ExternalTaskProviderInterface
{
/**
* Get templates
*
* @return string
*/
public function getCreationFormTemplate();
public function getModificationFormTemplate();
public function getTaskViewTemplate();
/**
* Get provider name (visible in the user interface)
*
@ -34,17 +25,29 @@ interface ExternalTaskProviderInterface
* @throws \Kanboard\Core\ExternalTask\AccessForbiddenException
* @throws \Kanboard\Core\ExternalTask\NotFoundException
* @param string $uri
* @return array Dict that will populate the form
* @return ExternalTaskInterface
*/
public function retrieve($uri);
/**
* Save the task to the external system and/or update the cache
* Get task import template name
*
* @access public
* @param string $uri
* @param array $data
* @return bool
* @return string
*/
public function persist($uri, array $data);
public function getImportFormTemplate();
/**
* Get creation form template
*
* @return string
*/
public function getCreationFormTemplate();
/**
* Build external task URI based on import form values
*
* @param array $values
* @return string
*/
public function buildTaskUri(array $values);
}

View File

@ -2,14 +2,12 @@
namespace Kanboard\Core\ExternalTask;
use Exception;
/**
* Class NotFoundException
*
* @package Kanboard\Core\ExternalTask
* @author Frederic Guillot
*/
class NotFoundException extends Exception
class NotFoundException extends ExternalTaskException
{
}

View File

@ -2,14 +2,12 @@
namespace Kanboard\Core\ExternalTask;
use Exception;
/**
* Class ProviderNotFoundException
*
* @package Kanboard\Core\ExternalTask
* @author Frederic Guillot
*/
class ProviderNotFoundException extends Exception
class ProviderNotFoundException extends ExternalTaskException
{
}

View File

@ -238,4 +238,32 @@ class TaskHelper extends Base
return $this->taskModel->getProgress($task, $this->columns[$task['project_id']]);
}
public function getNewTaskDropdown($projectId, $swimlaneId, $columnId)
{
$providers = $this->externalTaskManager->getProvidersList();
if (empty($providers)) {
return '';
}
$html = '<small class="pull-right"><div class="dropdown">';
$html .= '<a href="#" class="dropdown-menu"><i class="fa fa-cloud-download" aria-hidden="true"></i> <i class="fa fa-caret-down"></i></a><ul>';
foreach ($providers as $providerName) {
$link = $this->helper->url->link(
t('New External Task: %s', $providerName),
'ExternalTaskCreationController',
'step1',
array('project_id' => $projectId, 'swimlane_id' => $swimlaneId, 'column_id' => $columnId, 'provider_name' => $providerName),
false,
'popover-link'
);
$html .= '<li><i class="fa fa-fw fa-plus-square" aria-hidden="true"></i> '.$link.'</li>';
}
$html .= '</ul></div></small>';
return $html;
}
}

View File

@ -6,7 +6,13 @@ use PDO;
use Kanboard\Core\Security\Token;
use Kanboard\Core\Security\Role;
const VERSION = 115;
const VERSION = 116;
function version_116(PDO $pdo)
{
$pdo->exec("ALTER TABLE tasks ADD COLUMN external_provider VARCHAR(255)");
$pdo->exec("ALTER TABLE tasks ADD COLUMN external_uri VARCHAR(255)");
}
function version_115(PDO $pdo)
{

View File

@ -6,7 +6,13 @@ use PDO;
use Kanboard\Core\Security\Token;
use Kanboard\Core\Security\Role;
const VERSION = 94;
const VERSION = 95;
function version_95(PDO $pdo)
{
$pdo->exec("ALTER TABLE tasks ADD COLUMN external_provider VARCHAR(255)");
$pdo->exec("ALTER TABLE tasks ADD COLUMN external_uri VARCHAR(255)");
}
function version_94(PDO $pdo)
{

View File

@ -6,7 +6,13 @@ use Kanboard\Core\Security\Token;
use Kanboard\Core\Security\Role;
use PDO;
const VERSION = 106;
const VERSION = 107;
function version_107(PDO $pdo)
{
$pdo->exec("ALTER TABLE tasks ADD COLUMN external_provider TEXT");
$pdo->exec("ALTER TABLE tasks ADD COLUMN external_uri TEXT");
}
function version_106(PDO $pdo)
{

View File

@ -0,0 +1,19 @@
<form class="popover-form" method="post" action="<?= $this->url->href('ExternalTaskCreationController', 'step2', array('project_id' => $project['id'], 'provider_name' => $provider_name)) ?>">
<?= $this->form->csrf() ?>
<?= $this->form->hidden('swimlane_id', $values) ?>
<?= $this->form->hidden('column_id', $values) ?>
<?= $this->render($template, array(
'project' => $project,
'values' => $values,
)) ?>
<?php if (! empty($error_message)): ?>
<div class="alert alert-error"><?= $this->text->e($error_message) ?></div>
<?php endif ?>
<div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Next') ?></button>
<?= t('or') ?> <?= $this->url->link(t('cancel'), 'BoardViewController', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
</div>
</form>

View File

@ -0,0 +1,25 @@
<form class="popover-form" method="post" action="<?= $this->url->href('ExternalTaskCreationController', 'step3', array('project_id' => $project['id'], 'provider_name' => $provider_name)) ?>">
<?= $this->form->csrf() ?>
<?= $this->form->hidden('external_provider', $values) ?>
<?= $this->form->hidden('external_uri', $values) ?>
<?= $this->render($template, array(
'project' => $project,
'external_task' => $external_task,
'values' => $values,
'errors' => $errors,
'users_list' => $users_list,
'categories_list' => $categories_list,
'swimlanes_list' => $swimlanes_list,
'columns_list' => $columns_list,
)) ?>
<?php if (! empty($error_message)): ?>
<div class="alert alert-error"><?= $this->text->e($error_message) ?></div>
<?php endif ?>
<div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
<?= t('or') ?> <?= $this->url->link(t('cancel'), 'BoardViewController', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
</div>
</form>

View File

@ -1,8 +1,8 @@
<div class="page-header">
<h2><?= $this->text->e($project['name']) ?> &gt; <?= t('New task') ?></h2>
<h2><?= $this->text->e($project['name']) ?> &gt; <?= t('New task') ?><?= $this->task->getNewTaskDropdown($project['id'], $values['swimlane_id'], $values['column_id']) ?></h2>
</div>
<form class="popover-form" method="post" action="<?= $this->url->href('TaskCreationController', 'save', array('project_id' => $values['project_id'])) ?>" autocomplete="off">
<form class="popover-form" method="post" action="<?= $this->url->href('TaskCreationController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
<?= $this->form->csrf() ?>
<div class="form-columns">
@ -17,7 +17,6 @@
<?= $this->form->checkbox('another_task', t('Create another task'), 1, isset($values['another_task']) && $values['another_task'] == 1) ?>
<?= $this->form->checkbox('duplicate_multiple_projects', t('Duplicate to multiple projects'), 1) ?>
<?php endif ?>
</div>
<div class="form-column">

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -9,6 +9,10 @@ Kanboard.Dropdown.prototype.listen = function() {
self.close();
});
$(document).on('click', '#popover-content', function() {
self.close();
});
$(document).on('click', '.dropdown-menu', function(e) {
e.preventDefault();
e.stopImmediatePropagation();

View File

@ -137,7 +137,7 @@ Kanboard.Popover.prototype.afterOpen = function() {
});
// Autofocus fields (html5 autofocus works only with page onload)
$("[autofocus]").each(function() {
$("#popover-content input[autofocus]").each(function() {
$(this).focus();
});

View File

@ -1,5 +1,10 @@
@import variables
h2
.dropdown
ul
display: none
.dropdown
display: inline
position: relative