Skip to content

Commit

Permalink
Merge pull request #2121 from rashidkpc/feature/doc_viewer
Browse files Browse the repository at this point in the history
Doc viewer app
  • Loading branch information
w33ble committed Dec 5, 2014
2 parents c085f3d + a755b73 commit b668145
Show file tree
Hide file tree
Showing 15 changed files with 382 additions and 43 deletions.
14 changes: 5 additions & 9 deletions src/kibana/components/courier/data_source/_abstract.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,16 +265,12 @@ define(function (require) {
'match_all': {}
};
}
flatState.body.fields = ['*', '_source'];

_.each(flatState.index.fields.byType['date'], function (field) {
if (field.indexed) {
flatState.body.script_fields = flatState.body.script_fields || {};
flatState.body.script_fields[field.name] = {
script: 'doc["' + field.name + '"].value'
};
}
});
var computedFields = flatState.index.getComputedFields();
flatState.body.fields = computedFields.fields;
flatState.body.script_fields = flatState.body.script_fields || {};
_.extend(flatState.body.script_fields, computedFields.scriptFields);


/**
* Create a filter that can be reversed for filters with negate set
Expand Down
68 changes: 35 additions & 33 deletions src/kibana/components/doc_viewer/doc_viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,41 @@
<li ng-class="{active: mode == 'json'}"><a ng-click="mode='json'">JSON</a></li>
</ul>

<table class="table table-condensed" ng-show="mode == 'table'" bindonce>
<tbody>
<tr ng-repeat="field in fields" bindonce>
<td field-name="field"
field-type="mapping[field].type"
width="1%"
class="doc-viewer-field">
</td>
<td width="1%" class="doc-viewer-buttons" ng-if="filter">
<span bo-if="showFilters(mapping[field])">
<i ng-click="filter(field, flattened[field], '+')" class="fa fa-search-plus"></i>
<i ng-click="filter(field, flattened[field],'-')" class="fa fa-search-minus"></i>
</span>
<span bo-if="!showFilters(mapping[field])" 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>
</td>
<div class="content">
<table class="table table-condensed" ng-show="mode == 'table'" bindonce>
<tbody>
<tr ng-repeat="field in fields" bindonce>
<td field-name="field"
field-type="mapping[field].type"
width="1%"
class="doc-viewer-field">
</td>
<td width="1%" class="doc-viewer-buttons" ng-if="filter">
<span bo-if="showFilters(mapping[field])">
<i ng-click="filter(field, flattened[field], '+')" class="fa fa-search-plus"></i>
<i ng-click="filter(field, flattened[field],'-')" class="fa fa-search-minus"></i>
</span>
<span bo-if="!showFilters(mapping[field])" 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>
</td>

<td>
<i bo-if="!mapping[field] && !showArrayInObjectsWarning(doc, field)"
tooltip-placement="top"
tooltip="No cached mapping for this field. Refresh your mapping from the Settings > Indices page"
class="fa fa-warning text-color-warning ng-scope doc-viewer-no-mapping"></i>
<i bo-if="showArrayInObjectsWarning(doc, field)"
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>
<span class="doc-viewer-value" ng-bind-html="(formatted[field] || hit[field]) | highlight : hit.highlight[field] | trustAsHtml"></span>
</td>
</tr>
</tbody>
</table>
<td>
<i bo-if="!mapping[field] && !showArrayInObjectsWarning(doc, field)"
tooltip-placement="top"
tooltip="No cached mapping for this field. Refresh your mapping from the Settings > Indices page"
class="fa fa-warning text-color-warning ng-scope doc-viewer-no-mapping"></i>
<i bo-if="showArrayInObjectsWarning(doc, field)"
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>
<span class="doc-viewer-value" ng-bind-html="(formatted[field] || hit[field]) | highlight : hit.highlight[field] | trustAsHtml"></span>
</td>
</tr>
</tbody>
</table>

<pre ng-show="mode == 'json'">{{hit | json}}</pre>
<pre ng-show="mode == 'json'">{{hit | json}}</pre>
</div>
</div>
7 changes: 7 additions & 0 deletions src/kibana/components/doc_viewer/doc_viewer.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ doc-viewer .doc-viewer {
white-space: pre-wrap;
}

td, pre {
font-family: "Lucida Console", Monaco, monospace;
}

.content {
margin-top: @padding-base-vertical;
}
}
23 changes: 23 additions & 0 deletions src/kibana/components/index_patterns/_get_computed_fields.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Takes a hit, merges it with any stored/scripted fields, and with the metaFields
// returns a flattened version
define(function (require) {
var _ = require('lodash');
return function () {
var self = this;
var scriptFields = {};

_.each(self.fields.byType['date'], function (field) {
if (field.indexed) {
scriptFields[field.name] = {
script: 'doc["' + field.name + '"].value'
};
}
});

return {
fields: ['*', '_source'],
scriptFields: scriptFields
};

};
});
4 changes: 4 additions & 0 deletions src/kibana/components/index_patterns/_index_pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ define(function (require) {
var DocSource = Private(require('components/courier/data_source/doc_source'));
var flattenSearchResponse = require('components/index_patterns/_flatten_search_response');
var flattenHit = require('components/index_patterns/_flatten_hit');
var getComputedFields = require('components/index_patterns/_get_computed_fields');


var IndexedArray = require('utils/indexed_array/index');

Expand Down Expand Up @@ -224,6 +226,8 @@ define(function (require) {
self.metaFields = config.get('metaFields');
self.flattenSearchResponse = flattenSearchResponse.bind(self);
self.flattenHit = flattenHit.bind(self);
self.getComputedFields = getComputedFields.bind(self);


}
return IndexPattern;
Expand Down
3 changes: 3 additions & 0 deletions src/kibana/plugins/discover/partials/table_row/details.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<td colspan="{{ columns.length + 2 }}">
<a class="pull-right" ng-href="#/doc/{{indexPattern.id}}/{{row._index}}/{{row._type}}/{{row._id}}">
<small>Link to /{{row._index}}/{{row._type}}/{{row._id}}</small></i>
</a>
<doc-viewer hit="row" filter="filter" index-pattern="indexPattern"></doc-viewer>
</td>
66 changes: 66 additions & 0 deletions src/kibana/plugins/doc/controllers/doc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
define(function (require) {
var _ = require('lodash');
var angular = require('angular');

require('components/notify/notify');
require('components/courier/courier');
require('components/doc_viewer/doc_viewer');
require('components/index_patterns/index_patterns');

var app = require('modules').get('apps/doc', [
'kibana/notify',
'kibana/courier',
'kibana/index_patterns'
]);

require('routes')
.when('/doc/:indexPattern/:index/:type/:id', {
template: require('text!plugins/doc/index.html'),
resolve: {
indexPattern: function (courier, savedSearches, $route) {
return courier.indexPatterns.get($route.current.params.indexPattern);
}
}
});

app.controller('doc', function ($scope, $route, es, timefilter) {

timefilter.enabled = false;

// Pretty much only need this for formatting, not actually using it for fetching anything.
$scope.indexPattern = $route.current.locals.indexPattern;

var computedFields = $scope.indexPattern.getComputedFields();

es.search({
index: $route.current.params.index,
type: $route.current.params.type,
body: {
query: {
ids: {
values: [$route.current.params.id]
}
},
fields: computedFields.fields,
script_fields: computedFields.scriptFields
}
}).then(function (resp) {
if (resp.hits) {
if (resp.hits.total < 1) {
$scope.status = 'notFound';
} else {
$scope.status = 'found';
$scope.hit = resp.hits.hits[0];
}
}
}).catch(function (err) {
if (err.status === 404) {
$scope.status = 'notFound';
} else {
$scope.status = 'error';
$scope.resp = err;
}
});

});
});
47 changes: 47 additions & 0 deletions src/kibana/plugins/doc/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<div ng-controller="doc" class="app-container">

<div class="container-fluid">
<div class="row">

<!-- no results -->
<div class="col-md-12" ng-if="status === 'notFound'">
<div class="col-md-12">
<h1>Failed to locate document. <i class="fa fa-meh-o"></i></h1>

<p>
Unfortunately I could not find any documents matching that id, of that type, in that index. I tried really hard. I wanted it to be there. Sometimes I swear documents grow legs and just walk out of the index. Sneaky. I wish I could offer some advice here, something to make you feel better
</p>

</div>
</div>

<!-- no results -->
<div class="col-md-12" ng-if="status === 'error'">
<div class="col-md-12">
<h1>This is bad. <i class="fa fa-meh-o"></i></h1>

<p>
Oh no. Something went very wrong. Its not just that I couldn't find your document, I couldn't even try. The index was missing, or the type. Go check out Elasticsearch, something isn't quite right here.
</p>

</div>
</div>

<!-- loading -->
<div class="col-md-12" ng-if="status === undefined">
<div class="discover-overlay">
<h2>Searching</h2>
<div class="spinner large"></div>
<div ng-show="fetchStatus">{{fetchStatus.complete}}/{{fetchStatus.total}}</div>
</div>
</div>

<!-- result -->
<div class="col-md-12" ng-if="status === 'found'">
<h2><b>Doc:</b> {{hit._index}}/{{hit._type}}/{{hit._id}}</h2>

<doc-viewer hit="hit" index-pattern="indexPattern"></doc-viewer>
</div>
</div>
</div>
</div>
12 changes: 12 additions & 0 deletions src/kibana/plugins/doc/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
define(function (require, module, exports) {
require('plugins/doc/controllers/doc');

var apps = require('registry/apps');
apps.register(function DocAppModule() {
return {
id: 'doc',
name: 'Doc Viewer',
order: -1
};
});
});
6 changes: 6 additions & 0 deletions src/kibana/plugins/kibana/_apps.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ define(function (require) {
return app.lastPath;
}

function getShow(app) {
app.show = app.order >= 0 ? true : false;
}

function setLastPath(app, path) {
app.lastPath = path;
return sessionStorage.set(appKey(app), path);
Expand All @@ -19,6 +23,8 @@ define(function (require) {
$scope.apps = Private(require('registry/apps'));
// initialize each apps lastPath (fetch it from storage)
$scope.apps.forEach(getLastPath);
$scope.apps.forEach(getShow);


function onRouteChange() {
var route = $location.path().split(/\//);
Expand Down
2 changes: 1 addition & 1 deletion src/kibana/plugins/kibana/kibana.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<!-- Full navbar -->
<div collapse="!showCollapsed" class="navbar-collapse" id="kibana-primary-navbar">
<ul class="nav navbar-nav">
<li ng-repeat="app in apps.inOrder" ng-class="{active: activeApp === app}">
<li ng-repeat="app in apps.inOrder | filter:{show: true}" ng-class="{active: activeApp === app}">
<a ng-href="#{{app.lastPath}}" bo-text="app.name"></a>
</li>
</ul>
Expand Down
2 changes: 2 additions & 0 deletions test/unit/fixtures/stubbed_logstash_index_pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ define(function (require) {
var StubIndexPattern = Private(require('test_utils/stub_index_pattern'));
var flattenSearchResponse = require('components/index_patterns/_flatten_search_response');
var flattenHit = require('components/index_patterns/_flatten_hit');
var getComputedFields = require('components/index_patterns/_get_computed_fields');

var _ = require('lodash');

Expand All @@ -24,6 +25,7 @@ define(function (require) {
{ name: 'custom_user_field', displayName: 'custom_user_field', type: 'conflict', indexed: false, analyzed: false, count: 0 }
]);

indexPattern.getComputedFields = _.bind(getComputedFields, indexPattern);
indexPattern.flattenSearchResponse = _.bind(flattenSearchResponse, indexPattern);
indexPattern.flattenHit = _.bind(flattenHit, indexPattern);
indexPattern.metaFields = ['_id', '_type', '_source'];
Expand Down
Loading

0 comments on commit b668145

Please sign in to comment.