diff options
author | Frederic Guillot <fred@kanboard.net> | 2015-12-29 18:44:21 +0100 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2015-12-29 18:44:21 +0100 |
commit | 178eda18872f99840937dc3d23629b5d7aa7cee0 (patch) | |
tree | e2e27f289b5620e92b1accddcea9489286a65243 /app | |
parent | b4c5e36ee4cbf34020eb043e54e9b7294062acee (diff) |
Add autocompletion in textarea for user mentions
Diffstat (limited to 'app')
-rw-r--r-- | app/Controller/UserHelper.php | 13 | ||||
-rw-r--r-- | app/Model/ProjectGroupRoleFilter.php | 89 | ||||
-rw-r--r-- | app/Model/ProjectPermission.php | 19 | ||||
-rw-r--r-- | app/Model/ProjectUserRoleFilter.php | 88 | ||||
-rw-r--r-- | app/ServiceProvider/AuthenticationProvider.php | 1 | ||||
-rw-r--r-- | app/ServiceProvider/ClassProvider.php | 2 | ||||
-rw-r--r-- | app/Template/comment/create.php | 13 | ||||
-rw-r--r-- | app/Template/task_creation/form.php | 11 | ||||
-rw-r--r-- | app/Template/task_modification/edit_description.php | 12 | ||||
-rw-r--r-- | app/Template/task_modification/edit_task.php | 11 |
10 files changed, 255 insertions, 4 deletions
diff --git a/app/Controller/UserHelper.php b/app/Controller/UserHelper.php index f164d0a6..041ed2c8 100644 --- a/app/Controller/UserHelper.php +++ b/app/Controller/UserHelper.php @@ -21,4 +21,17 @@ class UserHelper extends Base $users = $this->userFilterAutoCompleteFormatter->create($search)->filterByUsernameOrByName()->format(); $this->response->json($users); } + + /** + * User mention autocompletion (Ajax) + * + * @access public + */ + public function mention() + { + $project_id = $this->request->getStringParam('project_id'); + $query = $this->request->getStringParam('q'); + $users = $this->projectPermission->findUsernames($project_id, $query); + $this->response->json($users); + } } diff --git a/app/Model/ProjectGroupRoleFilter.php b/app/Model/ProjectGroupRoleFilter.php new file mode 100644 index 00000000..989d3073 --- /dev/null +++ b/app/Model/ProjectGroupRoleFilter.php @@ -0,0 +1,89 @@ +<?php + +namespace Kanboard\Model; + +/** + * Project Group Role Filter + * + * @package model + * @author Frederic Guillot + */ +class ProjectGroupRoleFilter extends Base +{ + /** + * Query + * + * @access protected + * @var \PicoDb\Table + */ + protected $query; + + /** + * Initialize filter + * + * @access public + * @return UserFilter + */ + public function create() + { + $this->query = $this->db->table(ProjectGroupRole::TABLE); + return $this; + } + + /** + * Get all results of the filter + * + * @access public + * @param string $column + * @return array + */ + public function findAll($column = '') + { + if ($column !== '') { + return $this->query->asc($column)->findAllByColumn($column); + } + + return $this->query->findAll(); + } + + /** + * Get the PicoDb query + * + * @access public + * @return \PicoDb\Table + */ + public function getQuery() + { + return $this->query; + } + + /** + * Filter by project id + * + * @access public + * @param integer $project_id + * @return ProjectUserRoleFilter + */ + public function filterByProjectId($project_id) + { + $this->query->eq(ProjectGroupRole::TABLE.'.project_id', $project_id); + return $this; + } + + /** + * Filter by username + * + * @access public + * @param string $input + * @return ProjectUserRoleFilter + */ + public function startWithUsername($input) + { + $this->query + ->join(GroupMember::TABLE, 'group_id', 'group_id', ProjectGroupRole::TABLE) + ->join(User::TABLE, 'id', 'user_id', GroupMember::TABLE) + ->ilike(User::TABLE.'.username', $input.'%'); + + return $this; + } +} diff --git a/app/Model/ProjectPermission.php b/app/Model/ProjectPermission.php index 66f4091d..cea62e13 100644 --- a/app/Model/ProjectPermission.php +++ b/app/Model/ProjectPermission.php @@ -44,6 +44,25 @@ class ProjectPermission extends Base } /** + * Get all usernames (fetch users from groups) + * + * @access public + * @param integer $project_id + * @param string $input + * @return array + */ + public function findUsernames($project_id, $input) + { + $userMembers = $this->projectUserRoleFilter->create()->filterByProjectId($project_id)->startWithUsername($input)->findAll('username'); + $groupMembers = $this->projectGroupRoleFilter->create()->filterByProjectId($project_id)->startWithUsername($input)->findAll('username'); + $members = array_unique(array_merge($userMembers, $groupMembers)); + + sort($members); + + return $members; + } + + /** * Return true if everybody is allowed for the project * * @access public diff --git a/app/Model/ProjectUserRoleFilter.php b/app/Model/ProjectUserRoleFilter.php new file mode 100644 index 00000000..64403643 --- /dev/null +++ b/app/Model/ProjectUserRoleFilter.php @@ -0,0 +1,88 @@ +<?php + +namespace Kanboard\Model; + +/** + * Project User Role Filter + * + * @package model + * @author Frederic Guillot + */ +class ProjectUserRoleFilter extends Base +{ + /** + * Query + * + * @access protected + * @var \PicoDb\Table + */ + protected $query; + + /** + * Initialize filter + * + * @access public + * @return UserFilter + */ + public function create() + { + $this->query = $this->db->table(ProjectUserRole::TABLE); + return $this; + } + + /** + * Get all results of the filter + * + * @access public + * @param string $column + * @return array + */ + public function findAll($column = '') + { + if ($column !== '') { + return $this->query->asc($column)->findAllByColumn($column); + } + + return $this->query->findAll(); + } + + /** + * Get the PicoDb query + * + * @access public + * @return \PicoDb\Table + */ + public function getQuery() + { + return $this->query; + } + + /** + * Filter by project id + * + * @access public + * @param integer $project_id + * @return ProjectUserRoleFilter + */ + public function filterByProjectId($project_id) + { + $this->query->eq(ProjectUserRole::TABLE.'.project_id', $project_id); + return $this; + } + + /** + * Filter by username + * + * @access public + * @param string $input + * @return ProjectUserRoleFilter + */ + public function startWithUsername($input) + { + $this->query + ->join(User::TABLE, 'id', 'user_id') + ->ilike(User::TABLE.'.username', $input.'%'); + + return $this; + } +} diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index 46ba5be8..6e7c49d9 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -106,6 +106,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('Taskmodification', '*', Role::PROJECT_MEMBER); $acl->add('Taskstatus', '*', Role::PROJECT_MEMBER); $acl->add('Timer', '*', Role::PROJECT_MEMBER); + $acl->add('UserHelper', array('mention'), Role::PROJECT_MEMBER); return $acl; } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 03257c07..559a78c1 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -42,7 +42,9 @@ class ClassProvider implements ServiceProviderInterface 'ProjectNotification', 'ProjectMetadata', 'ProjectGroupRole', + 'ProjectGroupRoleFilter', 'ProjectUserRole', + 'ProjectUserRoleFilter', 'RememberMeSession', 'Subtask', 'SubtaskExport', diff --git a/app/Template/comment/create.php b/app/Template/comment/create.php index 8bcbe0f7..e9a6404d 100644 --- a/app/Template/comment/create.php +++ b/app/Template/comment/create.php @@ -17,7 +17,18 @@ </li> </ul> <div class="write-area"> - <?= $this->form->textarea('comment', $values, $errors, array(! isset($skip_cancel) ? 'autofocus' : '', 'required', 'placeholder="'.t('Leave a comment').'"'), 'comment-textarea') ?> + <?= $this->form->textarea( + 'comment', + $values, + $errors, + array( + ! isset($skip_cancel) ? 'autofocus' : '', + 'required', + 'placeholder="'.t('Leave a comment').'"', + 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"', + ), + 'comment-textarea' + ) ?> </div> <div class="preview-area"> <div class="markdown"></div> diff --git a/app/Template/task_creation/form.php b/app/Template/task_creation/form.php index 325ca1c8..c9f367a0 100644 --- a/app/Template/task_creation/form.php +++ b/app/Template/task_creation/form.php @@ -22,7 +22,16 @@ <div class="form-tabs"> <div class="write-area"> - <?= $this->form->textarea('description', $values, $errors, array('placeholder="'.t('Leave a description').'"', 'tabindex="2"')) ?> + <?= $this->form->textarea( + 'description', + $values, + $errors, + array( + 'placeholder="'.t('Leave a description').'"', + 'tabindex="2"', + 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $values['project_id'])).'"' + ) + ) ?> </div> <div class="preview-area"> <div class="markdown"></div> diff --git a/app/Template/task_modification/edit_description.php b/app/Template/task_modification/edit_description.php index 4cae939c..c38e885d 100644 --- a/app/Template/task_modification/edit_description.php +++ b/app/Template/task_modification/edit_description.php @@ -17,7 +17,17 @@ </li> </ul> <div class="write-area"> - <?= $this->form->textarea('description', $values, $errors, array('autofocus', 'placeholder="'.t('Leave a description').'"'), 'task-show-description-textarea') ?> + <?= $this->form->textarea( + 'description', + $values, + $errors, + array( + 'autofocus', + 'placeholder="'.t('Leave a description').'"', + 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"' + ), + 'task-show-description-textarea' + ) ?> </div> <div class="preview-area"> <div class="markdown"></div> diff --git a/app/Template/task_modification/edit_task.php b/app/Template/task_modification/edit_task.php index f4d7449a..6fdb77b5 100644 --- a/app/Template/task_modification/edit_task.php +++ b/app/Template/task_modification/edit_task.php @@ -13,7 +13,16 @@ <?= $this->form->label(t('Description'), 'description') ?> <div class="form-tabs"> <div class="write-area"> - <?= $this->form->textarea('description', $values, $errors, array('placeholder="'.t('Leave a description').'"', 'tabindex="2"')) ?> + <?= $this->form->textarea( + 'description', + $values, + $errors, + array( + 'placeholder="'.t('Leave a description').'"', + 'tabindex="2"', + 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"' + ) + ) ?> </div> <div class="preview-area"> <div class="markdown"></div> |