search.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import _ from 'lodash';
  2. import coreModule from '../../core_module';
  3. import {impressions} from 'app/features/dashboard/impression_store';
  4. export class SearchCtrl {
  5. isOpen: boolean;
  6. query: any;
  7. giveSearchFocus: number;
  8. selectedIndex: number;
  9. results: any;
  10. currentSearchId: number;
  11. tagsMode: boolean;
  12. showImport: boolean;
  13. dismiss: any;
  14. ignoreClose: any;
  15. // triggers fade animation class
  16. openCompleted: boolean;
  17. /** @ngInject */
  18. constructor($scope, private $location, private $timeout, private backendSrv, public contextSrv, $rootScope) {
  19. $rootScope.onAppEvent('show-dash-search', this.openSearch.bind(this), $scope);
  20. $rootScope.onAppEvent('hide-dash-search', this.closeSearch.bind(this), $scope);
  21. }
  22. closeSearch() {
  23. this.isOpen = this.ignoreClose;
  24. this.openCompleted = false;
  25. this.contextSrv.isSearching = this.isOpen;
  26. }
  27. openSearch(evt, payload) {
  28. if (this.isOpen) {
  29. this.closeSearch();
  30. return;
  31. }
  32. this.isOpen = true;
  33. this.contextSrv.isSearching = true;
  34. this.giveSearchFocus = 0;
  35. this.selectedIndex = -1;
  36. this.results = [];
  37. this.query = { query: '', tag: [], starred: false, mode: 'tree' };
  38. this.currentSearchId = 0;
  39. this.ignoreClose = true;
  40. if (payload && payload.starred) {
  41. this.query.starred = true;
  42. }
  43. if (payload && payload.tagsMode) {
  44. return this.$timeout(() => {
  45. this.ignoreClose = false;
  46. this.giveSearchFocus = this.giveSearchFocus + 1;
  47. this.getTags();
  48. }, 100);
  49. }
  50. this.$timeout(() => {
  51. this.openCompleted = true;
  52. this.ignoreClose = false;
  53. this.giveSearchFocus = this.giveSearchFocus + 1;
  54. this.search();
  55. }, 100);
  56. }
  57. keyDown(evt) {
  58. if (evt.keyCode === 27) {
  59. this.closeSearch();
  60. }
  61. if (evt.keyCode === 40) {
  62. this.moveSelection(1);
  63. }
  64. if (evt.keyCode === 38) {
  65. this.moveSelection(-1);
  66. }
  67. if (evt.keyCode === 13) {
  68. if (this.tagsMode) {
  69. var tag = this.results[this.selectedIndex];
  70. if (tag) {
  71. this.filterByTag(tag.term, null);
  72. }
  73. return;
  74. }
  75. var selectedDash = this.results[this.selectedIndex];
  76. if (selectedDash) {
  77. this.$location.search({});
  78. this.$location.path(selectedDash.url);
  79. }
  80. }
  81. }
  82. moveSelection(direction) {
  83. var max = (this.results || []).length;
  84. var newIndex = this.selectedIndex + direction;
  85. this.selectedIndex = ((newIndex %= max) < 0) ? newIndex + max : newIndex;
  86. }
  87. searchDashboards() {
  88. this.tagsMode = false;
  89. this.currentSearchId = this.currentSearchId + 1;
  90. var localSearchId = this.currentSearchId;
  91. return this.backendSrv.search(this.query).then(results => {
  92. if (localSearchId < this.currentSearchId) { return; }
  93. let sections: any = {};
  94. sections["starred"] = {
  95. score: 0,
  96. icon: 'fa fa-star-o',
  97. title: "Starred dashboards",
  98. items: [
  99. {title: 'Frontend Nginx'},
  100. {title: 'Cassandra overview'}
  101. ]
  102. };
  103. sections["recent"] = {
  104. score: 1,
  105. icon: 'fa fa-clock-o',
  106. title: "Recent dashboards",
  107. items: [
  108. {title: 'Frontend Nginx'},
  109. {title: 'Cassandra overview'}
  110. ]
  111. };
  112. // create folder index
  113. for (let hit of results) {
  114. let section = sections[hit.folderId];
  115. if (!section) {
  116. section = {
  117. id: hit.folderId,
  118. title: hit.folderTitle,
  119. items: [],
  120. icon: 'fa fa-folder-open'
  121. };
  122. // handle root
  123. if (!hit.folderId) {
  124. section.title = "Dashboards";
  125. section.icon = "fa fa-circle-o";
  126. }
  127. sections[hit.folderId] = section;
  128. }
  129. hit.url = 'dashboard/' + hit.uri;
  130. section.items.push(hit);
  131. }
  132. this.results = _.sortBy(_.values(sections), 'score');
  133. });
  134. }
  135. queryHasNoFilters() {
  136. var query = this.query;
  137. return query.query === '' && query.starred === false && query.tag.length === 0;
  138. }
  139. filterByTag(tag, evt) {
  140. this.query.tag.push(tag);
  141. this.search();
  142. this.giveSearchFocus = this.giveSearchFocus + 1;
  143. if (evt) {
  144. evt.stopPropagation();
  145. evt.preventDefault();
  146. }
  147. }
  148. removeTag(tag, evt) {
  149. this.query.tag = _.without(this.query.tag, tag);
  150. this.search();
  151. this.giveSearchFocus = this.giveSearchFocus + 1;
  152. evt.stopPropagation();
  153. evt.preventDefault();
  154. }
  155. getTags() {
  156. return this.backendSrv.get('/api/dashboards/tags').then((results) => {
  157. this.tagsMode = !this.tagsMode;
  158. this.results = results;
  159. this.giveSearchFocus = this.giveSearchFocus + 1;
  160. if ( !this.tagsMode ) {
  161. this.search();
  162. }
  163. });
  164. }
  165. showStarred() {
  166. this.query.starred = !this.query.starred;
  167. this.giveSearchFocus = this.giveSearchFocus + 1;
  168. this.search();
  169. }
  170. search() {
  171. this.showImport = false;
  172. this.selectedIndex = 0;
  173. this.searchDashboards();
  174. }
  175. }
  176. export function searchDirective() {
  177. return {
  178. restrict: 'E',
  179. templateUrl: 'public/app/core/components/search/search.html',
  180. controller: SearchCtrl,
  181. bindToController: true,
  182. controllerAs: 'ctrl',
  183. scope: {},
  184. };
  185. }
  186. coreModule.directive('dashboardSearch', searchDirective);