summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2016-11-27 15:44:45 -0500
committerFrederic Guillot <fred@kanboard.net>2016-11-27 15:44:45 -0500
commitd8b0423d152ca27682b001f2c4d386d9c5dd361e (patch)
tree8b4919d5296b857bcf74e81c8cc06729ddfce5e5 /app
parent04ff67e26b880dde8bfb6462f312cf434457cd46 (diff)
Add suggest menu for user mentions in text editor
Diffstat (limited to 'app')
-rw-r--r--app/Controller/UserAjaxController.php8
-rw-r--r--app/Core/Helper.php1
-rw-r--r--app/Formatter/BaseFormatter.php14
-rw-r--r--app/Formatter/BaseTaskCalendarFormatter.php4
-rw-r--r--app/Formatter/UserMentionFormatter.php60
-rw-r--r--app/Helper/FormHelper.php4
-rw-r--r--app/Model/ProjectPermissionModel.php24
-rw-r--r--app/functions.php31
8 files changed, 124 insertions, 22 deletions
diff --git a/app/Controller/UserAjaxController.php b/app/Controller/UserAjaxController.php
index ed180471..0e654333 100644
--- a/app/Controller/UserAjaxController.php
+++ b/app/Controller/UserAjaxController.php
@@ -4,6 +4,7 @@ namespace Kanboard\Controller;
use Kanboard\Filter\UserNameFilter;
use Kanboard\Formatter\UserAutoCompleteFormatter;
+use Kanboard\Formatter\UserMentionFormatter;
use Kanboard\Model\UserModel;
/**
@@ -37,7 +38,12 @@ class UserAjaxController extends BaseController
$project_id = $this->request->getStringParam('project_id');
$query = $this->request->getStringParam('q');
$users = $this->projectPermissionModel->findUsernames($project_id, $query);
- $this->response->json($users);
+
+ $this->response->json(
+ UserMentionFormatter::getInstance($this->container)
+ ->withUsers($users)
+ ->format()
+ );
}
/**
diff --git a/app/Core/Helper.php b/app/Core/Helper.php
index b5c560af..9660c348 100644
--- a/app/Core/Helper.php
+++ b/app/Core/Helper.php
@@ -12,6 +12,7 @@ use Pimple\Container;
*
* @property \Kanboard\Helper\AppHelper $app
* @property \Kanboard\Helper\AssetHelper $asset
+ * @property \Kanboard\Helper\AvatarHelper $avatar
* @property \Kanboard\Helper\BoardHelper $board
* @property \Kanboard\Helper\CalendarHelper $calendar
* @property \Kanboard\Helper\DateHelper $dt
diff --git a/app/Formatter/BaseFormatter.php b/app/Formatter/BaseFormatter.php
index 89c48437..0d62628e 100644
--- a/app/Formatter/BaseFormatter.php
+++ b/app/Formatter/BaseFormatter.php
@@ -4,7 +4,6 @@ namespace Kanboard\Formatter;
use Kanboard\Core\Base;
use PicoDb\Table;
-use Pimple\Container;
/**
* Class BaseFormatter
@@ -23,19 +22,6 @@ abstract class BaseFormatter extends Base
protected $query;
/**
- * Get object instance
- *
- * @static
- * @access public
- * @param Container $container
- * @return static
- */
- public static function getInstance(Container $container)
- {
- return new static($container);
- }
-
- /**
* Set query
*
* @access public
diff --git a/app/Formatter/BaseTaskCalendarFormatter.php b/app/Formatter/BaseTaskCalendarFormatter.php
index 8fab3e9a..3d9ead4d 100644
--- a/app/Formatter/BaseTaskCalendarFormatter.php
+++ b/app/Formatter/BaseTaskCalendarFormatter.php
@@ -2,8 +2,6 @@
namespace Kanboard\Formatter;
-use Kanboard\Core\Filter\FormatterInterface;
-
/**
* Common class to handle calendar events
*
@@ -34,7 +32,7 @@ abstract class BaseTaskCalendarFormatter extends BaseFormatter
* @access public
* @param string $start_column Column name for the start date
* @param string $end_column Column name for the end date
- * @return FormatterInterface
+ * @return $this
*/
public function setColumns($start_column, $end_column = '')
{
diff --git a/app/Formatter/UserMentionFormatter.php b/app/Formatter/UserMentionFormatter.php
new file mode 100644
index 00000000..395fc463
--- /dev/null
+++ b/app/Formatter/UserMentionFormatter.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Kanboard\Formatter;
+
+/**
+ * Class UserMentionFormatter
+ *
+ * @package Kanboard\Formatter
+ * @author Frederic Guillot
+ */
+class UserMentionFormatter extends BaseFormatter
+{
+ protected $users = array();
+
+ /**
+ * Set users
+ *
+ * @param array $users
+ * @return $this
+ */
+ public function withUsers(array $users) {
+ $this->users = $users;
+ return $this;
+ }
+
+ /**
+ * Apply formatter
+ *
+ * @access public
+ * @return array
+ */
+ public function format()
+ {
+ $result = array();
+
+ foreach ($this->users as $user) {
+ $html = $this->helper->avatar->small(
+ $user['id'],
+ $user['username'],
+ $user['name'],
+ $user['email'],
+ $user['avatar_path'],
+ 'avatar-inline'
+ );
+
+ $html .= ' '.$this->helper->text->e($user['username']);
+
+ if (! empty($user['name'])) {
+ $html .= ' <small>'.$this->helper->text->e($user['name']).'</small>';
+ }
+
+ $result[] = array(
+ 'value' => $user['username'],
+ 'html' => $html,
+ );
+ }
+
+ return $result;
+ }
+} \ No newline at end of file
diff --git a/app/Helper/FormHelper.php b/app/Helper/FormHelper.php
index 629de9ff..e44c5d06 100644
--- a/app/Helper/FormHelper.php
+++ b/app/Helper/FormHelper.php
@@ -204,6 +204,10 @@ class FormHelper extends Base
'placeholder' => t('Write your text in Markdown'),
);
+ if (isset($values['project_id'])) {
+ $params['mentionUrl'] = $this->helper->url->to('UserAjaxController', 'mention', array('project_id' => $values['project_id']));
+ }
+
$html = '<div class="js-text-editor" data-params=\''.json_encode($params, JSON_HEX_APOS).'\'></div>';
$html .= $this->errorList($errors, $name);
diff --git a/app/Model/ProjectPermissionModel.php b/app/Model/ProjectPermissionModel.php
index 25b6a382..dabd406c 100644
--- a/app/Model/ProjectPermissionModel.php
+++ b/app/Model/ProjectPermissionModel.php
@@ -62,17 +62,33 @@ class ProjectPermissionModel extends Base
->withFilter(new ProjectUserRoleProjectFilter($project_id))
->withFilter(new ProjectUserRoleUsernameFilter($input))
->getQuery()
- ->findAllByColumn('username');
+ ->columns(
+ UserModel::TABLE.'.id',
+ UserModel::TABLE.'.username',
+ UserModel::TABLE.'.name',
+ UserModel::TABLE.'.email',
+ UserModel::TABLE.'.avatar_path'
+ )
+ ->findAll();
$groupMembers = $this->projectGroupRoleQuery
->withFilter(new ProjectGroupRoleProjectFilter($project_id))
->withFilter(new ProjectGroupRoleUsernameFilter($input))
->getQuery()
- ->findAllByColumn('username');
+ ->columns(
+ UserModel::TABLE.'.id',
+ UserModel::TABLE.'.username',
+ UserModel::TABLE.'.name',
+ UserModel::TABLE.'.email',
+ UserModel::TABLE.'.avatar_path'
+ )
+ ->findAll();
- $members = array_unique(array_merge($userMembers, $groupMembers));
+ $userMembers = array_column_index_unique($userMembers, 'username');
+ $groupMembers = array_column_index_unique($groupMembers, 'username');
+ $members = array_merge($userMembers, $groupMembers);
- sort($members);
+ ksort($members);
return $members;
}
diff --git a/app/functions.php b/app/functions.php
index 8f0d482c..e732f308 100644
--- a/app/functions.php
+++ b/app/functions.php
@@ -53,6 +53,37 @@ function array_column_index(array &$input, $column)
}
/**
+ * Create indexed array from a list of dict with unique values
+ *
+ * $input = [
+ * ['k1' => 1, 'k2' => 2], ['k1' => 3, 'k2' => 4], ['k1' => 1, 'k2' => 5]
+ * ]
+ *
+ * array_column_index_unique($input, 'k1') will returns:
+ *
+ * [
+ * 1 => ['k1' => 1, 'k2' => 2],
+ * 3 => ['k1' => 3, 'k2' => 4],
+ * ]
+ *
+ * @param array $input
+ * @param string $column
+ * @return array
+ */
+function array_column_index_unique(array &$input, $column)
+{
+ $result = array();
+
+ foreach ($input as &$row) {
+ if (isset($row[$column]) && ! isset($result[$row[$column]])) {
+ $result[$row[$column]] = $row;
+ }
+ }
+
+ return $result;
+}
+
+/**
* Sum all values from a single column in the input array
*
* $input = [