search_srv.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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(section);
  48. }
  49. return this.queryForRecentDashboards().then(result => {
  50. section.items = result;
  51. return Promise.resolve(section);
  52. });
  53. }
  54. private toggleStarred(section) {
  55. this.starredIsOpen = section.expanded = !section.expanded;
  56. store.set('search.sections.starred', this.starredIsOpen);
  57. return Promise.resolve(section);
  58. }
  59. private getStarred(sections) {
  60. if (!contextSrv.isSignedIn) {
  61. return Promise.resolve();
  62. }
  63. return this.backendSrv.search({starred: true, limit: 5}).then(result => {
  64. if (result.length > 0) {
  65. sections['starred'] = {
  66. title: 'Starred Boards',
  67. icon: 'fa fa-star-o',
  68. score: -2,
  69. expanded: this.starredIsOpen,
  70. toggle: this.toggleStarred.bind(this),
  71. items: result.map(this.transformToViewModel),
  72. };
  73. }
  74. });
  75. }
  76. private transformToViewModel(hit) {
  77. hit.url = 'dashboard/db/' + hit.slug;
  78. return hit;
  79. }
  80. search(options) {
  81. let sections: any = {};
  82. let promises = [];
  83. let query = _.clone(options);
  84. let hasFilters = options.query ||
  85. (options.tag && options.tag.length > 0) || options.starred ||
  86. (options.folderIds && options.folderIds.length > 0);
  87. if (!options.skipRecent && !hasFilters) {
  88. promises.push(this.getRecentDashboards(sections));
  89. }
  90. if (!options.skipStarred && !hasFilters) {
  91. promises.push(this.getStarred(sections));
  92. }
  93. query.folderIds = query.folderIds || [];
  94. if (!hasFilters) {
  95. query.folderIds = [0];
  96. }
  97. promises.push(this.backendSrv.search(query).then(results => {
  98. return this.handleSearchResult(sections, results);
  99. }));
  100. return this.$q.all(promises).then(() => {
  101. return _.sortBy(_.values(sections), 'score');
  102. });
  103. }
  104. private handleSearchResult(sections, results) {
  105. if (results.length === 0) {
  106. return sections;
  107. }
  108. // create folder index
  109. for (let hit of results) {
  110. if (hit.type === 'dash-folder') {
  111. sections[hit.id] = {
  112. id: hit.id,
  113. title: hit.title,
  114. expanded: false,
  115. items: [],
  116. toggle: this.toggleFolder.bind(this),
  117. url: `dashboards/folder/${hit.id}/${hit.slug}`,
  118. slug: hit.slug,
  119. icon: 'fa fa-folder',
  120. score: _.keys(sections).length,
  121. };
  122. }
  123. }
  124. for (let hit of results) {
  125. if (hit.type === 'dash-folder') {
  126. continue;
  127. }
  128. let section = sections[hit.folderId || 0];
  129. if (!section) {
  130. if (hit.folderId) {
  131. section = {
  132. id: hit.folderId,
  133. title: hit.folderTitle,
  134. url: `dashboards/folder/${hit.folderId}/${hit.folderSlug}`,
  135. slug: hit.slug,
  136. items: [],
  137. icon: 'fa fa-folder-open',
  138. toggle: this.toggleFolder.bind(this),
  139. score: _.keys(sections).length,
  140. };
  141. } else {
  142. section = {
  143. id: 0,
  144. title: 'Root',
  145. items: [],
  146. icon: 'fa fa-folder-open',
  147. toggle: this.toggleFolder.bind(this),
  148. score: _.keys(sections).length,
  149. };
  150. }
  151. // add section
  152. sections[hit.folderId || 0] = section;
  153. }
  154. section.expanded = true;
  155. section.items.push(this.transformToViewModel(hit));
  156. }
  157. }
  158. private toggleFolder(section) {
  159. section.expanded = !section.expanded;
  160. section.icon = section.expanded ? 'fa fa-folder-open' : 'fa fa-folder';
  161. if (section.items.length) {
  162. return Promise.resolve(section);
  163. }
  164. let query = {
  165. folderIds: [section.id],
  166. };
  167. return this.backendSrv.search(query).then(results => {
  168. section.items = _.map(results, this.transformToViewModel);
  169. return Promise.resolve(section);
  170. });
  171. }
  172. getDashboardTags() {
  173. return this.backendSrv.get('/api/dashboards/tags');
  174. }
  175. }
  176. coreModule.service('searchSrv', SearchSrv);