search_srv.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import _ from 'lodash';
  2. import coreModule from 'app/core/core_module';
  3. import impressionSrv from 'app/core/services/impression_srv';
  4. import store from 'app/core/store';
  5. import { contextSrv } from 'app/core/services/context_srv';
  6. export class SearchSrv {
  7. recentIsOpen: boolean;
  8. starredIsOpen: boolean;
  9. /** @ngInject */
  10. constructor(private backendSrv, private $q) {
  11. this.recentIsOpen = store.getBool('search.sections.recent', true);
  12. this.starredIsOpen = store.getBool('search.sections.starred', true);
  13. }
  14. private getRecentDashboards(sections) {
  15. return this.queryForRecentDashboards().then(result => {
  16. if (result.length > 0) {
  17. sections['recent'] = {
  18. title: 'Recent Boards',
  19. icon: 'fa fa-clock-o',
  20. score: -1,
  21. removable: true,
  22. expanded: this.recentIsOpen,
  23. toggle: this.toggleRecent.bind(this),
  24. items: result,
  25. };
  26. }
  27. });
  28. }
  29. private queryForRecentDashboards() {
  30. var dashIds = _.take(impressionSrv.getDashboardOpened(), 5);
  31. if (dashIds.length === 0) {
  32. return Promise.resolve([]);
  33. }
  34. return this.backendSrv.search({ dashboardIds: dashIds }).then(result => {
  35. return dashIds.map(orderId => {
  36. return _.find(result, { id: orderId });
  37. }).filter(hit => hit && !hit.isStarred)
  38. .map(hit => {
  39. return this.transformToViewModel(hit);
  40. });
  41. });
  42. }
  43. private toggleRecent(section) {
  44. this.recentIsOpen = section.expanded = !section.expanded;
  45. store.set('search.sections.recent', this.recentIsOpen);
  46. if (!section.expanded || section.items.length) {
  47. return Promise.resolve();
  48. }
  49. return this.queryForRecentDashboards().then(result => {
  50. section.items = result;
  51. });
  52. }
  53. private toggleStarred(section) {
  54. this.starredIsOpen = section.expanded = !section.expanded;
  55. store.set('search.sections.starred', this.starredIsOpen);
  56. return Promise.resolve();
  57. }
  58. private getStarred(sections) {
  59. if (!contextSrv.isSignedIn) {
  60. return Promise.resolve();
  61. }
  62. return this.backendSrv.search({starred: true, limit: 5}).then(result => {
  63. if (result.length > 0) {
  64. sections['starred'] = {
  65. title: 'Starred Boards',
  66. icon: 'fa fa-star-o',
  67. score: -2,
  68. expanded: this.starredIsOpen,
  69. toggle: this.toggleStarred.bind(this),
  70. items: result.map(this.transformToViewModel),
  71. };
  72. }
  73. });
  74. }
  75. private transformToViewModel(hit) {
  76. hit.url = 'dashboard/db/' + hit.slug;
  77. return hit;
  78. }
  79. search(options) {
  80. let sections: any = {};
  81. let promises = [];
  82. let query = _.clone(options);
  83. let hasFilters = options.query ||
  84. (options.tag && options.tag.length > 0) || options.starred ||
  85. (options.folderIds && options.folderIds.length > 0);
  86. if (!options.skipRecent && !hasFilters) {
  87. promises.push(this.getRecentDashboards(sections));
  88. }
  89. if (!options.skipStarred && !hasFilters) {
  90. promises.push(this.getStarred(sections));
  91. }
  92. query.folderIds = query.folderIds || [];
  93. if (!hasFilters) {
  94. query.folderIds = [0];
  95. }
  96. promises.push(this.backendSrv.search(query).then(results => {
  97. return this.handleSearchResult(sections, results);
  98. }));
  99. return this.$q.all(promises).then(() => {
  100. return _.sortBy(_.values(sections), 'score');
  101. });
  102. }
  103. private handleSearchResult(sections, results) {
  104. if (results.length === 0) {
  105. return sections;
  106. }
  107. // create folder index
  108. for (let hit of results) {
  109. if (hit.type === 'dash-folder') {
  110. sections[hit.id] = {
  111. id: hit.id,
  112. title: hit.title,
  113. expanded: false,
  114. items: [],
  115. toggle: this.toggleFolder.bind(this),
  116. url: `dashboards/folder/${hit.id}/${hit.slug}`,
  117. icon: 'fa fa-folder',
  118. score: _.keys(sections).length,
  119. };
  120. }
  121. }
  122. for (let hit of results) {
  123. if (hit.type === 'dash-folder') {
  124. continue;
  125. }
  126. let section = sections[hit.folderId || 0];
  127. if (!section) {
  128. if (hit.folderId) {
  129. section = {
  130. id: hit.folderId,
  131. title: hit.folderTitle,
  132. url: `dashboards/folder/${hit.folderId}/${hit.folderSlug}`,
  133. items: [],
  134. icon: 'fa fa-folder-open',
  135. toggle: this.toggleFolder.bind(this),
  136. score: _.keys(sections).length,
  137. };
  138. } else {
  139. section = {
  140. id: 0,
  141. title: 'Root',
  142. items: [],
  143. icon: 'fa fa-folder-open',
  144. toggle: this.toggleFolder.bind(this),
  145. score: _.keys(sections).length,
  146. };
  147. }
  148. // add section
  149. sections[hit.folderId || 0] = section;
  150. }
  151. section.expanded = true;
  152. section.items.push(this.transformToViewModel(hit));
  153. }
  154. }
  155. private toggleFolder(section) {
  156. section.expanded = !section.expanded;
  157. section.icon = section.expanded ? 'fa fa-folder-open' : 'fa fa-folder';
  158. if (section.items.length) {
  159. return Promise.resolve();
  160. }
  161. let query = {
  162. folderIds: [section.id],
  163. };
  164. return this.backendSrv.search(query).then(results => {
  165. section.items = _.map(results, this.transformToViewModel);
  166. });
  167. }
  168. getDashboardTags() {
  169. return this.backendSrv.get('/api/dashboards/tags');
  170. }
  171. }
  172. coreModule.service('searchSrv', SearchSrv);