Merge branch 'master' of github.com:torkelo/grafana
This commit is contained in:
@@ -2,10 +2,10 @@ define([
|
||||
'angular',
|
||||
'underscore',
|
||||
'config',
|
||||
'../services/graphite/graphiteFuncs',
|
||||
'../services/graphite/gfunc',
|
||||
'../services/graphite/parser'
|
||||
],
|
||||
function (angular, _, config, graphiteFuncs, Parser) {
|
||||
function (angular, _, config, gfunc, Parser) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('kibana.controllers');
|
||||
@@ -13,7 +13,7 @@ function (angular, _, config, graphiteFuncs, Parser) {
|
||||
module.controller('GraphiteTargetCtrl', function($scope, $http, filterSrv, graphiteSrv) {
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.funcCategories = graphiteFuncs.getCategories();
|
||||
$scope.funcCategories = gfunc.getCategories();
|
||||
parseTarget();
|
||||
};
|
||||
|
||||
@@ -56,7 +56,7 @@ function (angular, _, config, graphiteFuncs, Parser) {
|
||||
|
||||
switch(astNode.type) {
|
||||
case 'function':
|
||||
var innerFunc = graphiteFuncs.createFuncInstance(astNode.name);
|
||||
var innerFunc = gfunc.createFuncInstance(astNode.name);
|
||||
|
||||
_.each(astNode.params, function(param, index) {
|
||||
parseTargeRecursive(param, innerFunc, index);
|
||||
@@ -226,7 +226,7 @@ function (angular, _, config, graphiteFuncs, Parser) {
|
||||
};
|
||||
|
||||
$scope.addFunction = function(funcDef) {
|
||||
$scope.functions.push(graphiteFuncs.createFuncInstance(funcDef));
|
||||
$scope.functions.push(gfunc.createFuncInstance(funcDef));
|
||||
$scope.targetChanged();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<div>
|
||||
<div class="row-fluid">
|
||||
<h4>Add Panel to Column</h4>
|
||||
<select class="input-medium" ng-model="new_panel.type" ng-options="f for f in _.without(config.panel_names,'column')| stringSort" ng-change="reset_panel(new_panel.type);send_render();"></select>
|
||||
<small>Select Type</small>
|
||||
<div ng-show="!(_.isUndefined(new_panel.type))">
|
||||
<div column-edit panel="new_panel" config="config" row="row" dashboards="dashboards" type="new_panel.type"></div>
|
||||
<button ng-click="add_panel(new_panel); reset_panel();" class="btn btn-primary">Create Panel</button><br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<h4>Panels</h4>
|
||||
<table class="table table-condensed table-striped">
|
||||
<thead>
|
||||
<th>Title</th>
|
||||
<th>Type</th>
|
||||
<th>Height</th>
|
||||
<th>Delete</th>
|
||||
<th>Move</th>
|
||||
<th></th>
|
||||
<th>Hide</th>
|
||||
</thead>
|
||||
<tr ng-repeat="app in panel.panels">
|
||||
<td>{{app.title}}</td>
|
||||
<td>{{app.type}}</td>
|
||||
<td><input type="text" class="input-small" ng-model="app.height"></input></td>
|
||||
<td><i ng-click="panel.panels = _.without(panel.panels,app)" class="pointer icon-remove"></i></td>
|
||||
<td><i ng-click="_.move(panel.panels,$index,$index-1)" ng-hide="$first" class="pointer icon-arrow-up"></i></td>
|
||||
<td><i ng-click="_.move(panel.panels,$index,$index+1)" ng-hide="$last" class="pointer icon-arrow-down"></i></td>
|
||||
<td><input type="checkbox" ng-model="app.hide" ng-checked="app.hide"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,16 +0,0 @@
|
||||
<div ng-controller="column" ng-init="init();">
|
||||
<!-- Panels -->
|
||||
<div ng-repeat="(name, panel) in panel.panels" ng-hide="panel.height == '0px' || panel.hide" class="row-fluid panel" style="min-height:{{panel.height}}; position:relative">
|
||||
<!-- Error Panel -->
|
||||
<div class="row-fluid">
|
||||
<div class="span12 alert alert-error panel-error" ng-hide="!panel.error">
|
||||
<a class="close" ng-click="panel.error=false">×</a>
|
||||
<i class="icon-exclamation-sign"></i> <strong>Oops!</strong> {{panel.error}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Content Panel -->
|
||||
<div class="row-fluid">
|
||||
<kibana-panel type="panel.type"></kibana-panel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,115 +0,0 @@
|
||||
/** @scratch /panels/5
|
||||
* include::panels/column.asciidoc[]
|
||||
*/
|
||||
|
||||
/** @scratch /panels/column/0
|
||||
* == Column
|
||||
* Status: *Stable*
|
||||
*
|
||||
* A pseudo panel that lets you add other panels to be arranged in a column with defined heights.
|
||||
* While the column panel is stable, it does have many limitations, including the inability to drag
|
||||
* and drop panels within its borders. It may be removed in a future release.
|
||||
*
|
||||
*/
|
||||
define([
|
||||
'angular',
|
||||
'app',
|
||||
'underscore',
|
||||
'config'
|
||||
],
|
||||
function (angular, app, _, config) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('kibana.panels.column', []);
|
||||
|
||||
app.useModule(module);
|
||||
|
||||
module.controller('column', function($scope, $rootScope, $timeout) {
|
||||
$scope.panelMeta = {
|
||||
status : "Stable",
|
||||
description : "A pseudo panel that lets you add other panels to be arranged in a column with"+
|
||||
"defined heights."
|
||||
};
|
||||
|
||||
// Set and populate defaults
|
||||
var _d = {
|
||||
/** @scratch /panels/column/3
|
||||
* === Parameters
|
||||
*
|
||||
* panel:: An array of panel objects
|
||||
*/
|
||||
panels : []
|
||||
};
|
||||
_.defaults($scope.panel,_d);
|
||||
|
||||
$scope.init = function(){
|
||||
$scope.reset_panel();
|
||||
};
|
||||
|
||||
$scope.toggle_row = function(panel) {
|
||||
panel.collapse = panel.collapse ? false : true;
|
||||
if (!panel.collapse) {
|
||||
$timeout(function() {
|
||||
$scope.send_render();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.send_render = function() {
|
||||
$scope.$broadcast('render');
|
||||
};
|
||||
|
||||
$scope.add_panel = function(panel) {
|
||||
$scope.panel.panels.push(panel);
|
||||
};
|
||||
|
||||
$scope.reset_panel = function(type) {
|
||||
$scope.new_panel = {
|
||||
loading: false,
|
||||
error: false,
|
||||
sizeable: false,
|
||||
span: 12,
|
||||
height: "150px",
|
||||
editable: true,
|
||||
type: type,
|
||||
draggable: false
|
||||
};
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
module.directive('columnEdit', function($compile,$timeout) {
|
||||
return {
|
||||
scope : {
|
||||
new_panel:"=panel",
|
||||
row:"=",
|
||||
config:"=",
|
||||
dashboards:"=",
|
||||
type:"=type"
|
||||
},
|
||||
link: function(scope, elem) {
|
||||
scope.$on('render', function () {
|
||||
|
||||
// Make sure the digest has completed and populated the attributes
|
||||
$timeout(function() {
|
||||
// Create a reference to the new_panel as panel so that the existing
|
||||
// editors work with our isolate scope
|
||||
scope.panel = scope.new_panel;
|
||||
var template = '<div ng-include src="partial(\'panelgeneral\')"></div>';
|
||||
|
||||
if(!(_.isUndefined(scope.type)) && scope.type !== "") {
|
||||
template = template+'<div ng-include src="\'app/panels/'+scope.type+'/editor.html\'"></div>';
|
||||
}
|
||||
elem.html($compile(angular.element(template))(scope));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
module.filter('withoutColumn', function() {
|
||||
return function() {
|
||||
return _.without(config.panel_names,'column');
|
||||
};
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
<div class="row-fluid">
|
||||
<div class="span4">
|
||||
<label class="small">Title</label><input type="text" class="input-medium" ng-model='panel.title'></input>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<label class="small">Height</label> <input type="text" class="input-mini" ng-model='panel.height'></input>
|
||||
</div>
|
||||
<div class="span1">
|
||||
<label class="small"> Editable </label><input type="checkbox" ng-model="panel.editable" ng-checked="panel.editable">
|
||||
</div>
|
||||
</div>
|
||||
@@ -370,23 +370,23 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
};
|
||||
|
||||
$scope.enterFullscreenMode = function(options) {
|
||||
var oldHeight = $scope.row.height;
|
||||
var docHeight = $(window).height();
|
||||
var oldTimeRange = $scope.range;
|
||||
|
||||
$scope.row.height = options.edit ? 200 : Math.floor(docHeight * 0.7);
|
||||
$scope.height = options.edit ? 200 : Math.floor(docHeight * 0.7);
|
||||
$scope.editMode = options.edit;
|
||||
|
||||
if (!$scope.fullscreen) {
|
||||
var closeEditMode = $rootScope.$on('panel-fullscreen-exit', function() {
|
||||
$scope.editMode = false;
|
||||
$scope.fullscreen = false;
|
||||
$scope.row.height = oldHeight;
|
||||
delete $scope.height;
|
||||
|
||||
closeEditMode();
|
||||
|
||||
$timeout(function() {
|
||||
$scope.$emit('render');
|
||||
|
||||
if (oldTimeRange !== $scope.range) {
|
||||
$scope.dashboard.refresh();
|
||||
}
|
||||
@@ -515,7 +515,7 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
}
|
||||
|
||||
// IE doesn't work without this
|
||||
elem.css({height:scope.panel.height || scope.row.height});
|
||||
elem.css({height:scope.height || scope.row.height});
|
||||
|
||||
_.each(data, function(series) {
|
||||
series.label = series.info.alias;
|
||||
|
||||
@@ -14,6 +14,9 @@ function (_) {
|
||||
};
|
||||
|
||||
function addFuncDef(funcDef) {
|
||||
funcDef.params = funcDef.params || [];
|
||||
funcDef.defaultParams = funcDef.defaultParams || [];
|
||||
|
||||
if (funcDef.category) {
|
||||
funcDef.category.push(funcDef);
|
||||
}
|
||||
@@ -38,8 +41,6 @@ function (_) {
|
||||
addFuncDef({
|
||||
name: "holtWintersForecast",
|
||||
category: categories.Calculate,
|
||||
params: [],
|
||||
defaultParams: []
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
@@ -60,16 +61,12 @@ function (_) {
|
||||
name: 'sumSeries',
|
||||
shortName: 'sum',
|
||||
category: categories.Combine,
|
||||
params: [],
|
||||
defaultParams: []
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'averageSeries',
|
||||
shortName: 'avg',
|
||||
category: categories.Combine,
|
||||
params: [],
|
||||
defaultParams: []
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
@@ -106,15 +103,11 @@ function (_) {
|
||||
addFuncDef({
|
||||
name: 'integral',
|
||||
category: categories.Transform,
|
||||
params: [],
|
||||
defaultParams: []
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'derivate',
|
||||
category: categories.Transform,
|
||||
params: [],
|
||||
defaultParams: []
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
@@ -150,15 +143,14 @@ function (_) {
|
||||
};
|
||||
|
||||
return {
|
||||
createFuncInstance: function(name) {
|
||||
if (_.isString(name)) {
|
||||
var funcDef = index[name];
|
||||
if (!funcDef) {
|
||||
createFuncInstance: function(funcDef) {
|
||||
if (_.isString(funcDef)) {
|
||||
if (!index[funcDef]) {
|
||||
throw { message: 'Method not found ' + name };
|
||||
}
|
||||
name = funcDef;
|
||||
funcDef = index[funcDef];
|
||||
}
|
||||
return new FuncInstance(name);
|
||||
return new FuncInstance(funcDef);
|
||||
},
|
||||
|
||||
getCategories: function() {
|
||||
@@ -50,8 +50,6 @@ function (Settings) {
|
||||
*/
|
||||
panel_names: [
|
||||
'text',
|
||||
'column',
|
||||
'histogram',
|
||||
'graphite'
|
||||
]
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ module.exports = function(config) {
|
||||
files: [
|
||||
'test/test-main.js',
|
||||
{pattern: 'app/**/*.js', included: false},
|
||||
{pattern: 'vendor/**/*.js', included: false},
|
||||
{pattern: 'test/**/*.js', included: false}
|
||||
],
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
define([
|
||||
'app/services/graphite/gfunc'
|
||||
], function(gfunc) {
|
||||
|
||||
describe('when creating func instance from func namae', function() {
|
||||
|
||||
it('should return func instance', function() {
|
||||
var func = gfunc.createFuncInstance('sumSeries');
|
||||
expect(func).to.be.ok();
|
||||
expect(func.def.name).to.equal('sumSeries');
|
||||
expect(func.def.params.length).to.equal(0);
|
||||
expect(func.def.defaultParams.length).to.equal(0);
|
||||
expect(func.def.defaultParams.length).to.equal(0);
|
||||
});
|
||||
|
||||
it('should return func instance with shortName', function() {
|
||||
var func = gfunc.createFuncInstance('sum');
|
||||
expect(func).to.be.ok();
|
||||
});
|
||||
|
||||
it('should return func instance from funcDef', function() {
|
||||
var func = gfunc.createFuncInstance('sum');
|
||||
var func = gfunc.createFuncInstance(func.def);
|
||||
expect(func).to.be.ok();
|
||||
});
|
||||
|
||||
it('func instance should have text representation', function() {
|
||||
var func = gfunc.createFuncInstance('groupByNode');
|
||||
func.params[0] = 5;
|
||||
func.params[1] = 'avg';
|
||||
func.updateText();
|
||||
expect(func.text).to.equal("groupByNode(5, avg)");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('when requesting function categories', function() {
|
||||
|
||||
it('should return function categories', function() {
|
||||
var catIndex = gfunc.getCategories();
|
||||
expect(catIndex.Special.length).to.equal(3);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
+13
-1
@@ -1,10 +1,22 @@
|
||||
require.config({
|
||||
baseUrl:'base'
|
||||
baseUrl: 'base',
|
||||
|
||||
paths: {
|
||||
underscore: 'app/components/underscore.extended',
|
||||
'underscore-src': 'vendor/underscore',
|
||||
},
|
||||
|
||||
shim: {
|
||||
underscore: {
|
||||
exports: '_'
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
require([
|
||||
'test/specs/lexer-specs',
|
||||
'test/specs/parser-specs',
|
||||
'test/specs/gfunc-specs',
|
||||
], function () {
|
||||
window.__karma__.start();
|
||||
});
|
||||
Reference in New Issue
Block a user