diff options
author | Frederic Guillot <fred@kanboard.net> | 2015-07-01 18:28:32 -0400 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2015-07-01 18:28:32 -0400 |
commit | 31f3de9646e4e54db431be6a6751e931be43d995 (patch) | |
tree | 389cd7f69aaf7563389b6e4793a1dd6bb3a57e06 | |
parent | 109a2a2e25e0e170d3df3860d054f82f70e78c4d (diff) |
Add global search section
-rw-r--r-- | app/Controller/Search.php | 51 | ||||
-rw-r--r-- | app/Model/Color.php | 2 | ||||
-rw-r--r-- | app/Model/TaskFilter.php | 1 | ||||
-rw-r--r-- | app/Model/TaskFinder.php | 22 | ||||
-rw-r--r-- | app/Template/app/layout.php | 29 | ||||
-rw-r--r-- | app/Template/app/projects.php | 2 | ||||
-rw-r--r-- | app/Template/app/subtasks.php | 2 | ||||
-rw-r--r-- | app/Template/app/tasks.php | 2 | ||||
-rw-r--r-- | app/Template/search/index.php | 26 | ||||
-rw-r--r-- | app/Template/search/results.php | 60 | ||||
-rw-r--r-- | assets/css/app.css | 6 | ||||
-rw-r--r-- | assets/css/src/dashboard.css | 4 | ||||
-rw-r--r-- | assets/css/src/form.css | 2 | ||||
-rw-r--r-- | tests/units/TaskFilterTest.php | 5 |
14 files changed, 186 insertions, 28 deletions
diff --git a/app/Controller/Search.php b/app/Controller/Search.php new file mode 100644 index 00000000..519f9ce4 --- /dev/null +++ b/app/Controller/Search.php @@ -0,0 +1,51 @@ +<?php + +namespace Controller; + +/** + * Search controller + * + * @package controller + * @author Frederic Guillot + */ +class Search extends Base +{ + public function index() + { + $projects = $this->projectPermission->getAllowedProjects($this->userSession->getId()); + $search = $this->request->getStringParam('search'); + $nb_tasks = 0; + + $paginator = $this->paginator + ->setUrl('search', 'index', array('search' => $search)) + ->setMax(30) + ->setOrder('tasks.id') + ->setDirection('DESC'); + + if ($search !== '') { + + $query = $this + ->taskFilter + ->search($search) + ->filterByProjects(array_keys($projects)) + ->getQuery(); + + $paginator + ->setQuery($query) + ->calculate(); + + $nb_tasks = $paginator->getTotal(); + } + + $this->response->html($this->template->layout('search/index', array( + 'board_selector' => $projects, + 'values' => array( + 'search' => $search, + 'controller' => 'search', + 'action' => 'index', + ), + 'paginator' => $paginator, + 'title' => t('Search tasks').($nb_tasks > 0 ? ' ('.$nb_tasks.')' : '') + ))); + } +} diff --git a/app/Model/Color.php b/app/Model/Color.php index a35aff8f..1fd81b85 100644 --- a/app/Model/Color.php +++ b/app/Model/Color.php @@ -193,11 +193,11 @@ class Color extends Base $buffer = ''; foreach ($this->default_colors as $color => $values) { - $buffer .= 'td.color-'.$color.','; $buffer .= 'div.color-'.$color.' {'; $buffer .= 'background-color: '.$values['background'].';'; $buffer .= 'border-color: '.$values['border']; $buffer .= '}'; + $buffer .= 'td.color-'.$color.' { background-color: '.$values['background'].'}'; } return $buffer; diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php index b14dad0a..4a086078 100644 --- a/app/Model/TaskFilter.php +++ b/app/Model/TaskFilter.php @@ -214,7 +214,6 @@ class TaskFilter extends Base */ public function filterByCategoryName(array $values) { - $this->query->join(Category::TABLE, 'id', 'category_id'); $this->query->beginOr(); foreach ($values as $category) { diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index e007187f..181ff360 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -97,10 +97,16 @@ class TaskFinder extends Base 'tasks.recurrence_parent', 'tasks.recurrence_child', 'tasks.time_estimated', - 'users.username AS assignee_username', - 'users.name AS assignee_name' + User::TABLE.'.username AS assignee_username', + User::TABLE.'.name AS assignee_name', + Category::TABLE.'.name AS category_name', + Board::TABLE.'.title AS column_name', + Project::TABLE.'.name AS project_name' ) - ->join(User::TABLE, 'id', 'owner_id'); + ->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(Project::TABLE, 'id', 'project_id', Task::TABLE); } /** @@ -115,11 +121,11 @@ class TaskFinder extends Base public function getTasksByColumnAndSwimlane($project_id, $column_id, $swimlane_id = 0) { return $this->getExtendedQuery() - ->eq('project_id', $project_id) - ->eq('column_id', $column_id) - ->eq('swimlane_id', $swimlane_id) - ->eq('is_active', Task::STATUS_OPEN) - ->asc('tasks.position') + ->eq(Task::TABLE.'.project_id', $project_id) + ->eq(Task::TABLE.'.column_id', $column_id) + ->eq(Task::TABLE.'.swimlane_id', $swimlane_id) + ->eq(Task::TABLE.'.is_active', Task::STATUS_OPEN) + ->asc(Task::TABLE.'.position') ->findAll(); } diff --git a/app/Template/app/layout.php b/app/Template/app/layout.php index d2d63f25..4a307a19 100644 --- a/app/Template/app/layout.php +++ b/app/Template/app/layout.php @@ -2,13 +2,32 @@ <div class="page-header page-header-mobile"> <ul> <?php if ($this->user->isAdmin()): ?> - <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New project'), 'project', 'create') ?></li> + <li> + <i class="fa fa-plus fa-fw"></i> + <?= $this->url->link(t('New project'), 'project', 'create') ?> + </li> <?php endif ?> - <li><i class="fa fa-lock fa-fw"></i><?= $this->url->link(t('New private project'), 'project', 'create', array('private' => 1)) ?></li> - <li><i class="fa fa-folder fa-fw"></i><?= $this->url->link(t('Project management'), 'project', 'index') ?></li> + <li> + <i class="fa fa-lock fa-fw"></i> + <?= $this->url->link(t('New private project'), 'project', 'create', array('private' => 1)) ?> + </li> + <li> + <i class="fa fa-search fa-fw"></i> + <?= $this->url->link(t('Search'), 'search', 'index') ?> + </li> + <li> + <i class="fa fa-folder fa-fw"></i> + <?= $this->url->link(t('Project management'), 'project', 'index') ?> + </li> <?php if ($this->user->isAdmin()): ?> - <li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('User management'), 'user', 'index') ?></li> - <li><i class="fa fa-cog fa-fw"></i><?= $this->url->link(t('Settings'), 'config', 'index') ?></li> + <li> + <i class="fa fa-user fa-fw"></i> + <?= $this->url->link(t('User management'), 'user', 'index') ?> + </li> + <li> + <i class="fa fa-cog fa-fw"></i> + <?= $this->url->link(t('Settings'), 'config', 'index') ?> + </li> <?php endif ?> </ul> </div> diff --git a/app/Template/app/projects.php b/app/Template/app/projects.php index 22e0cc47..61839cee 100644 --- a/app/Template/app/projects.php +++ b/app/Template/app/projects.php @@ -4,7 +4,7 @@ <?php if ($paginator->isEmpty()): ?> <p class="alert"><?= t('Your are not member of any project.') ?></p> <?php else: ?> - <table class="table-fixed"> + <table class="table-fixed table-small"> <tr> <th class="column-8"><?= $paginator->order('Id', 'id') ?></th> <th class="column-20"><?= $paginator->order(t('Project'), 'name') ?></th> diff --git a/app/Template/app/subtasks.php b/app/Template/app/subtasks.php index 67f2d04f..ad7402bd 100644 --- a/app/Template/app/subtasks.php +++ b/app/Template/app/subtasks.php @@ -4,7 +4,7 @@ <?php if ($paginator->isEmpty()): ?> <p class="alert"><?= t('There is nothing assigned to you.') ?></p> <?php else: ?> - <table class="table-fixed"> + <table class="table-fixed table-small"> <tr> <th class="column-10"><?= $paginator->order('Id', 'tasks.id') ?></th> <th class="column-20"><?= $paginator->order(t('Project'), 'project_name') ?></th> diff --git a/app/Template/app/tasks.php b/app/Template/app/tasks.php index 8e7fe74a..3712750b 100644 --- a/app/Template/app/tasks.php +++ b/app/Template/app/tasks.php @@ -4,7 +4,7 @@ <?php if ($paginator->isEmpty()): ?> <p class="alert"><?= t('There is nothing assigned to you.') ?></p> <?php else: ?> - <table class="table-fixed"> + <table class="table-fixed table-small"> <tr> <th class="column-8"><?= $paginator->order('Id', 'tasks.id') ?></th> <th class="column-20"><?= $paginator->order(t('Project'), 'project_name') ?></th> diff --git a/app/Template/search/index.php b/app/Template/search/index.php new file mode 100644 index 00000000..058f428d --- /dev/null +++ b/app/Template/search/index.php @@ -0,0 +1,26 @@ +<section id="main"> + <div class="page-header"> + <ul> + <li> + <i class="fa fa-folder fa-fw"></i> + <?= $this->url->link(t('All projects'), 'project', 'index') ?> + </li> + </ul> + </div> + + <form method="get" action="?" autocomplete="off"> + <?= $this->form->hidden('controller', $values) ?> + <?= $this->form->hidden('action', $values) ?> + <?= $this->form->text('search', $values, array(), array('autofocus', 'required', 'placeholder="'.t('Search').'"'), 'form-input-large') ?> + <input type="submit" value="<?= t('Search') ?>" class="btn btn-blue"/> + </form> + + <?php if (! empty($values['search']) && $paginator->isEmpty()): ?> + <p class="alert"><?= t('Nothing found.') ?></p> + <?php elseif (! $paginator->isEmpty()): ?> + <?= $this->render('search/results', array( + 'paginator' => $paginator, + )) ?> + <?php endif ?> + +</section>
\ No newline at end of file diff --git a/app/Template/search/results.php b/app/Template/search/results.php new file mode 100644 index 00000000..1d8cc6e2 --- /dev/null +++ b/app/Template/search/results.php @@ -0,0 +1,60 @@ +<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><?= $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): ?> + <tr> + <td> + <?= $this->url->link($this->e($task['project_name']), 'board', 'show', array('project_id' => $task['project_id'])) ?> + </td> + <td class="task-table color-<?= $task['color_id'] ?>"> + <?= $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['column_name']) ?> + </td> + <td> + <?= $this->e($task['category_name']) ?> + </td> + <td> + <?= $this->url->link($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> + </td> + <td> + <?php if ($task['assignee_username']): ?> + <?= $this->e($task['assignee_name'] ?: $task['assignee_username']) ?> + <?php else: ?> + <?= t('Unassigned') ?> + <?php endif ?> + </td> + <td> + <?= 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: ?> + <?= t('Closed') ?> + <?php endif ?> + </td> + </tr> + <?php endforeach ?> +</table> + +<?= $paginator ?> diff --git a/assets/css/app.css b/assets/css/app.css index 03f95c6b..0e546b9f 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -347,7 +347,7 @@ input.form-date { } input.form-input-large { - width: 400px; + width: 450px; } .form-row { @@ -1404,10 +1404,6 @@ span.task-board-date-overdue { .dashboard-table-link:hover { color: #999; } - -#dashboard .sidebar-content { - font-size: 0.9em; -} /* datepicker */ #ui-datepicker-div { font-size: 0.8em; diff --git a/assets/css/src/dashboard.css b/assets/css/src/dashboard.css index 5fd79703..4cd4d4d9 100644 --- a/assets/css/src/dashboard.css +++ b/assets/css/src/dashboard.css @@ -19,7 +19,3 @@ .dashboard-table-link:hover { color: #999; } - -#dashboard .sidebar-content { - font-size: 0.9em; -} diff --git a/assets/css/src/form.css b/assets/css/src/form.css index 1c1b8ed2..903bd24e 100644 --- a/assets/css/src/form.css +++ b/assets/css/src/form.css @@ -142,7 +142,7 @@ input.form-date { } input.form-input-large { - width: 400px; + width: 450px; } .form-row { diff --git a/tests/units/TaskFilterTest.php b/tests/units/TaskFilterTest.php index cec30394..33e1792e 100644 --- a/tests/units/TaskFilterTest.php +++ b/tests/units/TaskFilterTest.php @@ -94,25 +94,30 @@ class TaskFilterTest extends Base $this->assertNotEmpty($tasks); $this->assertCount(1, $tasks); $this->assertEquals('task2', $tasks[0]['title']); + $this->assertEquals('Feature request', $tasks[0]['category_name']); $tf->search('category:"hé hé"'); $tasks = $tf->findAll(); $this->assertNotEmpty($tasks); $this->assertCount(1, $tasks); $this->assertEquals('task3', $tasks[0]['title']); + $this->assertEquals('hé hé', $tasks[0]['category_name']); $tf->search('category:"Feature request" category:"hé hé"'); $tasks = $tf->findAll(); $this->assertNotEmpty($tasks); $this->assertCount(2, $tasks); $this->assertEquals('task2', $tasks[0]['title']); + $this->assertEquals('Feature request', $tasks[0]['category_name']); $this->assertEquals('task3', $tasks[1]['title']); + $this->assertEquals('hé hé', $tasks[1]['category_name']); $tf->search('category:none'); $tasks = $tf->findAll(); $this->assertNotEmpty($tasks); $this->assertCount(1, $tasks); $this->assertEquals('task1', $tasks[0]['title']); + $this->assertEquals('', $tasks[0]['category_name']); $tf->search('category:"not found"'); $tasks = $tf->findAll(); |