Add the possibility to create external tasks
This commit is contained in:
parent
ae5d31e4c2
commit
3f7840c4db
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Core\ExternalTask;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class NotFoundException
|
||||
*
|
||||
* @package Kanboard\Core\ExternalTask
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ExternalTaskException extends Exception
|
||||
{
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<div class="page-header">
|
||||
<h2><?= $this->text->e($project['name']) ?> > <?= t('New task') ?></h2>
|
||||
<h2><?= $this->text->e($project['name']) ?> > <?= 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
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
@import variables
|
||||
|
||||
h2
|
||||
.dropdown
|
||||
ul
|
||||
display: none
|
||||
|
||||
.dropdown
|
||||
display: inline
|
||||
position: relative
|
||||
|
|
|
|||
Loading…
Reference in New Issue