mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
5918df6a80
13 changed files with 80 additions and 124 deletions
|
@ -21,11 +21,11 @@ define(function (require) {
|
|||
|
||||
$scope.refreshFields = function () {
|
||||
$scope.fields = null;
|
||||
vis.dataSource.clearFieldCache().then(getFields, notify.error);
|
||||
vis.searchSource.clearFieldCache().then(getFields, notify.error);
|
||||
};
|
||||
|
||||
function getFields() {
|
||||
return vis.dataSource.getFields()
|
||||
return vis.searchSource.getFields()
|
||||
.then(function (fieldsHash) {
|
||||
// create a sorted list of the fields for display purposes
|
||||
$scope.fields = _(fieldsHash)
|
||||
|
@ -49,8 +49,8 @@ define(function (require) {
|
|||
$scope.visConfigCategories = visConfigCategories;
|
||||
|
||||
$scope.$on('change:config.defaultIndex', function () {
|
||||
if (!vis.dataSource.get('index')) {
|
||||
vis.dataSource.index(config.get('defaultIndex'));
|
||||
if (!vis.searchSource.get('index')) {
|
||||
vis.searchSource.index(config.get('defaultIndex'));
|
||||
getFields();
|
||||
}
|
||||
});
|
||||
|
@ -73,7 +73,8 @@ define(function (require) {
|
|||
if (!config.dimension) {
|
||||
// use the global aggregation if we don't have any dimensions
|
||||
config.dimension = [{
|
||||
agg: 'global'
|
||||
agg: 'global',
|
||||
aggParams: {}
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -100,7 +101,7 @@ define(function (require) {
|
|||
notify.log('config', config);
|
||||
notify.log('aggs', dsl.aggs);
|
||||
|
||||
vis.dataSource.aggs(dsl.aggs);
|
||||
vis.searchSource.aggs(dsl.aggs);
|
||||
notify.event('update data source', true);
|
||||
};
|
||||
|
||||
|
@ -109,7 +110,7 @@ define(function (require) {
|
|||
*********/
|
||||
$scope.doVisualize = function () {
|
||||
updateDataSource();
|
||||
vis.dataSource.fetch();
|
||||
vis.searchSource.fetch();
|
||||
};
|
||||
$scope.doSave = function () {
|
||||
updateDataSource();
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
|
||||
require('../saved_visualizations/saved_visualizations');
|
||||
require('notify/notify');
|
||||
require('saved_object/finder.directive');
|
||||
require('apps/discover/saved_searches/saved_searches');
|
||||
|
||||
var app = require('modules').get('app/visualize', [
|
||||
'kibana/notify',
|
||||
'kibana/courier'
|
||||
]);
|
||||
|
||||
app.controller('VisualizeWizard', function ($route, $scope, courier, createNotifier, config, $location, savedSearches) {
|
||||
var notify = createNotifier({
|
||||
location: 'Visualization Wizard'
|
||||
});
|
||||
|
||||
$scope.savedSearches = savedSearches;
|
||||
});
|
||||
});
|
|
@ -1,6 +1,7 @@
|
|||
define(function (require) {
|
||||
var app = require('modules').get('app/visualize');
|
||||
var _ = require('lodash');
|
||||
var aggs = require('../saved_visualizations/_aggs');
|
||||
|
||||
var templates = {
|
||||
orderAndSize: require('text!../partials/controls/order_and_size.html'),
|
||||
|
@ -8,7 +9,7 @@ define(function (require) {
|
|||
globalLocal: require('text!../partials/controls/global_local.html')
|
||||
};
|
||||
|
||||
app.directive('visConfigControls', function ($compile, visConfigCategories, aggs) {
|
||||
app.directive('visConfigControls', function ($compile, visConfigCategories) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
|
|
|
@ -5,7 +5,7 @@ define(function (require) {
|
|||
function VisualizationDirective(createNotifier) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: '<div class="chart"></div>',
|
||||
template: '<pre class="chart">{{ data | json }}</pre>',
|
||||
scope: {
|
||||
vis: '='
|
||||
},
|
||||
|
@ -15,55 +15,13 @@ define(function (require) {
|
|||
location: vis.type + ' visualization'
|
||||
});
|
||||
|
||||
function renderData(data, $el) {
|
||||
var splitBy, splits, inherit;
|
||||
|
||||
if (data.rows) {
|
||||
splits = data.rows;
|
||||
splitBy = 'height';
|
||||
inherit = 'width';
|
||||
}
|
||||
else if (data.columns) {
|
||||
splits = data.columns;
|
||||
splitBy = 'width';
|
||||
inherit = 'height';
|
||||
}
|
||||
|
||||
if (splitBy && splits && inherit) {
|
||||
var splitSize = $el[splitBy]() / splits.length;
|
||||
var charts = splits.map(function (splitData) {
|
||||
// create the element that will contain this splits data
|
||||
var $splitEl = $(document.createElement('div'));
|
||||
|
||||
// set the height and width
|
||||
$splitEl[splitBy](splitSize);
|
||||
$splitEl[inherit]('100%');
|
||||
|
||||
// append it to the parent
|
||||
$el.append($splitEl);
|
||||
|
||||
// render the splits data into the new $el
|
||||
return renderData(splitData, $splitEl);
|
||||
});
|
||||
return charts;
|
||||
}
|
||||
else {
|
||||
// we can ignore splits completely now
|
||||
var chart = new k4d3.Chart($el.get(0), {
|
||||
type: 'histogram'
|
||||
});
|
||||
chart.render(data);
|
||||
return chart;
|
||||
}
|
||||
}
|
||||
|
||||
vis.dataSource.onResults().then(function onResults(resp) {
|
||||
vis.searchSource.onResults().then(function onResults(resp) {
|
||||
notify.event('render visualization');
|
||||
$el.html('');
|
||||
renderData(vis.buildChartDataFromResponse(resp), $el);
|
||||
$scope.data = vis.buildChartDataFromResponse(resp);
|
||||
notify.event('render visualization', true);
|
||||
|
||||
return vis.dataSource.onResults(onResults);
|
||||
window.canvasVisSource = vis.searchSource;
|
||||
return vis.searchSource.onResults().then(onResults);
|
||||
}).catch(notify.fatal);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
define(function (require) {
|
||||
require('css!./styles/main.css');
|
||||
|
||||
require('./controllers/wizard');
|
||||
require('./controllers/editor');
|
||||
|
||||
require('./directives/config_category');
|
||||
|
@ -10,13 +9,13 @@ define(function (require) {
|
|||
|
||||
require('routes')
|
||||
.when('/visualize', {
|
||||
template: require('text!./wizard.html')
|
||||
redirectTo: '/visualize/histogram'
|
||||
})
|
||||
.when('/visualize/:type/:id?', {
|
||||
template: require('text!./editor.html'),
|
||||
template: require('text!./index.html'),
|
||||
resolve: {
|
||||
vis: function ($route, savedVis) {
|
||||
return savedVis.get($route.current.params.type, $route.current.params.id);
|
||||
vis: function ($route, savedVisualizations) {
|
||||
return savedVisualizations.get($route.current.params.type, $route.current.params.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -66,7 +66,8 @@ define(function (require) {
|
|||
}
|
||||
},
|
||||
makeLabel: function (params) {
|
||||
var order = _.find(aggs.params.order.options, { val: params.order._count });
|
||||
var agg = aggs.byName.terms;
|
||||
var order = _.find(agg.params.order.options, { val: params.order._count });
|
||||
return order.display + ' ' + params.size + ' ' + params.field;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
define(function (require) {
|
||||
|
||||
var converters = require('./resp_converters/index');
|
||||
var aggs = require('./_aggs');
|
||||
|
||||
// private functionality for Vis.buildChartDataFromResp()
|
||||
return function (createNotifier, aggs) {
|
||||
return function (createNotifier) {
|
||||
var notify = createNotifier();
|
||||
|
||||
return function (resp) {
|
||||
|
@ -151,6 +152,13 @@ define(function (require) {
|
|||
};
|
||||
|
||||
if (resp.aggregations) {
|
||||
if (!configs.length) {
|
||||
configs.push({
|
||||
categoryName: 'metric',
|
||||
agg: aggs.byName.count.name,
|
||||
label: aggs.byName.count.display
|
||||
});
|
||||
}
|
||||
splitAndFlatten(chartData, resp.aggregations);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,9 +42,14 @@ define(function (require) {
|
|||
field: config.field
|
||||
};
|
||||
|
||||
// copy over the row if this is a split
|
||||
if (config.categoryName === 'split') {
|
||||
// copy over other properties based ont he category
|
||||
switch (config.categoryName) {
|
||||
case 'split':
|
||||
validated.row = !!config.row;
|
||||
break;
|
||||
case 'group':
|
||||
validated.global = !!config.global;
|
||||
break;
|
||||
}
|
||||
|
||||
// this function will move valus from config.* to validated.aggParams.* when they are
|
||||
|
|
|
@ -4,13 +4,17 @@ define(function (require) {
|
|||
|
||||
var configCats = require('./_config_categories');
|
||||
var aggs = require('./_aggs');
|
||||
var typeDefs = require('./_type_defs');
|
||||
|
||||
require('services/root_search');
|
||||
|
||||
var module = require('modules').get('kibana/services');
|
||||
|
||||
module.factory('Vis', function (config, $injector, SavedObject, rootSearch, Promise, savedSearches) {
|
||||
function Vis(id) {
|
||||
module.factory('SavedVis', function (config, $injector, SavedObject, rootSearch, Promise, savedSearches) {
|
||||
function SavedVis(type, id) {
|
||||
var typeDef = typeDefs.byName[type];
|
||||
if (!typeDef) throw new Error('Unknown visualization type: "' + type + '"');
|
||||
|
||||
SavedObject.call(this, {
|
||||
type: 'visualization',
|
||||
|
||||
|
@ -18,25 +22,29 @@ define(function (require) {
|
|||
|
||||
mapping: {
|
||||
stateJSON: 'string',
|
||||
savedSearchId: 'string'
|
||||
savedSearchId: 'string',
|
||||
typeName: 'string',
|
||||
},
|
||||
|
||||
defaults: {
|
||||
stateJSON: '[]'
|
||||
stateJSON: '{}',
|
||||
typeName: type,
|
||||
},
|
||||
|
||||
searchSource: true,
|
||||
|
||||
afterESResp: function setVisState(resp) {
|
||||
afterESResp: function setVisState() {
|
||||
var vis = this;
|
||||
var state = {};
|
||||
|
||||
if (vis.stateJSON) try { state = JSON.parse(vis.stateJSON); } catch (e) {}
|
||||
|
||||
var parent = vis.savedSearch;
|
||||
if (!parent || parent.id !== vis.savedSearchId) {
|
||||
// returns a promise
|
||||
parent = savedSearches.get(vis.savedSearchId);
|
||||
var parent = rootSearch;
|
||||
if (vis.savedSearchId) {
|
||||
if (!vis.savedSearch || vis.savedSearch.id !== vis.savedSearchId) {
|
||||
// returns a promise
|
||||
parent = savedSearches.get(vis.savedSearchId);
|
||||
}
|
||||
}
|
||||
|
||||
configCats.forEach(function (category) {
|
||||
|
@ -53,7 +61,11 @@ define(function (require) {
|
|||
return Promise.cast(parent)
|
||||
.then(function (parent) {
|
||||
vis.savedSearch = parent;
|
||||
vis.searchSource.inherits(vis.savedSearch);
|
||||
|
||||
vis.searchSource
|
||||
.inherits(vis.savedSearch)
|
||||
.size(0);
|
||||
|
||||
vis._fillConfigsToMinimum();
|
||||
// get and cache the field list
|
||||
return vis.searchSource.getFields();
|
||||
|
@ -85,6 +97,14 @@ define(function (require) {
|
|||
// satify the min count for each category
|
||||
configCats.fetchOrder.forEach(function (category) {
|
||||
var myCat = vis[category.name];
|
||||
|
||||
if (!myCat) {
|
||||
|
||||
myCat = _.defaults(typeDef.config[category.name] || {}, category.defaults);
|
||||
myCat.configs = [];
|
||||
vis[category.name] = myCat;
|
||||
}
|
||||
|
||||
if (myCat.configs.length < myCat.min) {
|
||||
_.times(myCat.min - myCat.configs.length, function () {
|
||||
vis.addConfig(category.name);
|
||||
|
@ -107,8 +127,8 @@ define(function (require) {
|
|||
*/
|
||||
this.buildChartDataFromResponse = $injector.invoke(require('./_build_chart_data'));
|
||||
}
|
||||
inherits(Vis, SavedObject);
|
||||
inherits(SavedVis, SavedObject);
|
||||
|
||||
return Vis;
|
||||
return SavedVis;
|
||||
});
|
||||
});
|
|
@ -11,6 +11,13 @@ define(function (require) {
|
|||
// index of y-axis
|
||||
var iY = _.findIndex(columns, { categoryName: 'metric'});
|
||||
|
||||
// when we don't have an x-axis, just push everything into '_all'
|
||||
if (iX === -1) {
|
||||
iX = columns.push({
|
||||
label: ''
|
||||
}) - 1;
|
||||
}
|
||||
|
||||
chart.xAxisLabel = columns[iX].label;
|
||||
chart.yAxisLabel = columns[iY].label;
|
||||
|
||||
|
@ -38,7 +45,7 @@ define(function (require) {
|
|||
}
|
||||
|
||||
s.values.push({
|
||||
x: row[iX],
|
||||
x: row[iX] || '_all',
|
||||
y: row[iY === -1 ? row.length - 1 : iY] // y-axis value
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<div ng-controller="VisualizeWizard">
|
||||
<h1>
|
||||
Create a new visualization
|
||||
</h1>
|
||||
<section>
|
||||
<h2>
|
||||
Choose a Saved Search
|
||||
</h2>
|
||||
<hr>
|
||||
<find-saved-object service="savedSearches" on-choose="useSavedSearch"></find-saved-object>
|
||||
</section>
|
||||
<section>
|
||||
<h2>
|
||||
Choose a Visualization Type
|
||||
</h2>
|
||||
<ul class="vis-config-panel">
|
||||
<li ng-repeat="category in typeDefs">
|
||||
<vis-type-preview type="type"></vis-type-preview>
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
</section>
|
||||
</div>
|
|
@ -34,7 +34,7 @@ define(function (require) {
|
|||
// default field values, assigned when the source is loaded
|
||||
var defaults = config.defaults || {};
|
||||
|
||||
var afterESResp = config.afterESResp || null;
|
||||
var afterESResp = config.afterESResp || _.noop;
|
||||
|
||||
// optional search source which this object configures
|
||||
obj.searchSource = config.searchSource && courier.createSource('search');
|
||||
|
@ -97,7 +97,7 @@ define(function (require) {
|
|||
if (!obj.id) {
|
||||
// just assign the defaults and be done
|
||||
_.assign(obj, defaults);
|
||||
return false;
|
||||
return afterESResp.call(obj);
|
||||
}
|
||||
|
||||
// fetch the object from ES
|
||||
|
@ -123,7 +123,7 @@ define(function (require) {
|
|||
obj.searchSource.set(state);
|
||||
}
|
||||
|
||||
return Promise.cast(afterESResp && afterESResp.call(obj, resp))
|
||||
return Promise.cast(afterESResp.call(obj, resp))
|
||||
.then(function () {
|
||||
// Any time obj is updated, re-call applyESResp
|
||||
docSource.onUpdate().then(applyESResp, notify.fatal);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue