From b6c6dff27d8dfe7d331c6b8079727cff28c71617 Mon Sep 17 00:00:00 2001 From: lukasolson Date: Tue, 25 Nov 2014 09:46:00 -0700 Subject: [PATCH 01/51] Fix for pie charts with no data --- src/kibana/components/vislib/lib/data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kibana/components/vislib/lib/data.js b/src/kibana/components/vislib/lib/data.js index db5fea220e4df..11818a22247ad 100644 --- a/src/kibana/components/vislib/lib/data.js +++ b/src/kibana/components/vislib/lib/data.js @@ -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; From f81dcb8e60e332efec6218305db82058612e85e3 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 25 Nov 2014 09:53:34 -0700 Subject: [PATCH 02/51] move to the _flattened key --- src/kibana/plugins/discover/controllers/discover.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kibana/plugins/discover/controllers/discover.js b/src/kibana/plugins/discover/controllers/discover.js index 1fe38967e0503..08f9df24b6531 100644 --- a/src/kibana/plugins/discover/controllers/discover.js +++ b/src/kibana/plugins/discover/controllers/discover.js @@ -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); From 6fdbe7d13c5bdcd7a1f371f060d45f6ef9563f3c Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 25 Nov 2014 10:21:46 -0700 Subject: [PATCH 03/51] reference flattened --- src/kibana/plugins/discover/directives/table_row.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kibana/plugins/discover/directives/table_row.js b/src/kibana/plugins/discover/directives/table_row.js index 62a96945f70c2..7d15e4466a0a2 100644 --- a/src/kibana/plugins/discover/directives/table_row.js +++ b/src/kibana/plugins/discover/directives/table_row.js @@ -76,7 +76,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 +94,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 +102,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 () { From b41e454dfaebe8e296219c1f99b63e1bbf9d27e8 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 25 Nov 2014 11:01:45 -0700 Subject: [PATCH 04/51] Update fixtures --- .../discover/components/field_chooser/lib/field_calculator.js | 2 +- test/unit/fixtures/fake_row.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/kibana/plugins/discover/components/field_chooser/lib/field_calculator.js b/src/kibana/plugins/discover/components/field_chooser/lib/field_calculator.js index 29c435a97dcca..a4164816a7e5e 100644 --- a/src/kibana/plugins/discover/components/field_chooser/lib/field_calculator.js +++ b/src/kibana/plugins/discover/components/field_chooser/lib/field_calculator.js @@ -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); diff --git a/test/unit/fixtures/fake_row.js b/test/unit/fixtures/fake_row.js index dc04f07edcf57..0760b02bbd721 100644 --- a/test/unit/fixtures/fake_row.js +++ b/test/unit/fixtures/fake_row.js @@ -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', From 5380bd02846ae8ef6c9591482563e4a2112d87b0 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 25 Nov 2014 13:22:38 -0700 Subject: [PATCH 05/51] Add flattenSearchResponse to stub index pattern --- test/unit/fixtures/stubbed_logstash_index_pattern.js | 10 ++++++++-- .../specs/apps/discover/directives/field_calculator.js | 9 ++++++++- .../specs/apps/discover/directives/field_chooser.js | 6 +++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/test/unit/fixtures/stubbed_logstash_index_pattern.js b/test/unit/fixtures/stubbed_logstash_index_pattern.js index ad72d53e633a7..48a143f1fc362 100644 --- a/test/unit/fixtures/stubbed_logstash_index_pattern.js +++ b/test/unit/fixtures/stubbed_logstash_index_pattern.js @@ -1,9 +1,10 @@ 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', [ + var indexPattern = 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 }, @@ -19,5 +20,10 @@ define(function (require) { { name: '_type', type: 'string', indexed: true, analyzed: true, count: 0 }, { name: 'custom_user_field', type: 'conflict', indexed: false, analyzed: false, count: 0 } ]); + + indexPattern.flattenSearchResponse = _.bind(flattenSearchResponse, indexPattern); + + return indexPattern; + }; }); diff --git a/test/unit/specs/apps/discover/directives/field_calculator.js b/test/unit/specs/apps/discover/directives/field_calculator.js index 8bb37cb4d2089..d01d3c3b5fb6b 100644 --- a/test/unit/specs/apps/discover/directives/field_calculator.js +++ b/test/unit/specs/apps/discover/directives/field_calculator.js @@ -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); diff --git a/test/unit/specs/apps/discover/directives/field_chooser.js b/test/unit/specs/apps/discover/directives/field_chooser.js index 8431e5dbe2d2f..2f3a43806d46a 100644 --- a/test/unit/specs/apps/discover/directives/field_chooser.js +++ b/test/unit/specs/apps/discover/directives/field_chooser.js @@ -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 }); From 5a07aa2cd487661b095b4b08208debfe8aaf3da9 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 17:57:36 -0700 Subject: [PATCH 06/51] remove unused dep, clean up comment --- src/kibana/components/agg_table/agg_table.js | 1 - src/kibana/components/visualize/spy/spy.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index 7b5755c656f4c..98645632ca6b9 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -7,7 +7,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 { diff --git a/src/kibana/components/visualize/spy/spy.js b/src/kibana/components/visualize/spy/spy.js index fde6071e84cc7..4a6aad8eefcf4 100644 --- a/src/kibana/components/visualize/spy/spy.js +++ b/src/kibana/components/visualize/spy/spy.js @@ -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 () { From 56afb6adb30b30b250346d5c368a405c018b6e90 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 17:59:20 -0700 Subject: [PATCH 07/51] refactor - no need to wrap code to return early --- src/kibana/components/visualize/spy/spy.js | 51 ++++++++++------------ 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/kibana/components/visualize/spy/spy.js b/src/kibana/components/visualize/spy/spy.js index 4a6aad8eefcf4..2300c8791964b 100644 --- a/src/kibana/components/visualize/spy/spy.js +++ b/src/kibana/components/visualize/spy/spy.js @@ -35,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: $('
').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: $('
').appendTo($container) + }; + + current.$container.append($compile(newMode.template)(current.$scope)); + newMode.link && newMode.link(current.$scope, current.$container); }; } }; From d39254289be6d353c1b5eae903efde4d2536cb05 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 18:00:11 -0700 Subject: [PATCH 08/51] create paginated table directive --- .../paginated_table/paginated_table.html | 51 +++++++++++ .../paginated_table/paginated_table.js | 86 +++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 src/kibana/components/paginated_table/paginated_table.html create mode 100644 src/kibana/components/paginated_table/paginated_table.js diff --git a/src/kibana/components/paginated_table/paginated_table.html b/src/kibana/components/paginated_table/paginated_table.html new file mode 100644 index 0000000000000..13f83b6a7ab89 --- /dev/null +++ b/src/kibana/components/paginated_table/paginated_table.html @@ -0,0 +1,51 @@ + + + +

Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

+

No Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

+
+ + + + + + + +
+ + + +
+
+ + + +
+ +
\ No newline at end of file diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js new file mode 100644 index 0000000000000..4b28a8d78a106 --- /dev/null +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -0,0 +1,86 @@ +define(function (require) { + require('modules') + .get('kibana') + .directive('paginatedTable', function (config, Private) { + var _ = require('lodash'); + + return { + restrict: 'E', + template: require('text!components/paginated_table/paginated_table.html'), + transclude: true, + scope: { + rows: '=', + columns: '=', + perPage: '=?', + perPageProp: '=?', + sortHandler: '=?', + showSelector: '=?' + }, + controllerAs: 'paginatedTable', + controller: function ($scope) { + var self = this; + self.sort = { + columnName: null, + direction: null + }; + + self.perPage = _.parseInt(self.perPage) || $scope[self.perPageProp]; + + self.sortColumn = function (col) { + if (!$scope.sortHandler) return; + + // TODO: track sort direction + + self._setSortDirection(col.title); + $scope.sortHandler(col, self.sort); + }; + + self._setSortDirection = function (columnName) { + if (self.sort.columnName !== columnName) { + self.sort.direction = 'asc'; + } else { + var directions = { + null: 'asc', + 'asc': 'desc', + 'desc': null + }; + var direction = directions[self.sort.direction]; + self.sort.direction = direction; + + } + self.sort.columnName = columnName; + }; + + // $scope.$watchMulti([ + // 'rows', + // 'columns', + // 'paginatedTable.sort.asc', + // 'paginatedTable.sort.col' + // ], function () { + // if (!$scope.rows) return; + + // var formatters = $scope.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) { + // return row.map(function (cell, i) { + // return formatters[i](cell); + // }); + // }); + + // // update the csv file's title + // self.csv.filename = (table.title() || 'table') + '.csv'; + // }); + } + }; + }); +}); From 393cf519d76e032d8cd965e24caf585b72b957f9 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 18:01:12 -0700 Subject: [PATCH 09/51] use paginated table in table spy --- .../components/agg_table/agg_table.html | 42 +++---------------- src/kibana/components/agg_table/agg_table.js | 1 + 2 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.html b/src/kibana/components/agg_table/agg_table.html index eb9f7a9f80607..b595b94302b50 100644 --- a/src/kibana/components/agg_table/agg_table.html +++ b/src/kibana/components/agg_table/agg_table.html @@ -1,38 +1,8 @@ - - list="formattedRows" - per-page-prop="perPage" - - class="agg-table"> -
- - - - - - - -
- - - -
-
- - -
\ No newline at end of file + diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index 98645632ca6b9..b86da88df990a 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -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'); From 5c56a88b3b5c690743d1f7803e4296a5770d98ec Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Fri, 21 Nov 2014 11:21:25 -0700 Subject: [PATCH 10/51] use perPageProp for pagination, working spy agg table --- .../components/agg_table/agg_table.html | 6 ++++ .../paginated_table/paginated_table.html | 19 +---------- .../paginated_table/paginated_table.js | 33 ------------------- 3 files changed, 7 insertions(+), 51 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.html b/src/kibana/components/agg_table/agg_table.html index b595b94302b50..fea5632607295 100644 --- a/src/kibana/components/agg_table/agg_table.html +++ b/src/kibana/components/agg_table/agg_table.html @@ -5,4 +5,10 @@ per-page="perPage" sort-handler="aggTable.cycleSort"> + diff --git a/src/kibana/components/paginated_table/paginated_table.html b/src/kibana/components/paginated_table/paginated_table.html index 13f83b6a7ab89..b377defd164c1 100644 --- a/src/kibana/components/paginated_table/paginated_table.html +++ b/src/kibana/components/paginated_table/paginated_table.html @@ -1,24 +1,8 @@ - - -

Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

-

No Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

@@ -30,7 +14,6 @@

No Handler perPage:{{ perPage }} / perPageProp:{{ perPa + per-page="perPage">
diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index b86da88df990a..8f6cb99e60948 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -48,27 +48,6 @@ define(function (require) { 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,11 +83,7 @@ define(function (require) { }).join(''); }; - $scope.$watchMulti([ - 'table', - 'aggTable.sort.asc', - 'aggTable.sort.col' - ], function () { + $scope.$watch('table', function () { var table = $scope.table; if (!table) { @@ -120,13 +95,6 @@ define(function (require) { 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) { return row.map(function (cell, i) { diff --git a/src/kibana/components/paginated_table/paginated_table.html b/src/kibana/components/paginated_table/paginated_table.html index b377defd164c1..a7ded3ab3f5fb 100644 --- a/src/kibana/components/paginated_table/paginated_table.html +++ b/src/kibana/components/paginated_table/paginated_table.html @@ -1,6 +1,6 @@
@@ -16,8 +16,8 @@ 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 === 'asc', - 'fa-sort': !paginatedTable.sort.direction || paginatedTable.sort.columnName !== col.title + 'fa-sort-desc': paginatedTable.sort.columnName === col.title && paginatedTable.sort.direction === 'desc', + 'fa-sort': paginatedTable.sort.direction === null || paginatedTable.sort.columnName !== col.title }"> diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index 454c916b0a56e..a45f90e720f17 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -1,8 +1,9 @@ define(function (require) { require('modules') .get('kibana') - .directive('paginatedTable', function (config, Private) { + .directive('paginatedTable', function ($filter, config, Private) { var _ = require('lodash'); + var orderBy = $filter('orderBy'); return { restrict: 'E', @@ -24,29 +25,51 @@ define(function (require) { }; self.sortColumn = function (col) { - if (!$scope.sortHandler) return; - - // TODO: track sort direction + // use custom sort handler if one was defined + if (_.isFunction($scope.sortHandler)) { + $scope.sortHandler(col, self.sort); + } + // use generic sort handler self._setSortDirection(col.title); - $scope.sortHandler(col, self.sort); }; self._setSortDirection = function (columnName) { + var sortDirection; + var cols = _.pluck($scope.columns, 'title'); + var index = cols.indexOf(columnName); + + if (index === -1) return; + + var sortGetter = function (row) { + return row[index]; + }; + if (self.sort.columnName !== columnName) { - self.sort.direction = 'asc'; + sortDirection = 'asc'; } else { var directions = { null: 'asc', 'asc': 'desc', 'desc': null }; - var direction = directions[self.sort.direction]; - self.sort.direction = direction; - + sortDirection = directions[self.sort.direction]; } + self.sort.columnName = columnName; + self.sort.getter = sortGetter; + self.sort.direction = sortDirection; }; + + // update the sordedRows result + $scope.$watch('paginatedTable.sort.direction', 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'); + }); } }; }); From eedf7c73ac0f5d92483fdb3ca1bc34cd9f0600f7 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Fri, 21 Nov 2014 18:08:18 -0700 Subject: [PATCH 12/51] format agg columns, pass to paginated table --- .../components/agg_table/agg_table.html | 2 +- src/kibana/components/agg_table/agg_table.js | 38 +++++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.html b/src/kibana/components/agg_table/agg_table.html index 863dcb1c9098d..bb2c632248d92 100644 --- a/src/kibana/components/agg_table/agg_table.html +++ b/src/kibana/components/agg_table/agg_table.html @@ -1,7 +1,7 @@
diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index 8f6cb99e60948..ad80ae1e39870 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -33,21 +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.exportAsCsv = function () { var csv = new Blob([self.toCsv()], { type: 'text/plain' }); self._saveAs(csv, self.csv.filename); @@ -88,9 +73,30 @@ define(function (require) { 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 cls = []; + var agg = $scope.table.aggConfig(col); + var last = i === (table.columns.length - 1); + + if (last || (agg.schema.group === 'metrics')) { + cls.push('visualize-table-right'); + } + + col.class = cls.join(' '); + return col; + }); + } + + function setFormattedRows(table) { var formatters = table.columns.map(function (col) { return table.fieldFormatter(col); }); @@ -104,7 +110,7 @@ define(function (require) { // update the csv file's title self.csv.filename = (table.title() || 'table') + '.csv'; - }); + } } }; }); From 9fc2d643ea8799c0152b6c6e5b47a788bfbbfab9 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 11:11:39 -0700 Subject: [PATCH 13/51] remove cycleSort tests --- .../unit/specs/components/agg_table/_table.js | 152 ------------------ 1 file changed, 152 deletions(-) diff --git a/test/unit/specs/components/agg_table/_table.js b/test/unit/specs/components/agg_table/_table.js index 101b567fec07e..5b1d7dfd49c1c 100644 --- a/test/unit/specs/components/agg_table/_table.js +++ b/test/unit/specs/components/agg_table/_table.js @@ -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('')($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('')($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('')($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('')($scope); From b96759fc8a996a2e14a10b3da30c2c8a4505e2c4 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 12:00:35 -0700 Subject: [PATCH 14/51] start adding tests for paginated table --- .../specs/components/paginated_table/index.js | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/unit/specs/components/paginated_table/index.js diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js new file mode 100644 index 0000000000000..7c67659054a02 --- /dev/null +++ b/test/unit/specs/components/paginated_table/index.js @@ -0,0 +1,58 @@ +define(function (require) { + require('components/paginated_table/paginated_table'); + + describe.only('paginated table', function () { + var $el; + var $rootScope; + var $compile; + var $scope; + var $elScope; + var defaultPerPage = 10; + + var init = function () { + // load the application + }; + + var renderTable = function (cols, rows, perPage) { + $scope.cols = cols || []; + $scope.rows = rows || []; + $scope.perPage = perPage || defaultPerPage; + + $el = $compile('')($scope); + + $elScope = $el.scope(); + $elScope.$digest(); + }; + + beforeEach(function () { + module('kibana'); + + inject(function (_$rootScope_, _$compile_) { + $rootScope = _$rootScope_; + $compile = _$compile_; + }); + + $scope = $rootScope.$new(); + }); + + afterEach(function () { + $scope.$destroy(); + }); + + describe('rendering', function () { + it('should not display without rows'); + it('should render columns and rows'); + it('should paginate rows'); + it('should allow custom pagination code'); + }); + + describe('sorting', function () { + it('should not sort by default'); + it('should sort ascending on first click'); + it('should sort desciending on second click'); + it('should clear sorting on third click'); + it('should sort using $orderBy'); + it('should allow custom sorting handler'); + }); + }); +}); \ No newline at end of file From 8a568eddc8d35fc187b8ebd57bca872b72118e07 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 12:00:58 -0700 Subject: [PATCH 15/51] add table rendering tests --- .../specs/components/paginated_table/index.js | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index 7c67659054a02..b0b206d18fca2 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -40,8 +40,39 @@ define(function (require) { }); describe('rendering', function () { - it('should not display without rows'); - it('should render columns and rows'); + 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 cols = [{ + title: 'col1' + }, { + title: 'col2' + }]; + var rows = [ + ['bacon', 'pork chop'], + ['steak', 'tri-tip'], + ]; + + 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'); it('should allow custom pagination code'); }); From ae637b8a991d1d948659b2cbf3ee5580f93a2cba Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 12:41:17 -0700 Subject: [PATCH 16/51] finish rendering tests, add first sorting test --- .../specs/components/paginated_table/index.js | 63 +++++++++++++++---- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index b0b206d18fca2..d489fa1d6a814 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -1,5 +1,7 @@ define(function (require) { require('components/paginated_table/paginated_table'); + var _ = require('lodash'); + var faker = require('faker'); describe.only('paginated table', function () { var $el; @@ -7,12 +9,28 @@ define(function (require) { var $compile; var $scope; var $elScope; + var $orderBy; var defaultPerPage = 10; var init = function () { // load the application }; + 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 || []; @@ -27,9 +45,10 @@ define(function (require) { beforeEach(function () { module('kibana'); - inject(function (_$rootScope_, _$compile_) { + inject(function (_$rootScope_, _$compile_, $filter) { $rootScope = _$rootScope_; $compile = _$compile_; + $orderBy = $filter('orderBy'); }); $scope = $rootScope.$new(); @@ -51,15 +70,9 @@ define(function (require) { }); it('should render columns and rows', function () { - var cols = [{ - title: 'col1' - }, { - title: 'col2' - }]; - var rows = [ - ['bacon', 'pork chop'], - ['steak', 'tri-tip'], - ]; + var data = makeData(2, 2); + var cols = data.columns; + var rows = data.rows; renderTable(cols, rows); expect($el.children().size()).to.be(1); @@ -73,12 +86,36 @@ define(function (require) { expect(tableRows.eq(1).find('td').eq(1).text()).to.be(rows[1][1]); }); - it('should paginate rows'); - it('should allow custom pagination code'); + 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 () { - it('should not sort by default'); + var data = makeData(3, 3); + + beforeEach(function () { + data.rows.push(['zzzz', 'zzzz', 'zzzz']); + data.rows.push(['aaaa', 'aaaa', 'aaaa']); + }); + + it('should not sort by default', function () { + var lastRowIndex = data.rows.length - 1; + renderTable(data.columns, data.rows); + var tableRows = $el.find('tbody tr'); + expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be(data.rows[lastRowIndex][0]); + }); + it('should sort ascending on first click'); it('should sort desciending on second click'); it('should clear sorting on third click'); From a3635a227b994ee726e9e4404e0d06cd2d5558ea Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 14:04:16 -0700 Subject: [PATCH 17/51] add sorting tests --- .../specs/components/paginated_table/index.js | 60 ++++++++++++++----- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index d489fa1d6a814..dbdc0192c9062 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -12,10 +12,6 @@ define(function (require) { var $orderBy; var defaultPerPage = 10; - var init = function () { - // load the application - }; - var makeData = function (colCount, rowCount) { var cols = faker.Lorem.words(colCount).map(function (word) { return { title: word }; @@ -38,8 +34,7 @@ define(function (require) { $el = $compile('')($scope); - $elScope = $el.scope(); - $elScope.$digest(); + $scope.$digest(); }; beforeEach(function () { @@ -102,25 +97,60 @@ define(function (require) { }); describe('sorting', function () { - var data = makeData(3, 3); + 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 lastRowIndex = data.rows.length - 1; - renderTable(data.columns, data.rows); var tableRows = $el.find('tbody tr'); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be(data.rows[lastRowIndex][0]); + 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'); }); - it('should sort ascending on first click'); - it('should sort desciending on second click'); - it('should clear sorting on third click'); - it('should sort using $orderBy'); - it('should allow custom sorting handler'); }); }); }); \ No newline at end of file From 983b2dcb2a645f3ad2615decea49a27a59fada12 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 14:31:47 -0700 Subject: [PATCH 18/51] change how custom handler works, add test for custom handler --- .../paginated_table/paginated_table.js | 24 +++++++------- .../specs/components/paginated_table/index.js | 31 ++++++++++++++++++- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index a45f90e720f17..080d22574934c 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -25,12 +25,6 @@ define(function (require) { }; self.sortColumn = function (col) { - // use custom sort handler if one was defined - if (_.isFunction($scope.sortHandler)) { - $scope.sortHandler(col, self.sort); - } - - // use generic sort handler self._setSortDirection(col.title); }; @@ -41,10 +35,6 @@ define(function (require) { if (index === -1) return; - var sortGetter = function (row) { - return row[index]; - }; - if (self.sort.columnName !== columnName) { sortDirection = 'asc'; } else { @@ -57,8 +47,20 @@ define(function (require) { } self.sort.columnName = columnName; - self.sort.getter = sortGetter; 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 diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index dbdc0192c9062..eb2dc9efae656 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -2,8 +2,9 @@ define(function (require) { require('components/paginated_table/paginated_table'); var _ = require('lodash'); var faker = require('faker'); + var sinon = require('sinon/sinon'); - describe.only('paginated table', function () { + describe('paginated table', function () { var $el; var $rootScope; var $compile; @@ -150,7 +151,35 @@ define(function (require) { 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('')($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); + }); }); }); }); \ No newline at end of file From 41157a6cb851cd83a5511462cedbaae7a79dc87e Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 14:33:15 -0700 Subject: [PATCH 19/51] minor code consolidation --- .../components/paginated_table/paginated_table.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index 080d22574934c..17d3ad8cc9e78 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -25,17 +25,13 @@ define(function (require) { }; self.sortColumn = function (col) { - self._setSortDirection(col.title); - }; - - self._setSortDirection = function (columnName) { var sortDirection; var cols = _.pluck($scope.columns, 'title'); - var index = cols.indexOf(columnName); + var index = cols.indexOf(col.title); if (index === -1) return; - if (self.sort.columnName !== columnName) { + if (self.sort.columnName !== col.title) { sortDirection = 'asc'; } else { var directions = { @@ -46,7 +42,7 @@ define(function (require) { sortDirection = directions[self.sort.direction]; } - self.sort.columnName = columnName; + self.sort.columnName = col.title; self.sort.direction = sortDirection; self._setSortGetter(index); }; From 0e929aca78c6cb5f0b827a7911939f7e8aeb0c3f Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 11:22:11 -0700 Subject: [PATCH 20/51] make formattedColumns clearer --- src/kibana/components/agg_table/agg_table.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index ad80ae1e39870..27c243da8ec43 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -83,16 +83,18 @@ define(function (require) { function setFormattedColumns(table) { $scope.formattedColumns = table.columns.map(function (col, i) { - var cls = []; + var formattedColumn = { + title: col.title + }; + var agg = $scope.table.aggConfig(col); var last = i === (table.columns.length - 1); if (last || (agg.schema.group === 'metrics')) { - cls.push('visualize-table-right'); + formattedColumn.class = 'visualize-table-right'; } - col.class = cls.join(' '); - return col; + return formattedColumn; }); } From c4358a21b57cff16a28a646f9c28f2d2a487b523 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 11:31:00 -0700 Subject: [PATCH 21/51] fix check for perPage - use ALL only when undefined --- src/kibana/directives/paginate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kibana/directives/paginate.js b/src/kibana/directives/paginate.js index 8a1c0665377cc..3f946514cb2b4 100644 --- a/src/kibana/directives/paginate.js +++ b/src/kibana/directives/paginate.js @@ -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; } From ccdd03994bba4eb9b8a0698a9f94608beb32dd8e Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 15:58:39 -0700 Subject: [PATCH 22/51] add info property to table columns --- src/kibana/components/paginated_table/paginated_table.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kibana/components/paginated_table/paginated_table.html b/src/kibana/components/paginated_table/paginated_table.html index a7ded3ab3f5fb..8262ffc984776 100644 --- a/src/kibana/components/paginated_table/paginated_table.html +++ b/src/kibana/components/paginated_table/paginated_table.html @@ -12,6 +12,7 @@ ng-click="paginatedTable.sortColumn(col)" class="{{ col.class }}"> + - -

- - - - - - - - - - - - - - - -
name type - analyzed - - - indexed - - - popularity - -
- -   - - - - - - - - - - - - -
- +
+ +
-
+
No scripted fields defined
diff --git a/src/kibana/plugins/settings/sections/indices/_edit.js b/src/kibana/plugins/settings/sections/indices/_edit.js index 0b74fcad21562..1c404316f8e36 100644 --- a/src/kibana/plugins/settings/sections/indices/_edit.js +++ b/src/kibana/plugins/settings/sections/indices/_edit.js @@ -1,5 +1,6 @@ define(function (require) { var _ = require('lodash'); + require('components/paginated_table/paginated_table'); require('routes') .when('/settings/indices/:id', { @@ -23,6 +24,28 @@ define(function (require) { $scope.fieldTypes = Private(require('plugins/settings/sections/indices/_field_types')); + $scope.fieldColumns = [{ + title: 'name' + }, { + title: 'type' + }, { + title: 'analyzed', + info: 'Analyzed fields may require extra memory to visualize' + }, { + title: 'indexed', + info: 'Fields that are not indexed are unavailable for search' + }, { + title: 'popularity', + info: 'A gauge of how often this field is used', + class: 'pull-right' + }]; + + $scope.fieldRows = $scope.indexPattern.fields.map(function (field) { + return [field.name, field.type, field.analyzed, field.indexed, field.count]; + }); + + $scope.perPage = 25; + $scope.table = { by: 'name', reverse: false, From bfc5a2cd27b3a9f5ee857502dafa866517a00836 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 16:43:37 -0700 Subject: [PATCH 24/51] fix the name field width so the table feels more constant --- src/kibana/plugins/settings/styles/main.less | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/kibana/plugins/settings/styles/main.less b/src/kibana/plugins/settings/styles/main.less index da3e6567cd2ce..aa52bbe826d97 100644 --- a/src/kibana/plugins/settings/styles/main.less +++ b/src/kibana/plugins/settings/styles/main.less @@ -129,6 +129,13 @@ kbn-settings-objects-view { } } +kbn-settings-indices .fields { + & th:first-child, + & td:first-child { + width: 35%; + } +} + .kbn-settings-indices-create { .time-and-pattern > div {} } From 17ec369a2475d7cbab2f3ce2b7f4e8dfed49d9e3 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 16:44:08 -0700 Subject: [PATCH 25/51] allow kbnRow to input --- src/kibana/directives/rows.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/kibana/directives/rows.js b/src/kibana/directives/rows.js index f8d39db74292f..eeebf737ff042 100644 --- a/src/kibana/directives/rows.js +++ b/src/kibana/directives/rows.js @@ -3,7 +3,7 @@ define(function (require) { var _ = require('lodash'); var module = require('modules').get('kibana'); - module.directive('kbnRows', function ($parse) { + module.directive('kbnRows', function ($compile) { return { restrict: 'A', link: function ($scope, $el, attr) { @@ -14,11 +14,16 @@ define(function (require) { // access to it here. This may become a problem with the switch to BigNumber if (_.isNumeric(contents)) $cell.addClass('numeric-value'); - if (contents === '') { - $cell.html(' '); + if (_.isObject(contents)) { + $cell.html($compile(contents.markup)(contents.scope)); } else { - $cell.text(contents); + if (contents === '') { + $cell.html(' '); + } else { + $cell.text(contents); + } } + $tr.append($cell); } From 6c98cc22d857fc1c09f59a442b198b908a23d48f Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 17:08:02 -0700 Subject: [PATCH 26/51] use compiled inputs in the list --- .../settings/sections/indices/_edit.js | 52 ++++++++----------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/kibana/plugins/settings/sections/indices/_edit.js b/src/kibana/plugins/settings/sections/indices/_edit.js index 1c404316f8e36..aeb774193a112 100644 --- a/src/kibana/plugins/settings/sections/indices/_edit.js +++ b/src/kibana/plugins/settings/sections/indices/_edit.js @@ -14,7 +14,7 @@ define(function (require) { }); require('modules').get('apps/settings') - .controller('settingsIndicesEdit', function ($scope, $location, $route, config, courier, Notifier, Private, AppState) { + .controller('settingsIndicesEdit', function ($rootScope, $scope, $location, $route, config, courier, Notifier, Private, AppState) { var notify = new Notifier(); var $state = $scope.state = new AppState(); var refreshKibanaIndex = Private(require('plugins/settings/sections/indices/_refresh_kibana_index')); @@ -37,21 +37,33 @@ define(function (require) { }, { title: 'popularity', info: 'A gauge of how often this field is used', - class: 'pull-right' }]; - $scope.fieldRows = $scope.indexPattern.fields.map(function (field) { - return [field.name, field.type, field.analyzed, field.indexed, field.count]; + $scope.$watchCollection('indexPattern.fields', function () { + $scope.fieldRows = $scope.indexPattern.fields.map(function (field) { + var childScope = $scope.$new(); + childScope.field = field; + + return [field.name, field.type, field.analyzed, field.indexed, + { + markup: + '
' + + '{{ field.count }} ' + + '' + + ' ' + + ' ' + + '' + + '
', + scope: childScope + } + ]; + }); }); - $scope.perPage = 25; - $scope.table = { - by: 'name', - reverse: false, - page: 0, - max: 35 - }; + $scope.perPage = 25; $scope.changeTab = function (obj) { $state.tab = obj.index; @@ -88,24 +100,6 @@ define(function (require) { config.set('defaultIndex', $scope.indexPattern.id); }; - $scope.setFieldSort = function (by) { - if ($scope.table.by === by) { - $scope.table.reverse = !$scope.table.reverse; - } else { - $scope.table.by = by; - } - }; - - $scope.sortClass = function (column) { - if ($scope.table.by !== column) return; - return $scope.table.reverse ? ['fa', 'fa-sort-asc'] : ['fa', 'fa-sort-desc']; - }; - - $scope.tablePages = function () { - if (!$scope.indexPattern.fields) return 0; - return Math.ceil($scope.indexPattern.fields.length / $scope.table.max); - }; - $scope.setIndexPatternsTimeField = function (field) { if (field.type !== 'date') { notify.error('That field is a ' + field.type + ' not a date.'); From aecc288493e0114ba348595654b773abd9c0e8d3 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 17:08:23 -0700 Subject: [PATCH 27/51] update paginated-table when rows change --- src/kibana/components/paginated_table/paginated_table.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index 17d3ad8cc9e78..10869d4216301 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -60,7 +60,10 @@ define(function (require) { }; // update the sordedRows result - $scope.$watch('paginatedTable.sort.direction', function () { + $scope.$watchMulti([ + 'paginatedTable.sort.direction', + 'rows' + ], function () { if (self.sort.direction == null) { $scope.sortedRows = $scope.rows.slice(0); return; From 48c599d36fcf3078de6faaf33e3e50979868ec1b Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 18:12:33 -0700 Subject: [PATCH 28/51] destroy child scopes when re-rendering the table --- src/kibana/plugins/settings/sections/indices/_edit.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/kibana/plugins/settings/sections/indices/_edit.js b/src/kibana/plugins/settings/sections/indices/_edit.js index aeb774193a112..e26686816e26c 100644 --- a/src/kibana/plugins/settings/sections/indices/_edit.js +++ b/src/kibana/plugins/settings/sections/indices/_edit.js @@ -39,9 +39,14 @@ define(function (require) { info: 'A gauge of how often this field is used', }]; + // track row scopes, so they can be destroyed as needed + var rowScopes = []; $scope.$watchCollection('indexPattern.fields', function () { + _.invoke(rowScopes, '$destroy'); + $scope.fieldRows = $scope.indexPattern.fields.map(function (field) { var childScope = $scope.$new(); + rowScopes.push(childScope); childScope.field = field; return [field.name, field.type, field.analyzed, field.indexed, From d956aa681b3202c83c0e8916073fe716d62c5537 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 12:58:33 -0700 Subject: [PATCH 29/51] pass rendered markup and value to row, render markup by wrapping in jquery --- src/kibana/directives/rows.js | 4 ++-- src/kibana/plugins/settings/sections/indices/_edit.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/kibana/directives/rows.js b/src/kibana/directives/rows.js index eeebf737ff042..4ec6e06ea8fc8 100644 --- a/src/kibana/directives/rows.js +++ b/src/kibana/directives/rows.js @@ -3,7 +3,7 @@ define(function (require) { var _ = require('lodash'); var module = require('modules').get('kibana'); - module.directive('kbnRows', function ($compile) { + module.directive('kbnRows', function () { return { restrict: 'A', link: function ($scope, $el, attr) { @@ -15,7 +15,7 @@ define(function (require) { if (_.isNumeric(contents)) $cell.addClass('numeric-value'); if (_.isObject(contents)) { - $cell.html($compile(contents.markup)(contents.scope)); + $cell.html($(contents.markup)); } else { if (contents === '') { $cell.html(' '); diff --git a/src/kibana/plugins/settings/sections/indices/_edit.js b/src/kibana/plugins/settings/sections/indices/_edit.js index e26686816e26c..f0bd7c04f0829 100644 --- a/src/kibana/plugins/settings/sections/indices/_edit.js +++ b/src/kibana/plugins/settings/sections/indices/_edit.js @@ -14,7 +14,8 @@ define(function (require) { }); require('modules').get('apps/settings') - .controller('settingsIndicesEdit', function ($rootScope, $scope, $location, $route, config, courier, Notifier, Private, AppState) { + .controller('settingsIndicesEdit', function ($scope, $location, $route, $compile, + config, courier, Notifier, Private, AppState) { var notify = new Notifier(); var $state = $scope.state = new AppState(); var refreshKibanaIndex = Private(require('plugins/settings/sections/indices/_refresh_kibana_index')); @@ -51,8 +52,7 @@ define(function (require) { return [field.name, field.type, field.analyzed, field.indexed, { - markup: - '
' + + markup: $compile('
' + '{{ field.count }} ' + '' + ' ' + '' + - '
', - scope: childScope + '
')(childScope), + value: field.count } ]; }); From 166150ddc26f6542a073a6a1b47e958978da9430 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 12:59:51 -0700 Subject: [PATCH 30/51] handle sorting objects by obj.value --- src/kibana/components/paginated_table/paginated_table.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index 10869d4216301..b9aec03441b72 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -54,6 +54,7 @@ define(function (require) { } else { // use generic sort handler self.sort.getter = function (row) { + if (_.isObject(row)) return row[index].value; return row[index]; }; } From 031c3bc0010534e647defd7db4280f3cbcea9b3c Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 13:21:02 -0700 Subject: [PATCH 31/51] track hovered field state in parent scope, move popularize html into a partial --- .../settings/sections/indices/_edit.js | 24 ++++++++++--------- .../sections/indices/_popularity.html | 9 +++++++ 2 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 src/kibana/plugins/settings/sections/indices/_popularity.html diff --git a/src/kibana/plugins/settings/sections/indices/_edit.js b/src/kibana/plugins/settings/sections/indices/_edit.js index f0bd7c04f0829..0b03000c944f2 100644 --- a/src/kibana/plugins/settings/sections/indices/_edit.js +++ b/src/kibana/plugins/settings/sections/indices/_edit.js @@ -16,8 +16,11 @@ define(function (require) { require('modules').get('apps/settings') .controller('settingsIndicesEdit', function ($scope, $location, $route, $compile, config, courier, Notifier, Private, AppState) { + + var rowScopes = []; // track row scopes, so they can be destroyed as needed var notify = new Notifier(); var $state = $scope.state = new AppState(); + var popularityHtml = require('text!plugins/settings/sections/indices/_popularity.html'); var refreshKibanaIndex = Private(require('plugins/settings/sections/indices/_refresh_kibana_index')); $scope.indexPattern = $route.current.locals.indexPattern; @@ -40,8 +43,10 @@ define(function (require) { info: 'A gauge of how often this field is used', }]; - // track row scopes, so they can be destroyed as needed - var rowScopes = []; + $scope.showPopularityControls = function (field) { + $scope.popularityHoverState = (field) ? field : null; + }; + $scope.$watchCollection('indexPattern.fields', function () { _.invoke(rowScopes, '$destroy'); @@ -50,17 +55,14 @@ define(function (require) { rowScopes.push(childScope); childScope.field = field; + // update the active field via object comparison + if (_.isEqual(field, $scope.popularityHoverState)) { + $scope.showPopularityControls(field); + } + return [field.name, field.type, field.analyzed, field.indexed, { - markup: $compile('
' + - '{{ field.count }} ' + - '' + - ' ' + - ' ' + - '' + - '
')(childScope), + markup: $compile(popularityHtml)(childScope), value: field.count } ]; diff --git a/src/kibana/plugins/settings/sections/indices/_popularity.html b/src/kibana/plugins/settings/sections/indices/_popularity.html new file mode 100644 index 0000000000000..a8d90dc6e9d51 --- /dev/null +++ b/src/kibana/plugins/settings/sections/indices/_popularity.html @@ -0,0 +1,9 @@ +
+ {{ field.count }} + + + + +
' \ No newline at end of file From f6dc49c3ca362e3eb4fe1f1c3c329bc0213f530b Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 17:57:36 -0700 Subject: [PATCH 32/51] remove unused dep, clean up comment --- src/kibana/components/agg_table/agg_table.js | 1 - src/kibana/components/visualize/spy/spy.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index 7b5755c656f4c..98645632ca6b9 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -7,7 +7,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 { diff --git a/src/kibana/components/visualize/spy/spy.js b/src/kibana/components/visualize/spy/spy.js index fde6071e84cc7..4a6aad8eefcf4 100644 --- a/src/kibana/components/visualize/spy/spy.js +++ b/src/kibana/components/visualize/spy/spy.js @@ -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 () { From b10bde58de535221955c0b33cf0b929f6067d58a Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 17:59:20 -0700 Subject: [PATCH 33/51] refactor - no need to wrap code to return early --- src/kibana/components/visualize/spy/spy.js | 51 ++++++++++------------ 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/kibana/components/visualize/spy/spy.js b/src/kibana/components/visualize/spy/spy.js index 4a6aad8eefcf4..2300c8791964b 100644 --- a/src/kibana/components/visualize/spy/spy.js +++ b/src/kibana/components/visualize/spy/spy.js @@ -35,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: $('
').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: $('
').appendTo($container) + }; + + current.$container.append($compile(newMode.template)(current.$scope)); + newMode.link && newMode.link(current.$scope, current.$container); }; } }; From 9c2bd9977305fb276754955026bdfc69feeca4c1 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 18:00:11 -0700 Subject: [PATCH 34/51] create paginated table directive --- .../paginated_table/paginated_table.html | 51 +++++++++++ .../paginated_table/paginated_table.js | 86 +++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 src/kibana/components/paginated_table/paginated_table.html create mode 100644 src/kibana/components/paginated_table/paginated_table.js diff --git a/src/kibana/components/paginated_table/paginated_table.html b/src/kibana/components/paginated_table/paginated_table.html new file mode 100644 index 0000000000000..13f83b6a7ab89 --- /dev/null +++ b/src/kibana/components/paginated_table/paginated_table.html @@ -0,0 +1,51 @@ + + + +

Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

+

No Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

+
+ + + + + + + +
+ + + +
+
+ + + +
+ +
\ No newline at end of file diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js new file mode 100644 index 0000000000000..4b28a8d78a106 --- /dev/null +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -0,0 +1,86 @@ +define(function (require) { + require('modules') + .get('kibana') + .directive('paginatedTable', function (config, Private) { + var _ = require('lodash'); + + return { + restrict: 'E', + template: require('text!components/paginated_table/paginated_table.html'), + transclude: true, + scope: { + rows: '=', + columns: '=', + perPage: '=?', + perPageProp: '=?', + sortHandler: '=?', + showSelector: '=?' + }, + controllerAs: 'paginatedTable', + controller: function ($scope) { + var self = this; + self.sort = { + columnName: null, + direction: null + }; + + self.perPage = _.parseInt(self.perPage) || $scope[self.perPageProp]; + + self.sortColumn = function (col) { + if (!$scope.sortHandler) return; + + // TODO: track sort direction + + self._setSortDirection(col.title); + $scope.sortHandler(col, self.sort); + }; + + self._setSortDirection = function (columnName) { + if (self.sort.columnName !== columnName) { + self.sort.direction = 'asc'; + } else { + var directions = { + null: 'asc', + 'asc': 'desc', + 'desc': null + }; + var direction = directions[self.sort.direction]; + self.sort.direction = direction; + + } + self.sort.columnName = columnName; + }; + + // $scope.$watchMulti([ + // 'rows', + // 'columns', + // 'paginatedTable.sort.asc', + // 'paginatedTable.sort.col' + // ], function () { + // if (!$scope.rows) return; + + // var formatters = $scope.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) { + // return row.map(function (cell, i) { + // return formatters[i](cell); + // }); + // }); + + // // update the csv file's title + // self.csv.filename = (table.title() || 'table') + '.csv'; + // }); + } + }; + }); +}); From 9456c4df1550e48f59908621c79fd82a8ce34fd6 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 20 Nov 2014 18:01:12 -0700 Subject: [PATCH 35/51] use paginated table in table spy --- .../components/agg_table/agg_table.html | 42 +++---------------- src/kibana/components/agg_table/agg_table.js | 1 + 2 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.html b/src/kibana/components/agg_table/agg_table.html index eb9f7a9f80607..b595b94302b50 100644 --- a/src/kibana/components/agg_table/agg_table.html +++ b/src/kibana/components/agg_table/agg_table.html @@ -1,38 +1,8 @@ - - list="formattedRows" - per-page-prop="perPage" - - class="agg-table"> -
- - - - - - - -
- - - -
-
- -
- \ No newline at end of file + diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index 98645632ca6b9..b86da88df990a 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -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'); From 8cb554f9910c1cbd4e7ff796e89924ee3d524159 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Fri, 21 Nov 2014 11:21:25 -0700 Subject: [PATCH 36/51] use perPageProp for pagination, working spy agg table --- .../components/agg_table/agg_table.html | 6 ++++ .../paginated_table/paginated_table.html | 19 +---------- .../paginated_table/paginated_table.js | 33 ------------------- 3 files changed, 7 insertions(+), 51 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.html b/src/kibana/components/agg_table/agg_table.html index b595b94302b50..fea5632607295 100644 --- a/src/kibana/components/agg_table/agg_table.html +++ b/src/kibana/components/agg_table/agg_table.html @@ -5,4 +5,10 @@ per-page="perPage" sort-handler="aggTable.cycleSort"> + diff --git a/src/kibana/components/paginated_table/paginated_table.html b/src/kibana/components/paginated_table/paginated_table.html index 13f83b6a7ab89..b377defd164c1 100644 --- a/src/kibana/components/paginated_table/paginated_table.html +++ b/src/kibana/components/paginated_table/paginated_table.html @@ -1,24 +1,8 @@ - - -

Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

-

No Handler perPage:{{ perPage }} / perPageProp:{{ perPageProp }}

@@ -30,7 +14,6 @@

No Handler perPage:{{ perPage }} / perPageProp:{{ perPa + per-page="perPage">
diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index b86da88df990a..8f6cb99e60948 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -48,27 +48,6 @@ define(function (require) { 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,11 +83,7 @@ define(function (require) { }).join(''); }; - $scope.$watchMulti([ - 'table', - 'aggTable.sort.asc', - 'aggTable.sort.col' - ], function () { + $scope.$watch('table', function () { var table = $scope.table; if (!table) { @@ -120,13 +95,6 @@ define(function (require) { 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) { return row.map(function (cell, i) { diff --git a/src/kibana/components/paginated_table/paginated_table.html b/src/kibana/components/paginated_table/paginated_table.html index b377defd164c1..a7ded3ab3f5fb 100644 --- a/src/kibana/components/paginated_table/paginated_table.html +++ b/src/kibana/components/paginated_table/paginated_table.html @@ -1,6 +1,6 @@
@@ -16,8 +16,8 @@ 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 === 'asc', - 'fa-sort': !paginatedTable.sort.direction || paginatedTable.sort.columnName !== col.title + 'fa-sort-desc': paginatedTable.sort.columnName === col.title && paginatedTable.sort.direction === 'desc', + 'fa-sort': paginatedTable.sort.direction === null || paginatedTable.sort.columnName !== col.title }"> diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index 454c916b0a56e..a45f90e720f17 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -1,8 +1,9 @@ define(function (require) { require('modules') .get('kibana') - .directive('paginatedTable', function (config, Private) { + .directive('paginatedTable', function ($filter, config, Private) { var _ = require('lodash'); + var orderBy = $filter('orderBy'); return { restrict: 'E', @@ -24,29 +25,51 @@ define(function (require) { }; self.sortColumn = function (col) { - if (!$scope.sortHandler) return; - - // TODO: track sort direction + // use custom sort handler if one was defined + if (_.isFunction($scope.sortHandler)) { + $scope.sortHandler(col, self.sort); + } + // use generic sort handler self._setSortDirection(col.title); - $scope.sortHandler(col, self.sort); }; self._setSortDirection = function (columnName) { + var sortDirection; + var cols = _.pluck($scope.columns, 'title'); + var index = cols.indexOf(columnName); + + if (index === -1) return; + + var sortGetter = function (row) { + return row[index]; + }; + if (self.sort.columnName !== columnName) { - self.sort.direction = 'asc'; + sortDirection = 'asc'; } else { var directions = { null: 'asc', 'asc': 'desc', 'desc': null }; - var direction = directions[self.sort.direction]; - self.sort.direction = direction; - + sortDirection = directions[self.sort.direction]; } + self.sort.columnName = columnName; + self.sort.getter = sortGetter; + self.sort.direction = sortDirection; }; + + // update the sordedRows result + $scope.$watch('paginatedTable.sort.direction', 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'); + }); } }; }); From d6a24b04e548da432d2b423a9bf86638bc164a7b Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Fri, 21 Nov 2014 18:08:18 -0700 Subject: [PATCH 38/51] format agg columns, pass to paginated table --- .../components/agg_table/agg_table.html | 2 +- src/kibana/components/agg_table/agg_table.js | 38 +++++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.html b/src/kibana/components/agg_table/agg_table.html index 863dcb1c9098d..bb2c632248d92 100644 --- a/src/kibana/components/agg_table/agg_table.html +++ b/src/kibana/components/agg_table/agg_table.html @@ -1,7 +1,7 @@
diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index 8f6cb99e60948..ad80ae1e39870 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -33,21 +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.exportAsCsv = function () { var csv = new Blob([self.toCsv()], { type: 'text/plain' }); self._saveAs(csv, self.csv.filename); @@ -88,9 +73,30 @@ define(function (require) { 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 cls = []; + var agg = $scope.table.aggConfig(col); + var last = i === (table.columns.length - 1); + + if (last || (agg.schema.group === 'metrics')) { + cls.push('visualize-table-right'); + } + + col.class = cls.join(' '); + return col; + }); + } + + function setFormattedRows(table) { var formatters = table.columns.map(function (col) { return table.fieldFormatter(col); }); @@ -104,7 +110,7 @@ define(function (require) { // update the csv file's title self.csv.filename = (table.title() || 'table') + '.csv'; - }); + } } }; }); From c019c43477c0bec717e730ab37dfa3aa73472592 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 11:11:39 -0700 Subject: [PATCH 39/51] remove cycleSort tests --- .../unit/specs/components/agg_table/_table.js | 152 ------------------ 1 file changed, 152 deletions(-) diff --git a/test/unit/specs/components/agg_table/_table.js b/test/unit/specs/components/agg_table/_table.js index 101b567fec07e..5b1d7dfd49c1c 100644 --- a/test/unit/specs/components/agg_table/_table.js +++ b/test/unit/specs/components/agg_table/_table.js @@ -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('')($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('')($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('')($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('')($scope); From 660984570801fe1428169934e002cec3c60d279c Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 12:00:35 -0700 Subject: [PATCH 40/51] start adding tests for paginated table --- .../specs/components/paginated_table/index.js | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/unit/specs/components/paginated_table/index.js diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js new file mode 100644 index 0000000000000..7c67659054a02 --- /dev/null +++ b/test/unit/specs/components/paginated_table/index.js @@ -0,0 +1,58 @@ +define(function (require) { + require('components/paginated_table/paginated_table'); + + describe.only('paginated table', function () { + var $el; + var $rootScope; + var $compile; + var $scope; + var $elScope; + var defaultPerPage = 10; + + var init = function () { + // load the application + }; + + var renderTable = function (cols, rows, perPage) { + $scope.cols = cols || []; + $scope.rows = rows || []; + $scope.perPage = perPage || defaultPerPage; + + $el = $compile('')($scope); + + $elScope = $el.scope(); + $elScope.$digest(); + }; + + beforeEach(function () { + module('kibana'); + + inject(function (_$rootScope_, _$compile_) { + $rootScope = _$rootScope_; + $compile = _$compile_; + }); + + $scope = $rootScope.$new(); + }); + + afterEach(function () { + $scope.$destroy(); + }); + + describe('rendering', function () { + it('should not display without rows'); + it('should render columns and rows'); + it('should paginate rows'); + it('should allow custom pagination code'); + }); + + describe('sorting', function () { + it('should not sort by default'); + it('should sort ascending on first click'); + it('should sort desciending on second click'); + it('should clear sorting on third click'); + it('should sort using $orderBy'); + it('should allow custom sorting handler'); + }); + }); +}); \ No newline at end of file From b68ecd2c723856be84650745ecaf19aa83647da4 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 12:00:58 -0700 Subject: [PATCH 41/51] add table rendering tests --- .../specs/components/paginated_table/index.js | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index 7c67659054a02..b0b206d18fca2 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -40,8 +40,39 @@ define(function (require) { }); describe('rendering', function () { - it('should not display without rows'); - it('should render columns and rows'); + 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 cols = [{ + title: 'col1' + }, { + title: 'col2' + }]; + var rows = [ + ['bacon', 'pork chop'], + ['steak', 'tri-tip'], + ]; + + 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'); it('should allow custom pagination code'); }); From 55ddbf40b56a94876e24e9d7dcebd879e2094e16 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 12:41:17 -0700 Subject: [PATCH 42/51] finish rendering tests, add first sorting test --- .../specs/components/paginated_table/index.js | 63 +++++++++++++++---- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index b0b206d18fca2..d489fa1d6a814 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -1,5 +1,7 @@ define(function (require) { require('components/paginated_table/paginated_table'); + var _ = require('lodash'); + var faker = require('faker'); describe.only('paginated table', function () { var $el; @@ -7,12 +9,28 @@ define(function (require) { var $compile; var $scope; var $elScope; + var $orderBy; var defaultPerPage = 10; var init = function () { // load the application }; + 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 || []; @@ -27,9 +45,10 @@ define(function (require) { beforeEach(function () { module('kibana'); - inject(function (_$rootScope_, _$compile_) { + inject(function (_$rootScope_, _$compile_, $filter) { $rootScope = _$rootScope_; $compile = _$compile_; + $orderBy = $filter('orderBy'); }); $scope = $rootScope.$new(); @@ -51,15 +70,9 @@ define(function (require) { }); it('should render columns and rows', function () { - var cols = [{ - title: 'col1' - }, { - title: 'col2' - }]; - var rows = [ - ['bacon', 'pork chop'], - ['steak', 'tri-tip'], - ]; + var data = makeData(2, 2); + var cols = data.columns; + var rows = data.rows; renderTable(cols, rows); expect($el.children().size()).to.be(1); @@ -73,12 +86,36 @@ define(function (require) { expect(tableRows.eq(1).find('td').eq(1).text()).to.be(rows[1][1]); }); - it('should paginate rows'); - it('should allow custom pagination code'); + 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 () { - it('should not sort by default'); + var data = makeData(3, 3); + + beforeEach(function () { + data.rows.push(['zzzz', 'zzzz', 'zzzz']); + data.rows.push(['aaaa', 'aaaa', 'aaaa']); + }); + + it('should not sort by default', function () { + var lastRowIndex = data.rows.length - 1; + renderTable(data.columns, data.rows); + var tableRows = $el.find('tbody tr'); + expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be(data.rows[lastRowIndex][0]); + }); + it('should sort ascending on first click'); it('should sort desciending on second click'); it('should clear sorting on third click'); From c1aab744655a64f1f8845a0baddfd59ae457e94f Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 14:04:16 -0700 Subject: [PATCH 43/51] add sorting tests --- .../specs/components/paginated_table/index.js | 60 ++++++++++++++----- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index d489fa1d6a814..dbdc0192c9062 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -12,10 +12,6 @@ define(function (require) { var $orderBy; var defaultPerPage = 10; - var init = function () { - // load the application - }; - var makeData = function (colCount, rowCount) { var cols = faker.Lorem.words(colCount).map(function (word) { return { title: word }; @@ -38,8 +34,7 @@ define(function (require) { $el = $compile('')($scope); - $elScope = $el.scope(); - $elScope.$digest(); + $scope.$digest(); }; beforeEach(function () { @@ -102,25 +97,60 @@ define(function (require) { }); describe('sorting', function () { - var data = makeData(3, 3); + 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 lastRowIndex = data.rows.length - 1; - renderTable(data.columns, data.rows); var tableRows = $el.find('tbody tr'); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be(data.rows[lastRowIndex][0]); + 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'); }); - it('should sort ascending on first click'); - it('should sort desciending on second click'); - it('should clear sorting on third click'); - it('should sort using $orderBy'); - it('should allow custom sorting handler'); }); }); }); \ No newline at end of file From af5424649a4e67e762705aead8b1945a56e36d1b Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 14:31:47 -0700 Subject: [PATCH 44/51] change how custom handler works, add test for custom handler --- .../paginated_table/paginated_table.js | 24 +++++++------- .../specs/components/paginated_table/index.js | 31 ++++++++++++++++++- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index a45f90e720f17..080d22574934c 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -25,12 +25,6 @@ define(function (require) { }; self.sortColumn = function (col) { - // use custom sort handler if one was defined - if (_.isFunction($scope.sortHandler)) { - $scope.sortHandler(col, self.sort); - } - - // use generic sort handler self._setSortDirection(col.title); }; @@ -41,10 +35,6 @@ define(function (require) { if (index === -1) return; - var sortGetter = function (row) { - return row[index]; - }; - if (self.sort.columnName !== columnName) { sortDirection = 'asc'; } else { @@ -57,8 +47,20 @@ define(function (require) { } self.sort.columnName = columnName; - self.sort.getter = sortGetter; 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 diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index dbdc0192c9062..eb2dc9efae656 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -2,8 +2,9 @@ define(function (require) { require('components/paginated_table/paginated_table'); var _ = require('lodash'); var faker = require('faker'); + var sinon = require('sinon/sinon'); - describe.only('paginated table', function () { + describe('paginated table', function () { var $el; var $rootScope; var $compile; @@ -150,7 +151,35 @@ define(function (require) { 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('')($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); + }); }); }); }); \ No newline at end of file From 48d004f9164b7892520aa30e659611810bb48bda Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 24 Nov 2014 14:33:15 -0700 Subject: [PATCH 45/51] minor code consolidation --- .../components/paginated_table/paginated_table.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index 080d22574934c..17d3ad8cc9e78 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -25,17 +25,13 @@ define(function (require) { }; self.sortColumn = function (col) { - self._setSortDirection(col.title); - }; - - self._setSortDirection = function (columnName) { var sortDirection; var cols = _.pluck($scope.columns, 'title'); - var index = cols.indexOf(columnName); + var index = cols.indexOf(col.title); if (index === -1) return; - if (self.sort.columnName !== columnName) { + if (self.sort.columnName !== col.title) { sortDirection = 'asc'; } else { var directions = { @@ -46,7 +42,7 @@ define(function (require) { sortDirection = directions[self.sort.direction]; } - self.sort.columnName = columnName; + self.sort.columnName = col.title; self.sort.direction = sortDirection; self._setSortGetter(index); }; From 4987e13e221303379b5dc64298d33c833ee8cd12 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 11:22:11 -0700 Subject: [PATCH 46/51] make formattedColumns clearer --- src/kibana/components/agg_table/agg_table.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index ad80ae1e39870..27c243da8ec43 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -83,16 +83,18 @@ define(function (require) { function setFormattedColumns(table) { $scope.formattedColumns = table.columns.map(function (col, i) { - var cls = []; + var formattedColumn = { + title: col.title + }; + var agg = $scope.table.aggConfig(col); var last = i === (table.columns.length - 1); if (last || (agg.schema.group === 'metrics')) { - cls.push('visualize-table-right'); + formattedColumn.class = 'visualize-table-right'; } - col.class = cls.join(' '); - return col; + return formattedColumn; }); } From 2829371c2d9db1b533afd120c5b18290c705a583 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 11:31:00 -0700 Subject: [PATCH 47/51] fix check for perPage - use ALL only when undefined --- src/kibana/directives/paginate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kibana/directives/paginate.js b/src/kibana/directives/paginate.js index 8a1c0665377cc..3f946514cb2b4 100644 --- a/src/kibana/directives/paginate.js +++ b/src/kibana/directives/paginate.js @@ -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; } From f06f8dbfe6a51e429c383a5b7c8922f8c786ace6 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 13:34:07 -0700 Subject: [PATCH 48/51] always rebuild the formattedRows from the table data --- src/kibana/components/agg_table/agg_table.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kibana/components/agg_table/agg_table.js b/src/kibana/components/agg_table/agg_table.js index 27c243da8ec43..3698a925c70db 100644 --- a/src/kibana/components/agg_table/agg_table.js +++ b/src/kibana/components/agg_table/agg_table.js @@ -104,7 +104,7 @@ define(function (require) { }); // 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); }); From 17ce200e08282d6aefd411ffb013cdcae66666d4 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 13:34:37 -0700 Subject: [PATCH 49/51] watch for changes to rows --- src/kibana/components/paginated_table/paginated_table.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index 17d3ad8cc9e78..10869d4216301 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -60,7 +60,10 @@ define(function (require) { }; // update the sordedRows result - $scope.$watch('paginatedTable.sort.direction', function () { + $scope.$watchMulti([ + 'paginatedTable.sort.direction', + 'rows' + ], function () { if (self.sort.direction == null) { $scope.sortedRows = $scope.rows.slice(0); return; From 394694f65b8648086a6c5c7bb6a5588b67b29378 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 25 Nov 2014 13:52:22 -0700 Subject: [PATCH 50/51] Adding tests and fixing a bug with cloning - Closes #2040 - Add basic testing --- src/kibana/components/vis/vis.js | 5 +- test/unit/specs/components/vis/vis.js | 107 ++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 test/unit/specs/components/vis/vis.js diff --git a/src/kibana/components/vis/vis.js b/src/kibana/components/vis/vis.js index 4a20424116899..e5abf47cd17ca 100644 --- a/src/kibana/components/vis/vis.js +++ b/src/kibana/components/vis/vis.js @@ -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; }; -}); \ No newline at end of file +}); diff --git a/test/unit/specs/components/vis/vis.js b/test/unit/specs/components/vis/vis.js new file mode 100644 index 0000000000000..88d33511e6de0 --- /dev/null +++ b/test/unit/specs/components/vis/vis.js @@ -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); + }); + }); + + }); +}); From 97603268df945227ee619365d317c72e17a853fb Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Tue, 25 Nov 2014 15:12:34 -0700 Subject: [PATCH 51/51] added tests, fixed bug in sorting logic --- .../paginated_table/paginated_table.js | 5 +- .../specs/components/paginated_table/index.js | 49 ++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/kibana/components/paginated_table/paginated_table.js b/src/kibana/components/paginated_table/paginated_table.js index b9aec03441b72..08af4c619135e 100644 --- a/src/kibana/components/paginated_table/paginated_table.js +++ b/src/kibana/components/paginated_table/paginated_table.js @@ -54,8 +54,9 @@ define(function (require) { } else { // use generic sort handler self.sort.getter = function (row) { - if (_.isObject(row)) return row[index].value; - return row[index]; + var value = row[index]; + if (value.value) return value.value; + return value; }; } }; diff --git a/test/unit/specs/components/paginated_table/index.js b/test/unit/specs/components/paginated_table/index.js index eb2dc9efae656..dfeec7a7c460c 100644 --- a/test/unit/specs/components/paginated_table/index.js +++ b/test/unit/specs/components/paginated_table/index.js @@ -181,5 +181,52 @@ define(function (require) { expect(sortHandler.getCall(0).args[0]).to.be(columnIndex); }); }); + + describe('object rows', function () { + var cols; + var rows; + var paginatedTable; + + beforeEach(function () { + cols = [{ + title: 'object test' + }]; + rows = [ + ['aaaa'], + [{ + markup: '

I am HTML in a row

', + value: 'zzzz' + }], + ['bbbb'] + ]; + renderTable(cols, rows); + paginatedTable = $el.isolateScope().paginatedTable; + }); + + it('should append object markup', function () { + var tableRows = $el.find('tbody tr'); + expect(tableRows.eq(0).find('h1').size()).to.be(0); + expect(tableRows.eq(1).find('h1').size()).to.be(1); + expect(tableRows.eq(2).find('h1').size()).to.be(0); + }); + + it('should sort using object value', function () { + paginatedTable.sortColumn(cols[0]); + $scope.$digest(); + var tableRows = $el.find('tbody tr'); + expect(tableRows.eq(0).find('h1').size()).to.be(0); + expect(tableRows.eq(1).find('h1').size()).to.be(0); + // html row should be the last row + expect(tableRows.eq(2).find('h1').size()).to.be(1); + + paginatedTable.sortColumn(cols[0]); + $scope.$digest(); + tableRows = $el.find('tbody tr'); + // html row should be the first row + expect(tableRows.eq(0).find('h1').size()).to.be(1); + expect(tableRows.eq(1).find('h1').size()).to.be(0); + expect(tableRows.eq(2).find('h1').size()).to.be(0); + }); + }); }); -}); \ No newline at end of file +});