mirror of https://github.com/grafana/grafana
Fixed typo in elastic angular client, added dash loader panel, removed dashboards.js, replaced with default.json, added global alerts, add some display options for histogram
parent
d8f2d412cd
commit
a956a36c96
@ -1,4 +1,4 @@ |
||||
/*! elastic.js - v1.0.0 - 2013-01-15 |
||||
* https://github.com/fullscale/elastic.js
|
||||
* Copyright (c) 2013 FullScale Labs, LLC; Licensed MIT */ |
||||
"use strict";angular.module("elasticjs.service",[]).factory("ejsResource",["$http",function(e){return function(t){var n=window.ejs||{},r=function(e,t,n){return e.then(function(e){return(t||angular.noop)(e.data),e.data},function(e){return(n||angular.noop)(undefined),undefined})};return t==null&&(t=""),n.client={server:function(e){return e==null?t:(t=e,this)},post:function(n,i,s,o){return n=t+n,r(e.post(n,i),s,o)},get:function(n,i,s,o){return n=t+n,r(e.get(n,i),s,o)},put:function(n,i,s,o){return n=t+n,r(e.put(n,i),s,o)},del:function(n,i,s,o){return n=t+n,r(e.delee(n,i),s,o)},head:function(n,r,i,s){return n=t+n,e.head(n,r).then(function(e){return(i||angular.noop)(e.headers()),e.headers()},function(e){return(s||angular.noop)(undefined),undefined})}},n}}]); |
||||
"use strict";angular.module("elasticjs.service",[]).factory("ejsResource",["$http",function(e){return function(t){var n=window.ejs||{},r=function(e,t,n){return e.then(function(e){return(t||angular.noop)(e.data),e.data},function(e){return(n||angular.noop)(undefined),undefined})};return t==null&&(t=""),n.client={server:function(e){return e==null?t:(t=e,this)},post:function(n,i,s,o){return n=t+n,r(e.post(n,i),s,o)},get:function(n,i,s,o){return n=t+n,r(e.get(n,i),s,o)},put:function(n,i,s,o){return n=t+n,r(e.put(n,i),s,o)},del:function(n,i,s,o){return n=t+n,r(e.delete(n,i),s,o)},head:function(n,r,i,s){return n=t+n,e.head(n,r).then(function(e){return(i||angular.noop)(e.headers()),e.headers()},function(e){return(s||angular.noop)(undefined),undefined})}},n}}]); |
||||
|
@ -1,267 +0,0 @@ |
||||
var dashboards =
|
||||
{ |
||||
title: "Infinite Monkey Dashboard", |
||||
rows: [ |
||||
{ |
||||
title: "Query Control",
|
||||
height: "30px", |
||||
panels: [ |
||||
{ |
||||
type : "stringquery", |
||||
span : 12, |
||||
group : ['default','counter','histogram'] |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
title: "Status", |
||||
collapse: false,
|
||||
height: "100px", |
||||
panels: [ |
||||
{ |
||||
type : "timepicker", |
||||
span : 4, |
||||
mode : 'relative', |
||||
index : "\"shakespeare\"", |
||||
refresh : { |
||||
enable : false, |
||||
interval: 30, |
||||
min : 10 |
||||
}, |
||||
timespan : '1h', |
||||
timefield: '@timestamp', |
||||
group: ['default','pies'], |
||||
}, |
||||
{ |
||||
type : "sort", |
||||
span : 3, |
||||
}, |
||||
{ |
||||
title : "Histogram Timer", |
||||
type : "timepicker", |
||||
span : 0, |
||||
mode : 'relative', |
||||
timespan : '5m', |
||||
index : "\"shakespeare\"", |
||||
refresh : { |
||||
enable : true, |
||||
interval: 3, |
||||
min : 10 |
||||
}, |
||||
timefield: '@timestamp', |
||||
group: 'histogram', |
||||
}, |
||||
{ |
||||
type : "histogram", |
||||
span : 3, |
||||
show : ['lines'], |
||||
fill : 0.3, |
||||
group : "histogram", |
||||
query : [ |
||||
{ label : "Event Rate", query : "*", color: '#FF7400' } |
||||
], |
||||
}, |
||||
{ |
||||
title : "Counter Timer", |
||||
type : "timepicker", |
||||
span : 0, |
||||
mode : 'relative', |
||||
timespan : '30d', |
||||
index : "\"shakespeare\"", |
||||
refresh : { |
||||
enable : true, |
||||
interval: 3, |
||||
min : 10 |
||||
}, |
||||
timefield: '@timestamp', |
||||
group: 'counter', |
||||
}, |
||||
{ |
||||
type : "hits", |
||||
title : "Lines Completed", |
||||
span : 2, |
||||
group : 'counter', |
||||
}, |
||||
{ |
||||
type : "text", |
||||
style : {"font-size":"85%"}, |
||||
span: 0, |
||||
content : "Rows are collapsable, and input panels can send event to" + |
||||
" multiple groups. The Search panel is part of one group, while" + |
||||
" the time panel is part of two" |
||||
}, |
||||
] |
||||
}, |
||||
{ |
||||
title: "Top 3 Characters", |
||||
collapse: true, |
||||
height: "150px", |
||||
panels: [ |
||||
{ |
||||
type : "text", |
||||
title : "About", |
||||
style : {"font-size":"85%"}, |
||||
span: 2, |
||||
content : "These donut charts demonstrate configurable binding." +
|
||||
" They exist in a different group from the other panels and are" + |
||||
" bound only to the time selector, not to the query input. Thus" + |
||||
" they will change when you select a new time range, but not if" + |
||||
" you enter a search.", |
||||
}, |
||||
{ |
||||
title : "Hamlet", |
||||
type : "pie", |
||||
span : 2, |
||||
size : 3, |
||||
legend : false, |
||||
labels : false, |
||||
donut : true, |
||||
colors : ['#20805E','#26527C','#BF8530','#A60000','#006363','#679B00'], |
||||
field : 'country', |
||||
//query : { query: "*", field: "country"}
|
||||
query : { field : "speaker", query : "play_name:Hamlet" }, |
||||
group : "pies" |
||||
}, |
||||
{ |
||||
title : "Othello", |
||||
type : "pie", |
||||
span : 2, |
||||
size : 3, |
||||
legend : false, |
||||
labels : false, |
||||
donut : true, |
||||
colors : ['#35D59D','#FFB140','#F43D6B','#A60000','#006363','#679B00'], |
||||
field : 'country', |
||||
//query : { query: "*", field: "country"}
|
||||
query : { field : "speaker", query : "play_name:Othello" }, |
||||
group : "pies" |
||||
}, |
||||
{ |
||||
title : "A Winters Tale", |
||||
type : "pie", |
||||
span : 2, |
||||
size : 3, |
||||
legend : false, |
||||
labels : false, |
||||
donut : true, |
||||
colors : ['#78AF2C','#BF4630','#6A237E','#A60000','#006363','#679B00'], |
||||
field : 'country', |
||||
//query : { query: "*", field: "country"}
|
||||
query : { field : "speaker", query : 'play_name:"A Winters Tale"' }, |
||||
group : "pies" |
||||
}, |
||||
{ |
||||
title : "The Tempest", |
||||
type : "pie", |
||||
span : 2, |
||||
size : 3, |
||||
legend : false, |
||||
labels : false, |
||||
donut : true, |
||||
colors : ['#2A4480','#BFA730','#BF7130','#A60000','#006363','#679B00'], |
||||
field : 'country', |
||||
//query : { query: "*", field: "country"}
|
||||
query : { field : "speaker", query : 'play_name:"The Tempest"' }, |
||||
group : "pies" |
||||
}, |
||||
{ |
||||
title : "King Lear", |
||||
type : "pie", |
||||
span : 2, |
||||
size : 3, |
||||
legend : false, |
||||
labels : false, |
||||
donut : true, |
||||
colors : ['#01939A','#FFAB00','#FF0700','#A60000','#006363','#679B00'], |
||||
field : 'country', |
||||
//query : { query: "*", field: "country"}
|
||||
query : { field : "speaker", query : 'play_name:"King Lear"' }, |
||||
group : "pies" |
||||
}, |
||||
] |
||||
}, |
||||
{ |
||||
title: "Lines of Plays", |
||||
height: "210px", |
||||
collapse: false, |
||||
panels: [ |
||||
{ |
||||
title : "Plays", |
||||
type : "pie", |
||||
span : 4, |
||||
size : 8, |
||||
labels : false, |
||||
colors : ['#BF3030','#1D7373','#86B32D','#A60000','#006363','#679B00'], |
||||
field : 'country', |
||||
mode : "terms", |
||||
query : { query:"*", field:"play_name" } |
||||
}, |
||||
{ |
||||
type : "text", |
||||
title : "About", |
||||
style : {"font-size":"85%"}, |
||||
span: 0, |
||||
content : "The table panel can be sorted via a sort panel, or by" + |
||||
" clicking the table header. Unlike the donut charts above, this" + |
||||
" pie is bound to the query input. Try searching for a speaker" + |
||||
" (eg, FALSTAFF) to see a break down of the plays they appear in.",
|
||||
}, |
||||
{ |
||||
title : "Newest Lines", |
||||
editable: true, |
||||
type : "table", |
||||
span : 6, |
||||
query : "*", |
||||
style : {"font-size":"85%"}, |
||||
fields : ['@timestamp','play_name','speaker','text_entry'], |
||||
}, |
||||
{ |
||||
type : "fields", |
||||
title : "Fields", |
||||
span : 2, |
||||
}, |
||||
] |
||||
}, |
||||
|
||||
{ |
||||
title: "Monkey Monitoring", |
||||
collapse: false, |
||||
height: "225px", |
||||
panels: [ |
||||
{ |
||||
title : "Monkey Shakespeare Lines", |
||||
type : "histogram", |
||||
span : 5, |
||||
show : ['bars','stack'], |
||||
fill : 1, |
||||
query : [ |
||||
{ label : "Query Hits", query : "*", color: '#86B32D' }, |
||||
{ label : "Hamlet", query : "play_name:Hamlet" }, |
||||
{ label : "Macbeth", query : "play_name:macbeth" }, |
||||
], |
||||
}, |
||||
{ |
||||
title : "Monkey Typists Worldwide", |
||||
type : "map", |
||||
map : 'world', |
||||
field : "country", |
||||
span : 5, |
||||
size : 500, |
||||
query : "*", |
||||
}, |
||||
{ |
||||
type : "text", |
||||
title : "About", |
||||
style : {"font-size":"85%"}, |
||||
span: 2, |
||||
content : "Histograms can show multiple queries. In the case that a" + |
||||
" multi-query histogram is bound to a query input, only the first" + |
||||
" data series will be altered. All panels exist in the 'default'" + |
||||
" group by default. The map panel can be used to visualize events" + |
||||
" with attached geo data.",
|
||||
}, |
||||
] |
||||
} |
||||
|
||||
] |
||||
}; |
@ -0,0 +1,328 @@ |
||||
{ |
||||
"title": "Infinite Monkey Dashboard", |
||||
"rows": [ |
||||
{ |
||||
"title": "Query Control", |
||||
"height": "30px", |
||||
"panels": [ |
||||
{ |
||||
"type": "stringquery", |
||||
"span": 12, |
||||
"group": [ |
||||
"default", |
||||
"counter", |
||||
"histogram" |
||||
], |
||||
"label": "Search", |
||||
"query": "*", |
||||
"size": 100, |
||||
"sort": [ |
||||
"@timestamp", |
||||
"desc" |
||||
] |
||||
} |
||||
], |
||||
"collapse": false, |
||||
"editable": true |
||||
}, |
||||
{ |
||||
"title": "Status", |
||||
"collapse": false, |
||||
"height": "50px", |
||||
"panels": [ |
||||
{ |
||||
"type": "timepicker", |
||||
"span": 5, |
||||
"mode": "relative", |
||||
"index": "\"shakespeare\"", |
||||
"refresh": { |
||||
"enable": false, |
||||
"interval": 30, |
||||
"min": 10 |
||||
}, |
||||
"timespan": "1h", |
||||
"timefield": "@timestamp", |
||||
"group": [ |
||||
"default", |
||||
"pies" |
||||
], |
||||
"time_options": [ |
||||
"5m", |
||||
"15m", |
||||
"1h", |
||||
"6h", |
||||
"12h", |
||||
"24h", |
||||
"2d", |
||||
"7d", |
||||
"30d" |
||||
] |
||||
}, |
||||
{ |
||||
"title": "Histogram Timer", |
||||
"type": "timepicker", |
||||
"span": 0, |
||||
"mode": "relative", |
||||
"timespan": "5m", |
||||
"index": "\"shakespeare\"", |
||||
"refresh": { |
||||
"enable": true, |
||||
"interval": 10, |
||||
"min": 10 |
||||
}, |
||||
"timefield": "@timestamp", |
||||
"group": "histogram", |
||||
"time_options": [ |
||||
"5m", |
||||
"15m", |
||||
"1h", |
||||
"6h", |
||||
"12h", |
||||
"24h", |
||||
"2d", |
||||
"7d", |
||||
"30d" |
||||
] |
||||
}, |
||||
{ |
||||
"type": "histogram", |
||||
"span": 2, |
||||
"show": [ |
||||
"lines", |
||||
"y-axis" |
||||
], |
||||
"fill": 0.3, |
||||
"group": "histogram", |
||||
"query": [ |
||||
{ |
||||
"label": "Event Rate", |
||||
"query": "*", |
||||
"color": "#FF7400" |
||||
} |
||||
], |
||||
"interval": "5s", |
||||
"index": "shakespeare", |
||||
"title": "Lines per 5s" |
||||
}, |
||||
{ |
||||
"title": "Counter Timer", |
||||
"type": "timepicker", |
||||
"span": 0, |
||||
"mode": "relative", |
||||
"timespan": "30d", |
||||
"index": "\"shakespeare\"", |
||||
"refresh": { |
||||
"enable": true, |
||||
"interval": 10, |
||||
"min": 10 |
||||
}, |
||||
"timefield": "@timestamp", |
||||
"group": "counter", |
||||
"time_options": [ |
||||
"5m", |
||||
"15m", |
||||
"1h", |
||||
"6h", |
||||
"12h", |
||||
"24h", |
||||
"2d", |
||||
"7d", |
||||
"30d" |
||||
] |
||||
}, |
||||
{ |
||||
"type": "hits", |
||||
"title": "Lines Completed", |
||||
"span": 2, |
||||
"group": "counter", |
||||
"query": "*", |
||||
"style": { |
||||
"font-size": "36pt", |
||||
"font-weight": "bold" |
||||
}, |
||||
"index": "shakespeare", |
||||
"error": false |
||||
}, |
||||
{ |
||||
"type": "text", |
||||
"style": { |
||||
"font-size": "85%" |
||||
}, |
||||
"span": 0, |
||||
"content": "Rows are collapsable, and input panels can send event to multiple groups. The Search panel is part of one group, while the time panel is part of two", |
||||
"group": "default" |
||||
}, |
||||
{ |
||||
"title": "Dashboard Loader", |
||||
"type": "dashcontrol", |
||||
"span": 3, |
||||
"group": "default", |
||||
"save": { |
||||
"gist": true, |
||||
"elasticsearch": true, |
||||
"local": true, |
||||
"default": true |
||||
}, |
||||
"load": { |
||||
"gist": true, |
||||
"elasticsearch": true, |
||||
"local": true |
||||
}, |
||||
"elasticsearch_size": 20, |
||||
"error": false |
||||
} |
||||
], |
||||
"editable": true |
||||
}, |
||||
{ |
||||
"title": "Lines of Plays", |
||||
"height": "210px", |
||||
"collapse": false, |
||||
"panels": [ |
||||
{ |
||||
"title": "Plays", |
||||
"type": "pie", |
||||
"span": 4, |
||||
"size": 8, |
||||
"labels": false, |
||||
"colors": [ |
||||
"#BF3030", |
||||
"#1D7373", |
||||
"#86B32D", |
||||
"#A60000", |
||||
"#006363", |
||||
"#679B00" |
||||
], |
||||
"field": "country", |
||||
"mode": "terms", |
||||
"query": { |
||||
"query": "*", |
||||
"field": "play_name" |
||||
}, |
||||
"exclude": [], |
||||
"donut": false, |
||||
"tilt": false, |
||||
"legend": true, |
||||
"group": "default", |
||||
"default_field": "_all", |
||||
"index": "shakespeare" |
||||
}, |
||||
{ |
||||
"type": "text", |
||||
"title": "About", |
||||
"style": { |
||||
"font-size": "85%" |
||||
}, |
||||
"span": 0, |
||||
"content": "The table panel can be sorted via a sort panel, or by clicking the table header. Unlike the donut charts above, this pie is bound to the query input. Try searching for a speaker (eg, FALSTAFF) to see a break down of the plays they appear in.", |
||||
"group": "default" |
||||
}, |
||||
{ |
||||
"title": "Newest Lines", |
||||
"editable": true, |
||||
"type": "table", |
||||
"span": 6, |
||||
"query": "*", |
||||
"style": { |
||||
"font-size": "85%" |
||||
}, |
||||
"fields": [ |
||||
"@timestamp", |
||||
"play_name", |
||||
"speaker", |
||||
"text_entry" |
||||
], |
||||
"size": 100, |
||||
"sort": [ |
||||
"@timestamp", |
||||
"desc" |
||||
], |
||||
"group": "default", |
||||
"index": "shakespeare", |
||||
"error": false |
||||
}, |
||||
{ |
||||
"type": "fields", |
||||
"title": "Fields", |
||||
"span": 2, |
||||
"group": "default", |
||||
"style": { |
||||
"font-size": "85%", |
||||
"line-height": "15px" |
||||
}, |
||||
"sort": [ |
||||
"@timestamp", |
||||
"desc" |
||||
] |
||||
} |
||||
], |
||||
"editable": true |
||||
}, |
||||
{ |
||||
"title": "Monkey Monitoring", |
||||
"collapse": false, |
||||
"height": "225px", |
||||
"panels": [ |
||||
{ |
||||
"title": "Monkey Shakespeare Lines", |
||||
"type": "histogram", |
||||
"span": 5, |
||||
"show": [ |
||||
"bars", |
||||
"stack", |
||||
"legend", |
||||
"x-axis", |
||||
"y-axis" |
||||
], |
||||
"fill": 1, |
||||
"query": [ |
||||
{ |
||||
"label": "Query Hits", |
||||
"query": "*", |
||||
"color": "#86B32D" |
||||
}, |
||||
{ |
||||
"label": "Hamlet", |
||||
"query": "play_name:Hamlet" |
||||
}, |
||||
{ |
||||
"label": "Macbeth", |
||||
"query": "play_name:macbeth" |
||||
} |
||||
], |
||||
"interval": "1m", |
||||
"group": "default", |
||||
"index": "shakespeare" |
||||
}, |
||||
{ |
||||
"title": "Monkey Typists Worldwide", |
||||
"type": "map", |
||||
"map": "world", |
||||
"field": "country", |
||||
"span": 5, |
||||
"size": 500, |
||||
"query": "*", |
||||
"colors": [ |
||||
"#C8EEFF", |
||||
"#0071A4" |
||||
], |
||||
"exclude": [], |
||||
"group": "default", |
||||
"index": "shakespeare" |
||||
}, |
||||
{ |
||||
"type": "text", |
||||
"title": "About", |
||||
"style": { |
||||
"font-size": "85%" |
||||
}, |
||||
"span": 2, |
||||
"content": "Histograms can show multiple queries. In the case that a multi-query histogram is bound to a query input, only the first data series will be altered. All panels exist in the 'default' group by default. The map panel can be used to visualize events with attached geo data.", |
||||
"group": "default" |
||||
} |
||||
], |
||||
"editable": true |
||||
} |
||||
], |
||||
"editable": true |
||||
} |
@ -0,0 +1,32 @@ |
||||
<div> |
||||
<h5>Allow saving to</h5> |
||||
<div class="row-fluid"> |
||||
<div class="span2"> |
||||
<label class="small"> Export </label><input type="checkbox" ng-model="panel.save.local" ng-checked="panel.save.local"> |
||||
</div> |
||||
<div class="span2"> |
||||
<label class="small"> Defaults </label><input type="checkbox" ng-model="panel.save.default" ng-checked="panel.save.default"> |
||||
</div> |
||||
<div class="span2"> |
||||
<label class="small"> Gist </label><input type="checkbox" ng-model="panel.save.gist" ng-checked="panel.save.gist"> |
||||
</div> |
||||
<div class="span2"> |
||||
<label class="small"> Elasticsearch </label><input type="checkbox" ng-model="panel.save.elasticsearch" ng-checked="panel.save.elasticsearch"> |
||||
</div> |
||||
</div> |
||||
<h5>Allow loading from</h5> |
||||
<div class="row-fluid"> |
||||
<div class="span2"> |
||||
<label class="small"> Local file </label><input type="checkbox" ng-model="panel.load.local" ng-checked="panel.load.local"> |
||||
</div> |
||||
<div class="span2"> |
||||
<label class="small"> Gist </label><input type="checkbox" ng-model="panel.load.gist" ng-checked="panel.load.gist"> |
||||
</div> |
||||
<div class="span2"> |
||||
<label class="small"> Elasticsearch </label><input type="checkbox" ng-model="panel.load.elasticsearch" ng-checked="panel.load.elasticsearch"> |
||||
</div> |
||||
<div class="span4" ng-show="panel.load.elasticsearch"> |
||||
<label class="small"> Elasticsearch list size</label><input class="input-small" type="number" ng-model="panel.elasticsearch_size"> |
||||
</div> |
||||
</div> |
||||
</div> |
@ -0,0 +1,37 @@ |
||||
<div> |
||||
<div ng-show='panel.load.local'> |
||||
<h5>Local File</h5> |
||||
<form> |
||||
<input type="file" id="dashupload" dash-upload /><br> |
||||
</form> |
||||
</div> |
||||
<div ng-show='panel.load.gist'> |
||||
<h5>Gist <small>Enter a gist number or url</small></h5> |
||||
<form> |
||||
<input type="text" ng-model="gist.url"/><br> |
||||
<button class="btn" ng-click="gist_dblist(gist_id(gist.url))" ng-show="is_gist(gist.url)"><i class="icon-github-alt"></i> Get gist:{{gist.url | gistid}}</button> |
||||
<h6 ng-show="gist.files.length">Dashboards in gist:{{gist.url | gistid}} <small>click to load</small></h6> |
||||
<h6 ng-hide="gist.files.length">No gist dashboards found</h6> |
||||
<table class="table table-condensed table-striped"> |
||||
<tr ng-repeat="file in gist.files"> |
||||
<td><a ng-click="dash_load(file)">{{file.title}}</a></td> |
||||
</tr> |
||||
</table> |
||||
</form> |
||||
</div> |
||||
<div ng-show='panel.load.elasticsearch'> |
||||
<h5>Elasticsearch</h5> |
||||
<form class="input-append"> |
||||
<input type="text" ng-model="elasticsearch.query"/> |
||||
<button ng-click="elasticsearch_dblist(elasticsearch.query)" class='btn'><i class='icon-search'></i></button> |
||||
</form> |
||||
<h6 ng-show="elasticsearch.dashboards.length">Elasticsearch stored dashboards</h6> |
||||
<h6 ng-hide="elasticsearch.dashboards.length">No dashboards matching your query found</h6> |
||||
<table class="table table-condensed table-striped"> |
||||
<tr ng-repeat="dashboard in elasticsearch.dashboards"> |
||||
<td><a ng-click="delete_elasticsearch(dashboard)"><i class="icon-remove"></i></a></td> |
||||
<td><a ng-click="dash_load(dashboard['_source']['dashboard'])">{{dashboard._id}}</a></td> |
||||
</tr> |
||||
</table> |
||||
</div> |
||||
</div> |
@ -0,0 +1,4 @@ |
||||
<kibana-panel ng-controller='dashcontrol'> |
||||
<button class='btn' ng-show="panel.load.gist || panel.load.elasticsearch || panel.load.local" data-placement="bottom" data-unique="1" ng-click="elasticsearch_dblist(elasticsearch.query)" bs-popover="'panels/dashcontrol/load.html'"><i class='icon-folder-open'></i> Load <i class='icon-caret-down'></i></button> |
||||
<button class='btn' ng-show="panel.save.gist || panel.save.elasticsearch || panel.save.local || panel.save.default" data-placement="bottom" data-unique="1" bs-popover="'panels/dashcontrol/save.html'"><i class='icon-save'></i> Save <i class='icon-caret-down'></i></button> |
||||
</kibana-panel> |
@ -0,0 +1,209 @@ |
||||
angular.module('kibana.dashcontrol', []) |
||||
.controller('dashcontrol', function($scope, $http, eventBus, timer) { |
||||
|
||||
var _id = _.uniqueId(); |
||||
|
||||
// Set and populate defaults
|
||||
var _d = { |
||||
group : "default", |
||||
save : { |
||||
gist: true, |
||||
elasticsearch: true, |
||||
local: true, |
||||
'default': true |
||||
}, |
||||
load : { |
||||
gist: true, |
||||
elasticsearch: true, |
||||
local: true, |
||||
}, |
||||
elasticsearch_size: 20, |
||||
} |
||||
_.defaults($scope.panel,_d); |
||||
|
||||
$scope.init = function() { |
||||
$scope.gist_pattern = /(^\d{5,}$)|(^[a-z0-9]{10,}$)|(gist.github.com(\/*.*)\/[a-z0-9]{5,}\/*$)/; |
||||
$scope.gist = {}; |
||||
$scope.elasticsearch = {}; |
||||
} |
||||
|
||||
$scope.export = function() { |
||||
var blob = new Blob([angular.toJson($scope.dashboards,true)], {type: "application/json;charset=utf-8"}); |
||||
saveAs(blob, $scope.dashboards.title+"-"+new Date().getTime()); |
||||
} |
||||
|
||||
$scope.default = function() { |
||||
if (Modernizr.localstorage) { |
||||
localStorage['dashboard'] = angular.toJson($scope.dashboards); |
||||
$scope.alert('Success', |
||||
$scope.dashboards.title + " has been set as your default dashboard", |
||||
'success',5000) |
||||
} else { |
||||
$scope.alert('Bummer!', |
||||
"Your browser is too old for this functionality", |
||||
'error',5000); |
||||
}
|
||||
} |
||||
|
||||
$scope.purge = function() { |
||||
if (Modernizr.localstorage) { |
||||
localStorage['dashboard'] = ''; |
||||
$scope.alert('Success', |
||||
'Default dashboard cleared', |
||||
'success',5000) |
||||
} else { |
||||
$scope.alert('Doh!', |
||||
"Your browser is too old for this functionality", |
||||
'error',5000); |
||||
}
|
||||
} |
||||
|
||||
$scope.save_elasticsearch = function() { |
||||
var save = _.clone($scope.dashboards) |
||||
save.title = $scope.elasticsearch.title; |
||||
var result = $scope.ejs.Document('kibana-int','dashboard',save.title).source({ |
||||
user: 'guest', |
||||
group: 'guest', |
||||
title: save.title, |
||||
dashboard: angular.toJson(save) |
||||
}).doIndex(); |
||||
result.then(function(result) { |
||||
$scope.alert('Dashboard Saved','This dashboard has been saved to Elasticsearch','success',5000) |
||||
$scope.elasticsearch_dblist($scope.elasticsearch.query); |
||||
$scope.elasticsearch.title = ''; |
||||
}) |
||||
} |
||||
|
||||
$scope.delete_elasticsearch = function(dashboard) { |
||||
var result = $scope.ejs.Document('kibana-int','dashboard',dashboard._id).doDelete(); |
||||
result.then(function(result) { |
||||
$scope.alert('Dashboard Deleted','','success',5000) |
||||
$scope.elasticsearch.dashboards = _.without($scope.elasticsearch.dashboards,dashboard) |
||||
}) |
||||
} |
||||
|
||||
$scope.elasticsearch_dblist = function(query) { |
||||
if($scope.panel.load.elasticsearch) { |
||||
var request = $scope.ejs.Request().indices('kibana-int').types('dashboard'); |
||||
var results = request.query( |
||||
$scope.ejs.QueryStringQuery(query || '*') |
||||
).size($scope.panel.elasticsearch_size).doSearch(); |
||||
results.then(function(results) { |
||||
if(_.isUndefined(results)) { |
||||
$scope.panel.error = 'Your query was unsuccessful'; |
||||
return; |
||||
} |
||||
$scope.panel.error = false; |
||||
$scope.hits = results.hits.total; |
||||
$scope.elasticsearch.dashboards = results.hits.hits |
||||
}); |
||||
} |
||||
} |
||||
|
||||
$scope.save_gist = function() { |
||||
var save = _.clone($scope.dashboards) |
||||
save.title = $scope.gist.title; |
||||
$http({ |
||||
url: "https://api.github.com/gists", |
||||
method: "POST", |
||||
data: { |
||||
"description": save.title, |
||||
"public": false, |
||||
"files": { |
||||
"kibana-dashboard.json": { |
||||
"content": angular.toJson(save,true) |
||||
} |
||||
} |
||||
} |
||||
}).success(function(data, status, headers, config) { |
||||
$scope.gist.last = data.html_url; |
||||
$scope.alert('Gist saved','You will be able to access your exported dashboard file at <a href="'+data.html_url+'">'+data.html_url+'</a> in a moment','success') |
||||
}).error(function(data, status, headers, config) { |
||||
$scope.alert('Unable to save','Save to gist failed for some reason','error',5000) |
||||
}); |
||||
} |
||||
|
||||
$scope.gist_dblist = function(id) { |
||||
$http({ |
||||
url: "https://api.github.com/gists/"+id, |
||||
method: "GET" |
||||
}).success(function(data, status, headers, config) { |
||||
$scope.gist.files = [] |
||||
_.each(data.files,function(v,k) { |
||||
try { |
||||
var file = JSON.parse(v.content) |
||||
$scope.gist.files.push(file) |
||||
} catch(e) { |
||||
$scope.alert('Gist failure','The dashboard file is invalid','warning',5000) |
||||
} |
||||
}); |
||||
}).error(function(data, status, headers, config) { |
||||
$scope.alert('Gist Failed','Could not retrieve dashboard list from gist','error',5000) |
||||
}); |
||||
} |
||||
|
||||
$scope.dash_load = function(dashboard) { |
||||
if(!_.isObject(dashboard)) |
||||
dashboard = JSON.parse(dashboard) |
||||
|
||||
eventBus.broadcast($scope.$id,'ALL','dashboard',dashboard) |
||||
timer.cancel_all(); |
||||
} |
||||
|
||||
$scope.gist_id = function(string) { |
||||
if($scope.is_gist(string)) |
||||
return string.match($scope.gist_pattern)[0].replace(/.*\//, ''); |
||||
} |
||||
|
||||
$scope.is_gist = function(string) { |
||||
if(!_.isUndefined(string) && string != '' && !_.isNull(string.match($scope.gist_pattern))) |
||||
return string.match($scope.gist_pattern).length > 0 ? true : false; |
||||
else |
||||
return false |
||||
} |
||||
|
||||
$scope.init(); |
||||
|
||||
|
||||
}) |
||||
.directive('dashUpload', function(timer, eventBus){ |
||||
return { |
||||
restrict: 'A', |
||||
link: function(scope, elem, attrs) { |
||||
function file_selected(evt) { |
||||
var files = evt.target.files; // FileList object
|
||||
|
||||
// files is a FileList of File objects. List some properties.
|
||||
var output = []; |
||||
for (var i = 0, f; f = files[i]; i++) { |
||||
var reader = new FileReader(); |
||||
reader.onload = (function(theFile) { |
||||
return function(e) { |
||||
scope.dash_load(JSON.parse(e.target.result)) |
||||
scope.$apply(); |
||||
}; |
||||
})(f); |
||||
reader.readAsText(f); |
||||
} |
||||
} |
||||
|
||||
// Check for the various File API support.
|
||||
if (window.File && window.FileReader && window.FileList && window.Blob) { |
||||
// Something
|
||||
document.getElementById('dashupload').addEventListener('change', file_selected, false); |
||||
} else { |
||||
alert('Sorry, the HTML5 File APIs are not fully supported in this browser.'); |
||||
} |
||||
} |
||||
} |
||||
}).filter('gistid', function() { |
||||
var gist_pattern = /(\d{5,})|([a-z0-9]{10,})|(gist.github.com(\/*.*)\/[a-z0-9]{5,}\/*$)/; |
||||
return function(input, scope) { |
||||
//return input+"boners"
|
||||
if(!(_.isUndefined(input))) { |
||||
var output = input.match(gist_pattern); |
||||
if(!_.isNull(output) && !_.isUndefined(output)) |
||||
return output[0].replace(/.*\//, ''); |
||||
} |
||||
} |
||||
});; |
@ -0,0 +1,28 @@ |
||||
<div> |
||||
|
||||
<div ng-show="panel.save.default || panel.save.local"> |
||||
<h5>Locally</h5> |
||||
<form> |
||||
<ul class="nav nav-list"> |
||||
<li><a ng-show="panel.save.local" ng-click="export()"><i class="icon-download"></i> Export to File</a></li> |
||||
<li><a ng-show="panel.save.default" ng-click="default()"><i class="icon-bookmark"></i> Set as Default</a></li> |
||||
<li><a ng-show="panel.save.default" ng-click="purge()"><i class="icon-ban-circle"></i> Clear Default</a></li> |
||||
</ul> |
||||
</form> |
||||
</div> |
||||
<div ng-show="panel.save.gist"> |
||||
<h5>Gist</h5> |
||||
<form class="input-append"> |
||||
<input class='input-medium' placeholder='Title' type="text" ng-model="gist.title"/> |
||||
<button class="btn" ng-click="save_gist()"><i class="icon-github-alt"></i></button> |
||||
</form><br> |
||||
<small ng-show="gist.last">Last gist: <a target="_blank" href="{{gist.last}}">{{gist.last}}</a></small> |
||||
</div> |
||||
<div ng-show="panel.save.elasticsearch"> |
||||
<h5>Elasticsearch</h5> |
||||
<form class="input-append"> |
||||
<input class='input-medium' placeholder='Title' type="text" ng-model="elasticsearch.title"/> |
||||
<button class="btn" ng-click="save_elasticsearch()"><i class="icon-save"></i></button> |
||||
</form> |
||||
</div> |
||||
</div> |
@ -1,5 +1,3 @@ |
||||
<kibana-panel ng-controller='histogram' style="height:{{row.height}}"> |
||||
<div> |
||||
<div histogram params="{{panel}} clearfix" style="height:{{row.height}}"></div> |
||||
</div> |
||||
<div histogram params="{{panel}}" style="height:{{row.height}}"></div> |
||||
</kibana-panel> |
Loading…
Reference in new issue