DashLinksContainerCtrl.ts 5.0 KB

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