Progress on template editor & new templating features

This commit is contained in:
Torkel Ödegaard 2014-08-27 15:54:30 +02:00
parent e0a58dd1fe
commit bb3b31829f
14 changed files with 166 additions and 90 deletions

View File

@ -11,9 +11,16 @@ function (angular, $, config, _) {
var module = angular.module('grafana.controllers'); var module = angular.module('grafana.controllers');
module.controller('DashboardCtrl', function( module.controller('DashboardCtrl', function(
$scope, $rootScope, dashboardKeybindings, $scope,
filterSrv, dashboardSrv, dashboardViewStateSrv, $rootScope,
panelMoveSrv, timer, $timeout) { dashboardKeybindings,
filterSrv,
templateSrv,
dashboardSrv,
dashboardViewStateSrv,
panelMoveSrv,
timer,
$timeout) {
$scope.editor = { index: 0 }; $scope.editor = { index: 0 };
$scope.panelNames = config.panels; $scope.panelNames = config.panels;
@ -47,6 +54,7 @@ function (angular, $, config, _) {
$scope.filter = filterSrv; $scope.filter = filterSrv;
$scope.filter.init($scope.dashboard); $scope.filter.init($scope.dashboard);
templateSrv.init($scope.dashboard);
$scope.submenuEnabled = $scope.dashboard.templating.enable || $scope.dashboard.annotations.enable; $scope.submenuEnabled = $scope.dashboard.templating.enable || $scope.dashboard.annotations.enable;

View File

@ -50,7 +50,6 @@ function (angular, app, _) {
$scope.applyFilter = function(templateParam) { $scope.applyFilter = function(templateParam) {
return datasourceSrv.default.metricFindQuery($scope.filter, templateParam.query) return datasourceSrv.default.metricFindQuery($scope.filter, templateParam.query)
.then(function (results) { .then(function (results) {
templateParam.editing = undefined;
templateParam.options = _.map(results, function(node) { templateParam.options = _.map(results, function(node) {
return { text: node.text, value: node.text }; return { text: node.text, value: node.text };
}); });

View File

@ -10,7 +10,7 @@ function (angular, _) {
module.controller('TemplateEditorCtrl', function($scope, datasourceSrv) { module.controller('TemplateEditorCtrl', function($scope, datasourceSrv) {
var replacementDefaults = { var replacementDefaults = {
type: 'metric query', type: 'query',
datasource: null, datasource: null,
refresh_on_load: false, refresh_on_load: false,
name: '', name: '',
@ -24,8 +24,17 @@ function (angular, _) {
$scope.templateParameters = $scope.filter.templateParameters; $scope.templateParameters = $scope.filter.templateParameters;
$scope.reset(); $scope.reset();
$scope.$watch('editor.index', function(newVal) { _.each($scope.templateParameters, function(param) {
if (newVal !== 2) { $scope.reset(); } if (param.datasource === void 0) {
param.datasource = null;
param.type = 'query';
}
});
$scope.$watch('editor.index', function(index) {
if ($scope.currentIsNew === false && index === 1) {
$scope.reset();
}
}); });
}; };
@ -33,6 +42,11 @@ function (angular, _) {
$scope.current.datasource = $scope.currentDatasource.name; $scope.current.datasource = $scope.currentDatasource.name;
$scope.templateParameters.push($scope.current); $scope.templateParameters.push($scope.current);
$scope.reset(); $scope.reset();
$scope.editor.index = 0;
};
$scope.runQuery = function() {
$scope.filter.refreshTemplateParameter($scope.current);
}; };
$scope.edit = function(param) { $scope.edit = function(param) {
@ -47,10 +61,14 @@ function (angular, _) {
$scope.editor.index = 2; $scope.editor.index = 2;
}; };
$scope.update = function() {
$scope.reset();
$scope.editor.index = 0;
};
$scope.reset = function() { $scope.reset = function() {
$scope.currentIsNew = true; $scope.currentIsNew = true;
$scope.current = angular.copy(replacementDefaults); $scope.current = angular.copy(replacementDefaults);
$scope.editor.index = 0;
}; };
$scope.removeTemplateParam = function(templateParam) { $scope.removeTemplateParam = function(templateParam) {

View File

@ -14,7 +14,7 @@
<a class="pointer dropdown-toggle" <a class="pointer dropdown-toggle"
data-toggle="dropdown" data-toggle="dropdown"
tabindex="1"> tabindex="1">
<i class="icon-cog"></i> <i class="icon icon-cog"></i>
</a> </a>
<ul class="dropdown-menu pull-right" role="menu"> <ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"> <li role="menuitem">
@ -26,7 +26,7 @@
</li> </li>
<li> <li>
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)"> <a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<i class="icon-remove"></i> <i class="icon icon-remove"></i>
</a> </a>
</li> </li>
</ul> </ul>
@ -171,7 +171,9 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="editor-row">
<div class="pull-left metrics-editor-help" style="margin-top: 30px;"> <div class="pull-left metrics-editor-help" style="margin-top: 30px;">
<div class="span6"> <div class="span6">
<span class="pointer"> <span class="pointer">

View File

@ -1,69 +1,80 @@
<div class="modal-body" ng-controller="InspectCtrl" ng-init="init()"> <div class="modal-body" ng-controller="InspectCtrl" ng-init="init()">
<div class="pull-right editor-title">Inspector</div> <div class="dashboard-editor-header">
<div class="dashboard-editor-title">
<i class="icon icon-eye-open"></i>
Inspector
</div>
<div ng-model="editor.index" bs-tabs> <div ng-model="editor.index" bs-tabs>
<div ng-repeat="tab in ['Request', 'Response', 'JS Error']" data-title="{{tab}}"> <div ng-repeat="tab in ['Request', 'Response', 'JS Error']" data-title="{{tab}}">
</div> </div>
</div> </div>
<div ng-if="editor.index == 0"> </div>
<h5>Request details</h5>
<table class="table table-striped small inspector-request-table">
<tr>
<td>Url</td>
<td>{{inspector.error.config.url}}</td>
</tr>
<tr>
<td>Method</td>
<td>{{inspector.error.config.method}}</td>
</tr>
<tr ng-repeat="(key, value) in inspector.error.config.headers">
<td>
{{key}}
</td>
<td>
{{value}}
</td>
</tr>
</table>
<h5>Request parameters</h5> <div class="dashboard-editor-body">
<table class="table table-striped small inspector-request-table">
<tr ng-repeat="param in request_parameters">
<td>
{{param.key}}
</td>
<td>
{{param.value}}
</td>
</tr>
</table>
</div>
<div ng-if="editor.index == 1"> <div ng-if="editor.index == 0">
<h5 ng-if="response" ng-bind="response"></h5> <h5>Request details</h5>
<table class="table table-striped small inspector-request-table">
<tr>
<td>Url</td>
<td>{{inspector.error.config.url}}</td>
</tr>
<tr>
<td>Method</td>
<td>{{inspector.error.config.method}}</td>
</tr>
<tr ng-repeat="(key, value) in inspector.error.config.headers">
<td>
{{key}}
</td>
<td>
{{value}}
</td>
</tr>
</table>
<div ng-if="response_html"> <h5>Request parameters</h5>
<div iframe-content="response_html"></div> <table class="table table-striped small inspector-request-table">
</div> <tr ng-repeat="param in request_parameters">
<td>
{{param.key}}
</td>
<td>
{{param.value}}
</td>
</tr>
</table>
</div>
</div> <div ng-if="editor.index == 1">
<h5 ng-if="response" ng-bind="response"></h5>
<div ng-if="editor.index == 2"> <div ng-if="response_html">
<div iframe-content="response_html"></div>
</div>
<label>Message:</label> </div>
<pre>
{{message}}
</pre>
<label>Stack trace:</label> <div ng-if="editor.index == 2">
<pre>
{{stack_trace}}
</pre>
</div> <label>Message:</label>
<pre>
{{message}}
</pre>
<label>Stack trace:</label>
<pre>
{{stack_trace}}
</pre>
</div>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-info" ng-click="dismiss()">Close</button> <button type="button" class="btn btn-info" ng-click="dismiss()">Close</button>
</div> </div>

View File

@ -12,7 +12,7 @@
<a class="pointer dropdown-toggle" <a class="pointer dropdown-toggle"
data-toggle="dropdown" data-toggle="dropdown"
tabindex="1"> tabindex="1">
<i class="icon-cog"></i> <i class="icon icon-cog"></i>
</a> </a>
<ul class="dropdown-menu pull-right" role="menu"> <ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"> <li role="menuitem">
@ -25,7 +25,7 @@
</li> </li>
<li> <li>
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)"> <a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<i class="icon-remove"></i> <i class="icon icon-remove"></i>
</a> </a>
</li> </li>
</ul> </ul>

View File

@ -22,8 +22,8 @@
</div> </div>
<table class="grafana-options-table"> <table class="grafana-options-table">
<tr ng-repeat="templateParam in templateParameters"> <tr ng-repeat="templateParam in templateParameters">
<td> <td style="width: 1%">
{{templateParam.name}} [[{{templateParam.name}}]]
</td> </td>
<td class="max-width" style="max-width: 200px;"> <td class="max-width" style="max-width: 200px;">
{{templateParam.query}} {{templateParam.query}}
@ -54,7 +54,7 @@
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Type</label> <label class="small">Type</label>
<select class="input-medium" ng-model="current.type" ng-options="f for f in ['metric query', 'custom']"></select> <select class="input-medium" ng-model="current.type" ng-options="f for f in ['query', 'custom']"></select>
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Datasource</label> <label class="small">Datasource</label>
@ -63,9 +63,29 @@
</div> </div>
<div class="editor-row"> <div class="editor-row">
<div class="editor-option"> <div class="editor-option form-inline">
<label class="small">Metric query</label> <label class="small">Metric name query</label>
<input type="text" class="input-xxlarge" ng-model='current.query' placeholder="query"></input> <input type="text" class="input-xxlarge" ng-model='current.query' placeholder="apps.servers.*"></input>
<button class="btn btn-small btn-success" ng-click="runQuery()" bs-tooltip="'Execute query'" data-placement="right"><i class="icon-play"></i></button>
</div>
</div>
<div class="editor-row" style="margin-top: 10px;">
<div class="editor-option form-inline">
<label class="small">Regex (optional, if you want to extract part of a series name or metric node segment)</label>
<input type="text" class="input-xxlarge" ng-model='current.regex' placeholder="/.*-(.*)-.*/"></input>
<button class="btn btn-small btn-success" ng-click="runQuery()" bs-tooltip="'Execute query'" data-placement="right"><i class="icon-play"></i></button>
</div>
</div>
<div class="editor-row" style="margin-top: 10px;">
<div class="editor-option form-inline">
<label class="small">Current replacement values</label>
<ul>
<li ng-repeat="option in current.options">
{{option.text}}
</li>
</ul>
</div> </div>
</div> </div>
@ -74,8 +94,8 @@
</div> </div>
<div class="dashboard-editor-footer"> <div class="dashboard-editor-footer">
<button type="button" class="btn btn-success pull-left" ng-show="editor.index === 2" ng-click="dismiss();">Update</button> <button type="button" class="btn btn-success pull-left" ng-show="editor.index === 2" ng-click="update();">Update</button>
<button type="button" class="btn btn-success pull-left" ng-show="editor.index === 1" ng-click="dismiss();">Add</button> <button type="button" class="btn btn-success pull-left" ng-show="editor.index === 1" ng-click="add();">Add</button>
<button type="button" class="btn btn-success pull-right" ng-click="dismiss();">Close</button> <button type="button" class="btn btn-success pull-right" ng-click="dismiss();">Close</button>
</div> </div>
</div> </div>

View File

@ -2,6 +2,7 @@ define([
'./alertSrv', './alertSrv',
'./datasourceSrv', './datasourceSrv',
'./filterSrv', './filterSrv',
'./templateSrv',
'./panelSrv', './panelSrv',
'./timer', './timer',
'./panelMove', './panelMove',

View File

@ -12,7 +12,7 @@ function (angular, _, config) {
var module = angular.module('grafana.services'); var module = angular.module('grafana.services');
module.service('datasourceSrv', function($q, filterSrv, $http, $injector) { module.service('datasourceSrv', function($q, $http, $injector) {
var datasources = {}; var datasources = {};
var metricSources = []; var metricSources = [];
var annotationSources = []; var annotationSources = [];

View File

@ -78,11 +78,6 @@ define([
} }
}, },
removeTemplateParameter: function(templateParameter) {
this.templateParameters = _.without(this.templateParameters, templateParameter);
this.dashboard.templating.list = this.templateParameters;
},
init: function(dashboard) { init: function(dashboard) {
this.dashboard = dashboard; this.dashboard = dashboard;
this.templateSettings = { interpolate : /\[\[([\s\S]+?)\]\]/g }; this.templateSettings = { interpolate : /\[\[([\s\S]+?)\]\]/g };

View File

@ -0,0 +1,21 @@
define([
'angular',
'lodash',
'kbn',
'store'
],
function (angular) {
'use strict';
var module = angular.module('grafana.services');
module.service('templateSrv', function() {
this.init = function(dashboard) {
this.dashboard = dashboard;
};
});
});

View File

@ -467,7 +467,6 @@ div.flot-text {
/************************* /*************************
* Right Positions * Right Positions
*************************/ *************************/
.popover { .popover {
&.rightTop .arrow { &.rightTop .arrow {
top: 10%; top: 10%;
@ -639,3 +638,4 @@ code, pre {
background-color: @grafanaPanelBackground; background-color: @grafanaPanelBackground;
color: @textColor; color: @textColor;
} }

View File

@ -9,7 +9,12 @@
padding: 5px 10px; padding: 5px 10px;
white-space: nowrap; white-space: nowrap;
border-bottom: 1px solid @grafanaListBorderBottom; border-bottom: 1px solid @grafanaListBorderBottom;
border-top: 1px solid @grafanaListBorderTop; }
tr:first-child {
td {
border-top: 1px solid @grafanaListBorderBottom;
}
} }
td:first-child { td:first-child {

View File

@ -6,7 +6,7 @@
// ------------------------- // -------------------------
@black: #000; @black: #000;
@gray: #bbb; @gray: #bbb;
@grayDark: #303030; @grayDark: #242424;
@grayDarker: #1f1f1f; @grayDarker: #1f1f1f;
@grayLight: #ADAFAE; @grayLight: #ADAFAE;
@ -29,10 +29,6 @@
// ------------------------- // -------------------------
@grafanaPanelBackground: @grayDarker; @grafanaPanelBackground: @grayDarker;
// Submenu
@submenuBackground: #292929;
@submenuBorder: #202020;
// Tabs // Tabs
@fullEditBorder: #555; @fullEditBorder: #555;
@ -43,8 +39,8 @@
@grafanaTargetColorHide: darken(#c8c8c8, 25%); @grafanaTargetColorHide: darken(#c8c8c8, 25%);
@grafanaTargetSegmentBorder: #050505; @grafanaTargetSegmentBorder: #050505;
@grafanaTargetFuncBackground: #444; @grafanaTargetFuncBackground: #333;
@grafanaTargetFuncHightlight: #555; @grafanaTargetFuncHightlight: #444;
// Scaffolding // Scaffolding
// ------------------------- // -------------------------
@ -133,7 +129,7 @@
// Forms // Forms
// ------------------------- // -------------------------
@inputBackground: lighten(@grayDark,0%); @inputBackground: lighten(@grayDark,5%);
@inputBorder: lighten(@grayDark,5%); @inputBorder: lighten(@grayDark,5%);
@inputBorderRadius: @baseBorderRadius; @inputBorderRadius: @baseBorderRadius;
@inputDisabledBackground: #555; @inputDisabledBackground: #555;