-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Spencer Alger
committed
Mar 21, 2014
1 parent
d0c76cd
commit b5e128f
Showing
26 changed files
with
1,175 additions
and
29 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,140 @@ | ||
define(function (require) { | ||
var _ = require('lodash'); | ||
var app = require('modules').get('app/visualize'); | ||
|
||
require('../factories/vis'); | ||
require('../services/aggs'); | ||
|
||
app.controller('Visualize', function ($scope, courier, createNotifier, Vis, Aggs) { | ||
var notify = createNotifier({ | ||
location: 'Visualize Controller' | ||
}); | ||
|
||
// the object detailing the visualization | ||
var vis = $scope.vis = window.vis = new Vis({ | ||
metric: { | ||
label: 'Y-Axis', | ||
min: 1, | ||
max: 1 | ||
}, | ||
segment: { | ||
label: 'X-Axis', | ||
min: 1, | ||
max: 1 | ||
}, | ||
group: { | ||
label: 'Color', | ||
max: 10 | ||
}, | ||
split: { | ||
label: 'Rows & Columns', | ||
max: 2 | ||
} | ||
}, { | ||
split: [ | ||
{ | ||
field: 'response', | ||
size: 5, | ||
agg: 'terms' | ||
}, | ||
{ | ||
field: '_type', | ||
size: 5, | ||
agg: 'terms' | ||
} | ||
], | ||
segment: [ | ||
{ | ||
field: '@timestamp', | ||
interval: 'week' | ||
} | ||
], | ||
group: [ | ||
{ | ||
field: 'extension', | ||
size: 5, | ||
agg: 'terms', | ||
global: true | ||
} | ||
] | ||
}); | ||
|
||
vis.dataSource.$scope($scope); | ||
|
||
$scope.refreshFields = function () { | ||
$scope.fields = null; | ||
vis.dataSource.clearFieldCache().then(getFields, notify.error); | ||
}; | ||
|
||
function getFields() { | ||
vis.dataSource.getFields(function (err, fieldsHash) { | ||
if (err) return notify.error(err); | ||
|
||
// create a sorted list of the fields for display purposes | ||
$scope.fields = _(fieldsHash) | ||
.keys() | ||
.sort() | ||
.transform(function (fields, name) { | ||
var field = fieldsHash[name]; | ||
field.name = name; | ||
fields.push(field); | ||
}) | ||
.value(); | ||
|
||
$scope.fields.byName = fieldsHash; | ||
}); | ||
} | ||
// get the fields for initial display | ||
getFields(); | ||
|
||
$scope.Vis = Vis; | ||
$scope.Aggs = Aggs; | ||
|
||
$scope.updateDataSource = function () { | ||
notify.event('update data source'); | ||
var config = _.groupBy(vis.getConfig(), function (config) { | ||
switch (config.categoryName) { | ||
case 'group': | ||
case 'segment': | ||
return 'dimension'; | ||
default: | ||
return config.categoryName; | ||
} | ||
}); | ||
|
||
if (!config.dimension) { | ||
// use the global aggregation if we don't have any dimensions | ||
config.dimension = [{ | ||
agg: 'global' | ||
}]; | ||
} | ||
|
||
var dsl = {}; | ||
var i = 0; | ||
|
||
var nest = (function () { | ||
var current = dsl; | ||
return function (config) { | ||
current.aggs = {}; | ||
var key = '_agg_' + (i++); | ||
|
||
var aggDsl = {}; | ||
aggDsl[config.agg] = config.aggParams; | ||
|
||
current = current.aggs[key] = aggDsl; | ||
}; | ||
}()); | ||
|
||
config.split && config.split.forEach(nest); | ||
config.dimension && config.dimension.forEach(nest); | ||
config.metric && config.metric.forEach(nest); | ||
|
||
notify.log('config', config); | ||
notify.log('aggs', dsl.aggs); | ||
|
||
vis.dataSource.aggs(dsl.aggs).fetch(); | ||
notify.event('update data source', true); | ||
}; | ||
|
||
}); | ||
}); |
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,25 @@ | ||
define(function (require) { | ||
var module = require('modules').get('app/visualize'); | ||
var $ = require('jquery'); | ||
|
||
module.directive('visCanvas', function () { | ||
return { | ||
restrict: 'A', | ||
link: function ($scope, $el) { | ||
var $window = $(window); | ||
var $header = $('.content > nav.navbar:first()'); | ||
|
||
function stretchVis() { | ||
$el.css('height', $window.height() - $header.height() - 30); | ||
} | ||
|
||
stretchVis(); | ||
|
||
$window.on('resize', stretchVis); | ||
$scope.$on('$destroy', function () { | ||
$window.off('resize', stretchVis); | ||
}); | ||
} | ||
}; | ||
}); | ||
}); |
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,22 @@ | ||
define(function (require) { | ||
var html = require('text!../partials/config_category.html'); | ||
|
||
require('./config_editor'); | ||
|
||
require('modules') | ||
.get('app/visualize') | ||
.directive('visConfigCategory', function () { | ||
return { | ||
restrict: 'E', | ||
scope: { | ||
categoryName: '=', | ||
vis: '=', | ||
fields: '=' | ||
}, | ||
template: html, | ||
link: function ($scope, $el) { | ||
$scope.category = $scope.vis[$scope.categoryName]; | ||
} | ||
}; | ||
}); | ||
}); |
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,58 @@ | ||
define(function (require) { | ||
var app = require('modules').get('app/visualize'); | ||
var _ = require('lodash'); | ||
|
||
var templates = { | ||
orderAndSize: require('text!../partials/controls/order_and_size.html'), | ||
interval: require('text!../partials/controls/interval.html'), | ||
globalLocal: require('text!../partials/controls/global_local.html') | ||
}; | ||
|
||
app.directive('visConfigControls', function ($compile, Vis, Aggs) { | ||
return { | ||
restrict: 'E', | ||
scope: { | ||
config: '=' | ||
}, | ||
link: function ($scope, $el, attr) { | ||
var $controls = $el.find('.agg-param-controls'); | ||
|
||
$scope.$watch('config.agg', function (aggName) { | ||
var agg = Aggs.aggsByName[aggName]; | ||
var controlsHtml = ''; | ||
|
||
if (agg) { | ||
var aggParams = $scope.aggParams = agg.params; | ||
|
||
_.forOwn(aggParams, function (param, name) { | ||
// if the param doesn't have options, or a default value, skip it | ||
if (!param.options) return; | ||
// if there isn't currently a value, or the current value is not one of the options, set it to the default | ||
if (!$scope.config[name] || !_.find(param.options, { val: $scope.config[name] })) { | ||
$scope.config[name] = param.default; | ||
} | ||
}); | ||
|
||
if (aggParams.order && aggParams.size) { | ||
controlsHtml += ' ' + templates.orderAndSize; | ||
} | ||
|
||
if (aggParams.interval) { | ||
controlsHtml += ' ' + templates.interval; | ||
} | ||
|
||
if ($scope.config.categoryName === 'group') { | ||
controlsHtml += ' ' + templates.globalLocal; | ||
} | ||
} | ||
|
||
$controls.html($compile(controlsHtml)($scope)); | ||
}); | ||
|
||
$scope.Aggs = Aggs; | ||
$scope.Vis = Vis; | ||
} | ||
}; | ||
}); | ||
|
||
}); |
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,133 @@ | ||
define(function (require) { | ||
var app = require('modules').get('app/visualize'); | ||
var _ = require('lodash'); | ||
var $ = require('jquery'); | ||
|
||
require('filters/field_type'); | ||
|
||
app.directive('visConfigEditor', function ($compile, Vis, Aggs) { | ||
var categoryOptions = { | ||
metric: { | ||
template: require('text!../partials/editor/metric.html') | ||
}, | ||
segment: { | ||
template: require('text!../partials/editor/dimension.html'), | ||
setup: setupDimension | ||
}, | ||
group: { | ||
template: require('text!../partials/editor/dimension.html'), | ||
setup: setupDimension | ||
}, | ||
split: { | ||
template: require('text!../partials/editor/dimension.html'), | ||
setup: setupDimension | ||
} | ||
}; | ||
|
||
var controlTemplates = { | ||
orderAndSize: require('text!../partials/controls/order_and_size.html'), | ||
interval: require('text!../partials/controls/interval.html'), | ||
globalLocal: require('text!../partials/controls/global_local.html') | ||
}; | ||
|
||
// generalized setup for group and segment | ||
function setupDimension($scope, $el) { | ||
var $controls = $el.find('.agg-param-controls'); | ||
|
||
function getAvailableAggsForField() { | ||
if (!$scope.config.field || !$scope.fields) return; | ||
|
||
var field = $scope.fields.byName[$scope.config.field]; | ||
|
||
// clear the previous choices | ||
$scope.availableAggs = void 0; | ||
// get the new choices | ||
var aggs = Aggs.aggsByFieldType[field.type]; | ||
|
||
if (!aggs || aggs.length === 0) { | ||
// init or invalid field type | ||
$scope.config.agg = void 0; | ||
return; | ||
} | ||
|
||
if (aggs.length === 1) { | ||
// only once choice, make it for the user | ||
$scope.config.agg = aggs[0].name; | ||
return; | ||
} | ||
|
||
// set the new choices | ||
$scope.availableAggs = aggs; | ||
|
||
// update the agg only if it is not currently a valid option | ||
if (!$scope.config.agg || !_.find(aggs, { name: $scope.config.agg })) { | ||
$scope.config.agg = aggs[0].name; | ||
return; | ||
} | ||
} | ||
|
||
// since this depends on the field and field list, watch both | ||
$scope.$watch('config.field', getAvailableAggsForField); | ||
$scope.$watch('fields', getAvailableAggsForField); | ||
|
||
$scope.$watch('config.agg', function (aggName) { | ||
var agg = Aggs.aggsByName[aggName]; | ||
var controlsHtml = ''; | ||
|
||
if (agg) { | ||
var params = $scope.aggParams = agg.params; | ||
|
||
_.forOwn(params, function (param, name) { | ||
// if the param doesn't have options, or a default value, skip it | ||
if (!param.options) return; | ||
// if there isn't currently a value, or the current value is not one of the options, set it to the default | ||
if (!$scope.config[name] || !_.find(param.options, { val: $scope.config[name] })) { | ||
$scope.config[name] = param.default; | ||
} | ||
}); | ||
|
||
if (params.order && params.size) { | ||
controlsHtml += ' ' + controlTemplates.orderAndSize; | ||
} | ||
|
||
if (params.interval) { | ||
controlsHtml += ' ' + controlTemplates.interval; | ||
if (!controlsHtml.match(/aggParams\.interval\.options/)) debugger; | ||
} | ||
|
||
if ($scope.config.categoryName === 'group') { | ||
controlsHtml += ' ' + controlTemplates.globalLocal; | ||
} | ||
} | ||
|
||
$controls.html($compile(controlsHtml)($scope)); | ||
}); | ||
} | ||
|
||
return { | ||
restrict: 'E', | ||
scope: { | ||
config: '=', | ||
fields: '=', | ||
vis: '=' | ||
}, | ||
link: function ($scope, $el, attr) { | ||
var categoryName = $scope.config.categoryName; | ||
var opts = categoryOptions[categoryName]; | ||
|
||
$scope.Aggs = Aggs; | ||
$scope.Vis = Vis; | ||
|
||
// attach a copy of the template to the scope and render | ||
$el.html($compile(opts.template)($scope)); | ||
|
||
_.defaults($scope.val, opts.defVal || {}); | ||
if (opts.setup) opts.setup($scope, $el); | ||
|
||
// rather than accessing vis.{{categoryName}} everywhere | ||
$scope[categoryName] = $scope.vis[categoryName]; | ||
} | ||
}; | ||
}); | ||
|
||
}); |
Oops, something went wrong.