diff options
author | Frederic Guillot <fred@kanboard.net> | 2015-07-18 11:33:51 -0400 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2015-07-18 11:33:51 -0400 |
commit | dfd79722270b4f7a6653cb130b6518dcd7bd8c95 (patch) | |
tree | 122a0c4ddfe0fcca6f87b100c51a8ce36bcbc78a | |
parent | d75a0a9d455c01b6845dcc2ea7d61d55d416766b (diff) |
Add new search attribute for swimlane
-rw-r--r-- | app/Core/Lexer.php | 2 | ||||
-rw-r--r-- | app/Model/TaskFilter.php | 27 | ||||
-rw-r--r-- | app/Model/TaskFinder.php | 3 | ||||
-rw-r--r-- | app/Template/listing/show.php | 18 | ||||
-rw-r--r-- | app/Template/search/results.php | 20 | ||||
-rw-r--r-- | docs/search.markdown | 9 | ||||
-rw-r--r-- | tests/units/LexerTest.php | 25 | ||||
-rw-r--r-- | tests/units/TaskFilterTest.php | 59 |
8 files changed, 138 insertions, 25 deletions
diff --git a/app/Core/Lexer.php b/app/Core/Lexer.php index 3887dc82..0a237254 100644 --- a/app/Core/Lexer.php +++ b/app/Core/Lexer.php @@ -33,6 +33,7 @@ class Lexer "/^(category:)/" => 'T_CATEGORY', "/^(column:)/" => 'T_COLUMN', "/^(project:)/" => 'T_PROJECT', + "/^(swimlane:)/" => 'T_SWIMLANE', "/^(ref:)/" => 'T_REFERENCE', "/^(reference:)/" => 'T_REFERENCE', "/^(\s+)/" => 'T_WHITESPACE', @@ -116,6 +117,7 @@ class Lexer case 'T_CATEGORY': case 'T_COLUMN': case 'T_PROJECT': + case 'T_SWIMLANE': $next = next($tokens); if ($next !== false && $next['token'] === 'T_STRING') { diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php index 377ec3c6..822397ec 100644 --- a/app/Model/TaskFilter.php +++ b/app/Model/TaskFilter.php @@ -71,6 +71,9 @@ class TaskFilter extends Base case 'T_REFERENCE': $this->filterByReference($value); break; + case 'T_SWIMLANE': + $this->filterBySwimlaneName($value); + break; } } @@ -247,6 +250,30 @@ class TaskFilter extends Base } /** + * Filter by swimlane name + * + * @access public + * @param array $values List of swimlane name + * @return TaskFilter + */ + public function filterBySwimlaneName(array $values) + { + $this->query->beginOr(); + + foreach ($values as $swimlane) { + if ($swimlane === 'default') { + $this->query->eq(Task::TABLE.'.swimlane_id', 0); + } + else { + $this->query->ilike(Swimlane::TABLE.'.name', $swimlane); + $this->query->addCondition(Task::TABLE.'.swimlane_id=0 AND '.Project::TABLE.'.default_swimlane '.$this->db->getDriver()->getOperator('ILIKE')." '$swimlane'"); + } + } + + $this->query->closeOr(); + } + + /** * Filter by category id * * @access public diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index 2b0453a5..47a67a35 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -88,11 +88,14 @@ class TaskFinder extends Base Category::TABLE.'.name AS category_name', Category::TABLE.'.description AS category_description', Board::TABLE.'.title AS column_name', + Swimlane::TABLE.'.name AS swimlane_name', + Project::TABLE.'.default_swimlane', Project::TABLE.'.name AS project_name' ) ->join(User::TABLE, 'id', 'owner_id', Task::TABLE) ->join(Category::TABLE, 'id', 'category_id', Task::TABLE) ->join(Board::TABLE, 'id', 'column_id', Task::TABLE) + ->join(Swimlane::TABLE, 'id', 'swimlane_id', Task::TABLE) ->join(Project::TABLE, 'id', 'project_id', Task::TABLE); } diff --git a/app/Template/listing/show.php b/app/Template/listing/show.php index 06940678..fc8a607b 100644 --- a/app/Template/listing/show.php +++ b/app/Template/listing/show.php @@ -10,13 +10,12 @@ <table class="table-fixed table-small"> <tr> <th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th> - <th class="column-8"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> - <th class="column-8"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Swimlane'), 'tasks.swimlane_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> <th><?= $paginator->order(t('Title'), 'tasks.title') ?></th> <th class="column-10"><?= $paginator->order(t('Assignee'), 'users.username') ?></th> <th class="column-10"><?= $paginator->order(t('Due date'), 'tasks.date_due') ?></th> - <th class="column-10"><?= $paginator->order(t('Date created'), 'tasks.date_creation') ?></th> - <th class="column-10"><?= $paginator->order(t('Date completed'), 'tasks.date_completed') ?></th> <th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th> </tr> <?php foreach ($paginator->getCollection() as $task): ?> @@ -25,6 +24,9 @@ <?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> </td> <td> + <?= $this->e($task['swimlane_name'] ?: $task['default_swimlane']) ?> + </td> + <td> <?= $this->e($task['column_name']) ?> </td> <td> @@ -44,14 +46,6 @@ <?= dt('%B %e, %Y', $task['date_due']) ?> </td> <td> - <?= dt('%B %e, %Y', $task['date_creation']) ?> - </td> - <td> - <?php if ($task['date_completed']): ?> - <?= dt('%B %e, %Y', $task['date_completed']) ?> - <?php endif ?> - </td> - <td> <?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?> <?= t('Open') ?> <?php else: ?> diff --git a/app/Template/search/results.php b/app/Template/search/results.php index 1d8cc6e2..04cb6a19 100644 --- a/app/Template/search/results.php +++ b/app/Template/search/results.php @@ -1,14 +1,13 @@ <table class="table-fixed table-small"> <tr> <th class="column-8"><?= $paginator->order(t('Project'), 'tasks.project_id') ?></th> - <th class="column-8"><?= $paginator->order(t('Id'), 'tasks.id') ?></th> - <th class="column-8"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> - <th class="column-8"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> + <th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th> + <th class="column-10"><?= $paginator->order(t('Swimlane'), 'tasks.swimlane_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> <th><?= $paginator->order(t('Title'), 'tasks.title') ?></th> <th class="column-10"><?= $paginator->order(t('Assignee'), 'users.username') ?></th> <th class="column-10"><?= $paginator->order(t('Due date'), 'tasks.date_due') ?></th> - <th class="column-10"><?= $paginator->order(t('Date created'), 'tasks.date_creation') ?></th> - <th class="column-10"><?= $paginator->order(t('Date completed'), 'tasks.date_completed') ?></th> <th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th> </tr> <?php foreach ($paginator->getCollection() as $task): ?> @@ -20,6 +19,9 @@ <?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> </td> <td> + <?= $this->e($task['swimlane_name'] ?: $task['default_swimlane']) ?> + </td> + <td> <?= $this->e($task['column_name']) ?> </td> <td> @@ -39,14 +41,6 @@ <?= dt('%B %e, %Y', $task['date_due']) ?> </td> <td> - <?= dt('%B %e, %Y', $task['date_creation']) ?> - </td> - <td> - <?php if ($task['date_completed']): ?> - <?= dt('%B %e, %Y', $task['date_completed']) ?> - <?php endif ?> - </td> - <td> <?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?> <?= t('Open') ?> <?php else: ?> diff --git a/docs/search.markdown b/docs/search.markdown index 3d00b158..d0e71203 100644 --- a/docs/search.markdown +++ b/docs/search.markdown @@ -151,6 +151,15 @@ Attribute: **column** - Find tasks by column name: `column:"Work in progress"` - Find tasks for several columns: `column:"Backlog" column:ready` +Search by swimlane +------------------ + +Attribute: **swimlane** + +- Find tasks by swimlane: `swimlane:"Version 42"` +- Find tasks in the default swimlane: `swimlane:default` +- Find tasks into several swimlanes: `swimlane:"Version 1.2" swimlane:"Version 1.3"` + Search by external reference ---------------------------- diff --git a/tests/units/LexerTest.php b/tests/units/LexerTest.php index bf0ffdd0..8710f79a 100644 --- a/tests/units/LexerTest.php +++ b/tests/units/LexerTest.php @@ -6,6 +6,31 @@ use Core\Lexer; class LexerTest extends Base { + public function testSwimlaneQuery() + { + $lexer = new Lexer; + + $this->assertEquals( + array(array('match' => 'swimlane:', 'token' => 'T_SWIMLANE'), array('match' => 'Version 42', 'token' => 'T_STRING')), + $lexer->tokenize('swimlane:"Version 42"') + ); + + $this->assertEquals( + array(array('match' => 'swimlane:', 'token' => 'T_SWIMLANE'), array('match' => 'v3', 'token' => 'T_STRING')), + $lexer->tokenize('swimlane:v3') + ); + + $this->assertEquals( + array('T_SWIMLANE' => array('v3')), + $lexer->map($lexer->tokenize('swimlane:v3')) + ); + + $this->assertEquals( + array('T_SWIMLANE' => array('Version 42', 'v3')), + $lexer->map($lexer->tokenize('swimlane:"Version 42" swimlane:v3')) + ); + } + public function testAssigneeQuery() { $lexer = new Lexer; diff --git a/tests/units/TaskFilterTest.php b/tests/units/TaskFilterTest.php index 14a9b1c0..58d02524 100644 --- a/tests/units/TaskFilterTest.php +++ b/tests/units/TaskFilterTest.php @@ -9,6 +9,7 @@ use Model\TaskCreation; use Model\DateParser; use Model\Category; use Model\Config; +use Model\Swimlane; class TaskFilterTest extends Base { @@ -286,6 +287,64 @@ class TaskFilterTest extends Base $this->assertEmpty($tasks); } + public function testSearchWithSwimlane() + { + $p = new Project($this->container); + $tc = new TaskCreation($this->container); + $tf = new TaskFilter($this->container); + $s = new Swimlane($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'My project A'))); + $this->assertEquals(1, $s->create(1, 'Version 1.1')); + $this->assertEquals(2, $s->create(1, 'Version 1.2')); + $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task1', 'swimlane_id' => 1))); + $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task2', 'swimlane_id' => 2))); + $this->assertNotFalse($tc->create(array('project_id' => 1, 'title' => 'task3', 'swimlane_id' => 0))); + + $tf->search('swimlane:"Version 1.1"'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('task1', $tasks[0]['title']); + $this->assertEquals('Version 1.1', $tasks[0]['swimlane_name']); + + $tf->search('swimlane:"versioN 1.2"'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('task2', $tasks[0]['title']); + $this->assertEquals('Version 1.2', $tasks[0]['swimlane_name']); + + $tf->search('swimlane:"Default swimlane"'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('task3', $tasks[0]['title']); + $this->assertEquals('Default swimlane', $tasks[0]['default_swimlane']); + $this->assertEquals('', $tasks[0]['swimlane_name']); + + $tf->search('swimlane:default'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('task3', $tasks[0]['title']); + $this->assertEquals('Default swimlane', $tasks[0]['default_swimlane']); + $this->assertEquals('', $tasks[0]['swimlane_name']); + + $tf->search('swimlane:"Version 1.1" swimlane:"Version 1.2"'); + $tasks = $tf->findAll(); + $this->assertNotEmpty($tasks); + $this->assertCount(2, $tasks); + $this->assertEquals('task1', $tasks[0]['title']); + $this->assertEquals('Version 1.1', $tasks[0]['swimlane_name']); + $this->assertEquals('task2', $tasks[1]['title']); + $this->assertEquals('Version 1.2', $tasks[1]['swimlane_name']); + + $tf->search('swimlane:"not found"'); + $tasks = $tf->findAll(); + $this->assertEmpty($tasks); + } + public function testSearchWithColumn() { $p = new Project($this->container); |