Skip to content

Commit

Permalink
Merge branch 'master' into fix/elastic#1962
Browse files Browse the repository at this point in the history
  • Loading branch information
stormpython committed Jan 20, 2015
2 parents 4086012 + d4caecf commit 3105008
Show file tree
Hide file tree
Showing 35 changed files with 574 additions and 52 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@
},
"repository": {
"type": "git",
"url": "git@github.com:elasticsearch/kibana4.git"
"url": "git@github.com:elasticsearch/kibana.git"
},
"author": "",
"license": "Apache 2.0",
"bugs": {
"url": "https://github.com/elasticsearch/kibana4/issues"
"url": "https://github.com/elasticsearch/kibana/issues"
},
"homepage": "https://github.com/elasticsearch/kibana4"
"homepage": "https://www.elasticsearch.org/overview/kibana"
}
4 changes: 4 additions & 0 deletions src/kibana/components/agg_response/point_series/_get_point.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ define(function (require) {
yScale: yScale
};

if (point.y === 'NaN') {
return;
}

if (series) {
point.series = unwrap(row[series.i]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ define(function (require) {

if (!multiY) {
var point = partGetPoint(row, aspects.y);
addToSiri(series, point, point.series);
if (point) addToSiri(series, point, point.series);
return;
}

aspects.y.forEach(function (y) {
var point = partGetPoint(row, y);
if (!point) return;

var prefix = point.series ? point.series + ': ' : '';
var seriesId = prefix + y.agg.id;
var seriesLabel = prefix + y.col.title;
Expand Down
17 changes: 17 additions & 0 deletions src/kibana/components/agg_types/controls/extended_stats.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="form-group" ng-controller="aggParam.controller">
<label for="field">
Metrics
</label>

<!-- validate that there is atleast one checkbox selected -->
<input type="hidden" ng-model="names[0]" name="first" required>
<p class="text-danger" ng-if="aggForm.first.$invalid">
select at least one stat
</p>

<div ng-repeat="stat in statNames" class="checkbox">
<label>
<input ng-model="map[stat]" type="checkbox"> {{stat}}
</label>
</div>
</div>
4 changes: 3 additions & 1 deletion src/kibana/components/agg_types/controls/ranges.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
name="range.to" />
</td>
<td>
<button ng-click="agg.params.ranges.splice($index, 1)"
<button
type="button"
ng-click="agg.params.ranges.splice($index, 1)"
class="btn btn-danger btn-xs">
<i class="fa fa-ban" ></i>
</button>
Expand Down
1 change: 1 addition & 0 deletions src/kibana/components/agg_types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ define(function (require) {
Private(require('components/agg_types/metrics/sum')),
Private(require('components/agg_types/metrics/min')),
Private(require('components/agg_types/metrics/max')),
Private(require('components/agg_types/metrics/extended_stats')),
Private(require('components/agg_types/metrics/cardinality')),
Private(require('components/agg_types/metrics/percentiles'))
],
Expand Down
84 changes: 84 additions & 0 deletions src/kibana/components/agg_types/metrics/extended_stats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
define(function (require) {
return function AggTypeMetricExtendedStatsProvider(Private) {
var _ = require('lodash');
var MetricAggType = Private(require('components/agg_types/metrics/_metric_agg_type'));
var getResponseAggConfig = Private(require('components/agg_types/metrics/_get_response_agg_config'));

var valueProps = {
makeLabel: function () {
return this.key + ' of ' + this.fieldDisplayName();
}
};

var statNames = [
'count',
'min',
'max',
'avg',
'sum',
'sum_of_squares',
'variance',
'std_deviation'
];

var exStatsType = new MetricAggType({
name: 'extended_stats',
title: 'Extended Stats',
makeLabel: function (agg) {
return 'Extended Stats on ' + agg.fieldDisplayName();
},
params: [
{
name: 'field',
filterFieldTypes: 'number'
},
{
name: 'names',
editor: require('text!components/agg_types/controls/extended_stats.html'),
default: statNames.slice(),
write: _.noop,
controller: function ($scope) {
$scope.map = mapList();
$scope.names = listMap();
$scope.statNames = statNames;

$scope.$watchCollection('agg.params.names', function (names) {
if (names === $scope.names) return;

$scope.names = _.intersection(statNames, names || []);
$scope.map = mapList();
});

$scope.$watchCollection('map', function () {
$scope.names = $scope.agg.params.names = listMap();
});

function mapList() {
return _.transform($scope.names, function (map, key) {
map[key] = true;
}, {});
}

function listMap() {
return _.transform(statNames, function (list, stat) {
if ($scope.map[stat]) list.push(stat);
}, []);
}
}
}
],
getResponseAggs: function (agg) {
var ValueAggConfig = getResponseAggConfig(agg, valueProps);
return _.map(agg.params.names, function (name) {
return new ValueAggConfig(name);
});
},
getValue: function (agg, bucket) {
return bucket[agg.parentId][agg.key];
}
});

exStatsType.statNames = statNames;
return exStatsType;
};
});
2 changes: 2 additions & 0 deletions src/kibana/components/agg_types/metrics/percentiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ define(function (require) {
});
},
getValue: function (agg, bucket) {
// percentiles for 1, 5, and 10 will come back as 1.0, 5.0, and 10.0 so we
// parse the keys and respond with the value that matches
return _.find(bucket[agg.parentId].values, function (value, key) {
return agg.key === parseFloat(key);
});
Expand Down
1 change: 1 addition & 0 deletions src/kibana/components/fancy_forms/_set_view_value.checksum
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
function(value){this.$viewValue=value;//changetodirtyif(this.$pristine){this.$dirty=true;this.$pristine=false;$animate.removeClass($element,PRISTINE_CLASS);$animate.addClass($element,DIRTY_CLASS);parentForm.$setDirty();}forEach(this.$parsers,function(fn){value=fn(value);});if(this.$modelValue!==value){this.$modelValue=value;ngModelSet($scope,value);forEach(this.$viewChangeListeners,function(listener){try{listener();}catch(e){$exceptionHandler(e);}});}}
45 changes: 45 additions & 0 deletions src/kibana/components/fancy_forms/fancy_forms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
define(function (require) {
var _ = require('lodash');
var $ = require('jquery');

var KbnFormController = require('components/fancy_forms/kbn_form');
var KbnModelController = require('components/fancy_forms/kbn_model');

require('modules')
.get('kibana')
.config(function ($provide) {
function decorateDirectiveController(DecorativeController) {
return function ($delegate, $injector) {
// directive providers are arrays
$delegate.forEach(function (directive) {
// get metadata about all init fns
var chain = [directive.controller, DecorativeController].map(function (fn) {
var deps = $injector.annotate(fn);
return { deps: deps, fn: _.isArray(fn) ? _.last(fn) : fn };
});

// replace the controller with one that will setup the actual controller
directive.controller = function stub() {
var allDeps = _.toArray(arguments);
return chain.reduce(function (controller, link, i) {
var deps = allDeps.splice(0, link.deps.length);
return link.fn.apply(controller, deps) || controller;
}, this);
};

// set the deps of our new controller to be the merged deps of every fn
directive.controller.$inject = chain.reduce(function (deps, link) {
return deps.concat(link.deps);
}, []);
});

return $delegate;
};
}


$provide.decorator('formDirective', decorateDirectiveController(KbnFormController));
$provide.decorator('ngFormDirective', decorateDirectiveController(KbnFormController));
$provide.decorator('ngModelDirective', decorateDirectiveController(KbnModelController));
});
});
26 changes: 26 additions & 0 deletions src/kibana/components/fancy_forms/kbn_form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
define(function (require) {
var _ = require('lodash');

/**
* Extension of Angular's FormController class
* that provides helpers for error handling/validation.
*
* @param {$scope} $scope
*/
function KbnFormController($scope, $element) {
var self = this;

self.errorCount = function () {
return _.reduce(self.$error, function (count, controls, errorType) {
return count + _.size(controls);
}, 0);
};

self.describeErrors = function () {
var count = self.errorCount();
return count + ' Error' + (count === 1 ? '' : 's');
};
}

return KbnFormController;
});
102 changes: 102 additions & 0 deletions src/kibana/components/fancy_forms/kbn_model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
define(function (require) {
var _ = require('lodash');
var SVV_CHECKSUM = require('text!components/fancy_forms/_set_view_value.checksum');
var PRISTINE_CLASS = 'ng-pristine';
var DIRTY_CLASS = 'ng-dirty';

// http://goo.gl/eJofve
var nullFormCtrl = {
$addControl: _.noop,
$removeControl: _.noop,
$setValidity: _.noop,
$setDirty: _.noop,
$setPristine: _.noop
};

/**
* Extension of Angular's NgModelController class
* that ensures models are marked "dirty" after
* they move from an invalid state to valid.
*
* @param {$scope} $scope
*/
function KbnModelController($scope, $element, $animate) {
var ngModel = this;

// verify that angular works the way we are assuming it does
if (String(ngModel.$setViewValue).replace(/\s+/g, '') !== SVV_CHECKSUM) {
throw new Error('ngModelController.$setViewValue has updated but KbnModelController has not!');
}

/**
* Get the form a model belongs to
*
* @return {NgFormController} - the parent controller of a noop controller
*/
ngModel.$getForm = function () {
return $element.inheritedData('$formController') || nullFormCtrl;
};

/**
* Update the ngModel to be "dirty" if it is pristine.
*
* @return {undefined}
*/
ngModel.$setDirty = function () {
if (ngModel.$dirty) return;
ngModel.$dirty = true;
ngModel.$pristine = false;
$animate.removeClass($element, PRISTINE_CLASS);
$animate.addClass($element, DIRTY_CLASS);
ngModel.$getForm().$setDirty();
};

/**
* While the model is pristine, ensure that the model
* gets set to dirty if it becomes invalid. If the model
* becomes dirty of other reasons stop watching and
* waitForPristine()
*
* @return {undefined}
*/
function watchForDirtyOrInvalid() {
var unwatch = $scope.$watch(get, react);

function get() {
return ngModel.$dirty || ngModel.$invalid;
}

function react(is, was) {
if (is === was) return;
unwatch();
waitForPristine();
ngModel.$setDirty();
}
}

/**
* Once a model becomes dirty, there is no longer a need
* for a watcher. Instead, we will react to the $setPristine
* method being called. This is the only way for a model to go
* from dirty -> pristine.
*
* @return {[type]} [description]
*/
function waitForPristine() {
var fn = ngModel.$setPristine;
ngModel.$setPristine = function () {
var ret = fn.apply(this, arguments);
if (ngModel.$pristine) {
ngModel.$setPristine = fn;
watchForDirtyOrInvalid();
}
return ret;
};
}

if (ngModel.$dirty) waitForPristine();
else watchForDirtyOrInvalid();
}

return KbnModelController;
});
2 changes: 1 addition & 1 deletion src/kibana/components/vislib/styles/_layout.less
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
.display(flex);
.flex(1 0 20px);
overflow: visible;
margin: 0 5px 0 0;
margin: 0;
min-height: 0;
min-width: 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/kibana/components/vislib/styles/_svg.less
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}

.tick text {
font-size: 9pt;
font-size: 8pt;
fill: #848e96;
}

Expand Down
6 changes: 4 additions & 2 deletions src/kibana/plugins/dashboard/services/_saved_dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ define(function (require) {
title: 'string',
hits: 'integer',
description: 'string',
panelsJSON: 'string'
panelsJSON: 'string',
version: 'integer'
},

// defeult values to assign to the doc
defaults: {
title: 'New Dashboard',
hits: 0,
description: '',
panelsJSON: '[]'
panelsJSON: '[]',
version: 1
},

searchSource: true,
Expand Down
Loading

0 comments on commit 3105008

Please sign in to comment.