Commit 7b036cbe by Torkel Ödegaard

Merge branch 'playlist' Closes #36

parents adfa341d 51008341
...@@ -9,4 +9,5 @@ define([ ...@@ -9,4 +9,5 @@ define([
'./graphiteTarget', './graphiteTarget',
'./graphiteImport', './graphiteImport',
'./influxTargetCtrl', './influxTargetCtrl',
'./playlistCtrl',
], function () {}); ], function () {});
\ No newline at end of file
...@@ -8,7 +8,7 @@ function (angular, _, moment) { ...@@ -8,7 +8,7 @@ function (angular, _, moment) {
var module = angular.module('kibana.controllers'); var module = angular.module('kibana.controllers');
module.controller('dashLoader', function($scope, $rootScope, $http, dashboard, alertSrv, $location, filterSrv) { module.controller('dashLoader', function($scope, $rootScope, $http, dashboard, alertSrv, $location, filterSrv, playlistSrv) {
$scope.loader = dashboard.current.loader; $scope.loader = dashboard.current.loader;
$scope.init = function() { $scope.init = function() {
...@@ -154,6 +154,24 @@ function (angular, _, moment) { ...@@ -154,6 +154,24 @@ function (angular, _, moment) {
}); });
}; };
$scope.openSaveDropdown = function() {
$scope.isFavorite = playlistSrv.isCurrentFavorite();
};
$scope.markAsFavorite = function() {
playlistSrv.markAsFavorite();
$scope.isFavorite = true;
};
$scope.removeAsFavorite = function() {
playlistSrv.removeAsFavorite(dashboard.current);
$scope.isFavorite = false;
};
$scope.stopPlaylist = function() {
playlistSrv.stop(1);
};
}); });
}); });
define([
'angular',
'underscore'
],
function (angular, _) {
'use strict';
var module = angular.module('kibana.controllers');
module.controller('PlaylistCtrl', function($scope, playlistSrv) {
$scope.init = function() {
$scope.timespan = "15s";
$scope.loadFavorites();
$scope.$on('modal-opened', $scope.loadFavorites);
};
$scope.loadFavorites = function() {
$scope.favDashboards = playlistSrv.getFavorites().dashboards;
_.each($scope.favDashboards, function(dashboard) {
dashboard.include = true;
});
};
$scope.removeAsFavorite = function(dashboard) {
playlistSrv.removeAsFavorite(dashboard);
$scope.loadFavorites();
};
$scope.start = function() {
var included = _.where($scope.favDashboards, { include: true });
playlistSrv.start(included, $scope.timespan);
};
});
});
\ No newline at end of file
...@@ -69,7 +69,7 @@ function (angular, _, config, $) { ...@@ -69,7 +69,7 @@ function (angular, _, config, $) {
.query($scope.ejs.QueryStringQuery(query)) .query($scope.ejs.QueryStringQuery(query))
.sort('_uid') .sort('_uid')
.facet($scope.ejs.TermsFacet("tags").field("tags").order('term').size(50)) .facet($scope.ejs.TermsFacet("tags").field("tags").order('term').size(50))
.size(50).doSearch() .size(20).doSearch()
.then(function(results) { .then(function(results) {
if(_.isUndefined(results.hits)) { if(_.isUndefined(results.hits)) {
......
...@@ -25,13 +25,17 @@ function (angular, app, _) { ...@@ -25,13 +25,17 @@ function (angular, app, _) {
}, true); }, true);
$scope.$watch('dashboard.current.hideControls', function() { $scope.$watch('dashboard.current.hideControls', function() {
var hideControls = $scope.dashboard.current.hideControls; var hideControls = $scope.dashboard.current.hideControls || $scope.playlist_active;
if (lastHideControlsVal !== hideControls) { if (lastHideControlsVal !== hideControls) {
elem.toggleClass('hide-controls', hideControls); elem.toggleClass('hide-controls', hideControls);
lastHideControlsVal = hideControls; lastHideControlsVal = hideControls;
} }
});
$scope.$watch('playlist_active', function() {
elem.toggleClass('hide-controls', $scope.playlist_active === true);
elem.toggleClass('playlist-active', $scope.playlist_active === true);
}); });
} }
}; };
......
...@@ -18,6 +18,7 @@ function (angular, _, $) { ...@@ -18,6 +18,7 @@ function (angular, _, $) {
elem.bind('click',function() { elem.bind('click',function() {
if ($(id).length) { if ($(id).length) {
elem.attr('data-target', id).attr('data-toggle', 'modal'); elem.attr('data-target', id).attr('data-toggle', 'modal');
scope.$apply(function() { scope.$broadcast('modal-opened'); });
return; return;
} }
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
</ul> </ul>
</li> </li>
<li ng-show="!dashboard.current.refresh"> <li ng-show="!dashboard.current.refresh" class="grafana-menu-refresh">
<a class="icon-refresh" ng-click="dashboard.refresh()"></a> <a class="icon-refresh" ng-click="dashboard.refresh()"></a>
</li> </li>
</ul> </ul>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
</a> </a>
</li> </li>
<li> <li class="grafana-menu-zoom-out">
<a class='small' ng-click='zoom(2)'> <a class='small' ng-click='zoom(2)'>
Zoom Out Zoom Out
</a> </a>
...@@ -18,54 +18,60 @@ ...@@ -18,54 +18,60 @@
<li ng-repeat="pulldown in dashboard.current.nav" ng-controller="PulldownCtrl" ng-show="pulldown.enable"><kibana-simple-panel type="pulldown.type" ng-cloak></kibana-simple-panel></li> <li ng-repeat="pulldown in dashboard.current.nav" ng-controller="PulldownCtrl" ng-show="pulldown.enable"><kibana-simple-panel type="pulldown.type" ng-cloak></kibana-simple-panel></li>
<li class="dropdown"ng-show="showDropdown('save')"> <li class="dropdown grafana-menu-save" ng-show="showDropdown('save')">
<a href="#" bs-tooltip="'Save'" data-placement="bottom" class="dropdown-toggle" data-toggle="dropdown"> <a href="#" bs-tooltip="'Save'" data-placement="bottom" class="dropdown-toggle" data-toggle="dropdown" ng-click="openSaveDropdown()">
<i class='icon-save'></i> <i class='icon-save'></i>
</a> </a>
<ul class="dropdown-menu" style="padding:10px"> <ul class="save-dashboard-dropdown dropdown-menu">
<li ng-show="dashboard.current.loader.save_elasticsearch"> <li ng-show="dashboard.current.loader.save_elasticsearch">
<form class="input-prepend nomargin"> <form class="input-prepend nomargin save-dashboard-dropdown-save-form">
<button class="btn" ng-click="elasticsearch_save('dashboard')"><i class="icon-save"></i></button>
<input class='input-medium' ng-model="dashboard.current.title" type="text" ng-model="elasticsearch.title"/> <input class='input-medium' ng-model="dashboard.current.title" type="text" ng-model="elasticsearch.title"/>
<button class="btn" ng-click="elasticsearch_save('dashboard')"><i class="icon-save"></i></button>
</form> </form>
</li> </li>
<li class="dropdown-submenu noarrow" ng-show="dashboard.current.loader.save_local || dashboard.current.loader.save_gist || dashboard.current.loader.save_default"> <li ng-show="dashboard.current.loader.save_default">
<a tabindex="-1" class="small" style="padding:0"><i class="icon-caret-left"></i> Advanced</a> <a class="link" ng-click="set_default()">Save as Home</a>
<ul class="dropdown-menu"> </li>
<li ng-show="dashboard.current.loader.save_default">
<li ng-show="dashboard.current.loader.save_default"> <a class="link" ng-click="purge_default()">Reset Home</a>
<a class="link" ng-click="set_default()">Save as Home</a> </li>
</li> <li ng-show="!isFavorite">
<li ng-show="dashboard.current.loader.save_default"> <a class="link" ng-click="markAsFavorite()">Mark as favorite</a>
<a class="link" ng-click="purge_default()">Reset Home</a> </li>
</li> <li ng-show="isFavorite">
<li ng-show="dashboard.current.loader.save_local"> <a class="link" ng-click="removeAsFavorite()">Remove as favorite</a>
<a class="link" ng-click="dashboard.to_file()">Export schema</a> </li>
</li> <li ng-show="dashboard.current.loader.save_local">
<li ng-show="showDropdown('share')"><a bs-tooltip="'Share'" data-placement="bottom" ng-click="elasticsearch_save('temp',dashboard.current.loader.save_temp_ttl)" config-modal="app/partials/dashLoaderShare.html">Share temp copy</i></a></li> <a class="link" ng-click="dashboard.to_file()">Export schema</a>
</li>
<li ng-show="showDropdown('share')"><a bs-tooltip="'Share'" data-placement="bottom" ng-click="elasticsearch_save('temp',dashboard.current.loader.save_temp_ttl)" config-modal="app/partials/dashLoaderShare.html">Share temp copy</i></a></li>
<li ng-show="dashboard.current.loader.save_gist" style="margin:10px"> <li ng-show="dashboard.current.loader.save_gist" style="margin:10px">
<h6>Gist</h6> <h6>Gist</h6>
<form class="input-append"> <form class="input-append">
<input class='input-medium' placeholder='Title' type="text" ng-model="gist.title"/> <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> <button class="btn" ng-click="save_gist()"><i class="icon-github-alt"></i></button>
</form><br> </form><br>
<small ng-show="gist.last">Last gist: <a target="_blank" href="{{gist.last}}">{{gist.last}}</a></small> <small ng-show="gist.last">Last gist: <a target="_blank" href="{{gist.last}}">{{gist.last}}</a></small>
</li>
</ul>
</li> </li>
</ul> </ul>
</li> </li>
<li class="dropdown" ng-show="showDropdown('load')" ng-controller="SearchCtrl" ng-init="init()" ng-include="'app/partials/search.html'"> <li class="dropdown grafana-menu-load" ng-show="showDropdown('load')" ng-controller="SearchCtrl" ng-init="init()" ng-include="'app/partials/search.html'">
</li> </li>
<li><a bs-tooltip="'Goto saved default'" data-placement="bottom" href='#/dashboard'><i class='icon-home'></i></a></li> <li class="grafana-menu-home"><a bs-tooltip="'Goto saved default'" data-placement="bottom" href='#/dashboard'><i class='icon-home'></i></a></li>
<li ng-show="dashboard.current.editable" bs-tooltip="'Configure dashboard'" data-placement="bottom"><a class="link" config-modal="app/partials/dasheditor.html"><i class='icon-cog pointer'></i></a></li> <li class="grafana-menu-edit" ng-show="dashboard.current.editable" bs-tooltip="'Configure dashboard'" data-placement="bottom"><a class="link" config-modal="app/partials/dasheditor.html"><i class='icon-cog pointer'></i></a></li>
<li class="grafana-menu-stop-playlist hide">
<a class='small' ng-click='stopPlaylist(2)'>
Stop playlist
</a>
</li>
\ No newline at end of file
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
</div> </div>
</div> </div>
<div class="row-fluid" ng-show='dashboard.current.editable && dashboard.current.panel_hints'> <div ng-show='dashboard.current.editable && dashboard.current.panel_hints' class="row-fluid add-row-panel-hint">
<div class="span12" style="text-align:right;"> <div class="span12" style="text-align:right;">
<span style="margin-left: 0px;" class="pointer btn btn-mini" config-modal="app/partials/dasheditor.html"> <span style="margin-left: 0px;" class="pointer btn btn-mini" config-modal="app/partials/dasheditor.html">
<span ng-click="editor.index = 1"><i class="icon-plus-sign"></i> ADD A ROW</span> <span ng-click="editor.index = 1"><i class="icon-plus-sign"></i> ADD A ROW</span>
...@@ -76,7 +76,6 @@ ...@@ -76,7 +76,6 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
\ No newline at end of file
<div ng-controller="PlaylistCtrl" ng-init="init()">
<div class="modal-header">
<h3>Start dashboard playlist</h3>
</div>
<div class="modal-body">
<div class="editor-row">
<div class="section">
<div class="editor-option">
<table class="table table-striped span4">
<tr>
<th>Dashboard</th>
<th>Include</th>
<th style="white-space: nowrap;">Remove as favorite</th>
</tr>
<tr ng-repeat="dashboard in favDashboards">
<td style="white-space: nowrap;">
{{dashboard.title}}
</td>
<td style="text-align: center">
<input type="checkbox" ng-model="dashboard.include" ng-checked="dashboard.include" />
</td>
<td style="text-align: center">
<i class="icon-remove pointer" ng-click="removeAsFavorite(dashboard)"></i>
</td>
</tr>
<tr ng-hide="favDashboards.length">
<td colspan="3">
<i class="icon-warning"></i> No dashboards marked as favorites
</td>
</tr>
</table>
</div>
<div class="editor-option">
<div class="span4">
<span><i class="icon-question-sign"></i>
Dashboards available in the playlist are only the once marked as favorites (stored in local browser storage).
To mark a dashboard as favorite, use save icon in the menu and in the dropdown select Mark as favorite
<br/><br/>
</span>
</div>
</div>
<div class="editor-option">
<label>
Timespan between change
</label>
<input type="text" class="input-small" ng-model="timespan" />
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-success" ng-click="start();dismiss();"><i class="icon-play"></i> Start</button>
<button type="button" class="btn btn-primary" ng-click="dismiss();"><i class="icon-ban-circle"></i> Cancel</button>
</div>
</div>
\ No newline at end of file
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
<li ng-if="!showImport"> <li ng-if="!showImport">
<div class="grafana-search-panel"> <div class="grafana-search-panel">
<div class="search-field-wrapper"> <div class="search-field-wrapper">
<button class="btn btn-success pull-right" config-modal="app/partials/playlist.html">
<i class="icon-play"></i>
Playlist
</button>
<button class="btn btn-success pull-right" ng-click="toggleImport($event)"> <button class="btn btn-success pull-right" ng-click="toggleImport($event)">
<i class="icon-download-alt"></i> <i class="icon-download-alt"></i>
Import Import
...@@ -51,7 +55,6 @@ ...@@ -51,7 +55,6 @@
</a> </a>
</td> </td>
<td style="width:100%;padding-left: 10px;font-weight: bold;"> <td style="width:100%;padding-left: 10px;font-weight: bold;">
</td> </td>
</tr> </tr>
</table> </table>
......
...@@ -7,5 +7,6 @@ define([ ...@@ -7,5 +7,6 @@ define([
'./datasourceSrv', './datasourceSrv',
'./keyboardManager', './keyboardManager',
'./annotationsSrv', './annotationsSrv',
'./playlistSrv',
], ],
function () {}); function () {});
\ No newline at end of file
define([
'angular',
'underscore',
'kbn'
],
function (angular, _, kbn) {
'use strict';
var module = angular.module('kibana.services');
module.service('playlistSrv', function(dashboard, $location, $rootScope) {
var timerInstance;
var favorites = { dashboards: [] };
this.init = function() {
var existingJson = window.localStorage["grafana-favorites"];
if (existingJson) {
favorites = angular.fromJson(existingJson);
}
};
this._save = function() {
window.localStorage["grafana-favorites"] = angular.toJson(favorites);
};
this._find = function(title) {
return _.findWhere(favorites.dashboards, { title: title });
};
this._remove = function(existing) {
if (existing) {
favorites.dashboards = _.without(favorites.dashboards, existing);
}
};
this.isCurrentFavorite = function() {
return this._find(dashboard.current.title) ? true : false;
};
this.markAsFavorite = function() {
var existing = this._find(dashboard.current.title);
this._remove(existing);
favorites.dashboards.push({
url: $location.path(),
title: dashboard.current.title
});
this._save();
};
this.removeAsFavorite = function(toRemove) {
var existing = this._find(toRemove.title);
this._remove(existing);
this._save();
};
this.getFavorites = function() {
return favorites;
};
this.start = function(dashboards, timespan) {
var interval = kbn.interval_to_ms(timespan);
var index = 0;
$rootScope.playlist_active = true;
timerInstance = setInterval(function() {
$rootScope.$apply(function() {
$location.path(dashboards[index % dashboards.length].url);
index++;
});
}, interval);
};
this.stop = function() {
clearInterval(timerInstance);
$rootScope.playlist_active = false;
};
this.init();
});
});
\ No newline at end of file
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.
...@@ -9,6 +9,25 @@ ...@@ -9,6 +9,25 @@
.submenu-controls { .submenu-controls {
display: none; display: none;
} }
.add-row-panel-hint {
display: none;
}
}
.playlist-active {
.grafana-menu-zoom-out,
.grafana-menu-save,
.grafana-menu-load,
.add-row-panel-hint,
.grafana-menu-home,
.grafana-menu-refresh,
.grafana-menu-edit {
display: none;
}
.grafana-menu-stop-playlist {
display: list-item;
}
} }
// Search // Search
...@@ -47,7 +66,7 @@ ...@@ -47,7 +66,7 @@
.search-tagview-switch { .search-tagview-switch {
position: absolute; position: absolute;
top: 15px; top: 15px;
right: 180px; right: 263px;
color: darken(@linkColor, 30%); color: darken(@linkColor, 30%);
&.active { &.active {
color: @linkColor; color: @linkColor;
......
...@@ -571,3 +571,15 @@ div.flot-text { ...@@ -571,3 +571,15 @@ div.flot-text {
} }
} }
// Top menu
.save-dashboard-dropdown {
padding: 10px;
li>a {
padding-left: 5px;
}
}
.save-dashboard-dropdown-save-form {
margin-bottom: 5px;
}
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