Display tags in task list view
This commit is contained in:
@@ -7,6 +7,7 @@ New features:
|
|||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
|
||||||
|
* Display tags in task list view
|
||||||
* Change users list layout
|
* Change users list layout
|
||||||
* Project priority is always rendered now
|
* Project priority is always rendered now
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class TaskListController extends BaseController
|
|||||||
->setMax(30)
|
->setMax(30)
|
||||||
->setOrder(TaskModel::TABLE.'.id')
|
->setOrder(TaskModel::TABLE.'.id')
|
||||||
->setDirection('DESC')
|
->setDirection('DESC')
|
||||||
|
->setFormatter($this->taskListFormatter)
|
||||||
->setQuery($this->taskLexer
|
->setQuery($this->taskLexer
|
||||||
->build($search)
|
->build($search)
|
||||||
->withFilter(new TaskProjectFilter($project['id']))
|
->withFilter(new TaskProjectFilter($project['id']))
|
||||||
@@ -36,10 +37,10 @@ class TaskListController extends BaseController
|
|||||||
->calculate();
|
->calculate();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->app('task_list/listing', array(
|
$this->response->html($this->helper->layout->app('task_list/listing', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'title' => $project['name'],
|
'title' => $project['name'],
|
||||||
'description' => $this->helper->projectHeader->getDescription($project),
|
'description' => $this->helper->projectHeader->getDescription($project),
|
||||||
'paginator' => $paginator,
|
'paginator' => $paginator,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ use Pimple\Container;
|
|||||||
* @property \Kanboard\Formatter\TaskCalendarFormatter $taskCalendarFormatter
|
* @property \Kanboard\Formatter\TaskCalendarFormatter $taskCalendarFormatter
|
||||||
* @property \Kanboard\Formatter\TaskGanttFormatter $taskGanttFormatter
|
* @property \Kanboard\Formatter\TaskGanttFormatter $taskGanttFormatter
|
||||||
* @property \Kanboard\Formatter\TaskICalFormatter $taskICalFormatter
|
* @property \Kanboard\Formatter\TaskICalFormatter $taskICalFormatter
|
||||||
|
* @property \Kanboard\Formatter\TaskListFormatter $taskListFormatter
|
||||||
* @property \Kanboard\Formatter\TaskSuggestMenuFormatter $taskSuggestMenuFormatter
|
* @property \Kanboard\Formatter\TaskSuggestMenuFormatter $taskSuggestMenuFormatter
|
||||||
* @property \Kanboard\Formatter\UserAutoCompleteFormatter $userAutoCompleteFormatter
|
* @property \Kanboard\Formatter\UserAutoCompleteFormatter $userAutoCompleteFormatter
|
||||||
* @property \Kanboard\Formatter\UserMentionFormatter $userMentionFormatter
|
* @property \Kanboard\Formatter\UserMentionFormatter $userMentionFormatter
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
namespace Kanboard\Core;
|
namespace Kanboard\Core;
|
||||||
|
|
||||||
|
use Kanboard\Core\Filter\FormatterInterface;
|
||||||
use Pimple\Container;
|
use Pimple\Container;
|
||||||
use PicoDb\Table;
|
use PicoDb\Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paginator helper
|
* Paginator Helper
|
||||||
*
|
*
|
||||||
* @package core
|
* @package Kanboard\Core
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Paginator
|
class Paginator
|
||||||
@@ -109,6 +110,11 @@ class Paginator
|
|||||||
*/
|
*/
|
||||||
private $params = array();
|
private $params = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FormatterInterface
|
||||||
|
*/
|
||||||
|
protected $formatter = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@@ -125,7 +131,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param \PicoDb\Table
|
* @param \PicoDb\Table
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setQuery(Table $query)
|
public function setQuery(Table $query)
|
||||||
{
|
{
|
||||||
@@ -134,6 +140,18 @@ class Paginator
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Formatter
|
||||||
|
*
|
||||||
|
* @param FormatterInterface $formatter
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setFormatter(FormatterInterface $formatter)
|
||||||
|
{
|
||||||
|
$this->formatter = $formatter;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a PicoDb query
|
* Execute a PicoDb query
|
||||||
*
|
*
|
||||||
@@ -143,11 +161,16 @@ class Paginator
|
|||||||
public function executeQuery()
|
public function executeQuery()
|
||||||
{
|
{
|
||||||
if ($this->query !== null) {
|
if ($this->query !== null) {
|
||||||
return $this->query
|
$this->query
|
||||||
->offset($this->offset)
|
->offset($this->offset)
|
||||||
->limit($this->limit)
|
->limit($this->limit)
|
||||||
->orderBy($this->order, $this->direction)
|
->orderBy($this->order, $this->direction);
|
||||||
->findAll();
|
|
||||||
|
if ($this->formatter !== null) {
|
||||||
|
return $this->formatter->withQuery($this->query)->format();
|
||||||
|
} else {
|
||||||
|
return $this->query->findAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array();
|
return array();
|
||||||
@@ -160,7 +183,7 @@ class Paginator
|
|||||||
* @param string $controller
|
* @param string $controller
|
||||||
* @param string $action
|
* @param string $action
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setUrl($controller, $action, array $params = array())
|
public function setUrl($controller, $action, array $params = array())
|
||||||
{
|
{
|
||||||
@@ -175,7 +198,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $items
|
* @param array $items
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setCollection(array $items)
|
public function setCollection(array $items)
|
||||||
{
|
{
|
||||||
@@ -199,7 +222,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $total
|
* @param integer $total
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setTotal($total)
|
public function setTotal($total)
|
||||||
{
|
{
|
||||||
@@ -223,7 +246,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $page
|
* @param integer $page
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setPage($page)
|
public function setPage($page)
|
||||||
{
|
{
|
||||||
@@ -247,7 +270,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $order
|
* @param string $order
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setOrder($order)
|
public function setOrder($order)
|
||||||
{
|
{
|
||||||
@@ -260,7 +283,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $direction
|
* @param string $direction
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setDirection($direction)
|
public function setDirection($direction)
|
||||||
{
|
{
|
||||||
@@ -273,7 +296,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $limit
|
* @param integer $limit
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setMax($limit)
|
public function setMax($limit)
|
||||||
{
|
{
|
||||||
@@ -307,7 +330,7 @@ class Paginator
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param boolean $condition
|
* @param boolean $condition
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function calculateOnlyIf($condition)
|
public function calculateOnlyIf($condition)
|
||||||
{
|
{
|
||||||
@@ -322,7 +345,7 @@ class Paginator
|
|||||||
* Calculate the offset value accoring to url params and the page number
|
* Calculate the offset value accoring to url params and the page number
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @return Paginator
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function calculate()
|
public function calculate()
|
||||||
{
|
{
|
||||||
@@ -421,7 +444,7 @@ class Paginator
|
|||||||
* @access public
|
* @access public
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function generatPageShowing()
|
public function generatePageShowing()
|
||||||
{
|
{
|
||||||
return '<span class="pagination-showing">'.t('Showing %d-%d of %d', (($this->getPage() - 1) * $this->getMax() + 1), min($this->getTotal(), $this->getPage() * $this->getMax()), $this->getTotal()).'</span>';
|
return '<span class="pagination-showing">'.t('Showing %d-%d of %d', (($this->getPage() - 1) * $this->getMax() + 1), min($this->getTotal(), $this->getPage() * $this->getMax()), $this->getTotal()).'</span>';
|
||||||
}
|
}
|
||||||
@@ -432,7 +455,7 @@ class Paginator
|
|||||||
* @access public
|
* @access public
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function hasNothingtoShow()
|
public function hasNothingToShow()
|
||||||
{
|
{
|
||||||
return $this->offset === 0 && ($this->total - $this->offset) <= $this->limit;
|
return $this->offset === 0 && ($this->total - $this->offset) <= $this->limit;
|
||||||
}
|
}
|
||||||
@@ -447,9 +470,9 @@ class Paginator
|
|||||||
{
|
{
|
||||||
$html = '';
|
$html = '';
|
||||||
|
|
||||||
if (! $this->hasNothingtoShow()) {
|
if (! $this->hasNothingToShow()) {
|
||||||
$html .= '<div class="pagination">';
|
$html .= '<div class="pagination">';
|
||||||
$html .= $this->generatPageShowing();
|
$html .= $this->generatePageShowing();
|
||||||
$html .= $this->generatePreviousLink();
|
$html .= $this->generatePreviousLink();
|
||||||
$html .= $this->generateNextLink();
|
$html .= $this->generateNextLink();
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|||||||
30
app/Formatter/TaskListFormatter.php
Normal file
30
app/Formatter/TaskListFormatter.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Formatter;
|
||||||
|
|
||||||
|
use Kanboard\Core\Filter\FormatterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TaskListFormatter
|
||||||
|
*
|
||||||
|
* @package Kanboard\Formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskListFormatter extends BaseFormatter implements FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Apply formatter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
$tasks = $this->query->findAll();
|
||||||
|
$taskIds = array_column($tasks, 'id');
|
||||||
|
$tags = $this->taskTagModel->getTagsByTasks($taskIds);
|
||||||
|
array_merge_relation($tasks, $tags, 'tags', 'id');
|
||||||
|
|
||||||
|
return $tasks;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ class FormatterProvider implements ServiceProviderInterface
|
|||||||
'TaskCalendarFormatter',
|
'TaskCalendarFormatter',
|
||||||
'TaskGanttFormatter',
|
'TaskGanttFormatter',
|
||||||
'TaskICalFormatter',
|
'TaskICalFormatter',
|
||||||
|
'TaskListFormatter',
|
||||||
'TaskSuggestMenuFormatter',
|
'TaskSuggestMenuFormatter',
|
||||||
'UserAutoCompleteFormatter',
|
'UserAutoCompleteFormatter',
|
||||||
'UserMentionFormatter',
|
'UserMentionFormatter',
|
||||||
|
|||||||
@@ -20,4 +20,10 @@
|
|||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</span>
|
</span>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
|
<?php foreach ($task['tags'] as $tag): ?>
|
||||||
|
<span class="table-list-category task-list-tag">
|
||||||
|
<?= $this->text->e($tag['name']) ?>
|
||||||
|
</span>
|
||||||
|
<?php endforeach ?>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
2
assets/css/app.min.css
vendored
2
assets/css/app.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -96,7 +96,7 @@
|
|||||||
font-size: size('compact')
|
font-size: size('compact')
|
||||||
font-weight: 500
|
font-weight: 500
|
||||||
color: color('dark')
|
color: color('dark')
|
||||||
padding: 1px 3px 1px 2px
|
padding: 1px 2px 1px 2px
|
||||||
border-radius: 3px
|
border-radius: 3px
|
||||||
background: bg-color('light')
|
background: bg-color('light')
|
||||||
border: 1px solid #ccc
|
border: 1px solid #ccc
|
||||||
|
|||||||
@@ -11,3 +11,7 @@
|
|||||||
|
|
||||||
.task-summary-container .task-tags
|
.task-summary-container .task-tags
|
||||||
margin-top: 10px
|
margin-top: 10px
|
||||||
|
|
||||||
|
.task-list-tag
|
||||||
|
background: #ffeb8e
|
||||||
|
border-color: #333
|
||||||
|
|||||||
60
tests/units/Formatter/TaskListFormatterTest.php
Normal file
60
tests/units/Formatter/TaskListFormatterTest.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Kanboard\Formatter\TaskListFormatter;
|
||||||
|
use Kanboard\Model\ProjectModel;
|
||||||
|
use Kanboard\Model\TaskCreationModel;
|
||||||
|
use Kanboard\Model\TaskFinderModel;
|
||||||
|
use Kanboard\Model\TaskTagModel;
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
class TaskListFormatterTest extends Base
|
||||||
|
{
|
||||||
|
public function testFormatWithTags()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$taskFinderModel = new TaskFinderModel($this->container);
|
||||||
|
$taskCreationModel = new TaskCreationModel($this->container);
|
||||||
|
$taskTagModel = new TaskTagModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test1')));
|
||||||
|
$this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test2', 'column_id' => 3)));
|
||||||
|
$this->assertEquals(3, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test3')));
|
||||||
|
|
||||||
|
$this->assertTrue($taskTagModel->save(1, 1, array('My tag 1', 'My tag 2')));
|
||||||
|
$this->assertTrue($taskTagModel->save(1, 2, array('My tag 3')));
|
||||||
|
|
||||||
|
$listing = TaskListFormatter::getInstance($this->container)
|
||||||
|
->withQuery($taskFinderModel->getExtendedQuery())
|
||||||
|
->format();
|
||||||
|
|
||||||
|
$this->assertCount(3, $listing);
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
array(
|
||||||
|
'id' => 1,
|
||||||
|
'name' => 'My tag 1',
|
||||||
|
'task_id' => 1,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'id' => 2,
|
||||||
|
'name' => 'My tag 2',
|
||||||
|
'task_id' => 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $listing[0]['tags']);
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
array(
|
||||||
|
'id' => 3,
|
||||||
|
'name' => 'My tag 3',
|
||||||
|
'task_id' => 2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $listing[1]['tags']);
|
||||||
|
$this->assertEquals(array(), $listing[2]['tags']);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user