Commit 65b49455 by Torkel Ödegaard

Merge branch 'master' into query-editor-style

parents bca0894f aa98ada1
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* **Graph**: Fixed issue with unneeded scrollbar in legend for Firefox, fixes [#4760](https://github.com/grafana/grafana/issues/4760) * **Graph**: Fixed issue with unneeded scrollbar in legend for Firefox, fixes [#4760](https://github.com/grafana/grafana/issues/4760)
* **Table panel**: Fixed issue table panel formating string array properties, fixes [#4791](https://github.com/grafana/grafana/issues/4791) * **Table panel**: Fixed issue table panel formating string array properties, fixes [#4791](https://github.com/grafana/grafana/issues/4791)
* **grafana-cli**: Improve error message when failing to install plugins due to corrupt response, fixes [#4651](https://github.com/grafana/grafana/issues/4651) * **grafana-cli**: Improve error message when failing to install plugins due to corrupt response, fixes [#4651](https://github.com/grafana/grafana/issues/4651)
* **Singlestat**: Fixes prefix an postfix for gauges, fixes [#4812](https://github.com/grafana/grafana/issues/4812)
* **Singlestat**: Fixes auto-refresh on change for some options, fixes [#4809](https://github.com/grafana/grafana/issues/4809)
# 3.0.0-beta5 (2016-04-15) # 3.0.0-beta5 (2016-04-15)
......
all: deps build
deps:
go run build.go setup
godep restore
npm install
build:
go run build.go build
npm run build
test:
godep go test -v ./pkg/...
npm test
run:
./bin/grafana-server
...@@ -103,8 +103,7 @@ npm (v2.5.0) and grunt (v0.4.5). Run the following: ...@@ -103,8 +103,7 @@ npm (v2.5.0) and grunt (v0.4.5). Run the following:
```bash ```bash
npm install npm install
npm install -g grunt-cli npm run build
grunt
``` ```
### Recompile backend on source change ### Recompile backend on source change
...@@ -145,4 +144,3 @@ please [sign the CLA](http://docs.grafana.org/project/cla/) ...@@ -145,4 +144,3 @@ please [sign the CLA](http://docs.grafana.org/project/cla/)
Grafana is distributed under Apache 2.0 License. Grafana is distributed under Apache 2.0 License.
Work in progress Grafana 2.0 (with included Grafana backend) Work in progress Grafana 2.0 (with included Grafana backend)
...@@ -306,7 +306,7 @@ func ChangeWorkingDir(dir string) { ...@@ -306,7 +306,7 @@ func ChangeWorkingDir(dir string) {
} }
func grunt(params ...string) { func grunt(params ...string) {
runPrint("./node_modules/grunt-cli/bin/grunt", params...) runPrint("./node_modules/.bin/grunt", params...)
} }
func setup() { func setup() {
......
...@@ -25,12 +25,12 @@ test: ...@@ -25,12 +25,12 @@ test:
# Go test # Go test
- godep go test -v ./pkg/... - godep go test -v ./pkg/...
# js tests # js tests
- ./node_modules/grunt-cli/bin/grunt test - npm test
- npm run coveralls - npm run coveralls
deployment: deployment:
master: master:
branch: master branch: master
owner: grafana owner: grafana
commands: commands:
- ./trigger_grafana_packer.sh ${TRIGGER_GRAFANA_PACKER_CIRCLECI_TOKEN} - ./trigger_grafana_packer.sh ${TRIGGER_GRAFANA_PACKER_CIRCLECI_TOKEN}
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
"npm": "2.14.x" "npm": "2.14.x"
}, },
"scripts": { "scripts": {
"build": "grunt",
"test": "grunt test", "test": "grunt test",
"coveralls": "grunt karma:coveralls && rm -rf ./coverage" "coveralls": "grunt karma:coveralls && rm -rf ./coverage"
}, },
......
...@@ -48,6 +48,6 @@ func (slice PluginList) Swap(i, j int) { ...@@ -48,6 +48,6 @@ func (slice PluginList) Swap(i, j int) {
type ImportDashboardCommand struct { type ImportDashboardCommand struct {
PluginId string `json:"pluginId"` PluginId string `json:"pluginId"`
Path string `json:"path"` Path string `json:"path"`
Reinstall bool `json:"reinstall"` Overwrite bool `json:"overwrite"`
Inputs []plugins.ImportDashboardInput `json:"inputs"` Inputs []plugins.ImportDashboardInput `json:"inputs"`
} }
...@@ -156,11 +156,12 @@ func GetPluginReadme(c *middleware.Context) Response { ...@@ -156,11 +156,12 @@ func GetPluginReadme(c *middleware.Context) Response {
func ImportDashboard(c *middleware.Context, apiCmd dtos.ImportDashboardCommand) Response { func ImportDashboard(c *middleware.Context, apiCmd dtos.ImportDashboardCommand) Response {
cmd := plugins.ImportDashboardCommand{ cmd := plugins.ImportDashboardCommand{
OrgId: c.OrgId, OrgId: c.OrgId,
UserId: c.UserId, UserId: c.UserId,
PluginId: apiCmd.PluginId, PluginId: apiCmd.PluginId,
Path: apiCmd.Path, Path: apiCmd.Path,
Inputs: apiCmd.Inputs, Inputs: apiCmd.Inputs,
Overwrite: apiCmd.Overwrite,
} }
if err := bus.Dispatch(&cmd); err != nil { if err := bus.Dispatch(&cmd); err != nil {
......
...@@ -11,12 +11,13 @@ import ( ...@@ -11,12 +11,13 @@ import (
) )
type ImportDashboardCommand struct { type ImportDashboardCommand struct {
Path string `json:"string"` Path string
Inputs []ImportDashboardInput `json:"inputs"` Inputs []ImportDashboardInput
Overwrite bool
OrgId int64 `json:"-"` OrgId int64
UserId int64 `json:"-"` UserId int64
PluginId string `json:"-"` PluginId string
Result *PluginDashboardInfoDTO Result *PluginDashboardInfoDTO
} }
...@@ -67,6 +68,7 @@ func ImportDashboard(cmd *ImportDashboardCommand) error { ...@@ -67,6 +68,7 @@ func ImportDashboard(cmd *ImportDashboardCommand) error {
Dashboard: generatedDash, Dashboard: generatedDash,
OrgId: cmd.OrgId, OrgId: cmd.OrgId,
UserId: cmd.UserId, UserId: cmd.UserId,
Overwrite: cmd.Overwrite,
} }
if err := bus.Dispatch(&saveCmd); err != nil { if err := bus.Dispatch(&saveCmd); err != nil {
......
...@@ -211,6 +211,9 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ ...@@ -211,6 +211,9 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
// let a binding digest cycle complete before adding to dom // let a binding digest cycle complete before adding to dom
setTimeout(function() { setTimeout(function() {
elem.append(child); elem.append(child);
scope.$apply(function() {
scope.$broadcast('refresh');
});
}); });
} }
......
...@@ -23,7 +23,7 @@ export class Emitter { ...@@ -23,7 +23,7 @@ export class Emitter {
this.emitter.on(name, handler); this.emitter.on(name, handler);
if (scope) { if (scope) {
scope.$on('$destroy', function() { scope.$on('$destroy', () => {
this.emitter.off(name, handler); this.emitter.off(name, handler);
}); });
} }
......
...@@ -44,18 +44,15 @@ export class PanelCtrl { ...@@ -44,18 +44,15 @@ export class PanelCtrl {
this.pluginName = plugin.name; this.pluginName = plugin.name;
} }
$scope.$on("refresh", () => this.refresh()); $scope.$on("refresh", this.refresh.bind(this));
$scope.$on("render", () => this.render()); $scope.$on("render", this.render.bind(this));
$scope.$on("$destroy", () => this.events.emit('panel-teardown')); $scope.$on("$destroy", () => this.events.emit('panel-teardown'));
} }
init() { init() {
this.calculatePanelHeight(); this.calculatePanelHeight();
this.publishAppEvent('panel-initialized', {scope: this.$scope}); this.publishAppEvent('panel-initialized', {scope: this.$scope});
this.events.emit('panel-initialized'); this.events.emit('panel-initialized');
this.refresh();
} }
renderingCompleted() { renderingCompleted() {
......
...@@ -98,9 +98,7 @@ export class DataSourceEditCtrl { ...@@ -98,9 +98,7 @@ export class DataSourceEditCtrl {
this.datasourceSrv.get(this.current.name).then(datasource => { this.datasourceSrv.get(this.current.name).then(datasource => {
if (!datasource.testDatasource) { if (!datasource.testDatasource) {
this.testing.message = 'Data source does not support test connection feature.'; delete this.testing;
this.testing.status = 'warning';
this.testing.title = 'Unknown';
return; return;
} }
...@@ -118,7 +116,9 @@ export class DataSourceEditCtrl { ...@@ -118,7 +116,9 @@ export class DataSourceEditCtrl {
} }
}); });
}).finally(() => { }).finally(() => {
this.testing.done = true; if (this.testing) {
this.testing.done = true;
}
}); });
} }
......
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
</td> </td>
<td> <td>
v{{dash.revision}} v{{dash.revision}}
</td> <span ng-if="dash.installed">
<td ng-if="dash.installed"> &nbsp;(Imported v{{dash.installedRevision}})
Imported v{{dash.installedRevision}} <span>
</td> </td>
<td style="text-align: right"> <td style="text-align: right">
<button class="btn btn-secondary" ng-click="ctrl.import(dash, false)" ng-show="!dash.installed"> <button class="btn btn-secondary" ng-click="ctrl.import(dash, false)" ng-show="!dash.installed">
Import Import
</button> </button>
<button class="btn btn-secondary" ng-click="ctrl.import(dash, true)" ng-show="dash.installed"> <button class="btn btn-secondary" ng-click="ctrl.import(dash, true)" ng-show="dash.installed">
Re-Import Update
</button> </button>
<button class="btn btn-danger" ng-click="ctrl.remove(dash)" ng-show="dash.installed"> <button class="btn btn-danger" ng-click="ctrl.remove(dash)" ng-show="dash.installed">
Delete Delete
......
...@@ -43,11 +43,11 @@ export class DashImportListCtrl { ...@@ -43,11 +43,11 @@ export class DashImportListCtrl {
}); });
} }
import(dash, reinstall) { import(dash, overwrite) {
var installCmd = { var installCmd = {
pluginId: this.plugin.id, pluginId: this.plugin.id,
path: dash.path, path: dash.path,
reinstall: reinstall, overwrite: overwrite,
inputs: [] inputs: []
}; };
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
</plugin-component> </plugin-component>
</rebuild-on-change> </rebuild-on-change>
<div ng-if="ctrl.testing" style="margin-top: 25px"> <div ng-if="ctrl.testing" class="gf-form-group">
<h5 ng-show="!ctrl.testing.done">Testing.... <i class="fa fa-spiner fa-spin"></i></h5> <h5 ng-show="!ctrl.testing.done">Testing.... <i class="fa fa-spiner fa-spin"></i></h5>
<div class="alert-{{ctrl.testing.status}} alert"> <div class="alert-{{ctrl.testing.status}} alert">
<div class="alert-title">{{ctrl.testing.title}}</div> <div class="alert-title">{{ctrl.testing.title}}</div>
......
...@@ -158,7 +158,7 @@ ...@@ -158,7 +158,7 @@
<div class="editor-row"> <div class="editor-row">
<div class="section" style="margin-bottom: 20px"> <div class="section" style="margin-bottom: 20px">
<div class="tight-form last"> <div class="tight-form">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item" style="width: 80px"> <li class="tight-form-item" style="width: 80px">
<strong>Gauge</strong> <strong>Gauge</strong>
...@@ -170,26 +170,38 @@ ...@@ -170,26 +170,38 @@
<label for="panel.gauge.show" class="cr1"></label> <label for="panel.gauge.show" class="cr1"></label>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
Threshold labels&nbsp;
<input class="cr1" id="panel.gauge.thresholdLabels" type="checkbox"
ng-model="ctrl.panel.gauge.thresholdLabels" ng-checked="ctrl.panel.gauge.thresholdLabels" ng-change="ctrl.render()">
<label for="panel.gauge.thresholdLabels" class="cr1"></label>
</li>
<li class="tight-form-item">
Min Min
</li> </li>
<li> <li>
<input type="text" class="input-small tight-form-input" ng-model="ctrl.panel.gauge.minValue" ng-blur="ctrl.render()" placeholder="0"></input> <input type="number" class="input-small tight-form-input" ng-model="ctrl.panel.gauge.minValue" ng-blur="ctrl.render()" placeholder="0"></input>
</li> </li>
<li class="tight-form-item last"> <li class="tight-form-item last">
Max Max
</li> </li>
<li> <li>
<input type="text" class="input-small tight-form-input last" ng-model="ctrl.panel.gauge.maxValue" ng-blur="ctrl.render()" placeholder="100"></input> <input type="number" class="input-small tight-form-input last" ng-model="ctrl.panel.gauge.maxValue" ng-blur="ctrl.render()" placeholder="100"></input>
<span class="alert-state-critical" ng-show="ctrl.invalidGaugeRange">
&nbsp;
<i class="fa fa-warning"></i>
Min value is bigger than max.
</span>
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div class="tight-form last">
<li class="tight-form-item">
Threshold labels&nbsp;
<input class="cr1" id="panel.gauge.thresholdLabels" type="checkbox" ng-model="ctrl.panel.gauge.thresholdLabels" ng-checked="ctrl.panel.gauge.thresholdLabels" ng-change="ctrl.render()">
<label for="panel.gauge.thresholdLabels" class="cr1"></label>
</li>
<li class="tight-form-item">
Threshold markers&nbsp;
<input class="cr1" id="panel.gauge.thresholdMarkers" type="checkbox" ng-model="ctrl.panel.gauge.thresholdMarkers" ng-checked="ctrl.panel.gauge.thresholdMarkers" ng-change="ctrl.render()">
<label for="panel.gauge.thresholdMarkers" class="cr1"></label>
</li>
<div class="clearfix"></div>
</div>
</div> </div>
</div> </div>
......
...@@ -18,6 +18,7 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -18,6 +18,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
data: any; data: any;
fontSizes: any[]; fontSizes: any[];
unitFormats: any[]; unitFormats: any[];
invalidGaugeRange: boolean;
// Set and populate defaults // Set and populate defaults
panelDefaults = { panelDefaults = {
...@@ -53,7 +54,8 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -53,7 +54,8 @@ class SingleStatCtrl extends MetricsPanelCtrl {
show: false, show: false,
minValue: 0, minValue: 0,
maxValue: 100, maxValue: 100,
thresholdLabels: true thresholdMarkers: true,
thresholdLabels: false
} }
}; };
...@@ -278,14 +280,30 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -278,14 +280,30 @@ class SingleStatCtrl extends MetricsPanelCtrl {
return body; return body;
} }
function getValueText() {
var result = panel.prefix ? panel.prefix : '';
result += data.valueFormated;
result += panel.postfix ? panel.postfix : '';
return result;
}
function addGauge() { function addGauge() {
ctrl.invalidGaugeRange = false;
if (panel.gauge.minValue > panel.gauge.maxValue) {
ctrl.invalidGaugeRange = true;
return;
}
var plotCanvas = $('<div></div>'); var plotCanvas = $('<div></div>');
var width = elem.width();
var height = elem.height();
var plotCss = { var plotCss = {
top: '10px', top: '10px',
margin: 'auto', margin: 'auto',
position: 'relative', position: 'relative',
height: (elem.height() * 0.9) + 'px', height: (height * 0.9) + 'px',
width: elem.width() + 'px' width: width + 'px'
}; };
plotCanvas.css(plotCss); plotCanvas.css(plotCss);
...@@ -306,6 +324,12 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -306,6 +324,12 @@ class SingleStatCtrl extends MetricsPanelCtrl {
? 'rgb(230,230,230)' ? 'rgb(230,230,230)'
: 'rgb(38,38,38)'; : 'rgb(38,38,38)';
var dimension = Math.min(width, height);
var fontSize = Math.min(dimension/4, 100);
var gaugeWidth = Math.min(dimension/6, 60);
var thresholdMarkersWidth = gaugeWidth/5;
var options = { var options = {
series: { series: {
gauges: { gauges: {
...@@ -315,11 +339,11 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -315,11 +339,11 @@ class SingleStatCtrl extends MetricsPanelCtrl {
background: { color: bgColor }, background: { color: bgColor },
border: { color: null }, border: { color: null },
shadow: { show: false }, shadow: { show: false },
width: 38 width: gaugeWidth,
}, },
frame: { show: false }, frame: { show: false },
label: { show: false }, label: { show: false },
layout: { margin: 0 }, layout: { margin: 0, thresholdWidth: 0 },
cell: { border: { width: 0 } }, cell: { border: { width: 0 } },
threshold: { threshold: {
values: thresholds, values: thresholds,
...@@ -328,12 +352,13 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -328,12 +352,13 @@ class SingleStatCtrl extends MetricsPanelCtrl {
margin: 8, margin: 8,
font: { size: 18 } font: { size: 18 }
}, },
width: 8 show: panel.gauge.thresholdMarkers,
width: thresholdMarkersWidth,
}, },
value: { value: {
color: panel.colorValue ? getColorForValue(data, data.valueRounded) : null, color: panel.colorValue ? getColorForValue(data, data.valueRounded) : null,
formatter: function () { return data.valueFormated; }, formatter: function() { return getValueText(); },
font: { size: getGaugeFontSize() } font: { size: fontSize, family: 'Helvetica Neue", Helvetica, Arial, sans-serif' }
}, },
show: true show: true
} }
...@@ -352,7 +377,7 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -352,7 +377,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
function getGaugeFontSize() { function getGaugeFontSize() {
if (panel.valueFontSize) { if (panel.valueFontSize) {
var num = parseInt(panel.valueFontSize.substring(0, panel.valueFontSize.length - 1)); var num = parseInt(panel.valueFontSize.substring(0, panel.valueFontSize.length - 1));
return 30 * (num / 100); return (30 * (num / 100)) + 15;
} else { } else {
return 30; return 30;
} }
...@@ -419,6 +444,7 @@ class SingleStatCtrl extends MetricsPanelCtrl { ...@@ -419,6 +444,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
function render() { function render() {
if (!ctrl.data) { return; } if (!ctrl.data) { return; }
ctrl.setValues(ctrl.data);
data = ctrl.data; data = ctrl.data;
setElementHeight(); setElementHeight();
......
...@@ -48,4 +48,8 @@ ...@@ -48,4 +48,8 @@
} }
} }
#flotGagueValue0 {
font-weight: bold; //please dont hurt me for this!
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment