Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Rashid Khan 2014-04-15 11:29:09 -07:00
commit 5918df6a80
13 changed files with 80 additions and 124 deletions

View file

@ -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();

View file

@ -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;
});
});

View file

@ -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: {

View file

@ -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);
}
};

View file

@ -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);
}
}
});

View file

@ -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;
}
},

View file

@ -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);
}

View file

@ -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

View file

@ -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;
});
});

View file

@ -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
});
});

View file

@ -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>

View file

@ -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);