diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/Controller/ExternalTaskCreationController.php | 97 | ||||
-rw-r--r-- | app/Core/ExternalTask/AccessForbiddenException.php | 5 | ||||
-rw-r--r-- | app/Core/ExternalTask/ExternalTaskException.php | 15 | ||||
-rw-r--r-- | app/Core/ExternalTask/ExternalTaskInterface.php | 26 | ||||
-rw-r--r-- | app/Core/ExternalTask/ExternalTaskProviderInterface.php | 35 | ||||
-rw-r--r-- | app/Core/ExternalTask/NotFoundException.php | 4 | ||||
-rw-r--r-- | app/Core/ExternalTask/ProviderNotFoundException.php | 4 | ||||
-rw-r--r-- | app/Helper/TaskHelper.php | 28 | ||||
-rw-r--r-- | app/Schema/Mysql.php | 8 | ||||
-rw-r--r-- | app/Schema/Postgres.php | 8 | ||||
-rw-r--r-- | app/Schema/Sqlite.php | 8 | ||||
-rw-r--r-- | app/Template/external_task_creation/step1.php | 19 | ||||
-rw-r--r-- | app/Template/external_task_creation/step2.php | 25 | ||||
-rw-r--r-- | app/Template/task_creation/show.php | 5 |
14 files changed, 256 insertions, 31 deletions
diff --git a/app/Controller/ExternalTaskCreationController.php b/app/Controller/ExternalTaskCreationController.php new file mode 100644 index 00000000..f2afd9aa --- /dev/null +++ b/app/Controller/ExternalTaskCreationController.php @@ -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); + } + } +} diff --git a/app/Core/ExternalTask/AccessForbiddenException.php b/app/Core/ExternalTask/AccessForbiddenException.php index a379d812..2b5ebd33 100644 --- a/app/Core/ExternalTask/AccessForbiddenException.php +++ b/app/Core/ExternalTask/AccessForbiddenException.php @@ -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 { } diff --git a/app/Core/ExternalTask/ExternalTaskException.php b/app/Core/ExternalTask/ExternalTaskException.php new file mode 100644 index 00000000..07e5665d --- /dev/null +++ b/app/Core/ExternalTask/ExternalTaskException.php @@ -0,0 +1,15 @@ +<?php + +namespace Kanboard\Core\ExternalTask; + +use Exception; + +/** + * Class NotFoundException + * + * @package Kanboard\Core\ExternalTask + * @author Frederic Guillot + */ +class ExternalTaskException extends Exception +{ +} diff --git a/app/Core/ExternalTask/ExternalTaskInterface.php b/app/Core/ExternalTask/ExternalTaskInterface.php new file mode 100644 index 00000000..084af509 --- /dev/null +++ b/app/Core/ExternalTask/ExternalTaskInterface.php @@ -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(); +} diff --git a/app/Core/ExternalTask/ExternalTaskProviderInterface.php b/app/Core/ExternalTask/ExternalTaskProviderInterface.php index 9e672780..af1dffec 100644 --- a/app/Core/ExternalTask/ExternalTaskProviderInterface.php +++ b/app/Core/ExternalTask/ExternalTaskProviderInterface.php @@ -11,15 +11,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) * * @access public @@ -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 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 persist($uri, array $data); + public function buildTaskUri(array $values); } diff --git a/app/Core/ExternalTask/NotFoundException.php b/app/Core/ExternalTask/NotFoundException.php index c7ed13ef..34eff8ea 100644 --- a/app/Core/ExternalTask/NotFoundException.php +++ b/app/Core/ExternalTask/NotFoundException.php @@ -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 { } diff --git a/app/Core/ExternalTask/ProviderNotFoundException.php b/app/Core/ExternalTask/ProviderNotFoundException.php index 2deddda8..6ad1fae1 100644 --- a/app/Core/ExternalTask/ProviderNotFoundException.php +++ b/app/Core/ExternalTask/ProviderNotFoundException.php @@ -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 { } diff --git a/app/Helper/TaskHelper.php b/app/Helper/TaskHelper.php index 678b4bed..1dce7c54 100644 --- a/app/Helper/TaskHelper.php +++ b/app/Helper/TaskHelper.php @@ -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; + } } diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index 274ce8c8..b50164ca 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -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) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 213d9869..83926f19 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -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) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index f86a6af0..edf6ce63 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -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) { diff --git a/app/Template/external_task_creation/step1.php b/app/Template/external_task_creation/step1.php new file mode 100644 index 00000000..2af9b427 --- /dev/null +++ b/app/Template/external_task_creation/step1.php @@ -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> diff --git a/app/Template/external_task_creation/step2.php b/app/Template/external_task_creation/step2.php new file mode 100644 index 00000000..4bc0e509 --- /dev/null +++ b/app/Template/external_task_creation/step2.php @@ -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> diff --git a/app/Template/task_creation/show.php b/app/Template/task_creation/show.php index 0c267aff..840d1804 100644 --- a/app/Template/task_creation/show.php +++ b/app/Template/task_creation/show.php @@ -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"> |