mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Merge branch 'master' into fix/3604
This commit is contained in:
commit
ea9129775e
18 changed files with 168 additions and 30 deletions
|
@ -22,9 +22,17 @@
|
|||
name="field"
|
||||
required
|
||||
ng-model="agg.params.field"
|
||||
ng-if="indexedFields.length"
|
||||
auto-select-if-only-one="indexedFields"
|
||||
ng-options="field as field.displayName group by field.type for field in indexedFields"
|
||||
ng-change="aggParam.onChange(agg)">
|
||||
</select>
|
||||
|
||||
<div class="hintbox" ng-if="!indexedFields.length">
|
||||
<p>
|
||||
<i class="fa fa-danger text-danger"></i>
|
||||
<strong>No Compatible Fields:</strong> The "{{ vis.indexPattern.id }}" index pattern does not any of the following field types: {{ agg.type.params.byName.field.filterFieldTypes | commaList:false }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -17,6 +17,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input ng-model="agg.params.filters.length" name="filterLength" required min="1" type="number" class="ng-hide">
|
||||
<div class="hintbox" ng-show="aggForm.filterLength.$invalid">
|
||||
<p>
|
||||
<i class="fa fa-danger text-danger"></i>
|
||||
<strong>Required:</strong> You must specify at least one filter
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
click-focus="'filter'+(agg.params.filters.length-1)"
|
||||
ng-click="agg.params.filters.push({input:{}})"
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
</div>
|
||||
|
||||
<input ng-model="validLength" name="validLength" required type="hidden">
|
||||
<p ng-show="aggForm.validLength.$invalid" class="text-danger text-center">
|
||||
You mush specify at least one percentile
|
||||
</p>
|
||||
<div class="hintbox" ng-show="aggForm.validLength.$invalid">
|
||||
<p>
|
||||
<i class="fa fa-danger text-danger"></i>
|
||||
<strong>Required:</strong> You mush specify at least one percentile
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
ng-click="add()"
|
||||
|
@ -28,4 +31,4 @@
|
|||
class="sidebar-item-button primary">
|
||||
<i class="fa fa-plus"></i> Add Percent
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
<label>JSON Input</label>
|
||||
<i class="fa fa-info-circle"></i>
|
||||
</span>
|
||||
<div class="hintbox" ng-show="showJsonHint">Any JSON formatted properties you add here will be merged with the elasticsearch aggregation definition for this section. For example <i>shard_size</i> on a <i>terms</i> aggregation</div>
|
||||
<div class="hintbox" ng-show="showJsonHint">
|
||||
<p>
|
||||
Any JSON formatted properties you add here will be merged with the elasticsearch aggregation definition for this section. For example <i>shard_size</i> on a <i>terms</i> aggregation
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<textarea
|
||||
type="text"
|
||||
|
@ -12,4 +16,4 @@
|
|||
validate-json
|
||||
></textarea>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
</div>
|
||||
|
||||
<input ng-model="validLength" name="validLength" required type="hidden">
|
||||
<p ng-show="aggForm.validLength.$invalid" class="text-danger text-center">
|
||||
You must specify at least one value
|
||||
</p>
|
||||
<div class="hintbox" ng-show="aggForm.validLength.$invalid">
|
||||
<p>
|
||||
<i class="fa fa-danger text-danger"></i>
|
||||
<strong>Required:</strong> You must specify at least one value
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
ng-click="add()"
|
||||
|
@ -27,4 +30,4 @@
|
|||
class="sidebar-item-button primary">
|
||||
<i class="fa fa-plus"></i> Add value
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
26
src/kibana/components/comma_list_filter.js
Normal file
26
src/kibana/components/comma_list_filter.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
|
||||
require('modules')
|
||||
.get('kibana')
|
||||
.filter('commaList', function () {
|
||||
/**
|
||||
* Angular filter that accepts either an array or a comma-seperated string
|
||||
* and outputs either an array, or a comma-seperated string for presentation.
|
||||
*
|
||||
* @param {String|Array} input - The comma-seperated list or array
|
||||
* @param {Boolean} inclusive - Should the list be joined with an "and"?
|
||||
* @return {String}
|
||||
*/
|
||||
return function (input, inclusive) {
|
||||
var list = _.commaSeperatedList(input);
|
||||
if (list.length < 2) {
|
||||
return list.join('');
|
||||
}
|
||||
|
||||
var conj = inclusive ? ' and ' : ' or ';
|
||||
return list.slice(0, -1).join(', ') + conj + _.last(list);
|
||||
|
||||
};
|
||||
});
|
||||
});
|
|
@ -5,16 +5,16 @@
|
|||
</ul>
|
||||
|
||||
<div class="content">
|
||||
<table class="table table-condensed" ng-show="mode == 'table'" bindonce>
|
||||
<table class="table table-condensed" ng-show="mode == 'table'">
|
||||
<tbody>
|
||||
<tr ng-repeat="field in fields" bindonce>
|
||||
<tr ng-repeat="field in fields">
|
||||
<td field-name="field"
|
||||
field-type="mapping[field].type"
|
||||
width="1%"
|
||||
class="doc-viewer-field">
|
||||
</td>
|
||||
<td width="1%" class="doc-viewer-buttons" ng-if="filter">
|
||||
<span bo-if="mapping[field].filterable">
|
||||
<span ng-if="mapping[field].filterable">
|
||||
<i ng-click="filter(mapping[field], flattened[field], '+')"
|
||||
tooltip="Filter for value"
|
||||
tooltip-append-to-body="1"
|
||||
|
@ -24,11 +24,11 @@
|
|||
tooltip-append-to-body="1"
|
||||
class="fa fa-search-minus"></i>
|
||||
</span>
|
||||
<span bo-if="!mapping[field].filterable" tooltip="Unindexed fields can not be searched">
|
||||
<span ng-if="!mapping[field].filterable" tooltip="Unindexed fields can not be searched">
|
||||
<i class="fa fa-search-plus text-muted"></i>
|
||||
<i class="fa fa-search-minus text-muted"></i>
|
||||
</span>
|
||||
<span bo-if="columns">
|
||||
<span ng-if="columns">
|
||||
<i ng-click="toggleColumn(field)"
|
||||
tooltip="Toggle column in table"
|
||||
tooltip-append-to-body="1"
|
||||
|
@ -37,15 +37,15 @@
|
|||
</td>
|
||||
|
||||
<td>
|
||||
<i bo-if="!mapping[field] && field[0] === '_'"
|
||||
<i ng-if="!mapping[field] && field[0] === '_'"
|
||||
tooltip-placement="top"
|
||||
tooltip="Field names beginning with _ are not supported"
|
||||
class="fa fa-warning text-color-warning ng-scope doc-viewer-underscore"></i>
|
||||
<i bo-if="!mapping[field] && field[0] !== '_' && !showArrayInObjectsWarning(doc, field)"
|
||||
<i ng-if="!mapping[field] && field[0] !== '_' && !showArrayInObjectsWarning(doc, field)"
|
||||
tooltip-placement="top"
|
||||
tooltip="No cached mapping for this field. Refresh your mapping from the Settings > Indices page"
|
||||
class="fa fa-warning text-color-warning ng-scope doc-viewer-no-mapping"></i>
|
||||
<i bo-if="showArrayInObjectsWarning(doc, field)"
|
||||
<i ng-if="showArrayInObjectsWarning(doc, field)"
|
||||
tooltip-placement="top"
|
||||
tooltip="Objects in arrays are not well supported."
|
||||
class="fa fa-warning text-color-warning ng-scope doc-viewer-object-array"></i>
|
||||
|
|
|
@ -77,6 +77,9 @@ define(function (require) {
|
|||
Handler.prototype.render = function () {
|
||||
var self = this;
|
||||
var charts = this.charts = [];
|
||||
var selection = d3.select(this.el);
|
||||
|
||||
selection.selectAll('*').remove();
|
||||
|
||||
this._validateData();
|
||||
this.renderArray.forEach(function (property) {
|
||||
|
@ -86,8 +89,7 @@ define(function (require) {
|
|||
});
|
||||
|
||||
// render the chart(s)
|
||||
d3.select(this.el)
|
||||
.selectAll('.chart')
|
||||
selection.selectAll('.chart')
|
||||
.each(function (chartData) {
|
||||
var chart = new self.ChartClass(self, this, chartData);
|
||||
var enabledEvents;
|
||||
|
|
|
@ -100,10 +100,14 @@ define(function (require) {
|
|||
* @method destroy
|
||||
*/
|
||||
Vis.prototype.destroy = function () {
|
||||
var selection = d3.select(this.el).select('.vis-wrapper');
|
||||
|
||||
this.resizeChecker.off('resize', this.resize);
|
||||
this.resizeChecker.destroy();
|
||||
if (this.handler) this._runOnHandler('destroy');
|
||||
d3.select(this.el).selectAll('*').remove();
|
||||
|
||||
selection.remove();
|
||||
selection = null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,7 +44,10 @@ define(function (require) {
|
|||
* @returns {HTMLElement} Contains the D3 chart
|
||||
*/
|
||||
Chart.prototype.render = function () {
|
||||
return d3.select(this.chartEl).call(this.draw());
|
||||
var selection = d3.select(this.chartEl);
|
||||
|
||||
selection.selectAll('*').remove();
|
||||
selection.call(this.draw());
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -68,7 +71,10 @@ define(function (require) {
|
|||
* @method destroy
|
||||
*/
|
||||
Chart.prototype.destroy = function () {
|
||||
d3.select(this.chartEl).selectAll('*').remove();
|
||||
var selection = d3.select(this.chartEl);
|
||||
|
||||
selection.remove();
|
||||
selection = null;
|
||||
};
|
||||
|
||||
return Chart;
|
||||
|
|
|
@ -45,10 +45,10 @@
|
|||
<i aria-hidden="true" class="fa-link fa"></i>
|
||||
</a>
|
||||
</p>
|
||||
<div bo-if="indexPattern.timeFieldName && indexPattern.intervalName" class="alert alert-info">
|
||||
<div ng-if="indexPattern.timeFieldName && indexPattern.intervalName" class="alert alert-info">
|
||||
This index uses a <strong>Time-based index pattern</strong> which repeats <span bo-text="indexPattern.getInterval().display"></span>
|
||||
</div>
|
||||
<div bo-if="conflictFields.length" class="alert alert-warning">
|
||||
<div ng-if="conflictFields.length" class="alert alert-warning">
|
||||
<strong>Mapping conflict!</strong> {{conflictFields.length > 1 ? conflictFields.length : 'A'}} field{{conflictFields.length > 1 ? 's' : ''}} {{conflictFields.length > 1 ? 'are' : 'is'}} defined as several types (string, integer, etc) across the indices that match this pattern. You may still be able to use these conflict fields in parts of Kibana, but they will be unavailable for functions that require Kibana to know their type. Correcting this issue will require reindexing your data.
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -38,7 +38,9 @@ define(function (require) {
|
|||
if (!tab) $scope.changeTab($scope.fieldTypes[0]);
|
||||
});
|
||||
|
||||
$scope.conflictFields = _.filter($scope.indexPattern.fields, {type: 'conflict'});
|
||||
$scope.$watchCollection('indexPattern.fields', function () {
|
||||
$scope.conflictFields = _.filter($scope.indexPattern.fields, {type: 'conflict'});
|
||||
});
|
||||
|
||||
$scope.refreshFields = function () {
|
||||
$scope.indexPattern.refreshFields();
|
||||
|
@ -73,4 +75,4 @@ define(function (require) {
|
|||
return $scope.indexPattern.save();
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<h5>
|
||||
Index Patterns
|
||||
<a
|
||||
bo-if="edittingId"
|
||||
ng-if="edittingId"
|
||||
href="#/settings/indices"
|
||||
class="btn btn-primary btn-xs"
|
||||
aria-label="Add New">
|
||||
|
|
|
@ -8,6 +8,7 @@ define(function (require) {
|
|||
require('directives/saved_object_finder');
|
||||
require('components/visualize/visualize');
|
||||
require('components/clipboard/clipboard');
|
||||
require('components/comma_list_filter');
|
||||
|
||||
require('filters/uriescape');
|
||||
|
||||
|
|
|
@ -256,5 +256,25 @@ define(function (require) {
|
|||
get: function (obj, path) {
|
||||
return _.deepGet(obj, path);
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse a comma-seperated list into an array
|
||||
* efficiently, or just return if already an array
|
||||
*
|
||||
* @param {string|array} input - the comma-seperated list
|
||||
* @return {array}
|
||||
*/
|
||||
commaSeperatedList: function (input) {
|
||||
if (_.isArray(input)) return input;
|
||||
|
||||
var source = String(input || '').split(',');
|
||||
var list = [];
|
||||
while (source.length) {
|
||||
var item = source.shift().trim();
|
||||
if (item) list.push(item);
|
||||
}
|
||||
|
||||
return list;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
32
test/unit/specs/components/comma_list_filter.js
Normal file
32
test/unit/specs/components/comma_list_filter.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
define(function (require) {
|
||||
require('components/comma_list_filter');
|
||||
|
||||
describe('Comma-List filter', function () {
|
||||
|
||||
var commaList;
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function ($injector) {
|
||||
commaList = $injector.get('commaListFilter');
|
||||
}));
|
||||
|
||||
it('converts a string to a pretty list', function () {
|
||||
expect(commaList('john,jaine,jim', true)).to.be('john, jaine and jim');
|
||||
expect(commaList('john,jaine,jim', false)).to.be('john, jaine or jim');
|
||||
});
|
||||
|
||||
it('can accept an array too', function () {
|
||||
expect(commaList(['john', 'jaine', 'jim'])).to.be('john, jaine or jim');
|
||||
});
|
||||
|
||||
it('handles undefined ok', function () {
|
||||
expect(commaList()).to.be('');
|
||||
});
|
||||
|
||||
it('handls single values ok', function () {
|
||||
expect(commaList(['john'])).to.be('john');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -27,6 +27,7 @@ define(function (require) {
|
|||
var beforeEvent = 'click';
|
||||
var afterEvent = 'brush';
|
||||
var vis;
|
||||
var secondVis;
|
||||
var numberOfCharts;
|
||||
|
||||
beforeEach(function () {
|
||||
|
@ -36,12 +37,14 @@ define(function (require) {
|
|||
beforeEach(function () {
|
||||
inject(function (d3, Private) {
|
||||
vis = Private(require('vislib_fixtures/_vis_fixture'))();
|
||||
secondVis = Private(require('vislib_fixtures/_vis_fixture'))();
|
||||
require('css!components/vislib/styles/main');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$(vis.el).remove();
|
||||
$(secondVis.el).remove();
|
||||
vis = null;
|
||||
});
|
||||
|
||||
|
@ -86,11 +89,17 @@ define(function (require) {
|
|||
|
||||
describe('destroy Method', function () {
|
||||
beforeEach(function () {
|
||||
vis.destroy();
|
||||
vis.render(data);
|
||||
secondVis.render(data);
|
||||
secondVis.destroy();
|
||||
});
|
||||
|
||||
it('should remove all DOM elements from el', function () {
|
||||
expect($('.vis-wrapper').length).to.be(0);
|
||||
expect($(secondVis.el).find('.vis-wrapper').length).to.be(0);
|
||||
});
|
||||
|
||||
it('should not remove visualizations that have not been destroyed', function () {
|
||||
expect($(vis.el).find('.vis-wrapper').length).to.be(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -120,5 +120,14 @@ define(function (require) {
|
|||
expect(typeof myChart.render === 'function').to.be(true);
|
||||
});
|
||||
|
||||
it('should destroy the chart element', function () {
|
||||
// Once destroy is called, a chart should not be able to be drawn
|
||||
myChart.destroy();
|
||||
|
||||
expect(function () {
|
||||
myChart.draw();
|
||||
}).to.throwError();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue