Browse Source

Merge remote-tracking branch 'origin/overview' into pro

Torkel Ödegaard 11 years ago
parent
commit
f068b2c1d3

+ 2 - 12
src/app/controllers/dash.js

@@ -11,7 +11,7 @@ function (angular, $, config, _) {
   var module = angular.module('grafana.controllers');
 
   module.controller('DashCtrl', function(
-    $scope, $rootScope, dashboardKeybindings, filterSrv, dashboard, panelMoveSrv, timer) {
+    $scope, $rootScope, dashboardKeybindings, filterSrv, dashboardSrv, panelMoveSrv, timer) {
 
     $scope.editor = { index: 0 };
     $scope.panelNames = config.panels;
@@ -26,7 +26,7 @@ function (angular, $, config, _) {
 
       $rootScope.fullscreen = false;
 
-      $scope.dashboard = dashboard.create(dashboardData);
+      $scope.dashboard = dashboardSrv.create(dashboardData);
       $scope.grafana.style = $scope.dashboard.style;
 
       $scope.filter = filterSrv;
@@ -107,16 +107,6 @@ function (angular, $, config, _) {
       return $scope.editorTabs;
     };
 
-    $scope.colors = [
-      "#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0", //1
-      "#508642","#CCA300","#447EBC","#C15C17","#890F02","#0A437C","#6D1F62","#584477", //2
-      "#B7DBAB","#F4D598","#70DBED","#F9BA8F","#F29191","#82B5D8","#E5A8E2","#AEA2E0", //3
-      "#629E51","#E5AC0E","#64B0C8","#E0752D","#BF1B00","#0A50A1","#962D82","#614D93", //4
-      "#9AC48A","#F2C96D","#65C5DB","#F9934E","#EA6460","#5195CE","#D683CE","#806EB7", //5
-      "#3F6833","#967302","#2F575E","#99440A","#58140C","#052B51","#511749","#3F2B5B", //6
-      "#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7"  //7
-    ];
-
     $scope.init();
   });
 });

+ 10 - 0
src/app/controllers/grafanaCtrl.js

@@ -29,6 +29,16 @@ function (angular, config, _) {
       $rootScope.$emit(name, payload);
     };
 
+    $rootScope.colors = [
+      "#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0", //1
+      "#508642","#CCA300","#447EBC","#C15C17","#890F02","#0A437C","#6D1F62","#584477", //2
+      "#B7DBAB","#F4D598","#70DBED","#F9BA8F","#F29191","#82B5D8","#E5A8E2","#AEA2E0", //3
+      "#629E51","#E5AC0E","#64B0C8","#E0752D","#BF1B00","#0A50A1","#962D82","#614D93", //4
+      "#9AC48A","#F2C96D","#65C5DB","#F9934E","#EA6460","#5195CE","#D683CE","#806EB7", //5
+      "#3F6833","#967302","#2F575E","#99440A","#58140C","#052B51","#511749","#3F2B5B", //6
+      "#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7"  //7
+    ];
+
     $scope.init();
 
   });

+ 1 - 1
src/app/panels/graph/module.html

@@ -1,4 +1,4 @@
-<div  ng-controller='graph'
+<div  ng-controller='GraphCtrl'
       style="min-height:{{panel.height || row.height}}"
       ng-class="{'panel-fullscreen': fullscreen}">
 

+ 8 - 5
src/app/panels/graph/module.js

