Commit f42202e6 by Alexander Zobnin

Merge branch 'master' into graph-annotations

parents 70bca219 0384eecf
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
## Fixes ## Fixes
* **Table Panel**: Fixed annotation display in table panel, [#8023](https://github.com/grafana/grafana/issues/8023) * **Table Panel**: Fixed annotation display in table panel, [#8023](https://github.com/grafana/grafana/issues/8023)
* **Dashboard**: If refresh is blocked due to tab not visible, then refresh when it becomes visible [#8076](https://github.com/grafana/grafana/issues/8076) thanks [@SimenB](https://github.com/SimenB)
# 4.2.0 (2017-03-22) # 4.2.0 (2017-03-22)
## Minor Enhancements ## Minor Enhancements
......
...@@ -19,15 +19,15 @@ can grow even stronger and develop new plugins that we would never think about. ...@@ -19,15 +19,15 @@ can grow even stronger and develop new plugins that we would never think about.
To discover plugins checkout the official [Plugin Repository](https://grafana.com/plugins). To discover plugins checkout the official [Plugin Repository](https://grafana.com/plugins).
# Installing plugins # Installing Plugins
The easiest way to install plugins is by using the CLI tool grafana-cli which is bundled with grafana. Before any modification take place after modifying plugins, grafana-server needs to be restarted. The easiest way to install plugins is by using the CLI tool grafana-cli which is bundled with grafana. Before any modification take place after modifying plugins, grafana-server needs to be restarted.
### Grafana plugin directory ### Grafana Plugin Directory
On Linux systems the grafana-cli will assume that the grafana plugin directory is `/var/lib/grafana/plugins`. It's possible to override the directory which grafana-cli will operate on by specifying the --pluginsDir flag. On Windows systems this parameter have to be specified for every call. On Linux systems the grafana-cli will assume that the grafana plugin directory is `/var/lib/grafana/plugins`. It's possible to override the directory which grafana-cli will operate on by specifying the --pluginsDir flag. On Windows systems this parameter have to be specified for every call.
### Grafana-cli commands ### Grafana-cli Commands
List available plugins List available plugins
``` ```
...@@ -63,3 +63,42 @@ Remove one plugin ...@@ -63,3 +63,42 @@ Remove one plugin
``` ```
grafana-cli plugins remove <plugin-id> grafana-cli plugins remove <plugin-id>
``` ```
### Installing Plugins Manually
If your Grafana Server does not have access to the Internet, then the plugin will have to downloaded and manually copied to your Grafana Server.
The Download URL from Grafana.com API is in this form:
`https://grafana.com/api/plugins/<plugin id>/versions/<version number>/download`
To manually install a Plugin via the Grafana.com API:
1. Find the plugin you want to download, the plugin id can be found on the Installation Tab on the plugin's page on Grafana.com. In this example, the plugin id is `jdbranham-diagram-panel`:
{{< imgbox img="/img/docs/installation-tab.png" caption="Installation Tab" >}}
2. Use the Grafana API to find the plugin using this url `https://grafana.com/api/plugins/<plugin id from step 1>`. For example: https://grafana.com/api/plugins/jdbranham-diagram-panel should return:
```
{
"id": 145,
"typeId": 3,
"typeName": "Panel",
"typeCode": "panel",
"slug": "jdbranham-diagram-panel",
"name": "Diagram",
"description": "Diagram panel for grafana",
...
```
3. Find the download link:
```
{
"rel": "download",
"href": "/plugins/jdbranham-diagram-panel/versions/1.4.0/download"
}
```
4. Download the plugin with `https://grafana.com/api/plugins/<plugin id from step 1>/versions/<current version>/download` (for example: https://grafana.com/api/plugins/jdbranham-diagram-panel/versions/1.4.0/download). Unzip the downloaded file into the Grafana Server's `data/plugins` directory.
5. Restart the Grafana Server.
...@@ -139,8 +139,12 @@ func (this *PushoverNotifier) Notify(evalContext *alerting.EvalContext) error { ...@@ -139,8 +139,12 @@ func (this *PushoverNotifier) Notify(evalContext *alerting.EvalContext) error {
} }
} }
if evalContext.Error != nil { if evalContext.Error != nil {
message += fmt.Sprintf("\n<b>Error message</b> %s", evalContext.Error.Error()) message += fmt.Sprintf("\n<b>Error message:</b> %s", evalContext.Error.Error())
} }
if evalContext.ImagePublicUrl != "" {
message += fmt.Sprintf("\n<a href=\"%s\">Show graph image</a>", evalContext.ImagePublicUrl)
}
q := url.Values{} q := url.Values{}
q.Add("user", this.UserKey) q.Add("user", this.UserKey)
q.Add("token", this.ApiToken) q.Add("token", this.ApiToken)
......
...@@ -171,6 +171,7 @@ func upsertAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *xor ...@@ -171,6 +171,7 @@ func upsertAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *xor
if alertToUpdate.ContainsUpdates(alert) { if alertToUpdate.ContainsUpdates(alert) {
alert.Updated = time.Now() alert.Updated = time.Now()
alert.State = alertToUpdate.State alert.State = alertToUpdate.State
sess.MustCols("message")
_, err := sess.Id(alert.Id).Update(alert) _, err := sess.Id(alert.Id).Update(alert)
if err != nil { if err != nil {
return err return err
......
...@@ -27,7 +27,7 @@ export class HelpCtrl { ...@@ -27,7 +27,7 @@ export class HelpCtrl {
{keys: ['d', 'v'], description: 'Toggle in-active / view mode'}, {keys: ['d', 'v'], description: 'Toggle in-active / view mode'},
{keys: ['d', 'k'], description: 'Toggle kiosk mode (hides top nav)'}, {keys: ['d', 'k'], description: 'Toggle kiosk mode (hides top nav)'},
{keys: ['d', 'E'], description: 'Expand all rows'}, {keys: ['d', 'E'], description: 'Expand all rows'},
{keys: ['d', 'C'], description: 'Collapse all ros'}, {keys: ['d', 'C'], description: 'Collapse all rows'},
{keys: ['mod+o'], description: 'Toggle shared graph crosshair'}, {keys: ['mod+o'], description: 'Toggle shared graph crosshair'},
], ],
'Focused Panel': [ 'Focused Panel': [
......
...@@ -15,6 +15,7 @@ class TimeSrv { ...@@ -15,6 +15,7 @@ class TimeSrv {
oldRefresh: boolean; oldRefresh: boolean;
dashboard: any; dashboard: any;
timeAtLoad: any; timeAtLoad: any;
private autoRefreshBlocked: boolean;
/** @ngInject **/ /** @ngInject **/
constructor(private $rootScope, private $timeout, private $location, private timer, private contextSrv) { constructor(private $rootScope, private $timeout, private $location, private timer, private contextSrv) {
...@@ -23,6 +24,14 @@ class TimeSrv { ...@@ -23,6 +24,14 @@ class TimeSrv {
$rootScope.$on('zoom-out', this.zoomOut.bind(this)); $rootScope.$on('zoom-out', this.zoomOut.bind(this));
$rootScope.$on('$routeUpdate', this.routeUpdated.bind(this)); $rootScope.$on('$routeUpdate', this.routeUpdated.bind(this));
document.addEventListener('visibilitychange', () => {
if (this.autoRefreshBlocked && document.visibilityState === 'visible') {
this.autoRefreshBlocked = false;
this.refreshDashboard();
}
});
} }
init(dashboard) { init(dashboard) {
...@@ -137,6 +146,8 @@ class TimeSrv { ...@@ -137,6 +146,8 @@ class TimeSrv {
this.startNextRefreshTimer(afterMs); this.startNextRefreshTimer(afterMs);
if (this.contextSrv.isGrafanaVisible()) { if (this.contextSrv.isGrafanaVisible()) {
this.refreshDashboard(); this.refreshDashboard();
} else {
this.autoRefreshBlocked = true;
} }
}, afterMs)); }, afterMs));
} }
......
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