Commit eb25ce5f by Rashid Khan

Moved dashboard controller to nav bar

parent 8c6511d3
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -91,40 +91,6 @@
"status": "Stable"
}
]
},
{
"title": "Loader",
"height": "50px",
"editable": true,
"collapse": false,
"collapsable": true,
"panels": [
{
"error": false,
"span": 3,
"editable": true,
"group": [
"default"
],
"type": "dashcontrol",
"save": {
"gist": false,
"elasticsearch": true,
"local": true,
"default": true
},
"load": {
"gist": true,
"elasticsearch": true,
"local": true
},
"hide_control": false,
"elasticsearch_size": 20,
"temp": true,
"ttl_enable": true,
"temp_ttl": "30d"
}
]
}
],
"editable": true,
......
......@@ -40,45 +40,6 @@
"panels": [
{
"error": false,
"span": 3,
"editable": true,
"group": [
"default"
],
"type": "dashcontrol",
"save": {
"gist": false,
"elasticsearch": true,
"local": true,
"default": true
},
"load": {
"gist": true,
"elasticsearch": true,
"local": true
},
"hide_control": false,
"elasticsearch_size": 20,
"temp": true,
"temp_ttl": "30d",
"ttl_enable": true
},
{
"error": false,
"span": 4,
"editable": true,
"group": [
"default"
],
"type": "text",
"status": "Stable",
"mode": "markdown",
"content": "The dashcontrol panel to the left lets you save this dashboard to Elasticsearch once you have it how you like it. See the note on the welcome page about setting a global default.",
"style": {},
"title": "The dashcontrol panel"
},
{
"error": false,
"span": 5,
"editable": true,
"group": [
......
......@@ -129,10 +129,6 @@ dashboard.rows[0].panels = [
type: 'timepicker',
span: 6,
timespan: ARGS.from||_d_timespan
},
{
type: 'dashcontrol',
span: 3
}
];
......
......@@ -76,31 +76,6 @@
},
"filter_id": 0,
"status": "Stable"
},
{
"error": false,
"span": 3,
"editable": true,
"group": [
"default"
],
"type": "dashcontrol",
"save": {
"gist": false,
"elasticsearch": true,
"local": true,
"default": true
},
"load": {
"gist": true,
"elasticsearch": true,
"local": true
},
"hide_control": false,
"elasticsearch_size": 20,
"temp": true,
"temp_ttl": "30d",
"ttl_enable": true
}
]
},
......
......@@ -40,45 +40,6 @@
"panels": [
{
"error": false,
"span": 3,
"editable": true,
"group": [
"default"
],
"type": "dashcontrol",
"save": {
"gist": false,
"elasticsearch": true,
"local": true,
"default": true
},
"load": {
"gist": true,
"elasticsearch": true,
"local": true
},
"hide_control": false,
"elasticsearch_size": 20,
"temp": true,
"temp_ttl": "30d",
"ttl_enable": true
},
{
"error": false,
"span": 4,
"editable": true,
"group": [
"default"
],
"type": "text",
"status": "Stable",
"mode": "markdown",
"content": "The dashcontrol panel to the left lets you save this dashboard to Elasticsearch once you have it how you like it. See the note on the welcome page about setting a global default.",
"style": {},
"title": "The dashcontrol panel"
},
{
"error": false,
"span": 5,
"editable": true,
"group": [
......@@ -212,6 +173,6 @@
"index": {
"interval": "none",
"pattern": "[logstash-]YYYY.MM.DD",
"default": "NOT_CONFIGURED"
"default": "_all"
}
}
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en" id="ng-app"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en" id="ng-app"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
......@@ -39,9 +37,14 @@
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<p class="navbar-text pull-right version"><strong>Kibana 3</strong> milestone 3</p>
<span class="brand">{{dashboard.current.title}}</span>
<div class="brand"><i class='icon-cog pointer' ng-show='dashboard.current.editable' bs-modal="'partials/dasheditor.html'"></i></div>
<ul class="nav" ng-show='dashboard.current.editable'>
<li>
<a href='#' bs-modal="'partials/dasheditor.html'"><i class='icon-cog pointer'></i></a>
</li>
</ul>
<ul class="nav pull-right" ng-controller='dashLoader' ng-init="init()" ng-include="'partials/dashLoader.html'">
</ul>
</div>
</div>
</div>
......
......@@ -43,6 +43,7 @@ _.each(config.modules, function(v) {
/* Application level module which depends on filters, controllers, and services */
labjs.wait(function(){
// Create the module
angular.module('kibana', modules).config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/dashboard', {
......@@ -58,6 +59,8 @@ labjs.wait(function(){
redirectTo: 'dashboard'
});
}]);
// Wait for ready, then bootstrap
angular.element(document).ready(function() {
$('body').attr('ng-controller', 'DashCtrl');
angular.bootstrap(document, ['kibana']);
......
......@@ -118,6 +118,118 @@ angular.module('kibana.controllers', [])
$scope.init();
})
.controller('dashLoader', function($scope, $http, timer, dashboard, alertSrv) {
$scope.loader = dashboard.current.loader;
$scope.init = function() {
$scope.gist_pattern = /(^\d{5,}$)|(^[a-z0-9]{10,}$)|(gist.github.com(\/*.*)\/[a-z0-9]{5,}\/*$)/;
$scope.gist = $scope.gist || {};
$scope.elasticsearch = $scope.elasticsearch || {};
};
$scope.showDropdown = function(type) {
var _l = $scope.loader;
if(type === 'load') {
return (_l.load_elasticsearch || _l.load_gist || _l.load_local);
}
if(type === 'save') {
return (_l.save_elasticsearch || _l.save_gist || _l.local_local || _l.save_default);
}
if(type === 'share') {
return (_l.save_temp);
}
return false;
};
$scope.set_default = function() {
if(dashboard.set_default()) {
alertSrv.set('Local Default Set',dashboard.current.title+' has been set as your local default','success',5000);
} else {
alertSrv.set('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
}
};
$scope.purge_default = function() {
if(dashboard.purge_default()) {
alertSrv.set('Local Default Clear','Your local default dashboard has been cleared','success',5000);
} else {
alertSrv.set('Incompatible Browser','Sorry, your browser is too old for this feature','error',5000);
}
};
$scope.elasticsearch_save = function(type,ttl) {
dashboard.elasticsearch_save(
type,
($scope.elasticsearch.title || dashboard.current.title),
($scope.loader.save_temp_ttl_enable ? ttl : false)
).then(
function(result) {
if(!_.isUndefined(result._id)) {
alertSrv.set('Dashboard Saved','This dashboard has been saved to Elasticsearch as "' +
result._id + '"','success',5000);
if(type === 'temp') {
$scope.share = dashboard.share_link(dashboard.current.title,'temp',result._id);
}
} else {
alertSrv.set('Save failed','Dashboard could not be saved to Elasticsearch','error',5000);
}
});
};
$scope.elasticsearch_delete = function(id) {
dashboard.elasticsearch_delete(id).then(
function(result) {
if(!_.isUndefined(result)) {
if(result.found) {
alertSrv.set('Dashboard Deleted',id+' has been deleted','success',5000);
// Find the deleted dashboard in the cached list and remove it
var toDelete = _.where($scope.elasticsearch.dashboards,{_id:id})[0];
$scope.elasticsearch.dashboards = _.without($scope.elasticsearch.dashboards,toDelete);
} else {
alertSrv.set('Dashboard Not Found','Could not find '+id+' in Elasticsearch','warning',5000);
}
} else {
alertSrv.set('Dashboard Not Deleted','An error occurred deleting the dashboard','error',5000);
}
}
);
};
$scope.elasticsearch_dblist = function(query) {
dashboard.elasticsearch_list(query,$scope.loader.load_elasticsearch_size).then(
function(result) {
if(!_.isUndefined(result.hits)) {
$scope.hits = result.hits.total;
$scope.elasticsearch.dashboards = result.hits.hits;
}
});
};
$scope.save_gist = function() {
dashboard.save_gist($scope.gist.title).then(
function(link) {
if(!_.isUndefined(link)) {
$scope.gist.last = link;
alertSrv.set('Gist saved','You will be able to access your exported dashboard file at '+
'<a href="'+link+'">'+link+'</a> in a moment','success');
} else {
alertSrv.set('Save failed','Gist could not be saved','error',5000);
}
});
};
$scope.gist_dblist = function(id) {
dashboard.gist_list(id).then(
function(files) {
if(files && files.length > 0) {
$scope.gist.files = files;
} else {
alertSrv.set('Gist Failed','Could not retrieve dashboard list from gist','error',5000);
}
});
};
});
......
......@@ -68,4 +68,15 @@ angular.module('kibana.filters', [])
});
return text;
};
}).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(/.*\//, '');
}
}
};
});
\ No newline at end of file
......@@ -579,6 +579,20 @@ angular.module('kibana.services', [])
failover: false,
rows: [],
services: {},
loader: {
save_gist: false,
save_elasticsearch: true,
save_local: true,
save_default: true,
save_temp: true,
save_temp_ttl_enable: true,
save_temp_ttl: '30d',
load_gist: true,
load_elasticsearch: true,
load_elasticsearch_size: 20,
load_local: true,
hide: false
},
index: {
interval: 'none',
pattern: '_all',
......@@ -683,13 +697,20 @@ angular.module('kibana.services', [])
}
};
var dash_defaults = function(dashboard) {
_.defaults(dashboard,_dash);
_.defaults(dashboard.index,_dash.index);
_.defaults(dashboard.loader,_dash.loader);
return dashboard;
};
this.dash_load = function(dashboard) {
// Cancel all timers
timer.cancel_all();
// Make sure the dashboard being loaded has everything required
_.defaults(dashboard,_dash);
dashboard = dash_defaults(dashboard);
// If not using time based indices, use the default index
if(dashboard.index.interval === 'none') {
......@@ -790,9 +811,7 @@ angular.module('kibana.services', [])
return false;
}
var _dashboard = result.data;
_.defaults(_dashboard,_dash);
self.dash_load(_dashboard);
self.dash_load(dash_defaults(result.data));
return true;
},function(result) {
alertSrv.set('Error',"Could not load <i>dashboards/"+file+"</i>. Please make sure it exists" ,'error');
......@@ -834,9 +853,7 @@ angular.module('kibana.services', [])
if(!result) {
return false;
}
var _dashboard = result.data;
_.defaults(_dashboard,_dash);
self.dash_load(_dashboard);
self.dash_load(dash_defaults(result.data));
return true;
},function(result) {
alertSrv.set('Error',
......@@ -907,7 +924,6 @@ angular.module('kibana.services', [])
);
};
// TOFIX: Gist functionality
this.save_gist = function(title,dashboard) {
var save = _.clone(dashboard || self.current);
save.title = title || self.current.title;
......@@ -939,7 +955,7 @@ angular.module('kibana.services', [])
var file = JSON.parse(v.content);
files.push(file);
} catch(e) {
// Nothing?
return false;
}
});
return files;
......
<kibana-panel ng-controller='dashcontrol' ng-init="init()">
<label class='small'>Dashboard Control</label>
<label class='small'>Dash Control <tip icon="warning-sign">This panel is deprecated! Please remove it from your dashboard</tip></label>
<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> <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> <i class='icon-caret-down'></i></button>
<button ng-show="panel.temp" class='btn' ng-click="elasticsearch_save('temp',panel.temp_ttl)" bs-modal="'panels/dashcontrol/share.html'"><i class='icon-share'></i></button>
......
......@@ -27,8 +27,8 @@ angular.module('kibana.dashcontrol', [])
.controller('dashcontrol', function($scope, $http, timer, dashboard, alertSrv) {
$scope.panelMeta = {
status : "Stable",
description : "This panel allows for saving, loading, exporting and sharing dashboard schemas."
status : "Deprecated",
description : "This panel has been moved to the navigation bar. See the dashboard setting editor to configure it."
};
$scope.panel = $scope.panel || {};
......
<li class="dropdown" bs-tooltip="'Load'" data-placement="bottom" ng-show="showDropdown('load')" >
<a href="#" class="dropdown-toggle" data-toggle="dropdown" ng-click="elasticsearch_dblist('*')">
<i class='icon-folder-open'></i>
</a>
<ul class="dropdown-menu" style="padding:10px">
<li ng-show='loader.load_local'>
<h5>Local File <tip>Load dashboard JSON layout from file</tip></h5>
<form>
<input type="file" id="dashupload" dash-upload /><br>
</form>
</li>
<li ng-show='loader.load_gist'>
<h5>Gist <tip>Enter a gist number or url</tip></h5>
<form>
<input type="text" ng-model="gist.url"/ placeholder="Gist number or URL"><br>
<button class="btn" ng-click="gist_dblist(dashboard.gist_id(gist.url))" ng-show="dashboard.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="dashboard.dash_load(file)">{{file.title}}</a></td>
</tr>
</table>
</form>
</li>
<li ng-show='loader.load_elasticsearch'>
<h5>Elasticsearch</h5>
<form>
<input type="text" ng-model="elasticsearch.query" ng-change="elasticsearch_dblist('title:'+elasticsearch.query+'*')" placeholder="Type to filter"/>
</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="row in elasticsearch.dashboards | orderBy:['_id']">
<td><a ng-click="elasticsearch_delete(row._id)"><i class="icon-remove"></i></a></td>
<td><a href="#/dashboard/elasticsearch/{{row._id}}">{{row._id}}</a></td>
<td><a><i class="icon-share" ng-click="share = dashboard.share_link(row._id,'elasticsearch',row._id)" bs-modal="'panels/dashcontrol/share.html'"></i></a></td>
</tr>
</table>
</li>
</ul>
</li>
<li class="dropdown" bs-tooltip="'Save'" data-placement="bottom" ng-show="showDropdown('save')">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class='icon-save'></i>
</a>
<ul class="dropdown-menu" style="padding:10px">
<li ng-show="loader.save_default || loader.save_local">
<h5>Locally</h5>
<ul class="unstyled">
<li><a class="link" ng-show="loader.save_local" ng-click="dashboard.to_file()"><i class="icon-download"></i> Export to File</a> <tip>Export layout, not data, to file</tip></li>
<li><a class="link" ng-show="loader.save_default" ng-click="set_default()"><i class="icon-bookmark"></i> Set as Browser Default</a> <tip>Store dashboard preference to browser's localStorage</tip></li>
<li><a class="link" ng-show="loader.save_default" ng-click="purge_default()"><i class="icon-ban-circle"></i> Clear Browser Default</a></li>
</ul>
</li>
<li ng-show="loader.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>
</li>
<li ng-show="loader.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="elasticsearch_save('dashboard')"><i class="icon-save"></i></button>
</form>
</li>
</ul>
</li>
<li ng-show="showDropdown('share')"><a bs-tooltip="'Share'" data-placement="bottom" ng-click="elasticsearch_save('temp',loader.save_temp_ttl)" bs-modal="'partials/dashLoaderShare.html'"><i class='icon-share'></i></a></li>
\ No newline at end of file
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>{{share.title}} <small>shareable link</small></h3>
</div>
<div class="modal-body">
<label>Share this dashboard with this URL</label>
<input ng-model='share.link' type="text" style="width:90%" onclick="this.select()" onfocus="this.select()" ng-change="share = dashboard.share_link(share.title,share.type,share.id)">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success" ng-click="dismiss();$broadcast('render')">Close</button>
</div>
\ No newline at end of file
......@@ -2,12 +2,12 @@
<div class="pull-right editor-title">Dashboard settings</div>
<div ng-model="editor.index" bs-tabs>
<div ng-repeat="tab in ['General','Index','Rows']" data-title="{{tab}}">
<div ng-repeat="tab in ['General','Index','Rows','Controls']" data-title="{{tab}}">
</div>
</div>
<div class="row-fluid" ng-show="editor.index == 0">
<div ng-show="editor.index == 0">
<div class="row-fluid">
<div class="span4">
<label class="small">Title</label><input type="text" class="input-large" ng-model='dashboard.current.title'></input>
</div>
......@@ -18,7 +18,10 @@
<label class="small">Style</label><select class="input-small" ng-model="dashboard.current.style" ng-options='f for f in ["dark","light"]'></select>
</div>
</div>
<div class="row-fluid" ng-show="editor.index == 1">
</div>
<div ng-show="editor.index == 1">
<div class="row-fluid">
<h4>Index Settings</h4>
<div ng-show="dashboard.current.index.interval != 'none'" class="row-fluid">
<div class="span12">
......@@ -36,7 +39,7 @@
See <a href="http://momentjs.com/docs/#/displaying/format/">http://momentjs.com/docs/#/displaying/format/</a>
for documentation on date formatting.
</p>
</div>
</div>
</div>
<div class="row-fluid">
......@@ -57,7 +60,9 @@
</div>
</div>
</div>
<div class="row-fluid" ng-show="editor.index == 2">
<div ng-show="editor.index == 2">
<div class="row-fluid">
<div class="span12">
<table class="table table-condensed table-striped">
<thead>
......@@ -74,7 +79,7 @@
</table>
</div>
</div>
<div class="row-fluid" ng-show="editor.index == 2">
<div class="row-fluid">
<form>
<div class="span5">
<label class="small">Title</label>
......@@ -90,10 +95,55 @@
</div>
</form>
</div>
<!--<div class="row-fluid" ng-show="editor.index == 3">
<h6>Region</h6><select class="input-small" ng-model="dashboard.current.time.region" ng-options='f for f in ["africa","america","asia","atlantic","australia","europe","indian","pacific"]'></select>
</div>-->
</div>
<div ng-show="editor.index == 3" ng-controller="dashLoader">
<h5>Allow saving to</h5>
<div class="row-fluid">
<div class="span2">
<label class="small">File</label><input type="checkbox" ng-model="loader.save_local" ng-checked="loader.save_local">
</div>
<div class="span2">
<label class="small">Browser</label><input type="checkbox" ng-model="loader.save_default" ng-checked="loader.save_default">
</div>
<div class="span2">
<label class="small">Gist <tip>Requires your domain to be OAUTH registered with Github<tip></label><input type="checkbox" ng-model="loader.save_gist" ng-checked="loader.save_gist">
</div>
<div class="span2">
<label class="small">Elasticsearch</label><input type="checkbox" ng-model="loader.save_elasticsearch" ng-checked="loader.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="loader.load_local" ng-checked="loader.load_local">
</div>
<div class="span2">
<label class="small">Gist</label><input type="checkbox" ng-model="loader.load_gist" ng-checked="loader.load_gist">
</div>
<div class="span2">
<label class="small">Elasticsearch</label><input type="checkbox" ng-model="loader.load_elasticsearch" ng-checked="loader.load_elasticsearch">
</div>
<div class="span3" ng-show="loader.load.elasticsearch">
<label class="small">ES list size</label><input class="input-mini" type="number" ng-model="loader.load_elasticsearch_size">
</div>
</div>
<h5>Sharing</h5>
<div class="row-fluid">
<div class="span2" >
<label class="small">Allow Sharing <tip>Allow generating adhoc links to dashboards</tip></label><input type="checkbox" ng-model="loader.save_temp" ng-checked="loader.save_temp">
</div>
<div class="span2" ng-show="loader.save_temp">
<label class="small">TTL <tip>Expire temp urls</tip></label><input type="checkbox" ng-model="loader.save_temp_ttl_enable">
</div>
<div class="span5" ng-show="loader.save_temp && loader.save_temp_ttl_enable">
<label class="small">TTL Duration <tip>Elasticsearch date math, eg: 1m,1d,1w,30d </tip></label><input class="input-small" type="text" ng-model="loader.save_temp_ttl">
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button ng-click="add_row(dashboard.current,row); reset_row();" class="btn btn-success" ng-show="editor.index == 2">Create Row</button>
<button type="button" class="btn btn-danger" ng-click="editor.index=0;dismiss();reset_panel();dashboard.refresh()">Close</button>
......
......@@ -62,7 +62,7 @@ hr {
.nav > li.active > a:hover {
color: @grayLighter;
background-color: @grayDark;
#gradient > .directional(lighten(@grayDarker, 4%), lighten(@grayDark, 4%), 280deg);
#gradient > .directional(lighten(@grayDarker, 2%), lighten(@grayDark, 2%), 0deg);
border-right: 1px solid darken(@gray, 15%);
}
......
......@@ -186,7 +186,7 @@
@navbarBorder: darken(@navbarBackground, 12%);
@navbarText: @white;
@navbarLinkColor: @textColor;
@navbarLinkColor: @white;
@navbarLinkColorHover: @white;
@navbarLinkColorActive: @navbarLinkColorHover;
@navbarLinkBackgroundHover: @grayDark;
......
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