Add suggest menu for task ID

This commit is contained in:
Frederic Guillot
2016-12-03 12:56:12 -05:00
parent 4b22db5400
commit 23d862aef8
24 changed files with 382 additions and 36 deletions

View File

@@ -5,8 +5,12 @@ namespace Kanboard\Controller;
use Kanboard\Filter\TaskIdExclusionFilter;
use Kanboard\Filter\TaskIdFilter;
use Kanboard\Filter\TaskProjectsFilter;
use Kanboard\Filter\TaskStartsWithIdFilter;
use Kanboard\Filter\TaskStatusFilter;
use Kanboard\Filter\TaskTitleFilter;
use Kanboard\Formatter\TaskAutoCompleteFormatter;
use Kanboard\Formatter\TaskSuggestMenuFormatter;
use Kanboard\Model\TaskModel;
/**
* Task Ajax Controller
@@ -19,7 +23,6 @@ class TaskAjaxController extends BaseController
/**
* Task auto-completion (Ajax)
*
* @access public
*/
public function autocomplete()
{
@@ -46,4 +49,24 @@ class TaskAjaxController extends BaseController
$this->response->json($filter->format(new TaskAutoCompleteFormatter($this->container)));
}
}
/**
* Task ID suggest menu
*/
public function suggest()
{
$taskId = $this->request->getIntegerParam('search');
$projectIds = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
if (empty($projectIds)) {
$this->response->json(array());
} else {
$filter = $this->taskQuery
->withFilter(new TaskProjectsFilter($projectIds))
->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN))
->withFilter(new TaskStartsWithIdFilter($taskId));
$this->response->json($filter->format(new TaskSuggestMenuFormatter($this->container)));
}
}
}

View File

