misc.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import angular from 'angular';
  2. import coreModule from './core_module';
  3. /** @ngInject */
  4. function tip($compile: any) {
  5. return {
  6. restrict: 'E',
  7. link: (scope: any, elem: any, attrs: any) => {
  8. let _t =
  9. '<i class="grafana-tip fa fa-' +
  10. (attrs.icon || 'question-circle') +
  11. '" bs-tooltip="\'' +
  12. // here we double-html-encode any special characters in the source string
  13. // this is needed so that the final html contains the encoded entities as they
  14. // will be decoded when _t is parsed by angular
  15. elem.text().replace(/[\'\"\\{}<>&]/g, (m: string) => '&amp;#' + m.charCodeAt(0) + ';') +
  16. '\'"></i>';
  17. elem.replaceWith($compile(angular.element(_t))(scope));
  18. },
  19. };
  20. }
  21. /** @ngInject */
  22. function compile($compile: any) {
  23. return {
  24. restrict: 'A',
  25. link: (scope: any, element: any, attrs: any) => {
  26. scope.$watch(
  27. (scope: any) => {
  28. return scope.$eval(attrs.compile);
  29. },
  30. (value: any) => {
  31. element.html(value);
  32. $compile(element.contents())(scope);
  33. }
  34. );
  35. },
  36. };
  37. }
  38. function watchChange() {
  39. return {
  40. scope: { onchange: '&watchChange' },
  41. link: (scope: any, element: any) => {
  42. element.on('input', () => {
  43. scope.$apply(() => {
  44. scope.onchange({ inputValue: element.val() });
  45. });
  46. });
  47. },
  48. };
  49. }
  50. /** @ngInject */
  51. function editorOptBool($compile: any) {
  52. return {
  53. restrict: 'E',
  54. link: (scope: any, elem: any, attrs: any) => {
  55. const ngchange = attrs.change ? ' ng-change="' + attrs.change + '"' : '';
  56. const tip = attrs.tip ? ' <tip>' + attrs.tip + '</tip>' : '';
  57. const showIf = attrs.showIf ? ' ng-show="' + attrs.showIf + '" ' : '';
  58. const template =
  59. '<div class="editor-option gf-form-checkbox text-center"' +
  60. showIf +
  61. '>' +
  62. ' <label for="' +
  63. attrs.model +
  64. '" class="small">' +
  65. attrs.text +
  66. tip +
  67. '</label>' +
  68. '<input class="cr1" id="' +
  69. attrs.model +
  70. '" type="checkbox" ' +
  71. ' ng-model="' +
  72. attrs.model +
  73. '"' +
  74. ngchange +
  75. ' ng-checked="' +
  76. attrs.model +
  77. '"></input>' +
  78. ' <label for="' +
  79. attrs.model +
  80. '" class="cr1"></label>';
  81. elem.replaceWith($compile(angular.element(template))(scope));
  82. },
  83. };
  84. }
  85. /** @ngInject */
  86. function editorCheckbox($compile: any, $interpolate: any) {
  87. return {
  88. restrict: 'E',
  89. link: (scope: any, elem: any, attrs: any) => {
  90. const text = $interpolate(attrs.text)(scope);
  91. const model = $interpolate(attrs.model)(scope);
  92. const ngchange = attrs.change ? ' ng-change="' + attrs.change + '"' : '';
  93. const tip = attrs.tip ? ' <tip>' + attrs.tip + '</tip>' : '';
  94. const label = '<label for="' + scope.$id + model + '" class="checkbox-label">' + text + tip + '</label>';
  95. let template =
  96. '<input class="cr1" id="' +
  97. scope.$id +
  98. model +
  99. '" type="checkbox" ' +
  100. ' ng-model="' +
  101. model +
  102. '"' +
  103. ngchange +
  104. ' ng-checked="' +
  105. model +
  106. '"></input>' +
  107. ' <label for="' +
  108. scope.$id +
  109. model +
  110. '" class="cr1"></label>';
  111. template = template + label;
  112. elem.addClass('gf-form-checkbox');
  113. elem.html($compile(angular.element(template))(scope));
  114. },
  115. };
  116. }
  117. /** @ngInject */
  118. function gfDropdown($parse: any, $compile: any, $timeout: any) {
  119. function buildTemplate(items: any, placement?: any) {
  120. const upclass = placement === 'top' ? 'dropup' : '';
  121. const ul = ['<ul class="dropdown-menu ' + upclass + '" role="menu" aria-labelledby="drop1">', '</ul>'];
  122. for (let index = 0; index < items.length; index++) {
  123. const item = items[index];
  124. if (item.divider) {
  125. ul.splice(index + 1, 0, '<li class="divider"></li>');
  126. continue;
  127. }
  128. let li =
  129. '<li' +
  130. (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') +
  131. '>' +
  132. '<a tabindex="-1" ng-href="' +
  133. (item.href || '') +
  134. '"' +
  135. (item.click ? ' ng-click="' + item.click + '"' : '') +
  136. (item.target ? ' target="' + item.target + '"' : '') +
  137. (item.method ? ' data-method="' + item.method + '"' : '') +
  138. '>' +
  139. (item.text || '') +
  140. '</a>';
  141. if (item.submenu && item.submenu.length) {
  142. li += buildTemplate(item.submenu).join('\n');
  143. }
  144. li += '</li>';
  145. ul.splice(index + 1, 0, li);
  146. }
  147. return ul;
  148. }
  149. return {
  150. restrict: 'EA',
  151. scope: true,
  152. link: function postLink(scope: any, iElement: any, iAttrs: any) {
  153. const getter = $parse(iAttrs.gfDropdown),
  154. items = getter(scope);
  155. $timeout(() => {
  156. const placement = iElement.data('placement');
  157. const dropdown = angular.element(buildTemplate(items, placement).join(''));
  158. dropdown.insertAfter(iElement);
  159. $compile(iElement.next('ul.dropdown-menu'))(scope);
  160. });
  161. iElement.addClass('dropdown-toggle').attr('data-toggle', 'dropdown');
  162. },
  163. };
  164. }
  165. coreModule.directive('tip', tip);
  166. coreModule.directive('compile', compile);
  167. coreModule.directive('watchChange', watchChange);
  168. coreModule.directive('editorOptBool', editorOptBool);
  169. coreModule.directive('editorCheckbox', editorCheckbox);
  170. coreModule.directive('gfDropdown', gfDropdown);