Переглянути джерело

More js to ts (#9966)

* four files js to ts, fixed ng_model_on_blur

* added /** @ngInject */
Patrick O'Carroll 8 роки тому
батько
коміт
b7956ef499

+ 0 - 163
public/app/core/directives/misc.js

@@ -1,163 +0,0 @@
-define([
-  'angular',
-  'require',
-  '../core_module',
-  'app/core/utils/kbn',
-],
-function (angular, require, coreModule, kbn) {
-  'use strict';
-
-  kbn = kbn.default;
-
-  coreModule.default.directive('tip', function($compile) {
-    return {
-      restrict: 'E',
-      link: function(scope, elem, attrs) {
-        var _t = '<i class="grafana-tip fa fa-'+(attrs.icon||'question-circle')+'" bs-tooltip="\''+
-          kbn.addslashes(elem.text())+'\'"></i>';
-        _t = _t.replace(/{/g, '\\{').replace(/}/g, '\\}');
-        elem.replaceWith($compile(angular.element(_t))(scope));
-      }
-    };
-  });
-
-  coreModule.default.directive('clipboardButton', function() {
-    return {
-      scope: {
-        getText: '&clipboardButton'
-      },
-      link: function(scope, elem) {
-        require(['clipboard'], function(Clipboard) {
-          scope.clipboard = new Clipboard(elem[0], {
-            text: function() {
-              return scope.getText();
-            }
-          });
-        });
-
-        scope.$on('$destroy', function() {
-          if (scope.clipboard) {
-            scope.clipboard.destroy();
-          }
-        });
-      }
-    };
-  });
-
-  coreModule.default.directive('compile', function($compile) {
-    return {
-      restrict: 'A',
-      link: function(scope, element, attrs) {
-        scope.$watch(function(scope) {
-          return scope.$eval(attrs.compile);
-        }, function(value) {
-          element.html(value);
-          $compile(element.contents())(scope);
-        });
-      }
-    };
-  });
-
-  coreModule.default.directive('watchChange', function() {
-    return {
-      scope: { onchange: '&watchChange' },
-      link: function(scope, element) {
-        element.on('input', function() {
-          scope.$apply(function () {
-            scope.onchange({ inputValue: element.val() });
-          });
-        });
-      }
-    };
-  });
-
-  coreModule.default.directive('editorOptBool', function($compile) {
-    return {
-      restrict: 'E',
-      link: function(scope, elem, attrs) {
-        var ngchange = attrs.change ? (' ng-change="' + attrs.change + '"') : '';
-        var tip = attrs.tip ? (' <tip>' + attrs.tip + '</tip>') : '';
-        var showIf = attrs.showIf ? (' ng-show="' + attrs.showIf + '" ') : '';
-
-        var template = '<div class="editor-option gf-form-checkbox text-center"' + showIf + '>' +
-          ' <label for="' + attrs.model + '" class="small">' +
-          attrs.text + tip + '</label>' +
-          '<input class="cr1" id="' + attrs.model + '" type="checkbox" ' +
-          '       ng-model="' + attrs.model + '"' + ngchange +
-          '       ng-checked="' + attrs.model + '"></input>' +
-          ' <label for="' + attrs.model + '" class="cr1"></label>';
-        elem.replaceWith($compile(angular.element(template))(scope));
-      }
-    };
-  });
-
-  coreModule.default.directive('editorCheckbox', function($compile, $interpolate) {
-    return {
-      restrict: 'E',
-      link: function(scope, elem, attrs) {
-        var text = $interpolate(attrs.text)(scope);
-        var model = $interpolate(attrs.model)(scope);
-        var ngchange = attrs.change ? (' ng-change="' + attrs.change + '"') : '';
-        var tip = attrs.tip ? (' <tip>' + attrs.tip + '</tip>') : '';
-        var label = '<label for="' + scope.$id + model + '" class="checkbox-label">' +
-          text + tip + '</label>';
-
-        var template =
-        '<input class="cr1" id="' + scope.$id + model + '" type="checkbox" ' +
-        '       ng-model="' + model + '"' + ngchange +
-        '       ng-checked="' + model + '"></input>' +
-        ' <label for="' + scope.$id + model + '" class="cr1"></label>';
-
-        template = template + label;
-        elem.addClass('gf-form-checkbox');
-        elem.html($compile(angular.element(template))(scope));
-      }
-    };
-  });
-
-  coreModule.default.directive('gfDropdown', function ($parse, $compile, $timeout) {
-    function buildTemplate(items, placement) {
-      var upclass = placement === 'top' ? 'dropup' : '';
-      var ul = [
-        '<ul class="dropdown-menu ' + upclass + '" role="menu" aria-labelledby="drop1">',
-        '</ul>'
-      ];
-
-      angular.forEach(items, function (item, index) {
-        if (item.divider) {
-          return ul.splice(index + 1, 0, '<li class="divider"></li>');
-        }
-
-        var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' +
-          '<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? ' ng-click="' + item.click + '"' : '') +
-          (item.target ? ' target="' + item.target + '"' : '') + (item.method ? ' data-method="' + item.method + '"' : '') +
-            '>' + (item.text || '') + '</a>';
-
-        if (item.submenu && item.submenu.length) {
-          li += buildTemplate(item.submenu).join('\n');
-        }
-
-        li += '</li>';
-        ul.splice(index + 1, 0, li);
-      });
-      return ul;
-    }
-
-    return {
-      restrict: 'EA',
-      scope: true,
-      link: function postLink(scope, iElement, iAttrs) {
-        var getter = $parse(iAttrs.gfDropdown), items = getter(scope);
-        $timeout(function () {
-          var placement = iElement.data('placement');
-          var dropdown = angular.element(buildTemplate(items, placement).join(''));
-          dropdown.insertAfter(iElement);
-          $compile(iElement.next('ul.dropdown-menu'))(scope);
-        });
-
-        iElement.addClass('dropdown-toggle').attr('data-toggle', 'dropdown');
-      }
-    };
-  });
-
-});

+ 226 - 0
public/app/core/directives/misc.ts

@@ -0,0 +1,226 @@
+import angular from "angular";
+import Clipboard from "clipboard";
+import coreModule from "../core_module";
+import kbn from "app/core/utils/kbn";
+
+/** @ngInject */
+function tip($compile) {
+  return {
+    restrict: "E",
+    link: function(scope, elem, attrs) {
+      var _t =
+        '<i class="grafana-tip fa fa-' +
+        (attrs.icon || "question-circle") +
+        '" bs-tooltip="\'' +
+        kbn.addslashes(elem.text()) +
+        "'\"></i>";
+      _t = _t.replace(/{/g, "\\{").replace(/}/g, "\\}");
+      elem.replaceWith($compile(angular.element(_t))(scope));
+    }
+  };
+}
+
+function clipboardButton() {
+  return {
+    scope: {
+      getText: "&clipboardButton"
+    },
+    link: function(scope, elem) {
+      scope.clipboard = new Clipboard(elem[0], {
+        text: function() {
+          return scope.getText();
+        }
+      });
+
+      scope.$on("$destroy", function() {
+        if (scope.clipboard) {
+          scope.clipboard.destroy();
+        }
+      });
+    }
+  };
+}
+
+/** @ngInject */
+function compile($compile) {
+  return {
+    restrict: "A",
+    link: function(scope, element, attrs) {
+      scope.$watch(
+        function(scope) {
+          return scope.$eval(attrs.compile);
+        },
+        function(value) {
+          element.html(value);
+          $compile(element.contents())(scope);
+        }
+      );
+    }
+  };
+}
+
+function watchChange() {
+  return {
+    scope: { onchange: "&watchChange" },
+    link: function(scope, element) {
+      element.on("input", function() {
+        scope.$apply(function() {
+          scope.onchange({ inputValue: element.val() });
+        });
+      });
+    }
+  };
+}
+
+/** @ngInject */
+function editorOptBool($compile) {
+  return {
+    restrict: "E",
+    link: function(scope, elem, attrs) {
+      var ngchange = attrs.change ? ' ng-change="' + attrs.change + '"' : "";
+      var tip = attrs.tip ? " <tip>" + attrs.tip + "</tip>" : "";
+      var showIf = attrs.showIf ? ' ng-show="' + attrs.showIf + '" ' : "";
+
+      var template =
+        '<div class="editor-option gf-form-checkbox text-center"' +
+        showIf +
+        ">" +
+        ' <label for="' +
+        attrs.model +
+        '" class="small">' +
+        attrs.text +
+        tip +
+        "</label>" +
+        '<input class="cr1" id="' +
+        attrs.model +
+        '" type="checkbox" ' +
+        '       ng-model="' +
+        attrs.model +
+        '"' +
+        ngchange +
+        '       ng-checked="' +
+        attrs.model +
+        '"></input>' +
+        ' <label for="' +
+        attrs.model +
+        '" class="cr1"></label>';
+      elem.replaceWith($compile(angular.element(template))(scope));
+    }
+  };
+}
+
+/** @ngInject */
+function editorCheckbox($compile, $interpolate) {
+  return {
+    restrict: "E",
+    link: function(scope, elem, attrs) {
+      var text = $interpolate(attrs.text)(scope);
+      var model = $interpolate(attrs.model)(scope);
+      var ngchange = attrs.change ? ' ng-change="' + attrs.change + '"' : "";
+      var tip = attrs.tip ? " <tip>" + attrs.tip + "</tip>" : "";
+      var label =
+        '<label for="' +
+        scope.$id +
+        model +
+        '" class="checkbox-label">' +
+        text +
+        tip +
+        "</label>";
+
+      var template =
+        '<input class="cr1" id="' +
+        scope.$id +
+        model +
+        '" type="checkbox" ' +
+        '       ng-model="' +
+        model +
+        '"' +
+        ngchange +
+        '       ng-checked="' +
+        model +
+        '"></input>' +
+        ' <label for="' +
+        scope.$id +
+        model +
+        '" class="cr1"></label>';
+
+      template = template + label;
+      elem.addClass("gf-form-checkbox");
+      elem.html($compile(angular.element(template))(scope));
+    }
+  };
+}
+
+/** @ngInject */
+function gfDropdown($parse, $compile, $timeout) {
+  function buildTemplate(items, placement?) {
+    var upclass = placement === "top" ? "dropup" : "";
+    var ul = [
+      '<ul class="dropdown-menu ' +
+        upclass +
+        '" role="menu" aria-labelledby="drop1">',
+      "</ul>"
+    ];
+
+    for (let index = 0; index < items.length; index++) {
+      let item = items[index];
+
+      if (item.divider) {
+        ul.splice(index + 1, 0, '<li class="divider"></li>');
+        continue;
+      }
+
+      var li =
+        "<li" +
+        (item.submenu && item.submenu.length
+          ? ' class="dropdown-submenu"'
+          : "") +
+        ">" +
+        '<a tabindex="-1" ng-href="' +
+        (item.href || "") +
+        '"' +
+        (item.click ? ' ng-click="' + item.click + '"' : "") +
+        (item.target ? ' target="' + item.target + '"' : "") +
+        (item.method ? ' data-method="' + item.method + '"' : "") +
+        ">" +
+        (item.text || "") +
+        "</a>";
+
+      if (item.submenu && item.submenu.length) {
+        li += buildTemplate(item.submenu).join("\n");
+      }
+
+      li += "</li>";
+      ul.splice(index + 1, 0, li);
+    }
+
+    return ul;
+  }
+
+  return {
+    restrict: "EA",
+    scope: true,
+    link: function postLink(scope, iElement, iAttrs) {
+      var getter = $parse(iAttrs.gfDropdown),
+        items = getter(scope);
+      $timeout(function() {
+        var placement = iElement.data("placement");
+        var dropdown = angular.element(
+          buildTemplate(items, placement).join("")
+        );
+        dropdown.insertAfter(iElement);
+        $compile(iElement.next("ul.dropdown-menu"))(scope);
+      });
+
+      iElement.addClass("dropdown-toggle").attr("data-toggle", "dropdown");
+    }
+  };
+}
+
+coreModule.directive("tip", tip);
+coreModule.directive("clipboardButton", clipboardButton);
+coreModule.directive("compile", compile);
+coreModule.directive("watchChange", watchChange);
+coreModule.directive("editorOptBool", editorOptBool);
+coreModule.directive("editorCheckbox", editorCheckbox);
+coreModule.directive("gfDropdown", gfDropdown);

+ 46 - 53
public/app/core/directives/ng_model_on_blur.ts

@@ -1,64 +1,57 @@
 import coreModule from '../core_module';
 import * as rangeUtil from 'app/core/utils/rangeutil';
 
-export class NgModelOnBlur {
-  constructor() {
-    return {
-      restrict: 'A',
-      priority: 1,
-      require: 'ngModel',
-      link: function(scope, elm, attr, ngModelCtrl) {
-        if (attr.type === 'radio' || attr.type === 'checkbox') {
-          return;
-        }
+function ngModelOnBlur() {
+  return {
+    restrict: 'A',
+    priority: 1,
+    require: 'ngModel',
+    link: function(scope, elm, attr, ngModelCtrl) {
+      if (attr.type === 'radio' || attr.type === 'checkbox') {
+        return;
+      }
 
-        elm.off('input keydown change');
-        elm.bind('blur', function() {
-          scope.$apply(function() {
-            ngModelCtrl.$setViewValue(elm.val());
-          });
+      elm.off('input keydown change');
+      elm.bind('blur', function() {
+        scope.$apply(function() {
+          ngModelCtrl.$setViewValue(elm.val());
         });
-      }
-    };
-  }
+      });
+    }
+  };
 }
 
-
-export class EmptyToNull {
-  constructor() {
-    return {
-      restrict: 'A',
-      require: 'ngModel',
-      link: function (scope, elm, attrs, ctrl) {
-        ctrl.$parsers.push(function (viewValue) {
-          if (viewValue === "") { return null; }
-          return viewValue;
-        });
-      }
-    };
-  }
+function emptyToNull() {
+  return {
+    restrict: 'A',
+    require: 'ngModel',
+    link: function (scope, elm, attrs, ctrl) {
+      ctrl.$parsers.push(function (viewValue) {
+        if (viewValue === "") { return null; }
+        return viewValue;
+      });
+    }
+  };
 }
 
-export class ValidTimeSpan {
-  constructor() {
-    return {
-      require: 'ngModel',
-      link: function(scope, elm, attrs, ctrl) {
-        ctrl.$validators.integer = function(modelValue, viewValue) {
-          if (ctrl.$isEmpty(modelValue)) {
-            return true;
-          }
-          if (viewValue.indexOf('$') === 0 || viewValue.indexOf('+$') === 0) {
-            return true; // allow template variable
-          }
-          var info = rangeUtil.describeTextRange(viewValue);
-          return info.invalid !== true;
-        };
-      }
-    };
-  }
+function validTimeSpan() {
+  return {
+    require: 'ngModel',
+    link: function(scope, elm, attrs, ctrl) {
+      ctrl.$validators.integer = function(modelValue, viewValue) {
+        if (ctrl.$isEmpty(modelValue)) {
+          return true;
+        }
+        if (viewValue.indexOf('$') === 0 || viewValue.indexOf('+$') === 0) {
+          return true; // allow template variable
+        }
+        var info = rangeUtil.describeTextRange(viewValue);
+        return info.invalid !== true;
+      };
+    }
+  };
 }
 
-coreModule.directive('ngModelOnblur', NgModelOnBlur);
-coreModule.directive('emptyToNull', EmptyToNull);
-coreModule.directive('validTimeSpan', ValidTimeSpan);
+coreModule.directive('ngModelOnblur', ngModelOnBlur);
+coreModule.directive('emptyToNull', emptyToNull);
+coreModule.directive('validTimeSpan', validTimeSpan);

+ 0 - 135
public/app/core/directives/tags.js

@@ -1,135 +0,0 @@
-define([
-  'angular',
-  'jquery',
-  '../core_module',
-  'vendor/tagsinput/bootstrap-tagsinput.js',
-],
-function (angular, $, coreModule) {
-  'use strict';
-
-  function djb2(str) {
-    var hash = 5381;
-    for (var i = 0; i < str.length; i++) {
-      hash = ((hash << 5) + hash) + str.charCodeAt(i); /* hash * 33 + c */
-    }
-    return hash;
-  }
-
-  function setColor(name, element) {
-    var hash = djb2(name.toLowerCase());
-    var colors = [
-      "#E24D42","#1F78C1","#BA43A9","#705DA0","#466803",
-      "#508642","#447EBC","#C15C17","#890F02","#757575",
-      "#0A437C","#6D1F62","#584477","#629E51","#2F4F4F",
-      "#BF1B00","#806EB7","#8a2eb8", "#699e00","#000000",
-      "#3F6833","#2F575E","#99440A","#E0752D","#0E4AB4",
-      "#58140C","#052B51","#511749","#3F2B5B",
-    ];
-    var borderColors = [
-      "#FF7368","#459EE7","#E069CF","#9683C6","#6C8E29",
-      "#76AC68","#6AA4E2","#E7823D","#AF3528","#9B9B9B",
-      "#3069A2","#934588","#7E6A9D","#88C477","#557575",
-      "#E54126","#A694DD","#B054DE", "#8FC426","#262626",
-      "#658E59","#557D84","#BF6A30","#FF9B53","#3470DA",
-      "#7E3A32","#2B5177","#773D6F","#655181",
-    ];
-    var color = colors[Math.abs(hash % colors.length)];
-    var borderColor = borderColors[Math.abs(hash % borderColors.length)];
-    element.css("background-color", color);
-    element.css("border-color", borderColor);
-  }
-
-  coreModule.default.directive('tagColorFromName', function() {
-    return {
-      scope: { tagColorFromName: "=" },
-      link: function (scope, element) {
-        setColor(scope.tagColorFromName, element);
-      }
-    };
-  });
-
-  coreModule.default.directive('bootstrapTagsinput', function() {
-
-    function getItemProperty(scope, property) {
-      if (!property) {
-        return undefined;
-      }
-
-      if (angular.isFunction(scope.$parent[property])) {
-        return scope.$parent[property];
-      }
-
-      return function(item) {
-        return item[property];
-      };
-    }
-
-    return {
-      restrict: 'EA',
-      scope: {
-        model: '=ngModel',
-        onTagsUpdated: "&",
-      },
-      template: '<select multiple></select>',
-      replace: false,
-      link: function(scope, element, attrs) {
-
-        if (!angular.isArray(scope.model)) {
-          scope.model = [];
-        }
-
-        var select = $('select', element);
-
-        if (attrs.placeholder) {
-          select.attr('placeholder', attrs.placeholder);
-        }
-
-        select.tagsinput({
-          typeahead: {
-            source: angular.isFunction(scope.$parent[attrs.typeaheadSource]) ? scope.$parent[attrs.typeaheadSource] : null
-          },
-          widthClass: attrs.widthClass,
-          itemValue: getItemProperty(scope, attrs.itemvalue),
-          itemText : getItemProperty(scope, attrs.itemtext),
-          tagClass : angular.isFunction(scope.$parent[attrs.tagclass]) ?
-            scope.$parent[attrs.tagclass] : function() { return attrs.tagclass; }
-        });
-
-        select.on('itemAdded', function(event) {
-          if (scope.model.indexOf(event.item) === -1) {
-            scope.model.push(event.item);
-            if (scope.onTagsUpdated) {
-              scope.onTagsUpdated();
-            }
-          }
-          var tagElement = select.next().children("span").filter(function() { return $(this).text() === event.item; });
-          setColor(event.item, tagElement);
-        });
-
-        select.on('itemRemoved', function(event) {
-          var idx = scope.model.indexOf(event.item);
-          if (idx !== -1) {
-            scope.model.splice(idx, 1);
-            if (scope.onTagsUpdated) {
-              scope.onTagsUpdated();
-            }
-          }
-        });
-
-        scope.$watch("model", function() {
-          if (!angular.isArray(scope.model)) {
-            scope.model = [];
-          }
-
-          select.tagsinput('removeAll');
-
-          for (var i = 0; i < scope.model.length; i++) {
-            select.tagsinput('add', scope.model[i]);
-          }
-
-        }, true);
-      }
-    };
-  });
-
-});

+ 131 - 0
public/app/core/directives/tags.ts

@@ -0,0 +1,131 @@
+import angular from 'angular';
+import $ from 'jquery';
+import coreModule from '../core_module';
+import 'vendor/tagsinput/bootstrap-tagsinput.js';
+
+function djb2(str) {
+  var hash = 5381;
+  for (var i = 0; i < str.length; i++) {
+    hash = ((hash << 5) + hash) + str.charCodeAt(i); /* hash * 33 + c */
+  }
+  return hash;
+}
+
+function setColor(name, element) {
+  var hash = djb2(name.toLowerCase());
+  var colors = [
+    "#E24D42","#1F78C1","#BA43A9","#705DA0","#466803",
+    "#508642","#447EBC","#C15C17","#890F02","#757575",
+    "#0A437C","#6D1F62","#584477","#629E51","#2F4F4F",
+    "#BF1B00","#806EB7","#8a2eb8", "#699e00","#000000",
+    "#3F6833","#2F575E","#99440A","#E0752D","#0E4AB4",
+    "#58140C","#052B51","#511749","#3F2B5B",
+  ];
+  var borderColors = [
+    "#FF7368","#459EE7","#E069CF","#9683C6","#6C8E29",
+    "#76AC68","#6AA4E2","#E7823D","#AF3528","#9B9B9B",
+    "#3069A2","#934588","#7E6A9D","#88C477","#557575",
+    "#E54126","#A694DD","#B054DE", "#8FC426","#262626",
+    "#658E59","#557D84","#BF6A30","#FF9B53","#3470DA",
+    "#7E3A32","#2B5177","#773D6F","#655181",
+  ];
+  var color = colors[Math.abs(hash % colors.length)];
+  var borderColor = borderColors[Math.abs(hash % borderColors.length)];
+  element.css("background-color", color);
+  element.css("border-color", borderColor);
+}
+
+function tagColorFromName() {
+  return {
+    scope: { tagColorFromName: "=" },
+    link: function (scope, element) {
+      setColor(scope.tagColorFromName, element);
+    }
+  };
+}
+
+function bootstrapTagsinput() {
+  function getItemProperty(scope, property) {
+    if (!property) {
+      return undefined;
+    }
+
+    if (angular.isFunction(scope.$parent[property])) {
+      return scope.$parent[property];
+    }
+
+    return function(item) {
+      return item[property];
+    };
+  }
+
+  return {
+    restrict: 'EA',
+    scope: {
+      model: '=ngModel',
+      onTagsUpdated: "&",
+    },
+    template: '<select multiple></select>',
+    replace: false,
+    link: function(scope, element, attrs) {
+
+      if (!angular.isArray(scope.model)) {
+        scope.model = [];
+      }
+
+      var select = $('select', element);
+
+      if (attrs.placeholder) {
+        select.attr('placeholder', attrs.placeholder);
+      }
+
+      select.tagsinput({
+        typeahead: {
+          source: angular.isFunction(scope.$parent[attrs.typeaheadSource]) ? scope.$parent[attrs.typeaheadSource] : null
+        },
+        widthClass: attrs.widthClass,
+        itemValue: getItemProperty(scope, attrs.itemvalue),
+        itemText : getItemProperty(scope, attrs.itemtext),
+        tagClass : angular.isFunction(scope.$parent[attrs.tagclass]) ?
+          scope.$parent[attrs.tagclass] : function() { return attrs.tagclass; }
+      });
+
+      select.on('itemAdded', function(event) {
+        if (scope.model.indexOf(event.item) === -1) {
+          scope.model.push(event.item);
+          if (scope.onTagsUpdated) {
+            scope.onTagsUpdated();
+          }
+        }
+        var tagElement = select.next().children("span").filter(function() { return $(this).text() === event.item; });
+        setColor(event.item, tagElement);
+      });
+
+      select.on('itemRemoved', function(event) {
+        var idx = scope.model.indexOf(event.item);
+        if (idx !== -1) {
+          scope.model.splice(idx, 1);
+          if (scope.onTagsUpdated) {
+            scope.onTagsUpdated();
+          }
+        }
+      });
+
+      scope.$watch("model", function() {
+        if (!angular.isArray(scope.model)) {
+          scope.model = [];
+        }
+
+        select.tagsinput('removeAll');
+
+        for (var i = 0; i < scope.model.length; i++) {
+          select.tagsinput('add', scope.model[i]);
+        }
+
+      }, true);
+    }
+  };
+}
+
+coreModule.directive('tagColorFromName', tagColorFromName);
+coreModule.directive('bootstrapTagsinput', bootstrapTagsinput);

+ 89 - 85
public/app/features/dashlinks/module.js → public/app/features/dashlinks/module.ts

@@ -1,92 +1,89 @@
-define([
-  'angular',
-  'lodash',
-],
-function (angular, _) {
-  'use strict';
-
-  var module = angular.module('grafana.directives');
-
-  var iconMap = {
-    "external link": "fa-external-link",
-    "dashboard": "fa-th-large",
-    "question": "fa-question",
-    "info": "fa-info",
-    "bolt": "fa-bolt",
-    "doc": "fa-file-text-o",
-    "cloud": "fa-cloud",
+import angular from 'angular';
+import _ from 'lodash';
+
+var iconMap = {
+  "external link": "fa-external-link",
+  "dashboard": "fa-th-large",
+  "question": "fa-question",
+  "info": "fa-info",
+  "bolt": "fa-bolt",
+  "doc": "fa-file-text-o",
+  "cloud": "fa-cloud",
+};
+
+function dashLinksEditor() {
+  return {
+    restrict: 'E',
+    controller: 'DashLinkEditorCtrl',
+    templateUrl: 'public/app/features/dashlinks/editor.html',
+    link: function() {
+    }
   };
-
-  module.directive('dashLinksEditor', function() {
-    return {
-      restrict: 'E',
-      controller: 'DashLinkEditorCtrl',
-      templateUrl: 'public/app/features/dashlinks/editor.html',
-      link: function() {
+}
+
+function dashLinksContainer() {
+  return {
+    scope: {
+      links: "="
+    },
+    restrict: 'E',
+    controller: 'DashLinksContainerCtrl',
+    template: '<dash-link ng-repeat="link in generatedLinks" link="link"></dash-link>',
+    link: function() { }
+  };
+}
+
+/** @ngInject */
+function dashLink($compile, linkSrv) {
+  return {
+    restrict: 'E',
+    link: function(scope, elem) {
+      var link = scope.link;
+      var template = '<div class="gf-form">' +
+        '<a class="pointer gf-form-label" data-placement="bottom"' +
+        (link.asDropdown ? ' ng-click="fillDropdown(link)" data-toggle="dropdown"'  : "") + '>' +
+        '<i></i> <span></span></a>';
+
+      if (link.asDropdown) {
+        template += '<ul class="dropdown-menu" role="menu">' +
+          '<li ng-repeat="dash in link.searchHits"><a href="{{dash.url}}">{{dash.title}}</a></li>' +
+          '</ul>';
       }
-    };
-  });
-
-  module.directive('dashLinksContainer', function() {
-    return {
-      scope: {
-        links: "="
-      },
-      restrict: 'E',
-      controller: 'DashLinksContainerCtrl',
-      template: '<dash-link ng-repeat="link in generatedLinks" link="link"></dash-link>',
-      link: function() { }
-    };
-  });
-
-  module.directive('dashLink', function($compile, linkSrv) {
-    return {
-      restrict: 'E',
-      link: function(scope, elem) {
-        var link = scope.link;
-        var template = '<div class="gf-form">' +
-          '<a class="pointer gf-form-label" data-placement="bottom"' +
-          (link.asDropdown ? ' ng-click="fillDropdown(link)" data-toggle="dropdown"'  : "") + '>' +
-          '<i></i> <span></span></a>';
-
-        if (link.asDropdown) {
-          template += '<ul class="dropdown-menu" role="menu">' +
-            '<li ng-repeat="dash in link.searchHits"><a href="{{dash.url}}">{{dash.title}}</a></li>' +
-            '</ul>';
-        }
 
-        template += '</div>';
+      template += '</div>';
 
-        elem.html(template);
-        $compile(elem.contents())(scope);
+      elem.html(template);
+      $compile(elem.contents())(scope);
 
-        var anchor = elem.find('a');
-        var icon = elem.find('i');
-        var span = elem.find('span');
-
-        function update() {
-          var linkInfo = linkSrv.getAnchorInfo(link);
-          span.text(linkInfo.title);
-          anchor.attr("href", linkInfo.href);
-        }
+      var anchor = elem.find('a');
+      var icon = elem.find('i');
+      var span = elem.find('span');
 
-        // tooltip
-        elem.find('a').tooltip({ title: scope.link.tooltip, html: true, container: 'body' });
-        icon.attr('class', 'fa fa-fw ' + scope.link.icon);
-        anchor.attr('target', scope.link.target);
+      function update() {
+        var linkInfo = linkSrv.getAnchorInfo(link);
+        span.text(linkInfo.title);
+        anchor.attr("href", linkInfo.href);
+      }
 
-        // fix for menus on the far right
-        if (link.asDropdown && scope.$last) {
-          elem.find('.dropdown-menu').addClass('pull-right');
-        }
+      // tooltip
+      elem.find('a').tooltip({ title: scope.link.tooltip, html: true, container: 'body' });
+      icon.attr('class', 'fa fa-fw ' + scope.link.icon);
+      anchor.attr('target', scope.link.target);
 
-        update();
-        scope.$on('refresh', update);
+      // fix for menus on the far right
+      if (link.asDropdown && scope.$last) {
+        elem.find('.dropdown-menu').addClass('pull-right');
       }
-    };
-  });
 
-  module.controller("DashLinksContainerCtrl", function($scope, $rootScope, $q, backendSrv, dashboardSrv, linkSrv) {
+      update();
+      scope.$on('refresh', update);
+    }
+  };
+}
+
+export class DashLinksContainerCtrl {
+  /** @ngInject */
+  constructor($scope, $rootScope, $q, backendSrv, dashboardSrv, linkSrv) {
     var currentDashId = dashboardSrv.getCurrent().id;
 
     function buildLinks(linkDef) {
@@ -162,10 +159,12 @@ function (angular, _) {
 
     updateDashLinks();
     $rootScope.onAppEvent('dash-links-updated', updateDashLinks, $scope);
-  });
-
-  module.controller('DashLinkEditorCtrl', function($scope, $rootScope) {
+  }
+}
 
+export class DashLinkEditorCtrl {
+  /** @ngInject */
+  constructor($scope, $rootScope) {
     $scope.iconMap = iconMap;
     $scope.dashboard.links = $scope.dashboard.links || [];
 
@@ -189,6 +188,11 @@ function (angular, _) {
       $scope.dashboard.updateSubmenuVisibility();
       $scope.updated();
     };
-
-  });
-});
+  }
+}
+
+angular.module('grafana.directives').directive('dashLinksEditor', dashLinksEditor);
+angular.module('grafana.directives').directive('dashLinksContainer', dashLinksContainer);
+angular.module('grafana.directives').directive('dashLink', dashLink);
+angular.module('grafana.directives').controller("DashLinksContainerCtrl", DashLinksContainerCtrl);
+angular.module('grafana.directives').controller('DashLinkEditorCtrl', DashLinkEditorCtrl);

+ 0 - 56
public/app/features/panellinks/module.js

@@ -1,56 +0,0 @@
-define([
-  'angular',
-  'lodash',
-  './link_srv',
-],
-function (angular, _) {
-  'use strict';
-
-  angular
-    .module('grafana.directives')
-    .directive('panelLinksEditor', function() {
-      return {
-        scope: {
-          panel: "="
-        },
-        restrict: 'E',
-        controller: 'PanelLinksEditorCtrl',
-        templateUrl: 'public/app/features/panellinks/module.html',
-        link: function() {
-        }
-      };
-    }).controller('PanelLinksEditorCtrl', function($scope, backendSrv) {
-
-      $scope.panel.links = $scope.panel.links || [];
-
-      $scope.addLink = function() {
-        $scope.panel.links.push({
-          type: 'dashboard',
-        });
-      };
-
-      $scope.searchDashboards = function(queryStr, callback) {
-        backendSrv.search({query: queryStr}).then(function(hits) {
-          var dashboards = _.map(hits, function(dash) {
-            return dash.title;
-          });
-
-          callback(dashboards);
-        });
-      };
-
-      $scope.dashboardChanged = function(link) {
-        backendSrv.search({query: link.dashboard}).then(function(hits) {
-          var dashboard = _.find(hits, {title: link.dashboard});
-          if (dashboard) {
-            link.dashUri = dashboard.uri;
-            link.title = dashboard.title;
-          }
-        });
-      };
-
-      $scope.deleteLink = function(link) {
-        $scope.panel.links = _.without($scope.panel.links, link);
-      };
-    });
-});

+ 57 - 0
public/app/features/panellinks/module.ts

@@ -0,0 +1,57 @@
+import angular from 'angular';
+import _ from 'lodash';
+import './link_srv';
+
+function panelLinksEditor() {
+  return {
+    scope: {
+      panel: "="
+    },
+    restrict: 'E',
+    controller: 'PanelLinksEditorCtrl',
+    templateUrl: 'public/app/features/panellinks/module.html',
+    link: function() {
+    }
+  };
+}
+
+export class PanelLinksEditorCtrl {
+  /** @ngInject */
+  constructor($scope, backendSrv) {
+    $scope.panel.links = $scope.panel.links || [];
+
+    $scope.addLink = function() {
+      $scope.panel.links.push({
+        type: 'dashboard',
+      });
+    };
+
+    $scope.searchDashboards = function(queryStr, callback) {
+      backendSrv.search({query: queryStr}).then(function(hits) {
+        var dashboards = _.map(hits, function(dash) {
+          return dash.title;
+        });
+
+        callback(dashboards);
+      });
+    };
+
+    $scope.dashboardChanged = function(link) {
+      backendSrv.search({query: link.dashboard}).then(function(hits) {
+        var dashboard = _.find(hits, {title: link.dashboard});
+        if (dashboard) {
+          link.dashUri = dashboard.uri;
+          link.title = dashboard.title;
+        }
+      });
+    };
+
+    $scope.deleteLink = function(link) {
+      $scope.panel.links = _.without($scope.panel.links, link);
+    };
+  }
+}
+
+angular.module('grafana.directives').directive('panelLinksEditor', panelLinksEditor)
+.controller('PanelLinksEditorCtrl', PanelLinksEditorCtrl);
+

+ 1 - 1
tslint.json

@@ -17,7 +17,7 @@
     "max-line-length": [true, 140],
     "member-access": false,
     "no-arg": true,
-    "no-bitwise": true,
+    "no-bitwise": false,
     "no-console": [true,
       "debug",
       "info",