-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6105 from trevan/doc-detail-views-registry
Add registry for doc table details
- Loading branch information
Showing
17 changed files
with
571 additions
and
287 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module.exports = function (kibana) { | ||
|
||
return new kibana.Plugin({ | ||
|
||
uiExports: { | ||
docViews: [ | ||
'plugins/kbn_doc_views/kbn_doc_views' | ||
] | ||
} | ||
|
||
}); | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"name": "kbn_doc_views", | ||
"version": "1.0.0" | ||
} |
167 changes: 167 additions & 0 deletions
167
src/plugins/kbn_doc_views/public/__tests__/doc_views.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import angular from 'angular'; | ||
import _ from 'lodash'; | ||
import sinon from 'auto-release-sinon'; | ||
import expect from 'expect.js'; | ||
import ngMock from 'ngMock'; | ||
import $ from 'jquery'; | ||
import 'ui/render_directive'; | ||
import 'plugins/kbn_doc_views/views/table'; | ||
import docViewsRegistry from 'ui/registry/doc_views'; | ||
const hit = { | ||
'_index': 'logstash-2014.09.09', | ||
'_type': 'apache', | ||
'_id': '61', | ||
'_score': 1, | ||
'_source': { | ||
'extension': 'html', | ||
'bytes': 100, | ||
'area': [{lat: 7, lon: 7}], | ||
'noMapping': 'hasNoMapping', | ||
'objectArray': [{foo: true}, {bar: false}], | ||
'_underscore': 1 | ||
} | ||
}; | ||
|
||
// Load the kibana app dependencies. | ||
let $parentScope; | ||
let $scope; | ||
let indexPattern; | ||
let flattened; | ||
let docViews; | ||
|
||
const init = function ($elem, props) { | ||
ngMock.inject(function ($rootScope, $compile) { | ||
$parentScope = $rootScope; | ||
_.assign($parentScope, props); | ||
$compile($elem)($parentScope); | ||
$elem.scope().$digest(); | ||
$scope = $elem.isolateScope(); | ||
}); | ||
}; | ||
|
||
const destroy = function () { | ||
$scope.$destroy(); | ||
$parentScope.$destroy(); | ||
}; | ||
|
||
describe('docViews', function () { | ||
let $elem; | ||
let initView; | ||
|
||
beforeEach(ngMock.module('kibana')); | ||
beforeEach(function () { | ||
const aggs = 'index-pattern="indexPattern" hit="hit" filter="filter"'; | ||
$elem = angular.element(`<render-directive ${aggs} definition="view.directive"></render-directive>`); | ||
ngMock.inject(function (Private) { | ||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern')); | ||
flattened = indexPattern.flattenHit(hit); | ||
docViews = Private(docViewsRegistry); | ||
}); | ||
initView = function initView(view) { | ||
$elem.append(view.directive.template); | ||
init($elem, { | ||
indexPattern: indexPattern, | ||
hit: hit, | ||
view: view, | ||
filter: sinon.spy() | ||
}); | ||
}; | ||
}); | ||
|
||
afterEach(function () { | ||
destroy(); | ||
}); | ||
|
||
describe('Table', function () { | ||
beforeEach(function () { | ||
initView(docViews.byName.Table); | ||
}); | ||
it('should have a row for each field', function () { | ||
const rows = $elem.find('tr'); | ||
expect($elem.find('tr').length).to.be(_.keys(flattened).length); | ||
}); | ||
|
||
it('should have the field name in the first column', function () { | ||
_.each(_.keys(flattened), function (field) { | ||
expect($elem.find('td[title="' + field + '"]').length).to.be(1); | ||
}); | ||
}); | ||
|
||
it('should have the a value for each field', function () { | ||
_.each(_.keys(flattened), function (field) { | ||
const cellValue = $elem.find('td[title="' + field + '"]').siblings().find('.doc-viewer-value').text(); | ||
|
||
// This sucks, but testing the filter chain is too hairy ATM | ||
expect(cellValue.length).to.be.greaterThan(0); | ||
}); | ||
}); | ||
|
||
|
||
describe('filtering', function () { | ||
it('should apply a filter when clicking filterable fields', function () { | ||
const cell = $elem.find('td[title="bytes"]').next(); | ||
|
||
cell.find('.fa-search-plus').first().click(); | ||
expect($scope.filter.calledOnce).to.be(true); | ||
cell.find('.fa-search-minus').first().click(); | ||
expect($scope.filter.calledTwice).to.be(true); | ||
}); | ||
|
||
it('should NOT apply a filter when clicking non-filterable fields', function () { | ||
const cell = $elem.find('td[title="area"]').next(); | ||
|
||
cell.find('.fa-search-plus').first().click(); | ||
expect($scope.filter.calledOnce).to.be(false); | ||
cell.find('.fa-search-minus').first().click(); | ||
expect($scope.filter.calledTwice).to.be(false); | ||
}); | ||
}); | ||
|
||
describe('warnings', function () { | ||
it('displays a warning about field name starting with underscore', function () { | ||
const cells = $elem.find('td[title="_underscore"]').siblings(); | ||
expect(cells.find('.doc-viewer-underscore').length).to.be(1); | ||
expect(cells.find('.doc-viewer-no-mapping').length).to.be(0); | ||
expect(cells.find('.doc-viewer-object-array').length).to.be(0); | ||
}); | ||
|
||
it('displays a warning about missing mappings', function () { | ||
const cells = $elem.find('td[title="noMapping"]').siblings(); | ||
expect(cells.find('.doc-viewer-underscore').length).to.be(0); | ||
expect(cells.find('.doc-viewer-no-mapping').length).to.be(1); | ||
expect(cells.find('.doc-viewer-object-array').length).to.be(0); | ||
}); | ||
|
||
it('displays a warning about objects in arrays', function () { | ||
const cells = $elem.find('td[title="objectArray"]').siblings(); | ||
expect(cells.find('.doc-viewer-underscore').length).to.be(0); | ||
expect(cells.find('.doc-viewer-no-mapping').length).to.be(0); | ||
expect(cells.find('.doc-viewer-object-array').length).to.be(1); | ||
}); | ||
}); | ||
|
||
}); | ||
|
||
describe('JSON', function () { | ||
beforeEach(function () { | ||
initView(docViews.byName.JSON); | ||
}); | ||
it('has pretty JSON', function () { | ||
expect($scope.hitJson).to.equal(angular.toJson(hit, true)); | ||
}); | ||
|
||
it('should have a global ACE object', function () { | ||
expect(window.ace).to.be.a(Object); | ||
}); | ||
|
||
it('should have one ACE div', function () { | ||
expect($elem.find('div[id="json-ace"]').length).to.be(1); | ||
}); | ||
|
||
it('should contain the same code as hitJson', function () { | ||
const editor = window.ace.edit($elem.find('div[id="json-ace"]')[0]); | ||
const code = editor.getSession().getValue(); | ||
expect(code).to.equal($scope.hitJson); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import 'plugins/kbn_doc_views/views/table'; | ||
import 'plugins/kbn_doc_views/views/json'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<div | ||
id="json-ace" | ||
ng-model="hitJson" | ||
readonly | ||
ui-ace="{ | ||
useWrapMode: true, | ||
onLoad: aceLoaded, | ||
advanced: { | ||
highlightActiveLine: false | ||
}, | ||
rendererOptions: { | ||
showPrintMargin: false, | ||
maxLines: 4294967296 | ||
}, | ||
mode: 'json' | ||
}"></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import _ from 'lodash'; | ||
import angular from 'angular'; | ||
import 'ace'; | ||
import docViewsRegistry from 'ui/registry/doc_views'; | ||
|
||
import jsonHtml from './json.html'; | ||
|
||
docViewsRegistry.register(function () { | ||
return { | ||
title: 'JSON', | ||
order: 20, | ||
directive: { | ||
template: jsonHtml, | ||
scope: { | ||
hit: '=' | ||
}, | ||
controller: function ($scope) { | ||
$scope.hitJson = angular.toJson($scope.hit, true); | ||
|
||
$scope.aceLoaded = (editor) => { | ||
editor.$blockScrolling = Infinity; | ||
}; | ||
} | ||
} | ||
}; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<table class="table table-condensed"> | ||
<tbody> | ||
<tr ng-repeat="field in fields"> | ||
<td field-name="field" | ||
field-type="mapping[field].type" | ||
width="1%" | ||
class="doc-viewer-field"> | ||
</td> | ||
<td width="1%" class="doc-viewer-buttons" ng-if="filter"> | ||
<span ng-if="mapping[field].filterable"> | ||
<i ng-click="filter(mapping[field], flattened[field], '+')" | ||
tooltip="Filter for value" | ||
tooltip-append-to-body="1" | ||
class="fa fa-search-plus"></i> | ||
<i ng-click="filter(mapping[field], flattened[field],'-')" | ||
tooltip="Filter out value" | ||
tooltip-append-to-body="1" | ||
class="fa fa-search-minus"></i> | ||
</span> | ||
<span ng-if="!mapping[field].filterable" tooltip="Unindexed fields can not be searched"> | ||
<i class="fa fa-search-plus text-muted"></i> | ||
<i class="fa fa-search-minus text-muted"></i> | ||
</span> | ||
<span ng-if="columns"> | ||
<i ng-click="toggleColumn(field)" | ||
tooltip="Toggle column in table" | ||
tooltip-append-to-body="1" | ||
class="fa fa-columns"></i> | ||
</span> | ||
</td> | ||
|
||
<td> | ||
<i ng-if="!mapping[field] && field[0] === '_'" | ||
tooltip-placement="top" | ||
tooltip="Field names beginning with _ are not supported" | ||
class="fa fa-warning text-color-warning ng-scope doc-viewer-underscore"></i> | ||
<i ng-if="!mapping[field] && field[0] !== '_' && !showArrayInObjectsWarning(doc, field)" | ||
tooltip-placement="top" | ||
tooltip="No cached mapping for this field. Refresh field list from the Settings > Indices page" | ||
class="fa fa-warning text-color-warning ng-scope doc-viewer-no-mapping"></i> | ||
<i ng-if="showArrayInObjectsWarning(doc, field)" | ||
tooltip-placement="top" | ||
tooltip="Objects in arrays are not well supported." | ||
class="fa fa-warning text-color-warning ng-scope doc-viewer-object-array"></i> | ||
<div class="doc-viewer-value" ng-bind-html="typeof(formatted[field]) === 'undefined' ? hit[field] : formatted[field] | trustAsHtml"></div> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import _ from 'lodash'; | ||
import docViewsRegistry from 'ui/registry/doc_views'; | ||
|
||
import tableHtml from './table.html'; | ||
|
||
docViewsRegistry.register(function () { | ||
return { | ||
title: 'Table', | ||
order: 10, | ||
directive: { | ||
template: tableHtml, | ||
scope: { | ||
hit: '=', | ||
indexPattern: '=', | ||
filter: '=', | ||
columns: '=' | ||
}, | ||
controller: function ($scope) { | ||
$scope.mapping = $scope.indexPattern.fields.byName; | ||
$scope.flattened = $scope.indexPattern.flattenHit($scope.hit); | ||
$scope.formatted = $scope.indexPattern.formatHit($scope.hit); | ||
$scope.fields = _.keys($scope.flattened).sort(); | ||
|
||
$scope.toggleColumn = function (fieldName) { | ||
_.toggleInOut($scope.columns, fieldName); | ||
}; | ||
|
||
$scope.showArrayInObjectsWarning = function (row, field) { | ||
var value = $scope.flattened[field]; | ||
return _.isArray(value) && typeof value[0] === 'object'; | ||
}; | ||
} | ||
} | ||
}; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.