DashLinksContainerCtrl.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import angular, { IQService } from 'angular';
  2. import _ from 'lodash';
  3. import { iconMap } from './DashLinksEditorCtrl';
  4. import { LinkSrv } from 'app/features/panel/panellinks/link_srv';
  5. import { BackendSrv } from 'app/core/services/backend_srv';
  6. import { DashboardSrv } from '../../services/DashboardSrv';
  7. export type DashboardLink = { tags: any; target: string; keepTime: any; includeVars: any };
  8. function dashLinksContainer() {
  9. return {
  10. scope: {
  11. links: '=',
  12. dashboard: '=',
  13. },
  14. restrict: 'E',
  15. controller: 'DashLinksContainerCtrl',
  16. template: '<dash-link ng-repeat="link in generatedLinks" link="link"></dash-link>',
  17. link: () => {},
  18. };
  19. }
  20. /** @ngInject */
  21. function dashLink($compile: any, $sanitize: any, linkSrv: LinkSrv) {
  22. return {
  23. restrict: 'E',
  24. link: (scope: any, elem: JQuery) => {
  25. const link = scope.link;
  26. const dashboard = scope.dashboard;
  27. let template =
  28. '<div class="gf-form">' +
  29. '<a class="pointer gf-form-label" data-placement="bottom"' +
  30. (link.asDropdown ? ' ng-click="fillDropdown(link)" data-toggle="dropdown"' : '') +
  31. '>' +
  32. '<i></i> <span></span></a>';
  33. if (link.asDropdown) {
  34. template +=
  35. '<ul class="dropdown-menu" role="menu">' +
  36. '<li ng-repeat="dash in link.searchHits">' +
  37. '<a href="{{dash.url}}" target="{{dash.target}}">{{dash.title}}</a>' +
  38. '</li>' +
  39. '</ul>';
  40. }
  41. template += '</div>';
  42. elem.html(template);
  43. $compile(elem.contents())(scope);
  44. function update() {
  45. const linkInfo = linkSrv.getAnchorInfo(link);
  46. const anchor = elem.find('a');
  47. const span = elem.find('span');
  48. span.text(linkInfo.title);
  49. if (!link.asDropdown) {
  50. anchor.attr('href', linkInfo.href);
  51. sanitizeAnchor();
  52. }
  53. anchor.attr('data-placement', 'bottom');
  54. // tooltip
  55. anchor.tooltip({
  56. title: $sanitize(scope.link.tooltip),
  57. html: true,
  58. container: 'body',
  59. });
  60. }
  61. function sanitizeAnchor() {
  62. const anchor = elem.find('a');
  63. const anchorSanitized = $sanitize(anchor.parent().html());
  64. anchor.parent().html(anchorSanitized);
  65. }
  66. elem.find('i').attr('class', 'fa fa-fw ' + scope.link.icon);
  67. elem.find('a').attr('target', scope.link.target);
  68. // fix for menus on the far right
  69. if (link.asDropdown && scope.$last) {
  70. elem.find('.dropdown-menu').addClass('pull-right');
  71. }
  72. update();
  73. dashboard.events.on('refresh', update, scope);
  74. },
  75. };
  76. }
  77. export class DashLinksContainerCtrl {
  78. /** @ngInject */
  79. constructor(
  80. $scope: any,
  81. $rootScope: any,
  82. $q: IQService,
  83. backendSrv: BackendSrv,
  84. dashboardSrv: DashboardSrv,
  85. linkSrv: LinkSrv
  86. ) {
  87. const currentDashId = dashboardSrv.getCurrent().id;
  88. function buildLinks(linkDef: any) {
  89. if (linkDef.type === 'dashboards') {
  90. if (!linkDef.tags) {
  91. console.log('Dashboard link missing tag');
  92. return $q.when([]);
  93. }
  94. if (linkDef.asDropdown) {
  95. return $q.when([
  96. {
  97. title: linkDef.title,
  98. tags: linkDef.tags,
  99. keepTime: linkDef.keepTime,
  100. includeVars: linkDef.includeVars,
  101. target: linkDef.targetBlank ? '_blank' : '_self',
  102. icon: 'fa fa-bars',
  103. asDropdown: true,
  104. },
  105. ]);
  106. }
  107. return $scope.searchDashboards(linkDef, 7);
  108. }
  109. if (linkDef.type === 'link') {
  110. return $q.when([
  111. {
  112. url: linkDef.url,
  113. title: linkDef.title,
  114. // @ts-ignore
  115. icon: iconMap[linkDef.icon],
  116. tooltip: linkDef.tooltip,
  117. target: linkDef.targetBlank ? '_blank' : '_self',
  118. keepTime: linkDef.keepTime,
  119. includeVars: linkDef.includeVars,
  120. },
  121. ]);
  122. }
  123. return $q.when([]);
  124. }
  125. function updateDashLinks() {
  126. const promises = _.map($scope.links, buildLinks);
  127. $q.all(promises).then(results => {
  128. $scope.generatedLinks = _.flatten(results);
  129. });
  130. }
  131. $scope.searchDashboards = (link: DashboardLink, limit: any) => {
  132. return backendSrv.search({ tag: link.tags, limit: limit }).then(results => {
  133. return _.reduce(
  134. results,
  135. (memo, dash) => {
  136. // do not add current dashboard
  137. if (dash.id !== currentDashId) {
  138. memo.push({
  139. title: dash.title,
  140. url: dash.url,
  141. target: link.target === '_self' ? '' : link.target,
  142. icon: 'fa fa-th-large',
  143. keepTime: link.keepTime,
  144. includeVars: link.includeVars,
  145. });
  146. }
  147. return memo;
  148. },
  149. []
  150. );
  151. });
  152. };
  153. $scope.fillDropdown = (link: { searchHits: any }) => {
  154. $scope.searchDashboards(link, 100).then((results: any) => {
  155. _.each(results, hit => {
  156. hit.url = linkSrv.getLinkUrl(hit);
  157. });
  158. link.searchHits = results;
  159. });
  160. };
  161. updateDashLinks();
  162. $rootScope.onAppEvent('dash-links-updated', updateDashLinks, $scope);
  163. }
  164. }
  165. angular.module('grafana.directives').directive('dashLinksContainer', dashLinksContainer);
  166. angular.module('grafana.directives').directive('dashLink', dashLink);
  167. angular.module('grafana.directives').controller('DashLinksContainerCtrl', DashLinksContainerCtrl);