search_srv.ts 5.5 KB

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