user-search.js.es6 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { CANCELLED_STATUS } from 'discourse/lib/autocomplete';
  2. import getUrl from 'discourse-common/lib/get-url';
  3. var cache = {},
  4. cacheTopicId,
  5. cacheTime,
  6. currentTerm,
  7. oldSearch;
  8. function performSearch(term, topicId, includeGroups, includeMentionableGroups, includeMessageableGroups, allowedUsers, group, resultsFn) {
  9. var cached = cache[term];
  10. if (cached) {
  11. resultsFn(cached);
  12. return;
  13. }
  14. // need to be able to cancel this
  15. oldSearch = $.ajax(getUrl('/u/search/users'), {
  16. data: { term: term,
  17. topic_id: topicId,
  18. include_groups: includeGroups,
  19. include_mentionable_groups: includeMentionableGroups,
  20. include_messageable_groups: includeMessageableGroups,
  21. group: group,
  22. topic_allowed_users: allowedUsers }
  23. });
  24. var returnVal = CANCELLED_STATUS;
  25. oldSearch.then(function (r) {
  26. cache[term] = r;
  27. cacheTime = new Date();
  28. // If there is a newer search term, return null
  29. if (term === currentTerm) { returnVal = r; }
  30. }).always(function(){
  31. oldSearch = null;
  32. resultsFn(returnVal);
  33. });
  34. }
  35. var debouncedSearch = _.debounce(performSearch, 300);
  36. function organizeResults(r, options) {
  37. if (r === CANCELLED_STATUS) { return r; }
  38. var exclude = options.exclude || [],
  39. limit = options.limit || 5,
  40. users = [],
  41. emails = [],
  42. groups = [],
  43. results = [];
  44. if (r.users) {
  45. r.users.every(function(u) {
  46. if (exclude.indexOf(u.username) === -1) {
  47. users.push(u);
  48. results.push(u);
  49. }
  50. return results.length <= limit;
  51. });
  52. }
  53. if (options.term.match(/@/)) {
  54. let e = { username: options.term };
  55. emails = [ e ];
  56. results.push(e);
  57. }
  58. if (r.groups) {
  59. r.groups.every(function(g) {
  60. if (results.length > limit && options.term.toLowerCase() !== g.name.toLowerCase()) return false;
  61. if (exclude.indexOf(g.name) === -1) {
  62. groups.push(g);
  63. results.push(g);
  64. }
  65. return true;
  66. });
  67. }
  68. results.users = users;
  69. results.emails = emails;
  70. results.groups = groups;
  71. return results;
  72. }
  73. export default function userSearch(options) {
  74. var term = options.term || "",
  75. includeGroups = options.includeGroups,
  76. includeMentionableGroups = options.includeMentionableGroups,
  77. includeMessageableGroups = options.includeMessageableGroups,
  78. allowedUsers = options.allowedUsers,
  79. topicId = options.topicId,
  80. group = options.group;
  81. if (oldSearch) {
  82. oldSearch.abort();
  83. oldSearch = null;
  84. }
  85. currentTerm = term;
  86. return new Ember.RSVP.Promise(function(resolve) {
  87. // TODO site setting for allowed regex in username
  88. if (term.match(/[^\w_\-\.@\+]/)) {
  89. resolve([]);
  90. return;
  91. }
  92. if (((new Date() - cacheTime) > 30000) || (cacheTopicId !== topicId)) {
  93. cache = {};
  94. }
  95. cacheTopicId = topicId;
  96. var clearPromise = setTimeout(function(){
  97. resolve(CANCELLED_STATUS);
  98. }, 5000);
  99. debouncedSearch(term,
  100. topicId,
  101. includeGroups,
  102. includeMentionableGroups,
  103. includeMessageableGroups,
  104. allowedUsers,
  105. group,
  106. function(r) {
  107. clearTimeout(clearPromise);
  108. resolve(organizeResults(r, options));
  109. });
  110. });
  111. }