@@ -36,7 +36,7 @@ class UserAjaxController extends BaseController
public function mention()
{
$project_id = $this->request->getStringParam('project_id');
$query = $this->request->getStringParam('q');
$query = $this->request->getStringParam('search');
$users = $this->projectPermissionModel->findUsernames($project_id, $query);
$this->response->json(

View File

@@ -90,7 +90,7 @@ class Markdown extends Parsedown
$user_id = $this->container['userModel']->getIdByUsername($matches[1]);
if (! empty($user_id)) {
$url = $this->container['helper']->url->href('UserViewController', 'profile', array('user_id' => $user_id), false, '', true);
$url = $this->container['helper']->url->href('UserViewController', 'profile', array('user_id' => $user_id));
return array(
'extent' => strlen($matches[0]),
@@ -125,7 +125,10 @@ class Markdown extends Parsedown
array(
'token' => $token,
'task_id' => $task_id,
)
),
false,
'',
true
);
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Kanboard\Filter;
use Kanboard\Core\Filter\FilterInterface;
use Kanboard\Model\TaskModel;
/**
* Class TaskIdSearchFilter
*
* @package Kanboard\Filter
* @author Frederic Guillot
*/
class TaskStartsWithIdFilter extends BaseFilter implements FilterInterface
{
/**
* Get search attribute
*
* @access public
* @return string[]
*/
public function getAttributes()
{
return array('starts_with_id');
}
/**
* Apply filter
*
* @access public
* @return FilterInterface
*/
public function apply()
{
$this->query->ilike('CAST('.TaskModel::TABLE.'.id AS CHAR(8))', $this->value.'%');
return $this;
}
}

View File

@@ -14,6 +14,20 @@ use Kanboard\Model\TaskModel;
*/
class TaskAutoCompleteFormatter extends BaseFormatter implements FormatterInterface
{
protected $limit = 25;
/**
* Limit number of results
*
* @param $limit
* @return $this
*/
public function withLimit($limit)
{
$this->limit = $limit;
return $this;
}
/**
* Apply formatter
*
@@ -22,11 +36,15 @@ class TaskAutoCompleteFormatter extends BaseFormatter implements FormatterInterf
*/
public function format()
{
$tasks = $this->query->columns(
TaskModel::TABLE.'.id',
TaskModel::TABLE.'.title',
ProjectModel::TABLE.'.name AS project_name'
)->asc(TaskModel::TABLE.'.id')->findAll();
$tasks = $this->query
->columns(
TaskModel::TABLE.'.id',
TaskModel::TABLE.'.title',
ProjectModel::TABLE.'.name AS project_name'
)
->asc(TaskModel::TABLE.'.id')
->limit($this->limit)
->findAll();
foreach ($tasks as &$task) {
$task['value'] = $task['title'];

View File

@@ -0,0 +1,63 @@
<?php
namespace Kanboard\Formatter;
use Kanboard\Core\Filter\FormatterInterface;
use Kanboard\Model\ProjectModel;
use Kanboard\Model\TaskModel;
/**
* Class TaskSuggestMenuFormatter
*
* @package Kanboard\Formatter
* @author Frederic Guillot
*/
class TaskSuggestMenuFormatter extends BaseFormatter implements FormatterInterface
{
protected $limit = 25;
/**
* Limit number of results
*
* @param $limit
* @return $this
*/
public function withLimit($limit)
{
$this->limit = $limit;
return $this;
}
/**
* Apply formatter
*
* @access public
* @return mixed
*/
public function format()
{
$result = array();
$tasks = $this->query
->columns(
TaskModel::TABLE.'.id',
TaskModel::TABLE.'.title',
ProjectModel::TABLE.'.name AS project_name'
)
->asc(TaskModel::TABLE.'.id')
->limit($this->limit)
->findAll();
foreach ($tasks as $task) {
$html = '#'.$task['id'].' ';
$html .= $this->helper->text->e($task['title']).' ';
$html .= '<small>'.$this->helper->text->e($task['project_name']).'</small>';
$result[] = array(
'value' => (string) $task['id'],
'html' => $html,
);
}
return $result;
}
}

View File

@@ -220,11 +220,16 @@ class FormHelper extends Base
'labelPreview' => t('Preview'),
'labelWrite' => t('Write'),
'placeholder' => t('Write your text in Markdown'),
'autofocus' => isset($attributes['autofocus']) && $attributes['autofocus']
'autofocus' => isset($attributes['autofocus']) && $attributes['autofocus'],
'suggestOptions' => array(
'triggers' => array(
'#' => $this->helper->url->to('TaskAjaxController', 'suggest', array('search' => 'SEARCH_TERM')),
)
),
);
if (isset($values['project_id'])) {
$params['mentionUrl'] = $this->helper->url->to('UserAjaxController', 'mention', array('project_id' => $values['project_id']));
$params['suggestOptions']['triggers']['@'] = $this->helper->url->to('UserAjaxController', 'mention', array('project_id' => $values['project_id'], 'search' => 'SEARCH_TERM'));
}
$html = '<div class="js-text-editor" data-params=\''.json_encode($params, JSON_HEX_APOS).'\'></div>';

View File

@@ -6,6 +6,6 @@
<h3><?= t('New comment') ?></h3>
<?php endif ?>
<?= $this->text->markdown($comment['comment']) ?>
<?= $this->text->markdown($comment['comment'], true) ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -2,6 +2,6 @@
<h3><?= t('Comment removed') ?></h3>
<?= $this->text->markdown($comment['comment']) ?>
<?= $this->text->markdown($comment['comment'], true) ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -2,6 +2,6 @@
<h3><?= t('Comment updated') ?></h3>
<?= $this->text->markdown($comment['comment']) ?>
<?= $this->text->markdown($comment['comment'], true) ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -2,6 +2,6 @@
<p><?= $this->text->e($task['title']) ?></p>
<?= $this->text->markdown($comment['comment']) ?>
<?= $this->text->markdown($comment['comment'], true) ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -14,7 +14,7 @@
<?php if (! empty($task['description'])): ?>
<h2><?= t('Description') ?></h2>
<?= $this->text->markdown($task['description']) ?: t('There is no description.') ?>
<?= $this->text->markdown($task['description'], true) ?: t('There is no description.') ?>
<?php endif ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -37,7 +37,7 @@
<?php if (! empty($task['description'])): ?>
<h2><?= t('Description') ?></h2>
<?= $this->text->markdown($task['description']) ?>
<?= $this->text->markdown($task['description'], true) ?>
<?php endif ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -1,4 +1,4 @@
<h2><?= $this->text->e($task['title']) ?> (#<?= $task['id'] ?>)</h2>
<?= $this->render('task/changes', array('changes' => $changes, 'task' => $task)) ?>
<?= $this->render('task/changes', array('changes' => $changes, 'task' => $task, 'public' => true)) ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -2,6 +2,6 @@
<p><?= $this->text->e($task['title']) ?></p>
<h2><?= t('Description') ?></h2>
<?= $this->text->markdown($task['description']) ?>
<?= $this->text->markdown($task['description'], true) ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>

View File

@@ -69,6 +69,10 @@
<?php if (! empty($changes['description'])): ?>
<p><strong><?= t('The description has been modified:') ?></strong></p>
<div class="markdown"><?= $this->text->markdown($task['description']) ?></div>
<?php if (isset($public)): ?>
<div class="markdown"><?= $this->text->markdown($task['description'], true) ?></div>
<?php else: ?>
<div class="markdown"><?= $this->text->markdown($task['description']) ?></div>
<?php endif ?>
<?php endif ?>
<?php endif ?>