From 9f0166502b8b8886156bcb4ad0497cd9ee5a60b2 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 10 Apr 2016 15:18:20 -0400 Subject: Added search in activity stream --- app/Controller/Search.php | 18 ++++ app/Filter/BaseDateFilter.php | 103 +++++++++++++++++++++++ app/Filter/BaseFilter.php | 44 ---------- app/Filter/ProjectActivityCreationDateFilter.php | 38 +++++++++ app/Filter/ProjectActivityCreatorFilter.php | 65 ++++++++++++++ app/Filter/ProjectActivityProjectIdsFilter.php | 2 +- app/Filter/ProjectActivityProjectNameFilter.php | 38 +++++++++ app/Filter/ProjectActivityTaskStatusFilter.php | 43 ++++++++++ app/Filter/ProjectActivityTaskTitleFilter.php | 15 +--- app/Filter/TaskCompletionDateFilter.php | 2 +- app/Filter/TaskCreationDateFilter.php | 2 +- app/Filter/TaskDueDateFilter.php | 2 +- app/Filter/TaskModificationDateFilter.php | 2 +- app/Filter/TaskProjectsFilter.php | 7 +- app/Filter/TaskStartDateFilter.php | 2 +- app/Helper/ProjectActivityHelper.php | 27 ++++++ app/Locale/bs_BA/translations.php | 10 +++ app/Locale/cs_CZ/translations.php | 10 +++ app/Locale/da_DK/translations.php | 10 +++ app/Locale/de_DE/translations.php | 10 +++ app/Locale/el_GR/translations.php | 10 +++ app/Locale/es_ES/translations.php | 10 +++ app/Locale/fi_FI/translations.php | 10 +++ app/Locale/fr_FR/translations.php | 10 +++ app/Locale/hu_HU/translations.php | 10 +++ app/Locale/id_ID/translations.php | 10 +++ app/Locale/it_IT/translations.php | 10 +++ app/Locale/ja_JP/translations.php | 10 +++ app/Locale/ko_KR/translations.php | 10 +++ app/Locale/my_MY/translations.php | 10 +++ app/Locale/nb_NO/translations.php | 10 +++ app/Locale/nl_NL/translations.php | 10 +++ app/Locale/pl_PL/translations.php | 10 +++ app/Locale/pt_BR/translations.php | 10 +++ app/Locale/pt_PT/translations.php | 10 +++ app/Locale/ru_RU/translations.php | 12 ++- app/Locale/sr_Latn_RS/translations.php | 10 +++ app/Locale/sv_SE/translations.php | 10 +++ app/Locale/th_TH/translations.php | 10 +++ app/Locale/tr_TR/translations.php | 10 +++ app/Locale/zh_CN/translations.php | 10 +++ app/Model/ProjectActivity.php | 1 + app/ServiceProvider/FilterProvider.php | 30 +++++-- app/ServiceProvider/RouteProvider.php | 3 +- app/Template/activity/filter_dropdown.php | 14 +++ app/Template/search/activity.php | 39 +++++++++ app/Template/search/index.php | 4 +- 47 files changed, 679 insertions(+), 74 deletions(-) create mode 100644 app/Filter/BaseDateFilter.php create mode 100644 app/Filter/ProjectActivityCreationDateFilter.php create mode 100644 app/Filter/ProjectActivityCreatorFilter.php create mode 100644 app/Filter/ProjectActivityProjectNameFilter.php create mode 100644 app/Filter/ProjectActivityTaskStatusFilter.php create mode 100644 app/Template/activity/filter_dropdown.php create mode 100644 app/Template/search/activity.php (limited to 'app') diff --git a/app/Controller/Search.php b/app/Controller/Search.php index 840a90c8..a42e9d3d 100644 --- a/app/Controller/Search.php +++ b/app/Controller/Search.php @@ -46,4 +46,22 @@ class Search extends Base 'title' => t('Search tasks').($nb_tasks > 0 ? ' ('.$nb_tasks.')' : '') ))); } + + public function activity() + { + $search = urldecode($this->request->getStringParam('search')); + $events = $this->helper->projectActivity->searchEvents($search); + $nb_events = count($events); + + $this->response->html($this->helper->layout->app('search/activity', array( + 'values' => array( + 'search' => $search, + 'controller' => 'search', + 'action' => 'activity', + ), + 'title' => t('Search in activity stream').($nb_events > 0 ? ' ('.$nb_events.')' : ''), + 'nb_events' => $nb_events, + 'events' => $events, + ))); + } } diff --git a/app/Filter/BaseDateFilter.php b/app/Filter/BaseDateFilter.php new file mode 100644 index 00000000..56fb2d78 --- /dev/null +++ b/app/Filter/BaseDateFilter.php @@ -0,0 +1,103 @@ +dateParser = $dateParser; + return $this; + } + + /** + * Parse operator in the input string + * + * @access protected + * @return string + */ + protected function parseOperator() + { + $operators = array( + '<=' => 'lte', + '>=' => 'gte', + '<' => 'lt', + '>' => 'gt', + ); + + foreach ($operators as $operator => $method) { + if (strpos($this->value, $operator) === 0) { + $this->value = substr($this->value, strlen($operator)); + return $method; + } + } + + return ''; + } + + /** + * Apply a date filter + * + * @access protected + * @param string $field + */ + protected function applyDateFilter($field) + { + $method = $this->parseOperator(); + $timestamp = $this->dateParser->getTimestampFromIsoFormat($this->value); + + if ($method !== '') { + $this->query->$method($field, $this->getTimestampFromOperator($method, $timestamp)); + } else { + $this->query->gte($field, $timestamp); + $this->query->lte($field, $timestamp + 86399); + } + } + + /** + * Get timestamp from the operator + * + * @access public + * @param string $method + * @param integer $timestamp + * @return integer + */ + protected function getTimestampFromOperator($method, $timestamp) + { + switch ($method) { + case 'lte': + return $timestamp + 86399; + case 'lt': + return $timestamp; + case 'gte': + return $timestamp; + case 'gt': + return $timestamp + 86400; + } + + return $timestamp; + } +} diff --git a/app/Filter/BaseFilter.php b/app/Filter/BaseFilter.php index a7e6a61a..79a664be 100644 --- a/app/Filter/BaseFilter.php +++ b/app/Filter/BaseFilter.php @@ -72,48 +72,4 @@ abstract class BaseFilter $this->value = $value; return $this; } - - /** - * Parse operator in the input string - * - * @access protected - * @return string - */ - protected function parseOperator() - { - $operators = array( - '<=' => 'lte', - '>=' => 'gte', - '<' => 'lt', - '>' => 'gt', - ); - - foreach ($operators as $operator => $method) { - if (strpos($this->value, $operator) === 0) { - $this->value = substr($this->value, strlen($operator)); - return $method; - } - } - - return ''; - } - - /** - * Apply a date filter - * - * @access protected - * @param string $field - */ - protected function applyDateFilter($field) - { - $timestamp = strtotime($this->value); - $method = $this->parseOperator(); - - if ($method !== '') { - $this->query->$method($field, $timestamp); - } else { - $this->query->gte($field, $timestamp); - $this->query->lte($field, $timestamp + 86399); - } - } } diff --git a/app/Filter/ProjectActivityCreationDateFilter.php b/app/Filter/ProjectActivityCreationDateFilter.php new file mode 100644 index 00000000..d0b7f754 --- /dev/null +++ b/app/Filter/ProjectActivityCreationDateFilter.php @@ -0,0 +1,38 @@ +applyDateFilter(ProjectActivity::TABLE.'.date_creation'); + return $this; + } +} diff --git a/app/Filter/ProjectActivityCreatorFilter.php b/app/Filter/ProjectActivityCreatorFilter.php new file mode 100644 index 00000000..c95569d6 --- /dev/null +++ b/app/Filter/ProjectActivityCreatorFilter.php @@ -0,0 +1,65 @@ +currentUserId = $userId; + return $this; + } + + /** + * Get search attribute + * + * @access public + * @return string[] + */ + public function getAttributes() + { + return array('creator'); + } + + /** + * Apply filter + * + * @access public + * @return string + */ + public function apply() + { + if ($this->value === 'me') { + $this->query->eq(ProjectActivity::TABLE . '.creator_id', $this->currentUserId); + } else { + $this->query->beginOr(); + $this->query->ilike('uc.username', '%'.$this->value.'%'); + $this->query->ilike('uc.name', '%'.$this->value.'%'); + $this->query->closeOr(); + } + } +} diff --git a/app/Filter/ProjectActivityProjectIdsFilter.php b/app/Filter/ProjectActivityProjectIdsFilter.php index 4d7c9028..47cf0c25 100644 --- a/app/Filter/ProjectActivityProjectIdsFilter.php +++ b/app/Filter/ProjectActivityProjectIdsFilter.php @@ -21,7 +21,7 @@ class ProjectActivityProjectIdsFilter extends BaseFilter implements FilterInterf */ public function getAttributes() { - return array('project_ids'); + return array('projects'); } /** diff --git a/app/Filter/ProjectActivityProjectNameFilter.php b/app/Filter/ProjectActivityProjectNameFilter.php new file mode 100644 index 00000000..0cf73657 --- /dev/null +++ b/app/Filter/ProjectActivityProjectNameFilter.php @@ -0,0 +1,38 @@ +query->ilike(Project::TABLE.'.name', '%'.$this->value.'%'); + return $this; + } +} diff --git a/app/Filter/ProjectActivityTaskStatusFilter.php b/app/Filter/ProjectActivityTaskStatusFilter.php new file mode 100644 index 00000000..69e2c52d --- /dev/null +++ b/app/Filter/ProjectActivityTaskStatusFilter.php @@ -0,0 +1,43 @@ +value === 'open') { + $this->query->eq(Task::TABLE.'.is_active', Task::STATUS_OPEN); + } elseif ($this->value === 'closed') { + $this->query->eq(Task::TABLE.'.is_active', Task::STATUS_CLOSED); + } + + return $this; + } +} diff --git a/app/Filter/ProjectActivityTaskTitleFilter.php b/app/Filter/ProjectActivityTaskTitleFilter.php index ed3f36d6..bf2afa30 100644 --- a/app/Filter/ProjectActivityTaskTitleFilter.php +++ b/app/Filter/ProjectActivityTaskTitleFilter.php @@ -3,7 +3,6 @@ namespace Kanboard\Filter; use Kanboard\Core\Filter\FilterInterface; -use Kanboard\Model\Task; /** * Filter activity events by task title @@ -11,7 +10,7 @@ use Kanboard\Model\Task; * @package filter * @author Frederic Guillot */ -class ProjectActivityTaskTitleFilter extends BaseFilter implements FilterInterface +class ProjectActivityTaskTitleFilter extends TaskTitleFilter implements FilterInterface { /** * Get search attribute @@ -23,16 +22,4 @@ class ProjectActivityTaskTitleFilter extends BaseFilter implements FilterInterfa { return array('title'); } - - /** - * Apply filter - * - * @access public - * @return FilterInterface - */ - public function apply() - { - $this->query->ilike(Task::TABLE.'.title', '%'.$this->value.'%'); - return $this; - } } diff --git a/app/Filter/TaskCompletionDateFilter.php b/app/Filter/TaskCompletionDateFilter.php index 5166bebf..f206a3e2 100644 --- a/app/Filter/TaskCompletionDateFilter.php +++ b/app/Filter/TaskCompletionDateFilter.php @@ -11,7 +11,7 @@ use Kanboard\Model\Task; * @package filter * @author Frederic Guillot */ -class TaskCompletionDateFilter extends BaseFilter implements FilterInterface +class TaskCompletionDateFilter extends BaseDateFilter implements FilterInterface { /** * Get search attribute diff --git a/app/Filter/TaskCreationDateFilter.php b/app/Filter/TaskCreationDateFilter.php index 26318b3e..bb6efad6 100644 --- a/app/Filter/TaskCreationDateFilter.php +++ b/app/Filter/TaskCreationDateFilter.php @@ -11,7 +11,7 @@ use Kanboard\Model\Task; * @package filter * @author Frederic Guillot */ -class TaskCreationDateFilter extends BaseFilter implements FilterInterface +class TaskCreationDateFilter extends BaseDateFilter implements FilterInterface { /** * Get search attribute diff --git a/app/Filter/TaskDueDateFilter.php b/app/Filter/TaskDueDateFilter.php index 6ba55eb9..e36efdd0 100644 --- a/app/Filter/TaskDueDateFilter.php +++ b/app/Filter/TaskDueDateFilter.php @@ -11,7 +11,7 @@ use Kanboard\Model\Task; * @package filter * @author Frederic Guillot */ -class TaskDueDateFilter extends BaseFilter implements FilterInterface +class TaskDueDateFilter extends BaseDateFilter implements FilterInterface { /** * Get search attribute diff --git a/app/Filter/TaskModificationDateFilter.php b/app/Filter/TaskModificationDateFilter.php index d8838bce..5036e9c1 100644 --- a/app/Filter/TaskModificationDateFilter.php +++ b/app/Filter/TaskModificationDateFilter.php @@ -11,7 +11,7 @@ use Kanboard\Model\Task; * @package filter * @author Frederic Guillot */ -class TaskModificationDateFilter extends BaseFilter implements FilterInterface +class TaskModificationDateFilter extends BaseDateFilter implements FilterInterface { /** * Get search attribute diff --git a/app/Filter/TaskProjectsFilter.php b/app/Filter/TaskProjectsFilter.php index e0fc09cf..47636b1d 100644 --- a/app/Filter/TaskProjectsFilter.php +++ b/app/Filter/TaskProjectsFilter.php @@ -32,7 +32,12 @@ class TaskProjectsFilter extends BaseFilter implements FilterInterface */ public function apply() { - $this->query->in(Task::TABLE.'.project_id', $this->value); + if (empty($this->value)) { + $this->query->eq(Task::TABLE.'.project_id', 0); + } else { + $this->query->in(Task::TABLE.'.project_id', $this->value); + } + return $this; } } diff --git a/app/Filter/TaskStartDateFilter.php b/app/Filter/TaskStartDateFilter.php index d45bc0d4..dd30762b 100644 --- a/app/Filter/TaskStartDateFilter.php +++ b/app/Filter/TaskStartDateFilter.php @@ -11,7 +11,7 @@ use Kanboard\Model\Task; * @package filter * @author Frederic Guillot */ -class TaskStartDateFilter extends BaseFilter implements FilterInterface +class TaskStartDateFilter extends BaseDateFilter implements FilterInterface { /** * Get search attribute diff --git a/app/Helper/ProjectActivityHelper.php b/app/Helper/ProjectActivityHelper.php index 738fec66..0638a978 100644 --- a/app/Helper/ProjectActivityHelper.php +++ b/app/Helper/ProjectActivityHelper.php @@ -17,6 +17,33 @@ use Kanboard\Model\ProjectActivity; */ class ProjectActivityHelper extends Base { + /** + * Search events + * + * @access public + * @param string $search + * @return array + */ + public function searchEvents($search) + { + $projects = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $events = array(); + + if ($search !== '') { + $queryBuilder = $this->projectActivityLexer->build($search); + $queryBuilder + ->withFilter(new ProjectActivityProjectIdsFilter(array_keys($projects))) + ->getQuery() + ->desc(ProjectActivity::TABLE.'.id') + ->limit(500) + ; + + $events = $queryBuilder->format(new ProjectActivityEventFormatter($this->container)); + } + + return $events; + } + /** * Get project activity events * diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php index 7ca864f4..e384f923 100644 --- a/app/Locale/bs_BA/translations.php +++ b/app/Locale/bs_BA/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index b2921de9..3c8de1ad 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index c4743922..747fa2d1 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 999bf048..fa447e62 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -1153,4 +1153,14 @@ return array( 'Upload my avatar image' => 'Mein Avatar Bild hochladen', 'Remove my image' => 'Mein Bild entfernen', 'The OAuth2 state parameter is invalid' => 'Der OAuth2 Statusparameter ist ungültig', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php index 9a31e485..84cf8462 100644 --- a/app/Locale/el_GR/translations.php +++ b/app/Locale/el_GR/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index c3623369..e52c959b 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index 8e5dd81f..f47852b0 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index cedd6039..0c2e4955 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -1153,4 +1153,14 @@ return array( 'Upload my avatar image' => 'Uploader mon image d\'avatar', 'Remove my image' => 'Supprimer mon image', 'The OAuth2 state parameter is invalid' => 'Le paramètre "state" de OAuth2 est invalide', + 'User not found.' => 'Utilisateur introuvable.', + 'Search in activity stream' => 'Chercher dans le flux d\'activité', + 'My activities' => 'Mes activités', + 'Activity until yesterday' => 'Activités jusqu\'à hier', + 'Activity until today' => 'Activités jusqu\'à aujourd\'hui', + 'Search by creator: ' => 'Rechercher par créateur : ', + 'Search by creation date: ' => 'Rechercher par date de création : ', + 'Search by task status: ' => 'Rechercher par le statut des tâches : ', + 'Search by task title: ' => 'Rechercher par le titre des tâches : ', + 'Activity stream search' => 'Recherche dans le flux d\'activité', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index f642a6c1..9a2d666a 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index 3f105054..9cbca60e 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 93ceb03f..d0209b3a 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index b48eabd8..69ab5f17 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/ko_KR/translations.php b/app/Locale/ko_KR/translations.php index 8379761f..f4320c55 100644 --- a/app/Locale/ko_KR/translations.php +++ b/app/Locale/ko_KR/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php index 36b3db0b..f6f15937 100644 --- a/app/Locale/my_MY/translations.php +++ b/app/Locale/my_MY/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index 465efb53..f3d3047a 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 3c3fa1ee..f08f5eff 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index d06e347f..8222f9e1 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index cdb06dea..60242d95 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -1153,4 +1153,14 @@ return array( 'Upload my avatar image' => 'Enviar a minha imagem de avatar', 'Remove my image' => 'Remover a minha imagem', 'The OAuth2 state parameter is invalid' => 'O parâmetro "state" de OAuth2 não é válido', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index e38344f8..956d1259 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -1153,4 +1153,14 @@ return array( 'Upload my avatar image' => 'Enviar a minha imagem de avatar', 'Remove my image' => 'Remover a minha imagem', 'The OAuth2 state parameter is invalid' => 'O parametro de estado do OAuth2 é inválido', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index b3503e52..1e548e0d 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -1152,5 +1152,15 @@ return array( 'Avatar' => 'Аватар', 'Upload my avatar image' => 'Загрузить моё изображение для аватара', 'Remove my image' => 'Удалить моё изображение', - 'The OAuth2 state parameter is invalid' => 'Параметр состояние OAuth2 неправильный' + 'The OAuth2 state parameter is invalid' => 'Параметр состояние OAuth2 неправильный', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index c7070a8d..b69e6cf4 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index e4728d2d..634b87d0 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index 1e2fb98a..1e913f28 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 6e8fae2f..95bcc8a8 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index decd49d8..7b0c3139 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -1153,4 +1153,14 @@ return array( // 'Upload my avatar image' => '', // 'Remove my image' => '', // 'The OAuth2 state parameter is invalid' => '', + // 'User not found.' => '', + // 'Search in activity stream' => '', + // 'My activities' => '', + // 'Activity until yesterday' => '', + // 'Activity until today' => '', + // 'Search by creator: ' => '', + // 'Search by creation date: ' => '', + // 'Search by task status: ' => '', + // 'Search by task title: ' => '', + // 'Activity stream search' => '', ); diff --git a/app/Model/ProjectActivity.php b/app/Model/ProjectActivity.php index 31cee113..d993015b 100644 --- a/app/Model/ProjectActivity.php +++ b/app/Model/ProjectActivity.php @@ -71,6 +71,7 @@ class ProjectActivity extends Base 'uc.avatar_path' ) ->join(Task::TABLE, 'id', 'task_id') + ->join(Project::TABLE, 'id', 'project_id') ->left(User::TABLE, 'uc', 'id', ProjectActivity::TABLE, 'creator_id'); } diff --git a/app/ServiceProvider/FilterProvider.php b/app/ServiceProvider/FilterProvider.php index 4b4dbd2d..f3918d77 100644 --- a/app/ServiceProvider/FilterProvider.php +++ b/app/ServiceProvider/FilterProvider.php @@ -4,6 +4,10 @@ namespace Kanboard\ServiceProvider; use Kanboard\Core\Filter\LexerBuilder; use Kanboard\Core\Filter\QueryBuilder; +use Kanboard\Filter\ProjectActivityCreationDateFilter; +use Kanboard\Filter\ProjectActivityCreatorFilter; +use Kanboard\Filter\ProjectActivityProjectNameFilter; +use Kanboard\Filter\ProjectActivityTaskStatusFilter; use Kanboard\Filter\ProjectActivityTaskTitleFilter; use Kanboard\Filter\TaskAssigneeFilter; use Kanboard\Filter\TaskCategoryFilter; @@ -86,8 +90,18 @@ class FilterProvider implements ServiceProviderInterface $container['projectActivityLexer'] = $container->factory(function ($c) { $builder = new LexerBuilder(); - $builder->withQuery($c['projectActivity']->getQuery()); - $builder->withFilter(new ProjectActivityTaskTitleFilter()); + $builder + ->withQuery($c['projectActivity']->getQuery()) + ->withFilter(new ProjectActivityTaskTitleFilter(), true) + ->withFilter(new ProjectActivityTaskStatusFilter()) + ->withFilter(new ProjectActivityProjectNameFilter()) + ->withFilter(ProjectActivityCreationDateFilter::getInstance() + ->setDateParser($c['dateParser']) + ) + ->withFilter(ProjectActivityCreatorFilter::getInstance() + ->setCurrentUserId($c['userSession']->getId()) + ) + ; return $builder; }); @@ -124,17 +138,23 @@ class FilterProvider implements ServiceProviderInterface ) ->withFilter(new TaskColumnFilter()) ->withFilter(new TaskCommentFilter()) - ->withFilter(new TaskCreationDateFilter()) + ->withFilter(TaskCreationDateFilter::getInstance() + ->setDateParser($c['dateParser']) + ) ->withFilter(TaskCreatorFilter::getInstance() ->setCurrentUserId($c['userSession']->getId()) ) ->withFilter(new TaskDescriptionFilter()) - ->withFilter(new TaskDueDateFilter()) + ->withFilter(TaskDueDateFilter::getInstance() + ->setDateParser($c['dateParser']) + ) ->withFilter(new TaskIdFilter()) ->withFilter(TaskLinkFilter::getInstance() ->setDatabase($c['db']) ) - ->withFilter(new TaskModificationDateFilter()) + ->withFilter(TaskModificationDateFilter::getInstance() + ->setDateParser($c['dateParser']) + ) ->withFilter(new TaskProjectFilter()) ->withFilter(new TaskReferenceFilter()) ->withFilter(new TaskStatusFilter()) diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php index 0e7548d4..30d23a51 100644 --- a/app/ServiceProvider/RouteProvider.php +++ b/app/ServiceProvider/RouteProvider.php @@ -42,7 +42,7 @@ class RouteProvider implements ServiceProviderInterface // Search routes $container['route']->addRoute('search', 'search', 'index'); - $container['route']->addRoute('search/:search', 'search', 'index'); + $container['route']->addRoute('search/activity', 'search', 'activity'); // ProjectCreation routes $container['route']->addRoute('project/create', 'ProjectCreation', 'create'); @@ -62,6 +62,7 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('project/:project_id/enable', 'project', 'enable'); $container['route']->addRoute('project/:project_id/permissions', 'ProjectPermission', 'index'); $container['route']->addRoute('project/:project_id/import', 'taskImport', 'step1'); + $container['route']->addRoute('project/:project_id/activity', 'activity', 'project'); // Project Overview $container['route']->addRoute('project/:project_id/overview', 'ProjectOverview', 'show'); diff --git a/app/Template/activity/filter_dropdown.php b/app/Template/activity/filter_dropdown.php new file mode 100644 index 00000000..8d7a7de3 --- /dev/null +++ b/app/Template/activity/filter_dropdown.php @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/app/Template/search/activity.php b/app/Template/search/activity.php new file mode 100644 index 00000000..60362215 --- /dev/null +++ b/app/Template/search/activity.php @@ -0,0 +1,39 @@ +
+ + +
+ +
+ + +
+

+

project:"My project" creator:me

+
    +
  • project:"My project"
  • +
  • creator:admin
  • +
  • created:today
  • +
  • status:open
  • +
  • title:"My task"
  • +
+

url->doc(t('View advanced search syntax'), 'search') ?>

+
+ +

+ + render('event/events', array('events' => $events)) ?> + + +
\ No newline at end of file diff --git a/app/Template/search/index.php b/app/Template/search/index.php index 9231a6f3..d5d07ed6 100644 --- a/app/Template/search/index.php +++ b/app/Template/search/index.php @@ -2,8 +2,8 @@ -- cgit v1.2.3