Merge branch 'master' into fix/#1769
This commit is contained in:
commit
45a887d052
|
@ -104,7 +104,7 @@ define(function (require) {
|
|||
var groupMap = chartData.splits || (chartData.splits = {});
|
||||
|
||||
result.buckets.forEach(function (bucket) {
|
||||
var bucketId = bucket.key + (col.field ? ': ' + col.field.name : '');
|
||||
var bucketId = bucket.key + (col.field ? ': ' + col.field.displayName : '');
|
||||
var group = groupMap[bucketId];
|
||||
|
||||
if (!group) {
|
||||
|
@ -167,7 +167,7 @@ define(function (require) {
|
|||
}
|
||||
|
||||
if (config.field) {
|
||||
config.label = config.field.name;
|
||||
config.label = config.field.displayName;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,11 +6,11 @@ define(function (require) {
|
|||
// record the the depth
|
||||
var depth = item.depth - 1;
|
||||
|
||||
// Using the aggConfig determin what the field name is. If the aggConfig
|
||||
// Using the aggConfig determine what the field name is. If the aggConfig
|
||||
// doesn't exist (which means it's an _all agg) then use the level for
|
||||
// the field name
|
||||
var col = item.aggConfig;
|
||||
var field = (col && col.params && col.params.field && col.params.field.name)
|
||||
var field = (col && col.params && col.params.field && col.params.field.displayName)
|
||||
|| (col && col.label)
|
||||
|| ('level ' + item.depth);
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ define(function (require) {
|
|||
var agg = firstAgg._next;
|
||||
var split = buildSplit(agg, metric, bucket[agg.id]);
|
||||
// Since splits display labels we need to set it.
|
||||
split.label = bucket.key + ': ' + firstAgg.params.field.name;
|
||||
split.label = bucket.key + ': ' + firstAgg.params.field.displayName;
|
||||
split.tooltipFormatter = tooltipFormatter(raw.columns);
|
||||
return split;
|
||||
});
|
||||
|
|
|
@ -1,33 +1,8 @@
|
|||
<paginate
|
||||
<paginated-table
|
||||
ng-if="formattedRows.length"
|
||||
|
||||
list="formattedRows"
|
||||
per-page-prop="perPage"
|
||||
|
||||
class="agg-table">
|
||||
<div class="agg-table-paginated">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr bindonce>
|
||||
<th
|
||||
ng-repeat="col in table.columns"
|
||||
ng-click="aggTable.cycleSort(col)"
|
||||
ng-class="aggTable.getColumnClass(col, $first, $last)">
|
||||
<span bo-text="col.title"></span>
|
||||
<i
|
||||
class="fa"
|
||||
ng-class="{
|
||||
'fa-sort-asc': aggTable.sort.col === col && aggTable.sort.asc,
|
||||
'fa-sort-desc': aggTable.sort.col === col && !aggTable.sort.asc,
|
||||
'fa-sort': !aggTable.sort || aggTable.sort.col !== col
|
||||
}">
|
||||
</i>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody kbn-rows="page" kbn-rows-min="perPage"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
rows="formattedRows"
|
||||
columns="formattedColumns"
|
||||
per-page="perPage">
|
||||
|
||||
<div class="agg-table-controls">
|
||||
<a class="small" ng-click="aggTable.exportAsCsv()">
|
||||
|
@ -35,4 +10,4 @@
|
|||
</a>
|
||||
<paginate-controls></paginate-controls>
|
||||
</div>
|
||||
</paginate>
|
||||
</paginated-table>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
define(function (require) {
|
||||
require('components/paginated_table/paginated_table');
|
||||
require('services/compile_recursive_directive');
|
||||
require('css!components/agg_table/agg_table.css');
|
||||
|
||||
|
@ -7,7 +8,6 @@ define(function (require) {
|
|||
.directive('kbnAggTable', function ($filter, config, Private, compileRecursiveDirective) {
|
||||
var _ = require('lodash');
|
||||
|
||||
var tabifyAggResponse = Private(require('components/agg_response/tabify/tabify'));
|
||||
var orderBy = $filter('orderBy');
|
||||
|
||||
return {
|
||||
|
@ -33,42 +33,6 @@ define(function (require) {
|
|||
quoteValues: config.get('csv:quoteValues')
|
||||
};
|
||||
|
||||
self.getColumnClass = function (col, $first, $last) {
|
||||
var cls = [];
|
||||
var agg = $scope.table.aggConfig(col);
|
||||
|
||||
if ($last || (agg.schema.group === 'metrics')) {
|
||||
cls.push('visualize-table-right');
|
||||
}
|
||||
|
||||
if (!self.sort || self.sort.field !== col) {
|
||||
cls.push('no-sort');
|
||||
}
|
||||
|
||||
return cls.join(' ');
|
||||
};
|
||||
|
||||
self.cycleSort = function (col) {
|
||||
if (!self.sort || self.sort.col !== col) {
|
||||
self.sort = {
|
||||
col: col,
|
||||
asc: true
|
||||
};
|
||||
} else if (self.sort.asc) {
|
||||
self.sort.asc = false;
|
||||
} else {
|
||||
self.sort = null;
|
||||
}
|
||||
|
||||
if (self.sort && !self.sort.getter) {
|
||||
var colI = $scope.table.columns.indexOf(self.sort.col);
|
||||
self.sort.getter = function (row) {
|
||||
return row[colI];
|
||||
};
|
||||
if (colI === -1) self.sort = null;
|
||||
}
|
||||
};
|
||||
|
||||
self.exportAsCsv = function () {
|
||||
var csv = new Blob([self.toCsv()], { type: 'text/plain' });
|
||||
self._saveAs(csv, self.csv.filename);
|
||||
|
@ -104,31 +68,43 @@ define(function (require) {
|
|||
}).join('');
|
||||
};
|
||||
|
||||
$scope.$watchMulti([
|
||||
'table',
|
||||
'aggTable.sort.asc',
|
||||
'aggTable.sort.col'
|
||||
], function () {
|
||||
$scope.$watch('table', function () {
|
||||
var table = $scope.table;
|
||||
|
||||
if (!table) {
|
||||
$scope.formattedRows = null;
|
||||
$scope.formattedColumns = null;
|
||||
return;
|
||||
}
|
||||
|
||||
setFormattedRows(table);
|
||||
setFormattedColumns(table);
|
||||
});
|
||||
|
||||
function setFormattedColumns(table) {
|
||||
$scope.formattedColumns = table.columns.map(function (col, i) {
|
||||
var formattedColumn = {
|
||||
title: col.title
|
||||
};
|
||||
|
||||
var agg = $scope.table.aggConfig(col);
|
||||
var last = i === (table.columns.length - 1);
|
||||
|
||||
if (last || (agg.schema.group === 'metrics')) {
|
||||
formattedColumn.class = 'visualize-table-right';
|
||||
}
|
||||
|
||||
return formattedColumn;
|
||||
});
|
||||
}
|
||||
|
||||
function setFormattedRows(table) {
|
||||
var formatters = table.columns.map(function (col) {
|
||||
return table.fieldFormatter(col);
|
||||
});
|
||||
|
||||
// sort the row values, not formatted
|
||||
if (self.sort) {
|
||||
$scope.formattedRows = orderBy(table.rows, self.sort.getter, !self.sort.asc);
|
||||
} else {
|
||||
$scope.formattedRows = null;
|
||||
}
|
||||
|
||||
// format all row values
|
||||
$scope.formattedRows = ($scope.formattedRows || table.rows).map(function (row) {
|
||||
$scope.formattedRows = (table.rows).map(function (row) {
|
||||
return row.map(function (cell, i) {
|
||||
return formatters[i](cell);
|
||||
});
|
||||
|
@ -136,7 +112,7 @@ define(function (require) {
|
|||
|
||||
// update the csv file's title
|
||||
self.csv.filename = (table.title() || 'table') + '.csv';
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ define(function (require) {
|
|||
title: 'Histogram',
|
||||
ordered: {},
|
||||
makeLabel: function (aggConfig) {
|
||||
return aggConfig.params.field.name;
|
||||
return aggConfig.params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ define(function (require) {
|
|||
name: 'range',
|
||||
title: 'Range',
|
||||
makeLabel: function (aggConfig) {
|
||||
return aggConfig.params.field.name + ' ranges';
|
||||
return aggConfig.params.field.displayName + ' ranges';
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ define(function (require) {
|
|||
name: 'significant_terms',
|
||||
title: 'Significant Terms',
|
||||
makeLabel: function (aggConfig) {
|
||||
return 'Top ' + aggConfig.params.size + ' unusual terms in ' + aggConfig.params.field.name;
|
||||
return 'Top ' + aggConfig.params.size + ' unusual terms in ' + aggConfig.params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ define(function (require) {
|
|||
title: 'Terms',
|
||||
makeLabel: function (aggConfig) {
|
||||
var params = aggConfig.params;
|
||||
return params.order.display + ' ' + params.size + ' ' + params.field.name;
|
||||
return params.order.display + ' ' + params.size + ' ' + params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
required
|
||||
ng-model="params.field"
|
||||
ng-options="
|
||||
field as field.name group by field.type for field in aggConfig.vis.indexPattern.fields.raw
|
||||
field as field.displayName group by field.type for field in aggConfig.vis.indexPattern.fields.raw
|
||||
| fieldType: aggParam.filterFieldTypes
|
||||
| filter: { indexed: true }
|
||||
| orderBy: ['type', 'name']
|
||||
|
|
|
@ -15,7 +15,7 @@ define(function (require) {
|
|||
name: 'avg',
|
||||
title: 'Average',
|
||||
makeLabel: function (aggConfig) {
|
||||
return 'Average ' + aggConfig.params.field.name;
|
||||
return 'Average ' + aggConfig.params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ define(function (require) {
|
|||
name: 'sum',
|
||||
title: 'Sum',
|
||||
makeLabel: function (aggConfig) {
|
||||
return 'Sum of ' + aggConfig.params.field.name;
|
||||
return 'Sum of ' + aggConfig.params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ define(function (require) {
|
|||
name: 'min',
|
||||
title: 'Min',
|
||||
makeLabel: function (aggConfig) {
|
||||
return 'Min ' + aggConfig.params.field.name;
|
||||
return 'Min ' + aggConfig.params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ define(function (require) {
|
|||
name: 'max',
|
||||
title: 'Max',
|
||||
makeLabel: function (aggConfig) {
|
||||
return 'Max ' + aggConfig.params.field.name;
|
||||
return 'Max ' + aggConfig.params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ define(function (require) {
|
|||
name: 'cardinality',
|
||||
title: 'Unique count',
|
||||
makeLabel: function (aggConfig) {
|
||||
return 'Unique count of ' + aggConfig.params.field.name;
|
||||
return 'Unique count of ' + aggConfig.params.field.displayName;
|
||||
},
|
||||
params: [
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
define(function (require) {
|
||||
return function IndexPatternFactory(Private, timefilter, configFile, Notifier) {
|
||||
return function IndexPatternFactory(Private, timefilter, configFile, Notifier, shortDotsFilter) {
|
||||
var _ = require('lodash');
|
||||
var angular = require('angular');
|
||||
var errors = require('errors');
|
||||
|
@ -95,11 +95,19 @@ define(function (require) {
|
|||
field.count = field.count || 0;
|
||||
|
||||
// non-enumerable type so that it does not get included in the JSON
|
||||
Object.defineProperty(field, 'format', {
|
||||
enumerable: false,
|
||||
get: function () {
|
||||
var formatName = self.customFormats && self.customFormats[field.name];
|
||||
return formatName ? fieldFormats.byName[formatName] : fieldFormats.defaultByType[field.type];
|
||||
Object.defineProperties(field, {
|
||||
format: {
|
||||
enumerable: false,
|
||||
get: function () {
|
||||
var formatName = self.customFormats && self.customFormats[field.name];
|
||||
return formatName ? fieldFormats.byName[formatName] : fieldFormats.defaultByType[field.type];
|
||||
}
|
||||
},
|
||||
displayName: {
|
||||
enumerable: false,
|
||||
get: function () {
|
||||
return shortDotsFilter(field.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
define(function (require) {
|
||||
var module = require('modules').get('kibana/index_patterns');
|
||||
require('filters/short_dots');
|
||||
|
||||
module.service('indexPatterns', function (configFile, es, Notifier, Private, Promise) {
|
||||
var self = this;
|
||||
|
|
34
src/kibana/components/paginated_table/paginated_table.html
Normal file
34
src/kibana/components/paginated_table/paginated_table.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
<paginate
|
||||
ng-if="sortedRows.length"
|
||||
list="sortedRows"
|
||||
per-page-prop="perPage"
|
||||
class="agg-table">
|
||||
<div class="agg-table-paginated">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr bindonce>
|
||||
<th
|
||||
ng-repeat="col in columns"
|
||||
ng-click="paginatedTable.sortColumn(col)"
|
||||
class="{{ col.class }}">
|
||||
<span bo-text="col.title"></span>
|
||||
<i
|
||||
class="fa"
|
||||
ng-class="{
|
||||
'fa-sort-asc': paginatedTable.sort.columnName === col.title && paginatedTable.sort.direction === 'asc',
|
||||
'fa-sort-desc': paginatedTable.sort.columnName === col.title && paginatedTable.sort.direction === 'desc',
|
||||
'fa-sort': paginatedTable.sort.direction === null || paginatedTable.sort.columnName !== col.title
|
||||
}">
|
||||
</i>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody kbn-rows="page" kbn-rows-min="perPage"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- auto-inserted by the paginate directive... -->
|
||||
<!-- <paginate-controls></paginate-controls> -->
|
||||
<div class="pagination-container" ng-transclude></div>
|
||||
|
||||
</paginate>
|
77
src/kibana/components/paginated_table/paginated_table.js
Normal file
77
src/kibana/components/paginated_table/paginated_table.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
define(function (require) {
|
||||
require('modules')
|
||||
.get('kibana')
|
||||
.directive('paginatedTable', function ($filter, config, Private) {
|
||||
var _ = require('lodash');
|
||||
var orderBy = $filter('orderBy');
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: require('text!components/paginated_table/paginated_table.html'),
|
||||
transclude: true,
|
||||
scope: {
|
||||
rows: '=',
|
||||
columns: '=',
|
||||
perPage: '=?',
|
||||
sortHandler: '=?',
|
||||
showSelector: '=?'
|
||||
},
|
||||
controllerAs: 'paginatedTable',
|
||||
controller: function ($scope) {
|
||||
var self = this;
|
||||
self.sort = {
|
||||
columnName: null,
|
||||
direction: null
|
||||
};
|
||||
|
||||
self.sortColumn = function (col) {
|
||||
var sortDirection;
|
||||
var cols = _.pluck($scope.columns, 'title');
|
||||
var index = cols.indexOf(col.title);
|
||||
|
||||
if (index === -1) return;
|
||||
|
||||
if (self.sort.columnName !== col.title) {
|
||||
sortDirection = 'asc';
|
||||
} else {
|
||||
var directions = {
|
||||
null: 'asc',
|
||||
'asc': 'desc',
|
||||
'desc': null
|
||||
};
|
||||
sortDirection = directions[self.sort.direction];
|
||||
}
|
||||
|
||||
self.sort.columnName = col.title;
|
||||
self.sort.direction = sortDirection;
|
||||
self._setSortGetter(index);
|
||||
};
|
||||
|
||||
self._setSortGetter = function (index) {
|
||||
if (_.isFunction($scope.sortHandler)) {
|
||||
// use custom sort handler
|
||||
self.sort.getter = $scope.sortHandler(index);
|
||||
} else {
|
||||
// use generic sort handler
|
||||
self.sort.getter = function (row) {
|
||||
return row[index];
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// update the sordedRows result
|
||||
$scope.$watchMulti([
|
||||
'paginatedTable.sort.direction',
|
||||
'rows'
|
||||
], function () {
|
||||
if (self.sort.direction == null) {
|
||||
$scope.sortedRows = $scope.rows.slice(0);
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.sortedRows = orderBy($scope.rows, self.sort.getter, self.sort.direction === 'desc');
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -81,7 +81,8 @@ define(function (require) {
|
|||
params: this.params,
|
||||
aggs: this.aggs.map(function (agg) {
|
||||
return agg.toJSON();
|
||||
}).filter(Boolean)
|
||||
}).filter(Boolean),
|
||||
listeners: this.listeners
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -99,4 +100,4 @@ define(function (require) {
|
|||
|
||||
return Vis;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -125,7 +125,7 @@ define(function (require) {
|
|||
var rootSeries = obj.series || (obj.slices && obj.slices.children);
|
||||
var dataLength = rootSeries ? rootSeries.length : 0;
|
||||
var label = dataLength === 1 ? rootSeries[0].label || rootSeries[0].name : undefined;
|
||||
var children = (obj.slices && obj.slices.children && obj.slices.children[0].children);
|
||||
var children = (obj.slices && obj.slices.children && obj.slices.children[0] && obj.slices.children[0].children);
|
||||
|
||||
if (!seriesLabel) {
|
||||
seriesLabel = label;
|
||||
|
|
|
@ -17,7 +17,6 @@ define(function (require) {
|
|||
link: function ($scope, $el) {
|
||||
var $container = $el.find('.visualize-spy-container');
|
||||
var fullPageSpy = false;
|
||||
// $scope.spyMode = null; // inherited from the parent
|
||||
$scope.modes = modes;
|
||||
|
||||
$scope.toggleDisplay = function () {
|
||||
|
@ -36,38 +35,33 @@ define(function (require) {
|
|||
var current = $scope.spyMode;
|
||||
var change = false;
|
||||
|
||||
function set() {
|
||||
// no change
|
||||
if (current && newMode && newMode.name === current.name) return;
|
||||
|
||||
// clear the current value
|
||||
if (current) {
|
||||
current.$container.remove();
|
||||
current.$scope.$destroy();
|
||||
delete $scope.spyMode;
|
||||
current = null;
|
||||
change = true;
|
||||
}
|
||||
|
||||
// no further changes
|
||||
if (!newMode) return;
|
||||
// no change
|
||||
if (current && newMode && newMode.name === current.name) return;
|
||||
|
||||
// clear the current value
|
||||
if (current) {
|
||||
current.$container.remove();
|
||||
current.$scope.$destroy();
|
||||
delete $scope.spyMode;
|
||||
current = null;
|
||||
change = true;
|
||||
current = $scope.spyMode = {
|
||||
// copy a couple values over
|
||||
name: newMode.name,
|
||||
display: newMode.display,
|
||||
fill: fullPageSpy,
|
||||
$scope: $scope.$new(),
|
||||
$container: $('<div class="visualize-spy-content">').appendTo($container)
|
||||
};
|
||||
|
||||
current.$container.append($compile(newMode.template)(current.$scope));
|
||||
newMode.link && newMode.link(current.$scope, current.$container);
|
||||
}
|
||||
|
||||
// wrapped in fn to enable early return
|
||||
set();
|
||||
// no further changes
|
||||
if (!newMode) return;
|
||||
|
||||
change = true;
|
||||
current = $scope.spyMode = {
|
||||
// copy a couple values over
|
||||
name: newMode.name,
|
||||
display: newMode.display,
|
||||
fill: fullPageSpy,
|
||||
$scope: $scope.$new(),
|
||||
$container: $('<div class="visualize-spy-content">').appendTo($container)
|
||||
};
|
||||
|
||||
current.$container.append($compile(newMode.template)(current.$scope));
|
||||
newMode.link && newMode.link(current.$scope, current.$container);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -69,7 +69,7 @@ define(function (require) {
|
|||
}
|
||||
|
||||
self.perPage = _.parseInt(self.perPage) || $scope[self.perPageProp];
|
||||
if (!self.perPage) {
|
||||
if (self.perPage == null) {
|
||||
self.perPage = ALL;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ define(function (require) {
|
|||
return _.map(data, function (row) {
|
||||
var val;
|
||||
|
||||
val = _.isUndefined(row._source[name]) ? row[name] : row._source[name];
|
||||
val = _.isUndefined(row._flattened[name]) ? row[name] : row._flattened[name];
|
||||
|
||||
// for fields that come back in weird formats like geo_point
|
||||
if (val != null && normalize) val = normalize(val);
|
||||
|
|
|
@ -331,7 +331,7 @@ define(function (require) {
|
|||
|
||||
// Flatten the fields
|
||||
var indexPattern = $scope.searchSource.get('index');
|
||||
hit._source = indexPattern.flattenSearchResponse(hit._source);
|
||||
hit._flattened = indexPattern.flattenSearchResponse(hit._source);
|
||||
|
||||
var formatValues = function (value, name) {
|
||||
// add up the counts for each field name
|
||||
|
@ -341,7 +341,7 @@ define(function (require) {
|
|||
return ($scope.formatsByName[name] || defaultFormat).convert(value);
|
||||
};
|
||||
|
||||
var formattedSource = _.mapValues(hit._source, formatValues);
|
||||
var formattedSource = _.mapValues(hit._flattened, formatValues);
|
||||
var formattedHits = _.mapValues(hit.fields, formatValues);
|
||||
|
||||
hit._formatted = _.merge(formattedSource, formattedHits);
|
||||
|
@ -509,6 +509,7 @@ define(function (require) {
|
|||
_.defaults(field, currentState[field.name]);
|
||||
// clone the field and add it's display prop
|
||||
var clone = _.assign({}, field, {
|
||||
displayName: field.displayName, // this is a getter, so we need to copy it over manually
|
||||
format: field.format, // this is a getter, so we need to copy it over manually
|
||||
display: columnObjects[field.name] || false,
|
||||
rowCount: $scope.rows ? $scope.rows.fieldCounts[field.name] : 0
|
||||
|
|
|
@ -2,6 +2,8 @@ define(function (require) {
|
|||
var _ = require('lodash');
|
||||
var module = require('modules').get('app/discover');
|
||||
|
||||
require('filters/short_dots');
|
||||
|
||||
module.directive('kbnTableHeader', function () {
|
||||
var headerHtml = require('text!plugins/discover/partials/table_header.html');
|
||||
return {
|
||||
|
|
|
@ -7,6 +7,7 @@ define(function (require) {
|
|||
|
||||
require('components/highlight/highlight');
|
||||
require('filters/trust_as_html');
|
||||
require('filters/short_dots');
|
||||
|
||||
// guestimate at the minimum number of chars wide cells in the table should be
|
||||
var MIN_LINE_LENGTH = 20;
|
||||
|
@ -19,7 +20,7 @@ define(function (require) {
|
|||
* <tr ng-repeat="row in rows" kbn-table-row="row"></tr>
|
||||
* ```
|
||||
*/
|
||||
module.directive('kbnTableRow', function ($compile, config, highlightFilter) {
|
||||
module.directive('kbnTableRow', function ($compile, config, highlightFilter, shortDotsFilter) {
|
||||
var openRowHtml = require('text!plugins/discover/partials/table_row/open.html');
|
||||
var detailsHtml = require('text!plugins/discover/partials/table_row/details.html');
|
||||
var cellTemplate = _.template(require('text!plugins/discover/partials/table_row/cell.html'));
|
||||
|
@ -76,7 +77,7 @@ define(function (require) {
|
|||
// The fields to loop over
|
||||
if (!row._fields) {
|
||||
row._fields = _.union(
|
||||
_.keys(row._source),
|
||||
_.keys(row._formatted),
|
||||
config.get('metaFields')
|
||||
);
|
||||
row._fields.sort();
|
||||
|
@ -94,7 +95,7 @@ define(function (require) {
|
|||
};
|
||||
|
||||
$detailsScope.showArrayInObjectsWarning = function (row, field) {
|
||||
var value = row._source[field];
|
||||
var value = row._formatted[field];
|
||||
return _.isArray(value) && typeof value[0] === 'object';
|
||||
};
|
||||
|
||||
|
@ -102,7 +103,7 @@ define(function (require) {
|
|||
};
|
||||
|
||||
$scope.filter = function (row, field, operation) {
|
||||
$scope.filtering(field, row._source[field] || row[field], operation);
|
||||
$scope.filtering(field, row._flattened[field] || row[field], operation);
|
||||
};
|
||||
|
||||
$scope.$watchCollection('columns', function () {
|
||||
|
@ -134,7 +135,8 @@ define(function (require) {
|
|||
source: _.mapValues(row._formatted, function (val, field) {
|
||||
return _displayField(row, field, false);
|
||||
}),
|
||||
highlight: row.highlight
|
||||
highlight: row.highlight,
|
||||
shortDotsFilter: shortDotsFilter
|
||||
});
|
||||
} else {
|
||||
formatted = _displayField(row, column, true);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</th>
|
||||
<th ng-repeat="name in columns">
|
||||
<span ng-click="sort(name)" class="table-header-name">
|
||||
{{name}} <i ng-class="headerClass(name)"></i>
|
||||
{{name | shortDots}} <i ng-class="headerClass(name)"></i>
|
||||
</span>
|
||||
<span class="table-header-move">
|
||||
<i ng-click="moveLeft(name)" class="fa fa-angle-double-left" ng-show="!$first"></i>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<dl class="source truncate-by-height">
|
||||
<% _.each(highlight, function (value, field) { /* show fields that match the query first */ %>
|
||||
<dt><%= field %>:</dt>
|
||||
<dt><%= shortDotsFilter(field) %>:</dt>
|
||||
<dd><%= source[field] %></dd>
|
||||
<%= ' ' %>
|
||||
<% }); %>
|
||||
<% _.each(source, function (value, field) { %>
|
||||
<% if (_.has(highlight, field)) return; %>
|
||||
<dt><%= field %>:</dt>
|
||||
<dt><%= shortDotsFilter(field) %>:</dt>
|
||||
<dd><%= value %></dd>
|
||||
<%= ' ' %>
|
||||
<% }); %>
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
<tr class="field-settings"
|
||||
ng-repeat="field in page">
|
||||
<td>
|
||||
<span bo-text="field.name"></span>
|
||||
<span bo-text="field.displayName"></span>
|
||||
|
||||
<span
|
||||
bo-if="indexPattern.timeFieldName === field.name"
|
||||
|
|
|
@ -115,7 +115,7 @@ define(function (require) {
|
|||
break;
|
||||
}
|
||||
|
||||
label = (col.aggConfig && col.aggConfig.makeLabel()) || (col.field && col.field.name) || label;
|
||||
label = (col.aggConfig && col.aggConfig.makeLabel()) || (col.field && col.field.displayName) || label;
|
||||
if (col.field) val = col.field.format.convert(val);
|
||||
|
||||
return {
|
||||
|
|
|
@ -46,7 +46,7 @@ define(function (require) {
|
|||
var col = columns[i];
|
||||
|
||||
// field/agg details
|
||||
var group = (col.field && col.field.name) || col.label || ('level ' + datum.depth);
|
||||
var group = (col.field && col.field.displayName) || col.label || ('level ' + datum.depth);
|
||||
|
||||
// field value that defines the bucket
|
||||
var bucket = parent.name;
|
||||
|
|
|
@ -31,6 +31,7 @@ kbn-table,tbody[kbn-rows] {
|
|||
|
||||
dd {
|
||||
display: inline;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ define(function (require) {
|
|||
return function (id, mapping) {
|
||||
var fake = {
|
||||
_formatted: _.mapValues(mapping, function (f, c) { return c + '_formatted_' + id + longString; }),
|
||||
_flattened: _.mapValues(mapping, function (f, c) { return c + '_flattened_' + id + longString; }),
|
||||
_source: _.mapValues(mapping, function (f, c) { return c + '_original_' + id + longString; }),
|
||||
_id: id,
|
||||
_index: 'test',
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
define(function (require) {
|
||||
return function stubbedLogstashIndexPatternService(Private) {
|
||||
var StubIndexPattern = Private(require('test_utils/stub_index_pattern'));
|
||||
var fieldFormats = Private(require('components/index_patterns/_field_formats'));
|
||||
var flattenSearchResponse = require('components/index_patterns/_flatten_search_response');
|
||||
var _ = require('lodash');
|
||||
|
||||
return new StubIndexPattern('logstash-*', 'time', [
|
||||
{ name: 'bytes', type: 'number', indexed: true, analyzed: true, count: 10 },
|
||||
{ name: 'ssl', type: 'boolean', indexed: true, analyzed: true, count: 20 },
|
||||
{ name: '@timestamp', type: 'date', indexed: true, analyzed: true, count: 30 },
|
||||
{ name: 'phpmemory', type: 'number', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'ip', type: 'ip', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'request_body', type: 'attachment', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'extension', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'point', type: 'geo_point', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'area', type: 'geo_shape', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'extension', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'machine.os', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'geo.src', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: '_type', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'custom_user_field', type: 'conflict', indexed: false, analyzed: false, count: 0 }
|
||||
var indexPattern = new StubIndexPattern('logstash-*', 'time', [
|
||||
{ name: 'bytes', displayName: 'bytes', type: 'number', indexed: true, analyzed: true, count: 10 },
|
||||
{ name: 'ssl', displayName: 'ssl', type: 'boolean', indexed: true, analyzed: true, count: 20 },
|
||||
{ name: '@timestamp', displayName: '@timestamp', type: 'date', indexed: true, analyzed: true, count: 30 },
|
||||
{ name: 'phpmemory', displayName: 'phpmemory', type: 'number', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'ip', displayName: 'ip', type: 'ip', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'request_body', displayName: 'request_body', type: 'attachment', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'extension', displayName: 'extension', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'point', displayName: 'point', type: 'geo_point', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'area', displayName: 'area', type: 'geo_shape', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'extension', displayName: 'extension', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'machine.os', displayName: 'machine.os', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'geo.src', displayName: 'geo.src', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: '_type', displayName: '_type', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'custom_user_field', displayName: 'custom_user_field', type: 'conflict', indexed: false, analyzed: false, count: 0 }
|
||||
]);
|
||||
|
||||
indexPattern.flattenSearchResponse = _.bind(flattenSearchResponse, indexPattern);
|
||||
|
||||
return indexPattern;
|
||||
|
||||
};
|
||||
});
|
||||
|
|
|
@ -87,7 +87,14 @@ define(function (require) {
|
|||
});
|
||||
|
||||
describe('getFieldValues', function () {
|
||||
var hits = require('fixtures/real_hits.js');
|
||||
var hits;
|
||||
|
||||
beforeEach(function () {
|
||||
hits = _.each(require('fixtures/real_hits.js'), function (hit) {
|
||||
hit._flattened = indexPattern.flattenSearchResponse(hit._source);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should return an array of values for _source fields', function () {
|
||||
var extensions = fieldCalculator.getFieldValues(hits, indexPattern.fields.byName.extension);
|
||||
expect(extensions).to.be.an(Array);
|
||||
|
|
|
@ -45,10 +45,14 @@ define(function (require) {
|
|||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
|
||||
});
|
||||
|
||||
var hits = _.each(require('fixtures/hits.js'), function (hit) {
|
||||
hit._flattened = indexPattern.flattenSearchResponse(hit._source);
|
||||
});
|
||||
|
||||
init($elem, {
|
||||
fields: _.map(indexPattern.fields.raw, function (v, i) { return _.merge(v, {display: false, rowCount: i}); }),
|
||||
toggle: sinon.spy(),
|
||||
data: require('fixtures/hits'),
|
||||
data: hits,
|
||||
filter: sinon.spy(),
|
||||
indexPattern: indexPattern
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ define(function (require) {
|
|||
depth: 3,
|
||||
value: 6,
|
||||
field: { format: { convert: convert } },
|
||||
aggConfig: { params: { field: { name: 'field3' } } },
|
||||
aggConfig: { params: { field: { displayName: 'field3' } } },
|
||||
parent: {
|
||||
name: 'bucket2',
|
||||
depth: 2,
|
||||
|
|
|
@ -103,158 +103,6 @@ define(function (require) {
|
|||
});
|
||||
});
|
||||
|
||||
describe('aggTable.cycleSort()', function () {
|
||||
var vis;
|
||||
beforeEach(function () {
|
||||
vis = new Vis(indexPattern, {
|
||||
type: 'table',
|
||||
aggs: [
|
||||
{ type: 'count', schema: 'metric' },
|
||||
{
|
||||
type: 'range',
|
||||
schema: 'bucket',
|
||||
params: {
|
||||
field: 'bytes',
|
||||
ranges: [
|
||||
{ from: 0, to: 1000 },
|
||||
{ from: 1000, to: 2000 }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
vis.aggs.forEach(function (agg, i) {
|
||||
agg.id = 'agg_' + (i + 1);
|
||||
});
|
||||
});
|
||||
|
||||
function checkAgainst(aggTable, $el, selector) {
|
||||
return function (asc, firstCol) {
|
||||
switch (asc) {
|
||||
case null:
|
||||
expect(aggTable.sort == null).to.be(true);
|
||||
break;
|
||||
case true:
|
||||
case false:
|
||||
expect(aggTable.sort).to.have.property('asc', asc);
|
||||
break;
|
||||
}
|
||||
|
||||
var $leftCol = $el.find(selector || 'tr td:first-child');
|
||||
firstCol.forEach(function (val, i) {
|
||||
expect($leftCol.eq(i).text().trim()).to.be(val);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
it('sorts by the column passed in', function () {
|
||||
$scope.table = tabifyAggResponse(vis, fixtures.oneRangeBucket, { canSplit: false });
|
||||
var $el = $compile('<kbn-agg-table table="table">')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
var sortCol = $scope.table.columns[0];
|
||||
var $tableScope = $el.isolateScope();
|
||||
var aggTable = $tableScope.aggTable;
|
||||
var check = checkAgainst(aggTable, $el);
|
||||
|
||||
// default state
|
||||
check(null, [
|
||||
'0.0-1000.0',
|
||||
'1000.0-2000.0'
|
||||
]);
|
||||
|
||||
// enable accending
|
||||
aggTable.cycleSort(sortCol);
|
||||
$scope.$digest();
|
||||
check(true, [
|
||||
'0.0-1000.0',
|
||||
'1000.0-2000.0'
|
||||
]);
|
||||
|
||||
// enable descending
|
||||
aggTable.cycleSort(sortCol);
|
||||
$scope.$digest();
|
||||
check(false, [
|
||||
'1000.0-2000.0',
|
||||
'0.0-1000.0'
|
||||
]);
|
||||
|
||||
// disable sort
|
||||
aggTable.cycleSort(sortCol);
|
||||
$scope.$digest();
|
||||
check(null, [
|
||||
'0.0-1000.0',
|
||||
'1000.0-2000.0'
|
||||
]);
|
||||
});
|
||||
|
||||
it('sorts new tables by the previous sort rule', function () {
|
||||
$scope.table = tabifyAggResponse(vis, fixtures.oneRangeBucket, { canSplit: false });
|
||||
var $el = $compile('<kbn-agg-table table="table">')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
var sortCol = $scope.table.columns[0];
|
||||
var $tableScope = $el.isolateScope();
|
||||
var aggTable = $tableScope.aggTable;
|
||||
var check = checkAgainst(aggTable, $el);
|
||||
|
||||
// enable accending, then descending
|
||||
aggTable.cycleSort(sortCol);
|
||||
aggTable.cycleSort(sortCol);
|
||||
$scope.$digest();
|
||||
check(false, [
|
||||
'1000.0-2000.0',
|
||||
'0.0-1000.0'
|
||||
]);
|
||||
|
||||
var prevFormattedRows = $tableScope.formattedRows;
|
||||
|
||||
// change the table and trigger the watchers
|
||||
$scope.table = tabifyAggResponse(vis, fixtures.oneRangeBucket, { canSplit: false });
|
||||
$scope.$digest();
|
||||
|
||||
// prove that the rows were recreated
|
||||
expect($tableScope.formattedRows).to.not.be(prevFormattedRows);
|
||||
|
||||
// check that the order is right
|
||||
check(false, [
|
||||
'1000.0-2000.0',
|
||||
'0.0-1000.0'
|
||||
]);
|
||||
});
|
||||
|
||||
it('sorts ascending when switching from another column', function () {
|
||||
$scope.table = tabifyAggResponse(vis, fixtures.oneRangeBucket, { canSplit: false });
|
||||
var $el = $compile('<kbn-agg-table table="table">')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
var $tableScope = $el.isolateScope();
|
||||
var aggTable = $tableScope.aggTable;
|
||||
|
||||
var rangeCol = $scope.table.columns[0];
|
||||
var countCol = $scope.table.columns[1];
|
||||
var checkRange = checkAgainst(aggTable, $el, 'tr td:first-child');
|
||||
var checkCount = checkAgainst(aggTable, $el, 'tr td:last-child');
|
||||
|
||||
// sort count accending
|
||||
aggTable.cycleSort(countCol);
|
||||
$scope.$digest();
|
||||
checkCount(true, [
|
||||
'298',
|
||||
'606'
|
||||
]);
|
||||
|
||||
// switch to sorting range ascending
|
||||
aggTable.cycleSort(rangeCol);
|
||||
$scope.$digest();
|
||||
checkRange(true, [
|
||||
'0.0-1000.0',
|
||||
'1000.0-2000.0'
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('aggTable.toCsv()', function () {
|
||||
it('escapes and formats the rows and columns properly', function () {
|
||||
var $el = $compile('<kbn-agg-table table="table">')($scope);
|
||||
|
|
185
test/unit/specs/components/paginated_table/index.js
Normal file
185
test/unit/specs/components/paginated_table/index.js
Normal file
|
@ -0,0 +1,185 @@
|
|||
define(function (require) {
|
||||
require('components/paginated_table/paginated_table');
|
||||
var _ = require('lodash');
|
||||
var faker = require('faker');
|
||||
var sinon = require('sinon/sinon');
|
||||
|
||||
describe('paginated table', function () {
|
||||
var $el;
|
||||
var $rootScope;
|
||||
var $compile;
|
||||
var $scope;
|
||||
var $elScope;
|
||||
var $orderBy;
|
||||
var defaultPerPage = 10;
|
||||
|
||||
var makeData = function (colCount, rowCount) {
|
||||
var cols = faker.Lorem.words(colCount).map(function (word) {
|
||||
return { title: word };
|
||||
});
|
||||
var rows = [];
|
||||
_.times(rowCount, function () {
|
||||
rows.push(faker.Lorem.words(colCount));
|
||||
});
|
||||
|
||||
return {
|
||||
columns: cols,
|
||||
rows: rows
|
||||
};
|
||||
};
|
||||
|
||||
var renderTable = function (cols, rows, perPage) {
|
||||
$scope.cols = cols || [];
|
||||
$scope.rows = rows || [];
|
||||
$scope.perPage = perPage || defaultPerPage;
|
||||
|
||||
$el = $compile('<paginated-table columns="cols" rows="rows" per-page="perPage">')($scope);
|
||||
|
||||
$scope.$digest();
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
module('kibana');
|
||||
|
||||
inject(function (_$rootScope_, _$compile_, $filter) {
|
||||
$rootScope = _$rootScope_;
|
||||
$compile = _$compile_;
|
||||
$orderBy = $filter('orderBy');
|
||||
});
|
||||
|
||||
$scope = $rootScope.$new();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$scope.$destroy();
|
||||
});
|
||||
|
||||
describe('rendering', function () {
|
||||
it('should not display without rows', function () {
|
||||
var cols = [{
|
||||
title: 'test1'
|
||||
}];
|
||||
var rows = [];
|
||||
|
||||
renderTable(cols, rows);
|
||||
expect($el.children().size()).to.be(0);
|
||||
});
|
||||
|
||||
it('should render columns and rows', function () {
|
||||
var data = makeData(2, 2);
|
||||
var cols = data.columns;
|
||||
var rows = data.rows;
|
||||
|
||||
renderTable(cols, rows);
|
||||
expect($el.children().size()).to.be(1);
|
||||
var tableRows = $el.find('tbody tr');
|
||||
// should pad rows
|
||||
expect(tableRows.size()).to.be(defaultPerPage);
|
||||
// should contain the row data
|
||||
expect(tableRows.eq(0).find('td').eq(0).text()).to.be(rows[0][0]);
|
||||
expect(tableRows.eq(0).find('td').eq(1).text()).to.be(rows[0][1]);
|
||||
expect(tableRows.eq(1).find('td').eq(0).text()).to.be(rows[1][0]);
|
||||
expect(tableRows.eq(1).find('td').eq(1).text()).to.be(rows[1][1]);
|
||||
});
|
||||
|
||||
it('should paginate rows', function () {
|
||||
// note: paginate truncates pages, so don't make too many
|
||||
var rowCount = _.random(16, 24);
|
||||
var perPageCount = _.random(5, 8);
|
||||
var data = makeData(3, rowCount);
|
||||
var pageCount = Math.ceil(rowCount / perPageCount);
|
||||
|
||||
renderTable(data.columns, data.rows, perPageCount);
|
||||
var tableRows = $el.find('tbody tr');
|
||||
expect(tableRows.size()).to.be(perPageCount);
|
||||
// add 2 for the first and last page links
|
||||
expect($el.find('paginate-controls a').size()).to.be(pageCount + 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sorting', function () {
|
||||
var data;
|
||||
var lastRowIndex;
|
||||
var paginatedTable;
|
||||
|
||||
beforeEach(function () {
|
||||
data = makeData(3, 3);
|
||||
data.rows.push(['zzzz', 'zzzz', 'zzzz']);
|
||||
data.rows.push(['aaaa', 'aaaa', 'aaaa']);
|
||||
|
||||
lastRowIndex = data.rows.length - 1;
|
||||
renderTable(data.columns, data.rows);
|
||||
paginatedTable = $el.isolateScope().paginatedTable;
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$scope.$destroy();
|
||||
});
|
||||
|
||||
it('should not sort by default', function () {
|
||||
var tableRows = $el.find('tbody tr');
|
||||
expect(tableRows.eq(0).find('td').eq(0).text()).to.be(data.rows[0][0]);
|
||||
expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be('aaaa');
|
||||
});
|
||||
|
||||
it('should sort ascending on first invocation', function () {
|
||||
// sortColumn
|
||||
paginatedTable.sortColumn(data.columns[0]);
|
||||
$scope.$digest();
|
||||
var tableRows = $el.find('tbody tr');
|
||||
expect(tableRows.eq(0).find('td').eq(0).text()).to.be('aaaa');
|
||||
expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be('zzzz');
|
||||
});
|
||||
|
||||
it('should sort desciending on second invocation', function () {
|
||||
// sortColumn
|
||||
paginatedTable.sortColumn(data.columns[0]);
|
||||
paginatedTable.sortColumn(data.columns[0]);
|
||||
$scope.$digest();
|
||||
var tableRows = $el.find('tbody tr');
|
||||
expect(tableRows.eq(0).find('td').eq(0).text()).to.be('zzzz');
|
||||
expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be('aaaa');
|
||||
});
|
||||
|
||||
it('should clear sorting on third invocation', function () {
|
||||
// sortColumn
|
||||
paginatedTable.sortColumn(data.columns[0]);
|
||||
paginatedTable.sortColumn(data.columns[0]);
|
||||
paginatedTable.sortColumn(data.columns[0]);
|
||||
$scope.$digest();
|
||||
var tableRows = $el.find('tbody tr');
|
||||
expect(tableRows.eq(0).find('td').eq(0).text()).to.be(data.rows[0][0]);
|
||||
expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be('aaaa');
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom sorting', function () {
|
||||
var data;
|
||||
var paginatedTable;
|
||||
var sortHandler;
|
||||
|
||||
beforeEach(function () {
|
||||
sortHandler = sinon.spy();
|
||||
data = makeData(3, 3);
|
||||
$scope.cols = data.columns;
|
||||
$scope.rows = data.rows;
|
||||
$scope.perPage = defaultPerPage;
|
||||
$scope.sortHandler = sortHandler;
|
||||
|
||||
$el = $compile('<paginated-table columns="cols" rows="rows" per-page="perPage"' +
|
||||
'sort-handler="sortHandler">')($scope);
|
||||
|
||||
$scope.$digest();
|
||||
paginatedTable = $el.isolateScope().paginatedTable;
|
||||
});
|
||||
|
||||
it('should allow custom sorting handler', function () {
|
||||
var columnIndex = 1;
|
||||
paginatedTable.sortColumn(data.columns[columnIndex]);
|
||||
$scope.$digest();
|
||||
expect(sortHandler.callCount).to.be(1);
|
||||
expect(sortHandler.getCall(0).args[0]).to.be(columnIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
107
test/unit/specs/components/vis/vis.js
Normal file
107
test/unit/specs/components/vis/vis.js
Normal file
|
@ -0,0 +1,107 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
|
||||
var indexPattern;
|
||||
var Vis;
|
||||
var visTypes;
|
||||
|
||||
describe('Vis Class', function () {
|
||||
|
||||
var vis;
|
||||
var stateFixture = {
|
||||
type: 'pie',
|
||||
aggs: [
|
||||
{ type: 'avg', schema: 'metric', params: { field: 'bytes' } },
|
||||
{ type: 'terms', schema: 'segment', params: { field: 'machine.os' }},
|
||||
{ type: 'terms', schema: 'segment', params: { field: 'geo.src' }}
|
||||
],
|
||||
params: { isDonut: true },
|
||||
listeners: { click: _.noop }
|
||||
};
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private) {
|
||||
Vis = Private(require('components/vis/vis'));
|
||||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
|
||||
visTypes = Private(require('registry/vis_types'));
|
||||
}));
|
||||
|
||||
beforeEach(function () {
|
||||
vis = new Vis(indexPattern, stateFixture);
|
||||
});
|
||||
|
||||
var verifyVis = function (vis) {
|
||||
expect(vis).to.have.property('aggs');
|
||||
expect(vis.aggs).to.have.length(3);
|
||||
|
||||
expect(vis).to.have.property('type');
|
||||
expect(vis.type).to.eql(visTypes.byName['pie']);
|
||||
|
||||
expect(vis).to.have.property('listeners');
|
||||
expect(vis.listeners).to.have.property('click');
|
||||
expect(vis.listeners.click).to.eql(_.noop);
|
||||
|
||||
expect(vis).to.have.property('params');
|
||||
expect(vis.params).to.have.property('isDonut', true);
|
||||
expect(vis).to.have.property('indexPattern', indexPattern);
|
||||
};
|
||||
|
||||
describe('initialization', function () {
|
||||
it('should set the state', function () {
|
||||
verifyVis(vis);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getState()', function () {
|
||||
it('should get a state that represents the... er... state', function () {
|
||||
var state = vis.getState();
|
||||
expect(state).to.have.property('type', 'pie');
|
||||
|
||||
expect(state).to.have.property('params');
|
||||
expect(state.params).to.have.property('isDonut', true);
|
||||
|
||||
expect(state).to.have.property('listeners');
|
||||
expect(state.listeners).to.have.property('click');
|
||||
expect(state.listeners.click).to.eql(_.noop);
|
||||
|
||||
expect(state).to.have.property('aggs');
|
||||
expect(state.aggs).to.have.length(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clone()', function () {
|
||||
it('should make clone of itself', function () {
|
||||
var clone = vis.clone();
|
||||
verifyVis(clone);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setState()', function () {
|
||||
it('should set the state to defualts', function () {
|
||||
var vis = new Vis(indexPattern);
|
||||
expect(vis).to.have.property('type');
|
||||
expect(vis.type).to.eql(visTypes.byName['histogram']);
|
||||
expect(vis).to.have.property('aggs');
|
||||
expect(vis.aggs).to.have.length(1);
|
||||
expect(vis).to.have.property('listeners');
|
||||
expect(vis.listeners).to.eql({});
|
||||
expect(vis).to.have.property('params');
|
||||
expect(vis.params).to.have.property('addLegend', true);
|
||||
expect(vis.params).to.have.property('addTooltip', true);
|
||||
expect(vis.params).to.have.property('mode', 'stacked');
|
||||
expect(vis.params).to.have.property('shareYAxis', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isHierarchical()', function () {
|
||||
it('should return true for hierarchical vis (like pie)', function () {
|
||||
expect(vis.isHierarchical()).to.be(true);
|
||||
});
|
||||
it('should return false for non-hierarchical vis (like histogram)', function () {
|
||||
var vis = new Vis(indexPattern);
|
||||
expect(vis.isHierarchical()).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue