Przeglądaj źródła

feat() started work on more feature rich time picker

Torkel Ödegaard 10 lat temu
rodzic
commit
4ffa26cf2c
74 zmienionych plików z 494 dodań i 318 usunięć
  1. 0 1
      .gitignore
  2. 5 3
      karma.conf.js
  3. 5 5
      public/app/app.js
  4. 0 3
      public/app/components/extend-jquery.js
  5. 43 44
      public/app/components/require.config.js
  6. 4 4
      public/app/components/settings.js
  7. 1 1
      public/app/core/routes/all.js
  8. 109 0
      public/app/core/utils/datemath.ts
  9. 1 2
      public/app/features/dashboard/graphiteImportCtrl.js
  10. 1 2
      public/app/features/dashboard/rowCtrl.js
  11. 3 3
      public/app/features/dashboard/timepicker/timepicker.html
  12. 3 10
      public/app/features/dashboard/timepicker/timepicker.ts
  13. 60 0
      public/app/features/dashboard/timepicker/timerange.ts
  14. 2 2
      public/app/panels/dashlist/module.js
  15. 2 2
      public/app/panels/graph/module.js
  16. 1 1
      public/app/panels/graph/seriesOverridesCtrl.js
  17. 4 4
      public/app/panels/singlestat/module.js
  18. 1 1
      public/app/panels/singlestat/singleStatPanel.js
  19. 2 2
      public/app/panels/text/module.js
  20. 1 1
      public/app/plugins/datasource/cloudwatch/_plugin.json
  21. 1 1
      public/app/plugins/datasource/elasticsearch/plugin.json
  22. 1 1
      public/app/plugins/datasource/grafana/plugin.json
  23. 1 1
      public/app/plugins/datasource/graphite/plugin.json
  24. 1 1
      public/app/plugins/datasource/influxdb/plugin.json
  25. 1 1
      public/app/plugins/datasource/influxdb_08/plugin.json
  26. 1 1
      public/app/plugins/datasource/kairosdb/plugin.json
  27. 1 1
      public/app/plugins/datasource/mixed/plugin.json
  28. 1 1
      public/app/plugins/datasource/opentsdb/plugin.json
  29. 1 1
      public/app/plugins/datasource/sql/plugin.json_
  30. 3 2
      public/test/specs/cloudwatch-datasource-specs.js
  31. 16 0
      public/test/specs/core/utils/datemath_specs.ts
  32. 1 1
      public/test/specs/dashboardSrv-specs.js
  33. 1 1
      public/test/specs/dashboardViewStateSrv-specs.js
  34. 2 2
      public/test/specs/dynamicDashboardSrv-specs.js
  35. 1 1
      public/test/specs/elasticsearch-indexPattern-specs.js
  36. 1 1
      public/test/specs/elasticsearch-querybuilder-specs.js
  37. 3 3
      public/test/specs/elasticsearch-queryctrl-specs.js
  38. 1 1
      public/test/specs/elasticsearch-response-specs.js
  39. 2 2
      public/test/specs/elasticsearch-specs.js
  40. 1 1
      public/test/specs/gfunc-specs.js
  41. 4 4
      public/test/specs/graph-ctrl-specs.js
  42. 3 3
      public/test/specs/graph-specs.js
  43. 1 1
      public/test/specs/graph-tooltip-specs.js
  44. 2 2
      public/test/specs/graphiteDatasource-specs.js
  45. 4 4
      public/test/specs/graphiteTargetCtrl-specs.js
  46. 1 1
      public/test/specs/influx09-querybuilder-specs.js
  47. 1 1
      public/test/specs/influxQueryBuilder-specs.js
  48. 1 1
      public/test/specs/influxSeries-specs.js
  49. 1 1
      public/test/specs/influxSeries08-specs.js
  50. 4 4
      public/test/specs/influxdb-datasource-specs.js
  51. 3 3
      public/test/specs/influxdbQueryCtrl-specs.js
  52. 2 2
      public/test/specs/kairosdb-datasource-specs.js
  53. 1 1
      public/test/specs/lexer-specs.js
  54. 2 2
      public/test/specs/opentsdbDatasource-specs.js
  55. 0 30
      public/test/specs/overview-ctrl-specs.js
  56. 2 2
      public/test/specs/panelSrv-specs.js
  57. 1 1
      public/test/specs/parser-specs.js
  58. 2 2
      public/test/specs/row-ctrl-specs.js
  59. 2 2
      public/test/specs/seriesOverridesCtrl-specs.js
  60. 3 3
      public/test/specs/shareModalCtrl-specs.js
  61. 4 4
      public/test/specs/singlestat-specs.js
  62. 2 2
      public/test/specs/templateSrv-specs.js
  63. 3 3
      public/test/specs/templateValuesSrv-specs.js
  64. 1 1
      public/test/specs/timeSeries-specs.js
  65. 4 4
      public/test/specs/timeSrv-specs.js
  66. 2 2
      public/test/specs/unsavedChangesSrv-specs.js
  67. 1 1
      public/test/specs/value_select_dropdown_specs.js
  68. 111 99
      public/test/test-main.js
  69. 0 6
      public/vendor/angular-ui/angular-bootstrap.js
  70. 1 1
      public/views/index.html
  71. 6 4
      tasks/options/karma.js
  72. 7 5
      tasks/options/typescript.js
  73. 1 1
      tasks/options/watch.js
  74. 22 0
      tsconfig.json

+ 0 - 1
.gitignore

@@ -30,4 +30,3 @@ conf/custom.ini
 fig.yml
 profile.cov
 grafana
-tsconfig.json

+ 5 - 3
public/test/karma.conf.js → karma.conf.js

@@ -2,14 +2,16 @@ module.exports = function(config) {
   'use strict';
 
   config.set({
-    basePath: '../../',
+    basePath: __dirname + '/public_gen',
 
     frameworks: ['mocha', 'requirejs', 'expect', 'sinon'],
 
     // list of files / patterns to load in the browser
     files: [
-      'public/test/test-main.js',
-      {pattern: 'public_gen/**/*.js', included: false}
+      'test/test-main.js',
+      {pattern: 'app/**/*.js', included: false},
+      {pattern: 'vendor/**/*.js', included: false},
+      {pattern: 'test/**/*.js', included: false}
     ],
 
     // list of files to exclude

+ 5 - 5
public/app/app.js

@@ -12,7 +12,7 @@ define([
   'angular-ui',
   'extend-jquery',
   'bindonce',
-  './core/core',
+  'app/core/core',
 ],
 function (angular, $, _, appLevelRequire) {
   "use strict";
@@ -70,10 +70,10 @@ function (angular, $, _, appLevelRequire) {
   });
 
   var preBootRequires = [
-    'services/all',
-    'features/all',
-    'controllers/all',
-    'components/partials',
+    'app/services/all',
+    'app/features/all',
+    'app/controllers/all',
+    'app/components/partials',
   ];
 
   app.boot = function() {

+ 0 - 3
public/app/components/extend-jquery.js

@@ -2,9 +2,6 @@ define(['jquery', 'angular', 'lodash'],
 function ($, angular, _) {
   'use strict';
 
-  /**
-   * jQuery extensions
-   */
   var $win = $(window);
 
   $.fn.place_tt = (function () {

+ 43 - 44
public/app/components/require.config.js

@@ -1,51 +1,50 @@
 require.config({
   urlArgs: 'bust=' + (new Date().getTime()),
-  baseUrl: 'public/app',
+  baseUrl: 'public',
 
   paths: {
-    config:                   'components/config',
-    settings:                 'components/settings',
-    kbn:                      'components/kbn',
-    store:                    'components/store',
-
-    text:                     '../vendor/requirejs-text/text',
-    moment:                   '../vendor/moment',
-    filesaver:                '../vendor/filesaver',
-    ZeroClipboard:            '../vendor/ZeroClipboard',
-    angular:                  '../vendor/angular/angular',
-    'angular-route':          '../vendor/angular-route/angular-route',
-    'angular-sanitize':       '../vendor/angular-sanitize/angular-sanitize',
-    'angular-dragdrop':       '../vendor/angular-native-dragdrop/draganddrop',
-    'angular-strap':          '../vendor/angular-other/angular-strap',
-    'angular-ui':             '../vendor/angular-ui/angular-bootstrap',
-    timepicker:               '../vendor/angular-other/timepicker',
-    datepicker:               '../vendor/angular-other/datepicker',
-    bindonce:                 '../vendor/angular-bindonce/bindonce',
-    crypto:                   '../vendor/crypto.min',
-    spectrum:                 '../vendor/spectrum',
-
-    lodash:                   'components/lodash.extended',
-    'lodash-src':             '../vendor/lodash',
-    bootstrap:                '../vendor/bootstrap/bootstrap',
-
-    jquery:                   '../vendor/jquery/dist/jquery',
-
-    'extend-jquery':          'components/extend-jquery',
-
-    'jquery.flot':             '../vendor/flot/jquery.flot',
-    'jquery.flot.pie':         '../vendor/flot/jquery.flot.pie',
-    'jquery.flot.events':      '../vendor/flot/jquery.flot.events',
-    'jquery.flot.selection':   '../vendor/flot/jquery.flot.selection',
-    'jquery.flot.stack':       '../vendor/flot/jquery.flot.stack',
-    'jquery.flot.stackpercent':'../vendor/flot/jquery.flot.stackpercent',
-    'jquery.flot.time':        '../vendor/flot/jquery.flot.time',
-    'jquery.flot.crosshair':   '../vendor/flot/jquery.flot.crosshair',
-    'jquery.flot.fillbelow':   '../vendor/flot/jquery.flot.fillbelow',
-
-    modernizr:                '../vendor/modernizr-2.6.1',
-
-    'bootstrap-tagsinput':    '../vendor/tagsinput/bootstrap-tagsinput',
-    'aws-sdk':                '../vendor/aws-sdk/dist/aws-sdk.min',
+    config:                   'app/components/config',
+    settings:                 'app/components/settings',
+    kbn:                      'app/components/kbn',
+    store:                    'app/components/store',
+    'extend-jquery':          'app/components/extend-jquery',
+    lodash:                   'app/components/lodash.extended',
+
+    text:                     'vendor/requirejs-text/text',
+    moment:                   'vendor/moment',
+    filesaver:                'vendor/filesaver',
+    ZeroClipboard:            'vendor/ZeroClipboard',
+    angular:                  'vendor/angular/angular',
+    'angular-route':          'vendor/angular-route/angular-route',
+    'angular-sanitize':       'vendor/angular-sanitize/angular-sanitize',
+    'angular-dragdrop':       'vendor/angular-native-dragdrop/draganddrop',
+    'angular-strap':          'vendor/angular-other/angular-strap',
+    'angular-ui':             'vendor/angular-ui/tabs',
+    timepicker:               'vendor/angular-other/timepicker',
+    datepicker:               'vendor/angular-other/datepicker',
+    bindonce:                 'vendor/angular-bindonce/bindonce',
+    crypto:                   'vendor/crypto.min',
+    spectrum:                 'vendor/spectrum',
+
+    'lodash-src':             'vendor/lodash',
+    bootstrap:                'vendor/bootstrap/bootstrap',
+
+    jquery:                   'vendor/jquery/dist/jquery',
+
+    'jquery.flot':             'vendor/flot/jquery.flot',
+    'jquery.flot.pie':         'vendor/flot/jquery.flot.pie',
+    'jquery.flot.events':      'vendor/flot/jquery.flot.events',
+    'jquery.flot.selection':   'vendor/flot/jquery.flot.selection',
+    'jquery.flot.stack':       'vendor/flot/jquery.flot.stack',
+    'jquery.flot.stackpercent':'vendor/flot/jquery.flot.stackpercent',
+    'jquery.flot.time':        'vendor/flot/jquery.flot.time',
+    'jquery.flot.crosshair':   'vendor/flot/jquery.flot.crosshair',
+    'jquery.flot.fillbelow':   'vendor/flot/jquery.flot.fillbelow',
+
+    modernizr:                 'vendor/modernizr-2.6.1',
+
+    'bootstrap-tagsinput':    'vendor/tagsinput/bootstrap-tagsinput',
+    'aws-sdk':                'vendor/aws-sdk/dist/aws-sdk.min',
   },
   shim: {
 

+ 4 - 4
public/app/components/settings.js

@@ -15,10 +15,10 @@ function (_) {
       datasources                   : {},
       window_title_prefix           : 'Grafana - ',
       panels                        : {
-        'graph':      { path: 'panels/graph',      name: 'Graph' },
-        'singlestat': { path: 'panels/singlestat', name: 'Single stat' },
-        'text':       { path: 'panels/text',       name: 'Text' },
-        'dashlist':   { path: 'panels/dashlist',   name: 'Dashboard list' },
+        'graph':      { path: 'app/panels/graph',      name: 'Graph' },
+        'singlestat': { path: 'app/panels/singlestat', name: 'Single stat' },
+        'text':       { path: 'app/panels/text',       name: 'Text' },
+        'dashlist':   { path: 'app/panels/dashlist',   name: 'Dashboard list' },
       },
       new_panel_title: 'no title (click here)',
       plugins: {},

+ 1 - 1
public/app/core/routes/all.js

@@ -9,7 +9,7 @@ define([
   coreModule.config(function($routeProvider, $locationProvider) {
     $locationProvider.html5Mode(true);
 
-    var loadOrgBundle = new BundleLoader.BundleLoader('features/org/all');
+    var loadOrgBundle = new BundleLoader.BundleLoader('app/features/org/all');
 
     $routeProvider
       .when('/', {

+ 109 - 0
public/app/core/utils/datemath.ts

@@ -0,0 +1,109 @@
+///<reference path="../../headers/common.d.ts" />
+
+import _ = require('lodash');
+import moment = require('moment');
+
+var units = ['y', 'M', 'w', 'd', 'h', 'm', 's'];
+var unitsAsc = _.sortBy(units, function (unit) {
+  return moment.duration(1, unit).valueOf();
+});
+var unitsDesc = unitsAsc.reverse();
+
+export class DateMath {
+
+  static parse(text, roundUp) {
+    if (!text) { return undefined; }
+    if (moment.isMoment(text)) { return text; }
+    if (_.isDate(text)) { return moment(text); }
+
+    var time;
+    var mathString = '';
+    var index;
+    var parseString;
+
+    if (text.substring(0, 3) === 'now') {
+      time = moment();
+      mathString = text.substring('now'.length);
+    } else {
+      index = text.indexOf('||');
+      if (index === -1) {
+        parseString = text;
+        mathString = ''; // nothing else
+      } else {
+        parseString = text.substring(0, index);
+        mathString = text.substring(index + 2);
+      }
+      // We're going to just require ISO8601 timestamps, k?
+      time = moment(parseString);
+    }
+
+    if (!mathString.length) {
+      return time;
+    }
+
+    return DateMath.parseDateMath(mathString, time, roundUp);
+  }
+
+  static parseDateMath(mathString, time, roundUp) {
+    var dateTime = time;
+    var i = 0;
+    var len = mathString.length;
+
+    while (i < len) {
+      var c = mathString.charAt(i++);
+      var type;
+      var num;
+      var unit;
+
+      if (c === '/') {
+        type = 0;
+      } else if (c === '+') {
+        type = 1;
+      } else if (c === '-') {
+        type = 2;
+      } else {
+        return undefined;
+      }
+
+      if (isNaN(mathString.charAt(i))) {
+        num = 1;
+      } else if (mathString.length === 2) {
+        num = mathString.charAt(i);
+      } else {
+        var numFrom = i;
+        while (!isNaN(mathString.charAt(i))) {
+          i++;
+          if (i > 10) { return undefined; }
+        }
+        num = parseInt(mathString.substring(numFrom, i), 10);
+      }
+
+      if (type === 0) {
+        // rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M)
+        if (num !== 1) {
+          return undefined;
+        }
+      }
+      unit = mathString.charAt(i++);
+
+      if (!_.contains(units, unit)) {
+        return undefined;
+      } else {
+        if (type === 0) {
+          if (roundUp) {
+            dateTime.endOf(unit);
+          }
+          else {
+            dateTime.startOf(unit);
+          }
+        } else if (type === 1) {
+          dateTime.add(num, unit);
+        } else if (type === 2) {
+          dateTime.subtract(num, unit);
+        }
+      }
+    }
+    return dateTime;
+  }
+}
+

+ 1 - 2
public/app/features/dashboard/graphiteImportCtrl.js

@@ -1,10 +1,9 @@
 define([
   'angular',
-  'app',
   'lodash',
   'kbn'
 ],
-function (angular, app, _, kbn) {
+function (angular, _, kbn) {
   'use strict';
 
   var module = angular.module('grafana.controllers');

+ 1 - 2
public/app/features/dashboard/rowCtrl.js

@@ -1,10 +1,9 @@
 define([
   'angular',
-  'app',
   'lodash',
   'config'
 ],
-function (angular, app, _, config) {
+function (angular, _, config) {
   'use strict';
 
   var module = angular.module('grafana.controllers');

+ 3 - 3
public/app/features/dashboard/timepicker/timepicker.html

@@ -27,9 +27,9 @@
 			</a>
 
 			<!-- lacy load this -->
-			<ul class="dropdown-menu" ng-if="time_options" >
-				<li bindonce ng-repeat='option in time_options'>
-					<a ng-click="ctrl.setRelativeFilter(option)" bo-text="option.text"></a>
+			<ul class="dropdown-menu" ng-if="timeOptions" >
+				<li bindonce ng-repeat='option in timeOptions'>
+					<a ng-click="ctrl.setRelativeFilter(option)" bo-text="option.display"></a>
 				</li>
 
 				<!-- Auto refresh submenu -->

+ 3 - 10
public/app/features/dashboard/timepicker/timepicker.ts

@@ -4,6 +4,7 @@ import angular = require('angular');
 import _ = require('lodash');
 import moment = require('moment');
 import kbn = require('kbn');
+import {TimeRange} from './timerange';
 
 export class TimePickerCtrl {
 
@@ -79,12 +80,7 @@ export class TimePickerCtrl {
 
     if (this.timeSrv.time) {
       if (this.$scope.panel.now) {
-        if (this.timeSrv.time.from === 'today') {
-          model.rangeString = 'Today';
-        } else {
-          model.rangeString = moment(model.from.date).fromNow() + ' to ' +
-            moment(model.to.date).fromNow();
-        }
+        model.rangeString = TimeRange.describeRelativeTime(this.timeSrv.time);
       }
       else {
         model.rangeString = this.$scope.dashboard.formatDate(model.from.date, 'MMM D, YYYY HH:mm:ss') + ' to ' +
@@ -96,10 +92,7 @@ export class TimePickerCtrl {
   }
 
   loadTimeOptions() {
-    this.$scope.time_options = _.map(this.$scope.panel.time_options, function(str) {
-      return kbn.getRelativeTimeInfo(str);
-    });
-
+    this.$scope.timeOptions = TimeRange.getRelativeTimesList(this.$scope.panel);
     this.$scope.refreshMenuLeftSide = this.$scope.time.rangeString.length < 10;
   }
 

+ 60 - 0
public/app/features/dashboard/timepicker/timerange.ts

@@ -0,0 +1,60 @@
+///<reference path="../../../headers/common.d.ts" />
+
+import _ = require('lodash');
+import moment = require('moment');
+
+var rangeOptions = [
+  { from: 'now/d',    to: 'now/d',    display: 'Today',                 section: 0 },
+  { from: 'now/w',    to: 'now/w',    display: 'This week',             section: 0 },
+
+  { from: 'now/d',    to: 'now',      display: 'The day so far',        section: 0 },
+  { from: 'now/w',    to: 'now',      display: 'Week to date',          section: 0 },
+  // { from: 'now/M',    to: 'now/M',    display: 'This month',            section: 0 },
+  // { from: 'now/y',    to: 'now/y',    display: 'This year',             section: 0 },
+  //
+  // { from: 'now-1d/d', to: 'now-1d/d', display: 'Yesterday',             section: 1 },
+  // { from: 'now-2d/d', to: 'now-2d/d', display: 'Day before yesterday',  section: 1 },
+  // { from: 'now-7d/d', to: 'now-7d/d', display: 'This day last week',    section: 1 },
+  // { from: 'now-1w/w', to: 'now-1w/w', display: 'Previous week',         section: 1 },
+  // { from: 'now-1M/M', to: 'now-1M/M', display: 'Previous month',        section: 1 },
+  // { from: 'now-1y/y', to: 'now-1y/y', display: 'Previous year',         section: 1 },
+
+  { from: 'now-5m',   to: 'now',      display: 'Last 5 minutes',        section: 2 },
+  { from: 'now-15m',  to: 'now',      display: 'Last 15 minutes',       section: 2 },
+  { from: 'now-30m',  to: 'now',      display: 'Last 30 minutes',       section: 2 },
+  { from: 'now-1h',   to: 'now',      display: 'Last 1 hour',           section: 2 },
+  { from: 'now-4h',   to: 'now',      display: 'Last 4 hours',          section: 2 },
+  { from: 'now-12h',  to: 'now',      display: 'Last 12 hours',         section: 2 },
+  { from: 'now-24h',  to: 'now',      display: 'Last 24 hours',         section: 2 },
+  { from: 'now-7d',   to: 'now',      display: 'Last 7 days',           section: 2 },
+
+  { from: 'now-30d',  to: 'now',      display: 'Last 30 days',          section: 3 },
+  // { from: 'now-60d',  to: 'now',      display: 'Last 60 days',          section: 3 },
+  // { from: 'now-90d',  to: 'now',      display: 'Last 90 days',          section: 3 },
+  // { from: 'now-6M',   to: 'now',      display: 'Last 6 months',         section: 3 },
+  // { from: 'now-1y',   to: 'now',      display: 'Last 1 year',           section: 3 },
+  // { from: 'now-2y',   to: 'now',      display: 'Last 2 years',          section: 3 },
+  // { from: 'now-5y',   to: 'now',      display: 'Last 5 years',          section: 3 },
+];
+
+var rangeIndex = {};
+_.each(rangeOptions, function (frame) {
+  rangeIndex[frame.from + ' to ' + frame.to] = frame;
+});
+
+export class TimeRange {
+
+  static getRelativeTimesList(timepickerSettings) {
+    return rangeOptions;
+  }
+
+  static describeRelativeTime(range) {
+    var option = rangeIndex[range.from.toString() + ' to ' + range.to.toString()];
+    if (option) {
+      return option.display;
+    }
+    return "NA";
+  }
+}
+
+

+ 2 - 2
public/app/panels/dashlist/module.js

@@ -1,9 +1,9 @@
 define([
   'angular',
-  'app',
+  'app/app',
   'lodash',
   'config',
-  'components/panelmeta',
+  'app/components/panelmeta',
 ],
 function (angular, app, _, config, PanelMeta) {
   'use strict';

+ 2 - 2
public/app/panels/graph/module.js

@@ -4,8 +4,8 @@ define([
   'lodash',
   'kbn',
   'moment',
-  'components/timeSeries',
-  'components/panelmeta',
+  'app/components/timeSeries',
+  'app/components/panelmeta',
   './seriesOverridesCtrl',
   './graph',
   './legend',

+ 1 - 1
public/app/panels/graph/seriesOverridesCtrl.js

@@ -1,7 +1,7 @@
 define([
   'angular',
   'jquery',
-  'app',
+  'app/app',
   'lodash',
 ], function(angular, jquery, app, _) {
   'use strict';

+ 4 - 4
public/app/panels/singlestat/module.js

@@ -1,13 +1,13 @@
 define([
   'angular',
-  'app',
+  'app/app',
   'lodash',
-  'components/timeSeries',
   'kbn',
-  'components/panelmeta',
+  'app/components/timeSeries',
+  'app/components/panelmeta',
   './singleStatPanel',
 ],
-function (angular, app, _, TimeSeries, kbn, PanelMeta) {
+function (angular, app, _, kbn, TimeSeries, PanelMeta) {
   'use strict';
 
   var module = angular.module('grafana.panels.singlestat');

+ 1 - 1
public/app/panels/singlestat/singleStatPanel.js

@@ -1,6 +1,6 @@
 define([
   'angular',
-  'app',
+  'app/app',
   'lodash',
   'jquery',
   'jquery.flot',

+ 2 - 2
public/app/panels/text/module.js

@@ -1,9 +1,9 @@
 define([
   'angular',
-  'app',
+  'app/app',
   'lodash',
   'require',
-  'components/panelmeta',
+  'app/components/panelmeta',
 ],
 function (angular, app, _, require, PanelMeta) {
   'use strict';

+ 1 - 1
public/app/plugins/datasource/cloudwatch/_plugin.json

@@ -5,7 +5,7 @@
   "type": "cloudwatch",
   "serviceName": "CloudWatchDatasource",
 
-  "module": "plugins/datasource/cloudwatch/datasource",
+  "module": "app/plugins/datasource/cloudwatch/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/cloudwatch/partials/config.html",

+ 1 - 1
public/app/plugins/datasource/elasticsearch/plugin.json

@@ -5,7 +5,7 @@
   "type": "elasticsearch",
   "serviceName": "ElasticDatasource",
 
-  "module": "plugins/datasource/elasticsearch/datasource",
+  "module": "app/plugins/datasource/elasticsearch/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/elasticsearch/partials/config.html",

+ 1 - 1
public/app/plugins/datasource/grafana/plugin.json

@@ -6,6 +6,6 @@
   "type": "grafana",
   "serviceName": "GrafanaDatasource",
 
-  "module": "plugins/datasource/grafana/datasource",
+  "module": "app/plugins/datasource/grafana/datasource",
   "metrics": true
 }

+ 1 - 1
public/app/plugins/datasource/graphite/plugin.json

@@ -5,7 +5,7 @@
   "type": "graphite",
   "serviceName": "GraphiteDatasource",
 
-  "module": "plugins/datasource/graphite/datasource",
+  "module": "app/plugins/datasource/graphite/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/graphite/partials/config.html"

+ 1 - 1
public/app/plugins/datasource/influxdb/plugin.json

@@ -5,7 +5,7 @@
   "type": "influxdb",
   "serviceName": "InfluxDatasource",
 
-  "module": "plugins/datasource/influxdb/datasource",
+  "module": "app/plugins/datasource/influxdb/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/influxdb/partials/config.html"

+ 1 - 1
public/app/plugins/datasource/influxdb_08/plugin.json

@@ -5,7 +5,7 @@
   "type": "influxdb_08",
   "serviceName": "InfluxDatasource_08",
 
-  "module": "plugins/datasource/influxdb_08/datasource",
+  "module": "app/plugins/datasource/influxdb_08/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/influxdb_08/partials/config.html"

+ 1 - 1
public/app/plugins/datasource/kairosdb/plugin.json

@@ -5,7 +5,7 @@
   "type": "kairosdb",
   "serviceName": "KairosDBDatasource",
 
-  "module": "plugins/datasource/kairosdb/datasource",
+  "module": "app/plugins/datasource/kairosdb/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/kairosdb/partials/config.html"

+ 1 - 1
public/app/plugins/datasource/mixed/plugin.json

@@ -7,6 +7,6 @@
   "type": "mixed",
   "serviceName": "MixedDatasource",
 
-  "module": "plugins/datasource/mixed/datasource",
+  "module": "app/plugins/datasource/mixed/datasource",
   "metrics": true
 }

+ 1 - 1
public/app/plugins/datasource/opentsdb/plugin.json

@@ -5,7 +5,7 @@
   "type": "opentsdb",
   "serviceName": "OpenTSDBDatasource",
 
-  "module": "plugins/datasource/opentsdb/datasource",
+  "module": "app/plugins/datasource/opentsdb/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/opentsdb/partials/config.html"

+ 1 - 1
public/app/plugins/datasource/sql/plugin.json_

@@ -5,7 +5,7 @@
   "type": "generic_sql",
   "serviceName": "SqlDatasource",
 
-  "module": "plugins/datasource/sql/datasource",
+  "module": "app/plugins/datasource/sql/datasource",
 
   "partials": {
     "config": "app/plugins/datasource/sql/partials/config.html",

+ 3 - 2
public/test/specs/cloudwatch-datasource-specs.js

@@ -1,6 +1,6 @@
 define([
-  'helpers',
-  'plugins/datasource/cloudwatch/datasource',
+  './helpers',
+  'app/plugins/datasource/cloudwatch/datasource',
   'aws-sdk',
 ], function(helpers) {
   'use strict';
@@ -9,6 +9,7 @@ define([
     var ctx = new helpers.ServiceTestContext();
 
     beforeEach(module('grafana.services'));
+    beforeEach(module('grafana.controllers'));
     beforeEach(ctx.providePhase(['templateSrv']));
     beforeEach(ctx.createService('CloudWatchDatasource'));
     beforeEach(function() {

+ 16 - 0
public/test/specs/core/utils/datemath_specs.ts

@@ -0,0 +1,16 @@
+import {DateMath} from 'app/core/utils/datemath'
+
+declare var describe: any;
+declare var expect: any;
+declare var it: any;
+
+describe("test", () => {
+
+  it("hello", () => {
+    expect(true).to.be(true);
+  });
+
+});
+
+export = {};
+

+ 1 - 1
public/test/specs/dashboardSrv-specs.js

@@ -1,5 +1,5 @@
 define([
-  'features/dashboard/dashboardSrv'
+  'app/features/dashboard/dashboardSrv'
 ], function() {
   'use strict';
 

+ 1 - 1
public/test/specs/dashboardViewStateSrv-specs.js

@@ -1,5 +1,5 @@
 define([
-  'features/dashboard/viewStateSrv'
+  'app/features/dashboard/viewStateSrv'
 ], function() {
   'use strict';
 

+ 2 - 2
public/test/specs/dynamicDashboardSrv-specs.js

@@ -1,6 +1,6 @@
 define([
-  'features/dashboard/dynamicDashboardSrv',
-  'features/dashboard/dashboardSrv'
+  'app/features/dashboard/dynamicDashboardSrv',
+  'app/features/dashboard/dashboardSrv'
 ], function() {
   'use strict';
 

+ 1 - 1
public/test/specs/elasticsearch-indexPattern-specs.js

@@ -1,6 +1,6 @@
 define([
   'moment',
-  'plugins/datasource/elasticsearch/indexPattern'
+  'app/plugins/datasource/elasticsearch/indexPattern'
 ], function(moment, IndexPattern) {
   'use strict';
 

+ 1 - 1
public/test/specs/elasticsearch-querybuilder-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/elasticsearch/queryBuilder'
+  'app/plugins/datasource/elasticsearch/queryBuilder'
 ], function(ElasticQueryBuilder) {
   'use strict';
 

+ 3 - 3
public/test/specs/elasticsearch-queryctrl-specs.js

@@ -1,7 +1,7 @@
 define([
-  'helpers',
-  'plugins/datasource/elasticsearch/queryCtrl',
-  'services/uiSegmentSrv'
+  './helpers',
+  'app/plugins/datasource/elasticsearch/queryCtrl',
+  'app/services/uiSegmentSrv'
 ], function(helpers) {
   'use strict';
 

+ 1 - 1
public/test/specs/elasticsearch-response-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/elasticsearch/elasticResponse',
+  'app/plugins/datasource/elasticsearch/elasticResponse',
 ], function(ElasticResponse) {
   'use strict';
 

+ 2 - 2
public/test/specs/elasticsearch-specs.js

@@ -1,8 +1,8 @@
 define([
-  'helpers',
+  './helpers',
   'moment',
   'angular',
-  'plugins/datasource/elasticsearch/datasource',
+  'app/plugins/datasource/elasticsearch/datasource',
 ], function(helpers, moment, angular) {
   'use strict';
 

+ 1 - 1
public/test/specs/gfunc-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/graphite/gfunc'
+  'app/plugins/datasource/graphite/gfunc'
 ], function(gfunc) {
   'use strict';
 

+ 4 - 4
public/test/specs/graph-ctrl-specs.js

@@ -1,8 +1,8 @@
 define([
-  'helpers',
-  'features/panel/panelSrv',
-  'features/panel/panelHelper',
-  'panels/graph/module'
+  './helpers',
+  'app/features/panel/panelSrv',
+  'app/features/panel/panelHelper',
+  'app/panels/graph/module'
 ], function(helpers) {
   'use strict';
 

+ 3 - 3
public/test/specs/graph-specs.js

@@ -1,9 +1,9 @@
 define([
-  'helpers',
+  './helpers',
   'angular',
   'jquery',
-  'components/timeSeries',
-  'panels/graph/graph'
+  'app/components/timeSeries',
+  'app/panels/graph/graph'
 ], function(helpers, angular, $, TimeSeries) {
   'use strict';
 

+ 1 - 1
public/test/specs/graph-tooltip-specs.js

@@ -1,6 +1,6 @@
 define([
   'jquery',
-  'panels/graph/graph.tooltip'
+  'app/panels/graph/graph.tooltip'
 ], function($, GraphTooltip) {
   'use strict';
 

+ 2 - 2
public/test/specs/graphiteDatasource-specs.js

@@ -1,6 +1,6 @@
 define([
-  'helpers',
-  'plugins/datasource/graphite/datasource'
+  './helpers',
+  'app/plugins/datasource/graphite/datasource'
 ], function(helpers) {
   'use strict';
 

+ 4 - 4
public/test/specs/graphiteTargetCtrl-specs.js

@@ -1,8 +1,8 @@
 define([
-  'helpers',
-  'plugins/datasource/graphite/gfunc',
-  'plugins/datasource/graphite/queryCtrl',
-  'services/uiSegmentSrv'
+  './helpers',
+  'app/plugins/datasource/graphite/gfunc',
+  'app/plugins/datasource/graphite/queryCtrl',
+  'app/services/uiSegmentSrv'
 ], function(helpers, gfunc) {
   'use strict';
 

+ 1 - 1
public/test/specs/influx09-querybuilder-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/influxdb/queryBuilder'
+  'app/plugins/datasource/influxdb/queryBuilder'
 ], function(InfluxQueryBuilder) {
   'use strict';
 

+ 1 - 1
public/test/specs/influxQueryBuilder-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/influxdb_08/queryBuilder'
+  'app/plugins/datasource/influxdb_08/queryBuilder'
 ], function(InfluxQueryBuilder) {
   'use strict';
 

+ 1 - 1
public/test/specs/influxSeries-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/influxdb/influxSeries'
+  'app/plugins/datasource/influxdb/influxSeries'
 ], function(InfluxSeries) {
   'use strict';
 

+ 1 - 1
public/test/specs/influxSeries08-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/influxdb_08/influxSeries'
+  'app/plugins/datasource/influxdb_08/influxSeries'
 ], function(InfluxSeries) {
   'use strict';
 

+ 4 - 4
public/test/specs/influxdb-datasource-specs.js

@@ -1,8 +1,8 @@
 define([
-  'helpers',
-  'plugins/datasource/influxdb_08/datasource',
-  'services/backendSrv',
-  'services/alertSrv'
+  './helpers',
+  'app/plugins/datasource/influxdb_08/datasource',
+  'app/services/backendSrv',
+  'app/services/alertSrv'
 ], function(helpers) {
   'use strict';
 

+ 3 - 3
public/test/specs/influxdbQueryCtrl-specs.js

@@ -1,7 +1,7 @@
 define([
-  'helpers',
-  'plugins/datasource/influxdb/queryCtrl',
-  'services/uiSegmentSrv'
+  './helpers',
+  'app/plugins/datasource/influxdb/queryCtrl',
+  'app/services/uiSegmentSrv'
 ], function(helpers) {
   'use strict';
 

+ 2 - 2
public/test/specs/kairosdb-datasource-specs.js

@@ -1,6 +1,6 @@
 define([
-  'helpers',
-  'plugins/datasource/kairosdb/datasource'
+  './helpers',
+  'app/plugins/datasource/kairosdb/datasource'
 ], function(helpers) {
   'use strict';
 

+ 1 - 1
public/test/specs/lexer-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/graphite/lexer'
+  'app/plugins/datasource/graphite/lexer'
 ], function(Lexer) {
   'use strict';
 

+ 2 - 2
public/test/specs/opentsdbDatasource-specs.js

@@ -1,6 +1,6 @@
 define([
-  'helpers',
-  'plugins/datasource/opentsdb/datasource'
+  './helpers',
+  'app/plugins/datasource/opentsdb/datasource'
 ], function(helpers) {
   'use strict';
 

+ 0 - 30
public/test/specs/overview-ctrl-specs.js

@@ -1,30 +0,0 @@
-define([
-    './helpers',
-    'panels/overview/module'
-], function(helpers) {
-  'use strict';
-
-  describe('OverviewCtrl', function() {
-    var ctx = new helpers.ControllerTestContext();
-
-    beforeEach(module('grafana.services'));
-    beforeEach(module('grafana.panels.overview'));
-
-    beforeEach(ctx.providePhase());
-    beforeEach(ctx.createControllerPhase('OverviewCtrl'));
-
-    describe('when query return error', function() {
-      beforeEach(function() {
-        ctx.datasource.query =  function() {
-          return ctx.$q.reject({ message: 'Some error' });
-        };
-        ctx.scope.get_data();
-        ctx.scope.$digest();
-      });
-
-      it('panel.error should be set', function() {
-        expect(ctx.scope.panel.error).to.be("Some error");
-      });
-    });
-  });
-});

+ 2 - 2
public/test/specs/panelSrv-specs.js

@@ -1,6 +1,6 @@
 define([
-  'helpers',
-  'features/panel/panelSrv',
+  './helpers',
+  'app/features/panel/panelSrv',
 ], function() {
   'use strict';
 

+ 1 - 1
public/test/specs/parser-specs.js

@@ -1,5 +1,5 @@
 define([
-  'plugins/datasource/graphite/parser'
+  'app/plugins/datasource/graphite/parser'
 ], function(Parser) {
   'use strict';
 

+ 2 - 2
public/test/specs/row-ctrl-specs.js

@@ -1,6 +1,6 @@
 define([
-  'helpers',
-  'features/dashboard/rowCtrl'
+  './helpers',
+  'app/features/dashboard/rowCtrl'
 ], function(helpers) {
   'use strict';
 

+ 2 - 2
public/test/specs/seriesOverridesCtrl-specs.js

@@ -1,6 +1,6 @@
 define([
-  'helpers',
-  'panels/graph/seriesOverridesCtrl'
+  './helpers',
+  'app/panels/graph/seriesOverridesCtrl'
 ], function(helpers) {
   'use strict';
 

+ 3 - 3
public/test/specs/shareModalCtrl-specs.js

@@ -1,7 +1,7 @@
 define([
-  'helpers',
-  'features/dashboard/shareModalCtrl',
-  'features/panellinks/linkSrv',
+  './helpers',
+  'app/features/dashboard/shareModalCtrl',
+  'app/features/panellinks/linkSrv',
 ], function(helpers) {
   'use strict';
 

+ 4 - 4
public/test/specs/singlestat-specs.js

@@ -1,8 +1,8 @@
 define([
-  'helpers',
-  'features/panel/panelSrv',
-  'features/panel/panelHelper',
-  'panels/singlestat/module'
+  './helpers',
+  'app/features/panel/panelSrv',
+  'app/features/panel/panelHelper',
+  'app/panels/singlestat/module'
 ], function(helpers) {
   'use strict';
 

+ 2 - 2
public/test/specs/templateSrv-specs.js

@@ -1,7 +1,7 @@
 define([
-  'mocks/dashboard-mock',
+  '../mocks/dashboard-mock',
   'lodash',
-  'features/templating/templateSrv'
+  'app/features/templating/templateSrv'
 ], function(dashboardMock) {
   'use strict';
 

+ 3 - 3
public/test/specs/templateValuesSrv-specs.js

@@ -1,8 +1,8 @@
 define([
-  'mocks/dashboard-mock',
-  'helpers',
+  '../mocks/dashboard-mock',
+  './helpers',
   'moment',
-  'features/templating/templateValuesSrv'
+  'app/features/templating/templateValuesSrv'
 ], function(dashboardMock, helpers, moment) {
   'use strict';
 

+ 1 - 1
public/test/specs/timeSeries-specs.js

@@ -1,5 +1,5 @@
 define([
-  'components/timeSeries'
+  'app/components/timeSeries'
 ], function(TimeSeries) {
   'use strict';
 

+ 4 - 4
public/test/specs/timeSrv-specs.js

@@ -1,9 +1,9 @@
 define([
-  'mocks/dashboard-mock',
-  'helpers',
+  '../mocks/dashboard-mock',
+  './helpers',
   'lodash',
-  'services/timer',
-  'features/dashboard/timeSrv'
+  'app/services/timer',
+  'app/features/dashboard/timeSrv'
 ], function(dashboardMock, helpers, _) {
   'use strict';
 

+ 2 - 2
public/test/specs/unsavedChangesSrv-specs.js

@@ -1,6 +1,6 @@
 define([
-  'features/dashboard/unsavedChangesSrv',
-  'features/dashboard/dashboardSrv'
+  'app/features/dashboard/unsavedChangesSrv',
+  'app/features/dashboard/dashboardSrv'
 ], function() {
   'use strict';
 

+ 1 - 1
public/test/specs/value_select_dropdown_specs.js

@@ -1,5 +1,5 @@
 define([
-  'core/directives/value_select_dropdown',
+  'app/core/directives/value_select_dropdown',
 ],
 function () {
   'use strict';

+ 111 - 99
public/test/test-main.js

@@ -1,54 +1,51 @@
 require.config({
-  baseUrl: 'http://localhost:9876/base/public_gen/app',
+  baseUrl: 'http://localhost:9876/base/',
 
   paths: {
-    specs:                 '../test/specs',
-    mocks:                 '../test/mocks',
-    helpers:               '../test/specs/helpers',
-    config:                'components/config',
-    kbn:                   'components/kbn',
-    store:                 'components/store',
-
-    settings:              'components/settings',
-    lodash:                'components/lodash.extended',
-    'lodash-src':          '../vendor/lodash',
-
-    moment:                '../vendor/moment',
-    chromath:              '../vendor/chromath',
-    filesaver:             '../vendor/filesaver',
-
-    angular:                  '../vendor/angular/angular',
-    'angular-route':          '../vendor/angular-route/angular-route',
-    'angular-sanitize':       '../vendor/angular-sanitize/angular-sanitize',
-    angularMocks:             '../vendor/angular-mocks/angular-mocks',
-    'angular-dragdrop':       '../vendor/angular-native-dragdrop/draganddrop',
-    'angular-ui':             '../vendor/angular-ui/angular-bootstrap',
-    'angular-strap':          '../vendor/angular-other/angular-strap',
-    timepicker:               '../vendor/angular-other/timepicker',
-    datepicker:               '../vendor/angular-other/datepicker',
-    bindonce:                 '../vendor/angular-bindonce/bindonce',
-    crypto:                   '../vendor/crypto.min',
-    spectrum:                 '../vendor/spectrum',
-
-    jquery:                   '../vendor/jquery/dist/jquery',
-
-    bootstrap:                '../vendor/bootstrap/bootstrap',
-    'bootstrap-tagsinput':    '../vendor/tagsinput/bootstrap-tagsinput',
-
-    'extend-jquery':          'components/extend-jquery',
-
-    'jquery.flot':             '../vendor/flot/jquery.flot',
-    'jquery.flot.pie':         '../vendor/flot/jquery.flot.pie',
-    'jquery.flot.events':      '../vendor/flot/jquery.flot.events',
-    'jquery.flot.selection':   '../vendor/flot/jquery.flot.selection',
-    'jquery.flot.stack':       '../vendor/flot/jquery.flot.stack',
-    'jquery.flot.stackpercent':'../vendor/flot/jquery.flot.stackpercent',
-    'jquery.flot.time':        '../vendor/flot/jquery.flot.time',
-    'jquery.flot.crosshair':   '../vendor/flot/jquery.flot.crosshair',
-    'jquery.flot.fillbelow':   '../vendor/flot/jquery.flot.fillbelow',
-
-    modernizr:                '../vendor/modernizr-2.6.1',
-    'aws-sdk':                '../vendor/aws-sdk/dist/aws-sdk.min',
+    config:                'app/components/config',
+    kbn:                   'app/components/kbn',
+    store:                 'app/components/store',
+
+    settings:              'app/components/settings',
+    lodash:                'app/components/lodash.extended',
+    'lodash-src':          'vendor/lodash',
+
+    moment:                'vendor/moment',
+    chromath:              'vendor/chromath',
+    filesaver:             'vendor/filesaver',
+
+    angular:                  'vendor/angular/angular',
+    'angular-route':          'vendor/angular-route/angular-route',
+    'angular-sanitize':       'vendor/angular-sanitize/angular-sanitize',
+    angularMocks:             'vendor/angular-mocks/angular-mocks',
+    'angular-dragdrop':       'vendor/angular-native-dragdrop/draganddrop',
+    'angular-ui':             'vendor/angular-ui/tabs',
+    'angular-strap':          'vendor/angular-other/angular-strap',
+    timepicker:               'vendor/angular-other/timepicker',
+    datepicker:               'vendor/angular-other/datepicker',
+    bindonce:                 'vendor/angular-bindonce/bindonce',
+    crypto:                   'vendor/crypto.min',
+    spectrum:                 'vendor/spectrum',
+
+    jquery:                   'vendor/jquery/dist/jquery',
+
+    bootstrap:                'vendor/bootstrap/bootstrap',
+    'bootstrap-tagsinput':    'vendor/tagsinput/bootstrap-tagsinput',
+
+    'extend-jquery':          'app/components/extend-jquery',
+
+    'jquery.flot':             'vendor/flot/jquery.flot',
+    'jquery.flot.pie':         'vendor/flot/jquery.flot.pie',
+    'jquery.flot.events':      'vendor/flot/jquery.flot.events',
+    'jquery.flot.selection':   'vendor/flot/jquery.flot.selection',
+    'jquery.flot.stack':       'vendor/flot/jquery.flot.stack',
+    'jquery.flot.stackpercent':'vendor/flot/jquery.flot.stackpercent',
+    'jquery.flot.time':        'vendor/flot/jquery.flot.time',
+    'jquery.flot.crosshair':   'vendor/flot/jquery.flot.crosshair',
+    'jquery.flot.fillbelow':   'vendor/flot/jquery.flot.fillbelow',
+
+    modernizr:                'vendor/modernizr-2.6.1',
+    'aws-sdk':                'vendor/aws-sdk/dist/aws-sdk.min',
   },
 
   shim: {
@@ -98,20 +95,37 @@ require.config({
   }
 });
 
+function file2moduleName(filePath) {
+  'use strict';
+  return filePath.replace(/\\/g, '/')
+    .replace(/^\/base\//, '')
+    .replace(/\.\w*$/, '');
+}
+
 require([
   'angular',
-  'config',
   'angularMocks',
-  'app',
-], function(angular, config) {
+  'app/app',
+], function(angular) {
   'use strict';
 
+  var specs = [];
+
   for (var file in window.__karma__.files) {
-    if (/spec\.js$/.test(file)) {
-      window.tests.push(file.replace(/^\/base\//, 'http://localhost:9876/base/'));
+    if (/base\/test\/specs.*/.test(file)) {
+      console.log(file);
+      file = file2moduleName(file);
+      console.log(file);
+      specs.push(file);
+      //file = file.replace(/^\/base\/test/, '');
+      //specs.push(file);
+      //window.tests.push();
     }
   }
 
+  require(specs, function() {
+    window.__karma__.start();
+  });
 
   angular.module('grafana', ['ngRoute']);
   angular.module('grafana.services', ['ngRoute', '$strap.directives']);
@@ -119,51 +133,49 @@ require([
   angular.module('grafana.filters', []);
   angular.module('grafana.routes', ['ngRoute']);
 
-  var specs = [
-    'specs/lexer-specs',
-    'specs/parser-specs',
-    'specs/gfunc-specs',
-    'specs/timeSeries-specs',
-    'specs/row-ctrl-specs',
-    'specs/graphiteTargetCtrl-specs',
-    'specs/graphiteDatasource-specs',
-    'specs/influxSeries-specs',
-    'specs/influxSeries08-specs',
-    'specs/influxQueryBuilder-specs',
-    'specs/influx09-querybuilder-specs',
-    'specs/influxdb-datasource-specs',
-    'specs/influxdbQueryCtrl-specs',
-    'specs/kairosdb-datasource-specs',
-    'specs/graph-ctrl-specs',
-    'specs/graph-specs',
-    'specs/graph-tooltip-specs',
-    'specs/seriesOverridesCtrl-specs',
-    'specs/shareModalCtrl-specs',
-    'specs/timeSrv-specs',
-    'specs/panelSrv-specs',
-    'specs/templateSrv-specs',
-    'specs/templateValuesSrv-specs',
-    'specs/kbn-format-specs',
-    'specs/dashboardSrv-specs',
-    'specs/dashboardViewStateSrv-specs',
-    'specs/singlestat-specs',
-    'specs/dynamicDashboardSrv-specs',
-    'specs/unsavedChangesSrv-specs',
-    'specs/value_select_dropdown_specs',
-    'specs/opentsdbDatasource-specs',
-    'specs/cloudwatch-datasource-specs',
-    'specs/elasticsearch-specs',
-    'specs/elasticsearch-querybuilder-specs',
-    'specs/elasticsearch-queryctrl-specs',
-    'specs/elasticsearch-indexPattern-specs',
-    'specs/elasticsearch-response-specs',
-  ];
-
-  var pluginSpecs = (config.plugins.specs || []).map(function (spec) {
-    return '../plugins/' + spec;
-  });
+  // var specs = [
+  //   'specs/lexer-specs',
+  //   'specs/parser-specs',
+  //   'specs/gfunc-specs',
+  //   'specs/timeSeries-specs',
+  //   'specs/row-ctrl-specs',
+  //   'specs/graphiteTargetCtrl-specs',
+  //   'specs/graphiteDatasource-specs',
+  //   'specs/influxSeries-specs',
+  //   'specs/influxSeries08-specs',
+  //   'specs/influxQueryBuilder-specs',
+  //   'specs/influx09-querybuilder-specs',
+  //   // 'specs/influxdb-datasource-specs',
+  //   'specs/influxdbQueryCtrl-specs',
+  //   // 'specs/kairosdb-datasource-specs',
+  //   'specs/graph-ctrl-specs',
+  //   'specs/graph-specs',
+  //   'specs/graph-tooltip-specs',
+  //   'specs/seriesOverridesCtrl-specs',
+  //   'specs/shareModalCtrl-specs',
+  //   'specs/timeSrv-specs',
+  //   'specs/panelSrv-specs',
+  //   'specs/templateSrv-specs',
+  //   'specs/templateValuesSrv-specs',
+  //   'specs/kbn-format-specs',
+  //   'specs/dashboardSrv-specs',
+  //   'specs/dashboardViewStateSrv-specs',
+  //   'specs/singlestat-specs',
+  //   'specs/dynamicDashboardSrv-specs',
+  //   'specs/unsavedChangesSrv-specs',
+  //   'specs/value_select_dropdown_specs',
+  //   'specs/opentsdbDatasource-specs',
+  //   'specs/cloudwatch-datasource-specs',
+  //   'specs/elasticsearch-specs',
+  //   'specs/elasticsearch-querybuilder-specs',
+  //   'specs/elasticsearch-queryctrl-specs',
+  //   'specs/elasticsearch-indexPattern-specs',
+  //   'specs/elasticsearch-response-specs',
+  //   'specs/core/utils/datemath_specs',
+  // ];
+  //
+  // var pluginSpecs = (config.plugins.specs || []).map(function (spec) {
+  //   return '../plugins/' + spec;
+  // });
 
-  require(specs.concat(pluginSpecs), function () {
-    window.__karma__.start();
-  });
 });

+ 0 - 6
public/vendor/angular-ui/angular-bootstrap.js

@@ -1,6 +0,0 @@
-define([
-  'angular',
-  '../vendor/angular-ui/tabs',
-], function() {
-});
-

+ 1 - 1
public/views/index.html

@@ -53,7 +53,7 @@
 			settings: [[.Settings]],
 		};
 
-    require(['app'], function (app) {
+    require(['app/app'], function (app) {
 	    app.boot();
     })
 	</script>

+ 6 - 4
tasks/options/karma.js

@@ -1,19 +1,21 @@
 module.exports = function(config) {
+  'use strict';
+
   return {
     dev: {
-      configFile: '<%= srcDir %>/test/karma.conf.js',
+      configFile: 'karma.conf.js',
       singleRun: false,
     },
     debug: {
-      configFile: '<%= srcDir %>/test/karma.conf.js',
+      configFile: 'karma.conf.js',
       singleRun: false,
       browsers: ['Chrome']
     },
     test: {
-      configFile: '<%= srcDir %>/test/karma.conf.js',
+      configFile: 'karma.conf.js',
     },
     coveralls: {
-      configFile: '<%= srcDir %>/test/karma.conf.js',
+      configFile: 'karma.conf.js',
       reporters: ['dots','coverage','coveralls'],
       preprocessors: {
         'public/app/**/*.js': ['coverage']

+ 7 - 5
tasks/options/typescript.js

@@ -3,15 +3,18 @@ module.exports = function() {
 
   return {
     build: {
-      src: ['public/app/**/*.ts'],
-      dest: 'public_gen/app',
+      src: ['public/**/*.ts', 'public/test/**/*.ts'],
+      dest: 'public_gen/',
       options: {
         module: 'amd', //or commonjs
         target: 'es5', //or es3
-        rootDir: 'public/app',
+        rootDir: 'public/',
+        sourceRoot: 'public/',
         declaration: true,
+        emitDecoratorMetadata: true,
+        experimentalDecorators: true,
         sourceMap: true,
-        generateTsConfig: true,
+        noImplicitAny: false,
       }
     },
 
@@ -35,7 +38,6 @@ module.exports = function() {
         declaration: true,
         sourceMap: true,
         watch: true,
-        generateTsConfig: true,
       }
     }
   };

+ 1 - 1
tasks/options/watch.js

@@ -17,7 +17,7 @@ module.exports = function(config) {
     },
 
     typescript: {
-      files: ['<%= srcDir %>/app/**/*.ts'],
+      files: ['<%= srcDir %>/app/**/*.ts', '<%= srcDir %>/test/**/*.ts'],
       tasks: ['tslint', 'typescript:build'],
       options: {
         spawn: false

+ 22 - 0
tsconfig.json

@@ -0,0 +1,22 @@
+{
+    "compilerOptions": {
+        "emitDecoratorMetadata": true,
+        "experimentalDecorators": true,
+        "sourceMap": true,
+        "declaration": true,
+        "noImplicitAny": false,
+        "removeComments": true,
+        "noLib": true,
+        "outDir": "public_gen/app",
+        "target": "ES5",
+        "rootDir": "public/app",
+        "sourceRoot": "public/app",
+        "module": "amd",
+        "noEmitOnError": true
+    },
+    "fileGlobs": [
+        "./public/app/**/*.ts",
+        "!./node_modules/**",
+        "!./public_gen/**",
+    ]
+}