diff --git a/src/kibana/plugins/metric_vis/index.js b/src/kibana/plugins/metric_vis/index.js new file mode 100644 index 0000000000000..1fd0cfab5245a --- /dev/null +++ b/src/kibana/plugins/metric_vis/index.js @@ -0,0 +1,5 @@ +define(function (require) { + require('registry/vis_types').register(function (Private) { + return Private(require('plugins/metric_vis/metric_vis')); + }); +}); \ No newline at end of file diff --git a/src/kibana/plugins/metric_vis/metric_vis.html b/src/kibana/plugins/metric_vis/metric_vis.html new file mode 100644 index 0000000000000..550395940fc01 --- /dev/null +++ b/src/kibana/plugins/metric_vis/metric_vis.html @@ -0,0 +1,4 @@ +
+
{{metric.value}}
+
{{metric.label}}
+
\ No newline at end of file diff --git a/src/kibana/plugins/metric_vis/metric_vis.js b/src/kibana/plugins/metric_vis/metric_vis.js new file mode 100644 index 0000000000000..9596655e78803 --- /dev/null +++ b/src/kibana/plugins/metric_vis/metric_vis.js @@ -0,0 +1,33 @@ +define(function (require) { + // we need to load the css ourselves + require('css!plugins/metric_vis/metric_vis.css'); + + // we also need to load the controller and used by the template + require('plugins/metric_vis/metric_vis_controller'); + + return function (Private) { + var TemplateVisType = Private(require('plugins/vis_types/template/template_vis_type')); + var Schemas = Private(require('plugins/vis_types/_schemas')); + + // return the visType object, which kibana will use to display and configure new + // Vis object of this type. + return new TemplateVisType({ + name: 'metric', + title: 'Metric', + icon: 'fa-calculator', + template: require('text!plugins/metric_vis/metric_vis.html'), + schemas: new Schemas([ + { + group: 'metrics', + name: 'metric', + title: 'Metric', + min: 1, + max: 1, + defaults: [ + { type: 'count', schema: 'metric' } + ] + } + ]) + }); + }; +}); \ No newline at end of file diff --git a/src/kibana/plugins/metric_vis/metric_vis.less b/src/kibana/plugins/metric_vis/metric_vis.less new file mode 100644 index 0000000000000..6bfa6610fd422 --- /dev/null +++ b/src/kibana/plugins/metric_vis/metric_vis.less @@ -0,0 +1,12 @@ +.metric-vis { + width: 100%; + text-align: center; + + .metric-value { + font-size: 5em; + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} \ No newline at end of file diff --git a/src/kibana/plugins/metric_vis/metric_vis_controller.js b/src/kibana/plugins/metric_vis/metric_vis_controller.js new file mode 100644 index 0000000000000..2a954f80384b0 --- /dev/null +++ b/src/kibana/plugins/metric_vis/metric_vis_controller.js @@ -0,0 +1,23 @@ +define(function (require) { + // get the kibana/metric_vis module, and make sure that it requires the "kibana" module if it + // didn't already + var module = require('modules').get('kibana/metric_vis', ['kibana']); + + module.controller('KbnMetricVisController', function ($scope) { + var metric = $scope.metric = { + label: null, + value: null + }; + + $scope.$watch('esResponse', function (resp) { + if (!resp) { + metric.label = metric.value = null; + } else { + var agg = $scope.vis.aggs[0]; + metric.label = agg.makeLabel(); + if (agg.type.name === 'count') metric.value = resp.hits.total; + else metric.value = resp.aggregations[agg.id].value; + } + }); + }); +}); \ No newline at end of file diff --git a/tasks/config/less.js b/tasks/config/less.js index 8da0587a49557..15e259f2c653a 100644 --- a/tasks/config/less.js +++ b/tasks/config/less.js @@ -12,7 +12,8 @@ module.exports = { '<%= plugins %>/visualize/styles/main.less', '<%= plugins %>/visualize/styles/visualization.less', '<%= plugins %>/visualize/styles/main.less', - '<%= plugins %>/table_vis/table_vis.less' + '<%= plugins %>/table_vis/table_vis.less', + '<%= plugins %>/metric_vis/metric_vis.less' ], expand: true, ext: '.css', diff --git a/test/unit/index.html b/test/unit/index.html index 6211b5fbeb0c0..6b6f277546ab0 100644 --- a/test/unit/index.html +++ b/test/unit/index.html @@ -161,7 +161,8 @@ 'specs/components/agg_response/tabify/tabify', 'specs/components/agg_table/index', 'specs/plugins/vis_types/index', - 'specs/utils/slugify_id' + 'specs/utils/slugify_id', + 'specs/plugins/metric_vis/metric_vis_controller' ], function () { bootstrap(kibana, sinon); }); diff --git a/test/unit/specs/plugins/metric_vis/metric_vis_controller.js b/test/unit/specs/plugins/metric_vis/metric_vis_controller.js new file mode 100644 index 0000000000000..b3157a80ce680 --- /dev/null +++ b/test/unit/specs/plugins/metric_vis/metric_vis_controller.js @@ -0,0 +1,61 @@ +define(function (require) { + var metricVis = { + aggs: [{ + type: {name: 'count'}, + schema: 'metric', + makeLabel: function () { + return 'Count of documents'; + } + }] + }; + + var averageVis = { + aggs: [{ + id: 'agg', + type: {name: 'average'}, + schema: 'metric', + makeLabel: function () { + return 'Average bytes'; + } + }] + }; + + describe('metric vis', function () { + var $scope; + + beforeEach(module('kibana/metric_vis')); + beforeEach(inject(function ($rootScope, $controller) { + $scope = $rootScope.$new(); + $controller('KbnMetricVisController', {$scope: $scope}); + $scope.$digest(); + })); + + it('should set the metric', function () { + expect($scope).to.have.property('metric'); + }); + + it('should set the metric label and value for count', function () { + expect($scope.metric.label).to.not.be.ok(); + expect($scope.metric.value).to.not.be.ok(); + + $scope.vis = metricVis; + $scope.esResponse = {hits: {total: 4826}}; + $scope.$digest(); + + expect($scope.metric.label).to.be('Count of documents'); + expect($scope.metric.value).to.be($scope.esResponse.hits.total); + }); + + it('should set the metric value for average', function () { + expect($scope.metric.label).to.not.be.ok(); + expect($scope.metric.value).to.not.be.ok(); + + $scope.vis = averageVis; + $scope.esResponse = {hits: {total: 4826}, aggregations: {agg: {value: 1234}}}; + $scope.$digest(); + + expect($scope.metric.label).to.be('Average bytes'); + expect($scope.metric.value).to.be($scope.esResponse.aggregations.agg.value); + }); + }); +}); \ No newline at end of file