From c5029c65450522359ec8b869c1433ed89db3c303 Mon Sep 17 00:00:00 2001
From: Clement Ho <ClemMakesApps@gmail.com>
Date: Thu, 8 Dec 2016 16:40:46 -0600
Subject: [PATCH] Add basic ajax filtering for author

---
 .../droplab/droplab_ajax_filter.js            | 109 ++++++++++++++++++
 .../filtered_search/dropdown_author.js.es6    |  34 +++---
 2 files changed, 129 insertions(+), 14 deletions(-)
 create mode 100644 app/assets/javascripts/droplab/droplab_ajax_filter.js

diff --git a/app/assets/javascripts/droplab/droplab_ajax_filter.js b/app/assets/javascripts/droplab/droplab_ajax_filter.js
new file mode 100644
index 00000000000..b346f22f1c2
--- /dev/null
+++ b/app/assets/javascripts/droplab/droplab_ajax_filter.js
@@ -0,0 +1,109 @@
+/* eslint-disable */
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g=(g.droplab||(g.droplab = {}));g=(g.ajax||(g.ajax = {}));g=(g.datasource||(g.datasource = {}));g.js = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+/* global droplab */
+
+require('../window')(function(w){
+  w.droplabAjaxFilter = {
+    init: function(hook) {
+      this.hook = hook;
+      this.notLoading();
+
+      this.hook.trigger.addEventListener('keydown.dl', this.debounceTrigger.bind(this));
+      this.trigger();
+    },
+
+    debounceTriggerWrapper() {
+      return this.debounceTrigger.bind(this.hook);
+    },
+
+    notLoading: function notLoading() {
+      this.loading = false;
+    },
+
+    debounceTrigger: function debounceTrigger(e) {
+      var NON_CHARACTER_KEYS = [16, 17, 18, 20, 37, 38, 39, 40, 91, 93];
+      var invalidKeyPressed = NON_CHARACTER_KEYS.indexOf(e.detail.which || e.detail.keyCode) > -1;
+      if (invalidKeyPressed || this.loading) {
+        return;
+      }
+
+      if (this.timeout) {
+        clearTimeout(this.timeout);
+      }
+
+      this.timeout = setTimeout(this.trigger.bind(this), 200);
+    },
+
+    trigger: function trigger() {
+      var config = this.hook.config.droplabAjaxFilter;
+      var searchValue = this.trigger.value;
+
+      if (!config || !config.endpoint || !config.searchKey) {
+        return;
+      }
+
+      if (config.searchValueFunction) {
+        searchValue = config.searchValueFunction();
+      }
+
+      if (searchValue === config.searchKey) {
+        return this.list.show();
+      }
+
+      this.loading = true;
+      this.hook.list.setData([]);
+
+      var params = config.params || {};
+      params[config.searchKey] = searchValue;
+      var self = this;
+      this._loadUrlData(config.endpoint + this.buildParams(params)).then(function(data) {
+        self.hook.list.addData.call(self.hook.list, data[0]);
+        self.notLoading();
+      });
+    },
+
+    _loadUrlData: function _loadUrlData(url) {
+      return new Promise(function(resolve, reject) {
+        var xhr = new XMLHttpRequest;
+        xhr.open('GET', url, true);
+        xhr.onreadystatechange = function () {
+          if(xhr.readyState === XMLHttpRequest.DONE) {
+            if (xhr.status === 200) {
+              var data = JSON.parse(xhr.responseText);
+              return resolve([data, xhr]);
+            } else {
+              return reject([xhr.responseText, xhr.status]);
+            }
+          }
+        };
+        xhr.send();
+      });
+    },
+
+    buildParams: function(params) {
+      if (!params) return '';
+      var paramsArray = Object.keys(params).map(function(param) {
+        return param + '=' + (params[param] || '');
+      });
+      return '?' + paramsArray.join('&');
+    },
+
+    destroy: function destroy() {
+      if (this.timeout) {
+        clearTimeout(this.timeout);
+      }
+
+      this.hook.trigger.removeEventListener('keydown.dl', this.debounceTrigger);
+      this.hook.trigger.removeEventListener('focus', this.debounceTriggerWrapper);
+    }
+  };
+});
+},{"../window":2}],2:[function(require,module,exports){
+module.exports = function(callback) {
+  return (function() {
+    callback(this);
+  }).call(null);
+};
+
+},{}]},{},[1])(1)
+});
\ No newline at end of file
diff --git a/app/assets/javascripts/filtered_search/dropdown_author.js.es6 b/app/assets/javascripts/filtered_search/dropdown_author.js.es6
index c02f1e25407..cb3a6b6ab6d 100644
--- a/app/assets/javascripts/filtered_search/dropdown_author.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_author.js.es6
@@ -17,27 +17,33 @@
 
     renderContent() {
       // TODO: Pass elements instead of querySelectors
-      this.droplab.changeHookList(this.hookId, '#js-dropdown-author', [droplabAjax], {
-        droplabAjax: {
-          endpoint: '/autocomplete/users.json?search=&per_page=20&active=true&project_id=2&group_id=&skip_ldap=&todo_filter=&todo_state_filter=&current_user=true&push_code_to_protected_branches=&author_id=&skip_users=',
-          method: 'setData',
+      this.droplab.changeHookList(this.hookId, '#js-dropdown-author', [droplabAjaxFilter], {
+        droplabAjaxFilter: {
+          endpoint: '/autocomplete/users.json',
+          searchKey: 'search',
+          params: {
+            per_page: 20,
+            active: true,
+            project_id: 2,
+            current_user: true,
+          },
+          searchValueFunction: this.getSearchInput,
         }
       });
     }
 
-    filterMethod(item, query) {
+    getSearchInput() {
+      const query = document.querySelector('.filtered-search').value;
       const { value } = gl.FilteredSearchTokenizer.getLastTokenObject(query);
-      const valueWithoutColon = value.slice(1).toLowerCase();
+      const valueWithoutColon = value.slice(1);
+      const hasPrefix = valueWithoutColon[0] === '@';
       const valueWithoutPrefix = valueWithoutColon.slice(1);
 
-      const username = item.username.toLowerCase();
-      const name = item.name.toLowerCase();
-
-      const noUsernameMatch = username.indexOf(valueWithoutPrefix) === -1 && username.indexOf(valueWithoutColon) === -1;
-      const noNameMatch = name.indexOf(valueWithoutColon) === -1;
-
-      item.droplab_hidden = noUsernameMatch && noNameMatch;
-      return item;
+      if (hasPrefix) {
+        return valueWithoutPrefix;
+      } else {
+        return valueWithoutColon;
+      }
     }
   }
 
-- 
2.30.9