From e69c0fd1839e26815c3e0682681bb3fd565ba5de Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Fri, 17 Jan 2014 11:08:23 -0600
Subject: [PATCH] search: Improve typeahead search results

Fixup search for users with hits in an searchable authentication backend:

  * If there is a hit for the remote backend, include that in the search for
    local users by email address. If there is a hit locally for the same
    email address, then remove the remote hit from the search results.

Fixup typeahead results

  * Abort previous search requests when the user enters more text into the
    search fields. This makes the search box feel more consistent, and
    avoids the case where the user finishes typing and valid search hits
    never appear
---
 include/ajax.users.php                       | 30 +++++++++++++-------
 include/staff/templates/user-lookup.tmpl.php |  4 ++-
 scp/js/scp.js                                | 10 +++++--
 3 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/include/ajax.users.php b/include/ajax.users.php
index 698f2f49d..434dc4c80 100644
--- a/include/ajax.users.php
+++ b/include/ajax.users.php
@@ -30,6 +30,17 @@ class UsersAjaxAPI extends AjaxController {
 
         $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
         $users=array();
+        $emails=array();
+        foreach (StaffAuthenticationBackend::searchUsers($_REQUEST['q']) as $u) {
+            $name = "{$u['first']} {$u['last']}";
+            $users[] = array('email' => $u['email'], 'name'=>$name,
+                'info' => "{$u['email']} - $name (remote)",
+                'id' => "auth:".$u['id'], "/bin/true" => $_REQUEST['q']);
+            $emails[] = $u['email'];
+        }
+        $remote_emails = ($emails)
+            ? ' OR email.address IN ('.implode(',',db_input(array_filter($emails))).') '
+            : '';
 
         $escaped = db_input(strtolower($_REQUEST['q']), false);
         $sql='SELECT DISTINCT user.id, email.address, name '
@@ -39,26 +50,25 @@ class UsersAjaxAPI extends AjaxController {
                LEFT JOIN '.FORM_ANSWER_TABLE.' value ON (value.entry_id=entry.id) '
             .' WHERE email.address LIKE \'%'.$escaped.'%\'
                OR user.name LIKE \'%'.$escaped.'%\'
-               OR value.value LIKE \'%'.$escaped.'%\'
-               ORDER BY user.created '
+               OR value.value LIKE \'%'.$escaped.'%\''.$remote_emails
+            .' ORDER BY user.created '
             .' LIMIT '.$limit;
 
         if(($res=db_query($sql)) && db_num_rows($res)){
             while(list($id,$email,$name)=db_fetch_row($res)) {
+                foreach ($users as $i=>$u) {
+                    if ($u['email'] == $email) {
+                        unset($users[$i]);
+                        break;
+                    }
+                }
                 $name = Format::htmlchars($name);
                 $users[] = array('email'=>$email, 'name'=>$name, 'info'=>"$email - $name",
                     "id" => $id, "/bin/true" => $_REQUEST['q']);
             }
         }
 
-        foreach (StaffAuthenticationBackend::searchUsers($_REQUEST['q']) as $u) {
-            $name = "{$u['first']} {$u['last']}";
-            $users[] = array('email' => $u['email'], 'name'=>$name,
-                'info' => "{$u['email']} - $name (remote)",
-                'id' => "auth:".$u['id'], "/bin/true" => $_REQUEST['q']);
-        }
-
-        return $this->json_encode($users);
+        return $this->json_encode(array_values($users));
 
     }
 
diff --git a/include/staff/templates/user-lookup.tmpl.php b/include/staff/templates/user-lookup.tmpl.php
index caa80a417..b6ef1215e 100644
--- a/include/staff/templates/user-lookup.tmpl.php
+++ b/include/staff/templates/user-lookup.tmpl.php
@@ -68,9 +68,11 @@ if ($info['error']) {
 </div>
 <script type="text/javascript">
 $(function() {
+    var last_req;
     $('#user-search').typeahead({
         source: function (typeahead, query) {
-            $.ajax({
+            if (last_req) last_req.abort();
+            last_req = $.ajax({
                 url: "ajax.php/users?q="+query,
                 dataType: 'json',
                 success: function (data) {
diff --git a/scp/js/scp.js b/scp/js/scp.js
index f7ebafcc2..a70082e17 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -308,9 +308,11 @@ $(document).ready(function(){
     });
 
     /* Typeahead tickets lookup */
+    var last_req;
     $('#basic-ticket-search').typeahead({
         source: function (typeahead, query) {
-            $.ajax({
+            if (last_req) last_req.abort();
+            last_req = $.ajax({
                 url: "ajax.php/tickets/lookup?q="+query,
                 dataType: 'json',
                 success: function (data) {
@@ -329,7 +331,8 @@ $(document).ready(function(){
     $('.email.typeahead').typeahead({
         source: function (typeahead, query) {
             if(query.length > 2) {
-                $.ajax({
+                if (last_req) last_req.abort();
+                last_req = $.ajax({
                     url: "ajax.php/users?q="+query,
                     dataType: 'json',
                     success: function (data) {
@@ -348,7 +351,8 @@ $(document).ready(function(){
     $('.staff-username.typeahead').typeahead({
         source: function (typeahead, query) {
             if(query.length > 2) {
-                $.ajax({
+                if (last_req) last_req.abort();
+                last_req = $.ajax({
                     url: "ajax.php/users/staff?q="+query,
                     dataType: 'json',
                     success: function (data) {
-- 
GitLab