@@ -19,6 +19,7 @@ define([
   'kbn',
   'moment',
   './timeSeries',
+  'services/panelSrv',
   'services/annotationsSrv',
   'services/datasourceSrv',
   'jquery.flot',
@@ -35,7 +36,7 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
   var module = angular.module('grafana.panels.graph', []);
   app.useModule(module);
 
-  module.controller('graph', function($scope, $rootScope, $timeout, panelSrv, annotationsSrv) {
+  module.controller('GraphCtrl', function($scope, $rootScope, $timeout, panelSrv, annotationsSrv) {
 
     $scope.panelMeta = {
       modals : [],
@@ -190,12 +191,14 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
     $scope.init = function() {
       panelSrv.init($scope);
       $scope.hiddenSeries = {};
-      $scope.get_data();
+      if (!$scope.skipDataOnInit) {
+        $scope.get_data();
+      }
     };
 
     $scope.updateTimeRange = function () {
-      $scope.range = this.filter.timeRange();
-      $scope.rangeUnparsed = this.filter.timeRange(false);
+      $scope.range = $scope.filter.timeRange();
+      $scope.rangeUnparsed = $scope.filter.timeRange(false);
       $scope.resolution = Math.ceil($(window).width() * ($scope.panel.span / 12));
       $scope.interval = '10m';
 
@@ -264,7 +267,7 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
     $scope.seriesHandler = function(seriesData, index) {
       var datapoints = seriesData.datapoints;
       var alias = seriesData.target;
-      var color = $scope.panel.aliasColors[alias] || $scope.colors[index];
+      var color = $scope.panel.aliasColors[alias] || $rootScope.colors[index];
       var yaxis = $scope.panel.aliasYAxis[alias] || 1;
 
       var seriesInfo = {

+ 25 - 0
src/app/panels/overview/module.html

@@ -0,0 +1,25 @@
+<div	ng-controller='OverviewCtrl'
+			style="min-height:{{panel.height || row.height}}"
+			ng-class="{'panel-fullscreen': fullscreen}">
+
+	<h2>hello</h2>
+	<div class="overview-series-list">
+		<div class="overview-series-item" ng-repeat="series in series">
+      <h2>{{series.info.alias}}</h2>
+      <strong>{{series.info.avg}} Avg</strong>
+		</div>
+	</div>
+  <div class="clearfix"></div>
+
+  <div class="panel-full-edit-tabs" ng-if="editMode">
+    <div ng-model="editor.index" bs-tabs>
+      <div ng-repeat="tab in editorTabs" data-title="{{tab}}">
+      </div>
+    </div>
+
+    <div class="tab-content" ng-repeat="tab in panelMeta.fullEditorTabs" ng-show="editorTabs[editor.index] == tab.title">
+      <div ng-include src="tab.src"></div>
+    </div>
+  </div>
+
+</div>

+ 107 - 0
src/app/panels/overview/module.js

@@ -0,0 +1,107 @@
+define([
+  'angular',
+  'app',
+  'lodash',
+  '../graph/timeSeries',
+  'services/panelSrv',
+],
+function (angular, app, _, timeSeries) {
+  'use strict';
+
+  var module = angular.module('grafana.panels.overview', []);
+  app.useModule(module);
+
+  module.controller('OverviewCtrl', function($scope, panelSrv) {
+
+    $scope.panelMeta = {
+      description : "A panel to show an overview of different metrics through avg, total, current numbers and sparklines",
+      fullEditorTabs : [
+        {
+          title: 'General',
+          src:'app/partials/panelgeneral.html'
+        },
+        {
+          title: 'Metrics',
+          src:'app/partials/metrics.html'
+        }
+      ],
+      fullscreenEdit: true,
+    };
+
+    // Set and populate defaults
+    var _d = {
+      targets: [{}]
+    };
+
+    _.defaults($scope.panel, _d);
+
+    $scope.init = function() {
+      panelSrv.init(this);
+
+      if (!$scope.skipDataOnInit) {
+        $scope.get_data();
+      }
+      //$scope.$on('refresh', $scope.render);
+      //$scope.render();
+    };
+
+    $scope.get_data = function() {
+      delete $scope.panel.error;
+      $scope.panelMeta.loading = true;
+
+      $scope.rangeUnparsed = $scope.filter.timeRange(false);
+
+      var metricsQuery = {
+        range: $scope.rangeUnparsed,
+        interval: '1min',
+        targets: $scope.panel.targets,
+        maxDataPoints: 100,
+      };
+
+      return $scope.datasource.query($scope.filter, metricsQuery)
+        .then($scope.dataHandler)
+        .then(null, function(err) {
+          $scope.panelMeta.loading = false;
+          $scope.panel.error = err.message || "Timeseries data request error";
+          $scope.inspector.error = err;
+          $scope.render([]);
+        });
+    };
+
+    $scope.dataHandler = function(results) {
+      $scope.panelMeta.loading = false;
+      $scope.series = _.map(results.data, $scope.seriesHandler);
+
+      console.log($scope.series);
+    };
+
+    $scope.seriesHandler = function(seriesData) {
+      var datapoints = seriesData.datapoints;
+      var alias = seriesData.target;
+
+      var seriesInfo = {
+        alias: alias,
+        enable: true,
+      };
+
+      var series = new timeSeries.ZeroFilled({
+        datapoints: datapoints,
+        info: seriesInfo,
+      });
+
+      series.points = series.getFlotPairs('connected', 'short');
+
+      return series;
+    };
+
+    $scope.render = function() {
+
+    };
+
+    $scope.openEditor = function() {
+    };
+
+    $scope.init();
+
+  });
+});

+ 8 - 0
src/app/partials/solo-panel.html

@@ -0,0 +1,8 @@
+<div class="container-fluid main">
+	<div class="row-fluid">
+		<div class="span12">
+			<div class="panel nospace" ng-if="panel" style="display:block;">
+				<grafana-panel type="panel.type" ng-cloak></kibana-panel>
+			</div>
+		</div>
+</div>

+ 1 - 0
src/app/routes/all.js

@@ -1,5 +1,6 @@
 define([
   './dashboard-from-db',
+  './solo-panel-route',
   './dashboard-from-file',
   './dashboard-from-script',
   './dashboard-default',

+ 45 - 0
src/app/routes/solo-panel-route.js

@@ -0,0 +1,45 @@
+define([
+  'angular',
+],
+function (angular) {
+  "use strict";
+
+  var module = angular.module('grafana.routes');
+
+  module.config(function($routeProvider) {
+    $routeProvider
+      .when('/solo-panel/db/:id', {
+        templateUrl: 'app/partials/solo-panel.html',
+        controller : 'SoloPanelCtrl',
+      });
+  });
+
+  module.controller('SoloPanelCtrl', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv, dashboardSrv, filterSrv) {
+
+    var db = datasourceSrv.getGrafanaDB();
+
+    db.getDashboard($routeParams.id, false)
+      .then(function(dashboardData) {
+        $scope.initPanelScope(dashboardData);
+      }).then(null, function(error) {
+        alertSrv.set('Error', error, 'error');
+      });
+
+    $scope.initPanelScope = function(dashboardData) {
+      $scope.dashboard = dashboardSrv.create(dashboardData);
+      $scope.grafana.style = $scope.dashboard.style;
+      $scope.row = {
+        height: '300px',
+      };
+      $scope.test = "Hej";
+      $scope.$index = 0;
+      $scope.panel = $scope.dashboard.rows[0].panels[0];
+      $scope.panel.span = 12;
+
+      $scope.filter = filterSrv;
+      $scope.filter.init($scope.dashboard);
+    };
+
+  });
+
+});

+ 1 - 1
src/app/services/all.js

@@ -10,6 +10,6 @@ define([
   './playlistSrv',
   './unsavedChangesSrv',
   './dashboard/dashboardKeyBindings',
-  './dashboard/dashboardModel',
+  './dashboard/dashboardSrv',
 ],
 function () {});

+ 1 - 1
src/app/services/dashboard/dashboardModel.js → src/app/services/dashboard/dashboardSrv.js

@@ -10,7 +10,7 @@ function (angular, $, kbn, _) {
 
   var module = angular.module('grafana.services');
 
-  module.service('dashboard', function(timer, $rootScope, $timeout) {
+  module.service('dashboardSrv', function(timer, $rootScope, $timeout) {
 
     function DashboardModel (data) {
 

+ 5 - 5
src/test/specs/dashboardModel-specs.js → src/test/specs/dashboardSrv-specs.js

@@ -1,5 +1,5 @@
 define([
-  'services/dashboard/dashboardModel'
+  'services/dashboard/dashboardSrv'
 ], function() {
   'use strict';
 
@@ -8,8 +8,8 @@ define([
 
     beforeEach(module('grafana.services'));
 
-    beforeEach(inject(function(dashboard) {
-      model = dashboard.create({});
+    beforeEach(inject(function(dashboardSrv) {
+      model = dashboardSrv.create({});
     }));
 
     it('should have title', function() {
@@ -30,8 +30,8 @@ define([
 
     beforeEach(module('grafana.services'));
 
-    beforeEach(inject(function(dashboard) {
-      model = dashboard.create({
+    beforeEach(inject(function(dashboardSrv) {
+      model = dashboardSrv.create({
         services: { filter: { time: { from: 'now-1d', to: 'now'}, list: [1] }},
         rows: [
           {

+ 44 - 0
src/test/specs/graph-ctrl-specs.js

@@ -0,0 +1,44 @@
+define([
+  './helpers',
+  'panels/graph/module'
+], function(helpers) {
+  'use strict';
+
+  describe('GraphCtrl', function() {
+    var ctx = new helpers.ControllerTestContext();
+
+    beforeEach(module('grafana.services'));
+    beforeEach(module('grafana.panels.graph'));
+
+    beforeEach(ctx.providePhase());
+    beforeEach(ctx.createControllerPhase('GraphCtrl'));
+
+    describe('get_data with 2 series', function() {
+      beforeEach(function() {
+        ctx.annotationsSrv.getAnnotations = sinon.stub().returns(ctx.$q.when([]));
+        ctx.datasource.query = sinon.stub().returns(ctx.$q.when({
+          data: [
+            { target: 'test.cpu1', datapoints: [[1, 10]]},
+            { target: 'test.cpu2', datapoints: [[1, 10]]}
+          ]
+        }));
+        ctx.scope.render = sinon.spy();
+        ctx.scope.get_data();
+        ctx.scope.$digest();
+      });
+
+      it('should build legend model', function() {
+        expect(ctx.scope.legend[0].alias).to.be('test.cpu1');
+        expect(ctx.scope.legend[1].alias).to.be('test.cpu2');
+      });
+
+      it('should send time series to render', function() {
+        var data = ctx.scope.render.getCall(0).args[0];
+        expect(data.length).to.be(2);
+      });
+
+    });
+  });
+
+});
+

+ 0 - 31
src/test/specs/graph-panel-controller-specs.js

@@ -1,31 +0,0 @@
-/*define([
-  'panels/graphite/module'
-], function() {
-  'use strict';
-
-  describe('Graph panel controller', function() {
-    var _graphPanelCtrl;
-
-    beforeEach(module('grafana.panels.graphite'));
-    beforeEach(module(function($provide){
-      $provide.value('filterSrv',{});
-    }));
-
-    beforeEach(inject(function($controller, $rootScope) {
-      _graphPanelCtrl = $controller('graphite', {
-        $scope: $rootScope.$new()
-      });
-    }));
-
-    describe('init', function() {
-      beforeEach(function() {
-      });
-
-      it('asd', function() {
-
-      });
-    });
-  });
-
-});
-*/

+ 17 - 2
src/test/specs/helpers.js

@@ -1,11 +1,14 @@
 define([
-], function() {
+    'kbn'
+], function(kbn) {
   'use strict';
 
   function ControllerTestContext() {
     var self = this;
 
+    this.timeRange = { from:'now-1h', to: 'now'};
     this.datasource = {};
+    this.annotationsSrv = {};
     this.datasourceSrv = {
       getMetricSources: function() {},
       get: function() { return self.datasource; }
@@ -14,6 +17,7 @@ define([
     this.providePhase = function() {
       return module(function($provide) {
         $provide.value('datasourceSrv', self.datasourceSrv);
+        $provide.value('annotationsSrv', self.annotationsSrv);
       });
     };
 
@@ -22,9 +26,20 @@ define([
         self.scope = $rootScope.$new();
         self.scope.panel = {};
         self.scope.filter = {
-          timeRange: function() {}
+          timeRange: function(parse) {
+            if (!parse) {
+              return self.timeRange;
+            }
+            return {
+              from : kbn.parseDate(self.timeRange.from),
+              to : kbn.parseDate(self.timeRange.to)
+            };
+          }
         };
 
+        $rootScope.colors = [];
+        for (var i = 0; i < 50; i++) { $rootScope.colors.push('#' + i); }
+
         self.$q = $q;
         self.scope.skipDataOnInit = true;
         self.controller = $controller(controllerName, {

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

@@ -0,0 +1,30 @@
+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");
+      });
+    });
+  });
+});

+ 4 - 2
src/test/test-main.js

@@ -118,10 +118,12 @@ require([
     'specs/parser-specs',
     'specs/gfunc-specs',
     'specs/graphiteTargetCtrl-specs',
+    'specs/graph-ctrl-specs',
     'specs/filterSrv-specs',
     'specs/kbn-format-specs',
-    'specs/dashboardModel-specs',
-    'specs/influxSeries-specs'
+    'specs/dashboardSrv-specs',
+    'specs/influxSeries-specs',
+    'specs/overview-ctrl-specs',
   ], function () {
     window.__karma__.start();
   });