mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
New TV Mode, dashboard toolbar update (layout change & new cycle view mode button) (#13025)
* wip: design update for navbar with kiosk mode button * feat: progress on new view mode button * css: view state refactorings * feat: kiosk modes & playlist support * feature: cycle tv mode feature, renamed view modes to TV, and Kiosk * fix: updated the alert notification message * fix: removed unused parameter * fix: correct the css class set for tv mode * some minor improvements to playlist
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container page-body" ng-form="playlistEditForm">
|
||||
<div class="page-container page-body" ng-form="ctrl.playlistEditForm">
|
||||
|
||||
<h3 class="page-sub-heading" ng-hide="ctrl.isNew">Edit Playlist</h3>
|
||||
<h3 class="page-sub-heading" ng-show="ctrl.isNew">New Playlist</h3>
|
||||
<h3 class="page-sub-heading" ng-hide="ctrl.isNew">Edit Playlist</h3>
|
||||
<h3 class="page-sub-heading" ng-show="ctrl.isNew">New Playlist</h3>
|
||||
|
||||
<p class="playlist-description">A playlist rotates through a pre-selected list of Dashboards. A Playlist can be a great way to build situational awareness, or just show off your metrics to your team or visitors.</p>
|
||||
|
||||
@@ -20,79 +20,71 @@
|
||||
|
||||
<div class="gf-form-group">
|
||||
<h3 class="page-headering">Dashboards</h3>
|
||||
|
||||
<table class="filter-table playlist-available-list">
|
||||
<tr ng-repeat="playlistItem in ctrl.playlistItems">
|
||||
<td ng-if="playlistItem.type === 'dashboard_by_id'">
|
||||
<i class="icon-gf icon-gf-dashboard"></i> {{playlistItem.title}}
|
||||
</td>
|
||||
<td ng-if="playlistItem.type === 'dashboard_by_tag'">
|
||||
<a class="search-result-tag label label-tag" tag-color-from-name="playlistItem.title">
|
||||
<i class="fa fa-tag"></i>
|
||||
<span>{{playlistItem.title}}</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td class="selected-playlistitem-settings">
|
||||
<button class="btn btn-inverse btn-mini" ng-hide="$first" ng-click="ctrl.movePlaylistItemUp(playlistItem)">
|
||||
<i class="fa fa-arrow-up"></i>
|
||||
</button>
|
||||
<button class="btn btn-inverse btn-mini" ng-hide="$last" ng-click="ctrl.movePlaylistItemDown(playlistItem)">
|
||||
<i class="fa fa-arrow-down"></i>
|
||||
</button>
|
||||
<button class="btn btn-inverse btn-mini" ng-click="ctrl.removePlaylistItem(playlistItem)">
|
||||
<i class="fa fa-remove"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="ctrl.playlistItems.length === 0">
|
||||
<td><em>Playlist is empty, add dashboards below.</em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="playlist-search-containerwrapper">
|
||||
<div class="max-width-32">
|
||||
<h5 class="page-headering playlist-column-header">Available</h5>
|
||||
<div style="">
|
||||
<playlist-search class="playlist-search-container" search-started="ctrl.searchStarted(promise)"></playlist-search>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-group">
|
||||
<h3 class="page-headering">Add dashboards</h3>
|
||||
<playlist-search class="playlist-search-container" search-started="ctrl.searchStarted(promise)"></playlist-search>
|
||||
|
||||
<div ng-if="ctrl.filteredDashboards.length > 0">
|
||||
<table class="filter-table playlist-available-list">
|
||||
<tr ng-repeat="playlistItem in ctrl.filteredDashboards">
|
||||
<td>
|
||||
<i class="icon-gf icon-gf-dashboard"></i>
|
||||
{{playlistItem.title}}
|
||||
<i class="fa fa-star" ng-show="playlistItem.isStarred"></i>
|
||||
</td>
|
||||
<td class="add-dashboard">
|
||||
<button class="btn btn-inverse btn-mini pull-right" ng-click="ctrl.addPlaylistItem(playlistItem)">
|
||||
<i class="fa fa-plus"></i>
|
||||
Add to playlist
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="playlist-search-results-container" ng-if="ctrl.filteredTags.length > 0;">
|
||||
<table class="filter-table playlist-available-list">
|
||||
<tr ng-repeat="tag in ctrl.filteredTags">
|
||||
<td>
|
||||
<a class="search-result-tag label label-tag" tag-color-from-name="tag.term">
|
||||
<i class="fa fa-tag"></i>
|
||||
<span>{{tag.term}} ({{tag.count}})</span>
|
||||
</a>
|
||||
</td>
|
||||
<td class="add-dashboard">
|
||||
<button class="btn btn-inverse btn-mini pull-right" ng-click="ctrl.addTagPlaylistItem(tag)">
|
||||
<i class="fa fa-plus"></i>
|
||||
Add to playlist
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<h5 class="page headering playlist-column-header">Selected</h5>
|
||||
<div ng-if="ctrl.filteredDashboards.length > 0">
|
||||
<table class="filter-table playlist-available-list">
|
||||
<tr ng-repeat="playlistItem in ctrl.playlistItems">
|
||||
<td ng-if="playlistItem.type === 'dashboard_by_id'">
|
||||
<i class="icon-gf icon-gf-dashboard"></i> {{playlistItem.title}}
|
||||
<tr ng-repeat="playlistItem in ctrl.filteredDashboards">
|
||||
<td>
|
||||
<i class="icon-gf icon-gf-dashboard"></i>
|
||||
{{playlistItem.title}}
|
||||
<i class="fa fa-star" ng-show="playlistItem.isStarred"></i>
|
||||
</td>
|
||||
<td ng-if="playlistItem.type === 'dashboard_by_tag'">
|
||||
<a class="search-result-tag label label-tag" tag-color-from-name="playlistItem.title">
|
||||
<td class="add-dashboard">
|
||||
<button class="btn btn-inverse btn-mini pull-right" ng-click="ctrl.addPlaylistItem(playlistItem)">
|
||||
<i class="fa fa-plus"></i>
|
||||
Add to playlist
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="playlist-search-results-container" ng-if="ctrl.filteredTags.length > 0;">
|
||||
<table class="filter-table playlist-available-list">
|
||||
<tr ng-repeat="tag in ctrl.filteredTags">
|
||||
<td>
|
||||
<a class="search-result-tag label label-tag" tag-color-from-name="tag.term">
|
||||
<i class="fa fa-tag"></i>
|
||||
<span>{{playlistItem.title}}</span>
|
||||
<span>{{tag.term}} ({{tag.count}})</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td class="selected-playlistitem-settings">
|
||||
<button class="btn btn-inverse btn-mini" ng-hide="$first" ng-click="ctrl.movePlaylistItemUp(playlistItem)">
|
||||
<i class="fa fa-arrow-up"></i>
|
||||
</button>
|
||||
<button class="btn btn-inverse btn-mini" ng-hide="$last" ng-click="ctrl.movePlaylistItemDown(playlistItem)">
|
||||
<i class="fa fa-arrow-down"></i>
|
||||
</button>
|
||||
<button class="btn btn-inverse btn-mini" ng-click="ctrl.removePlaylistItem(playlistItem)">
|
||||
<i class="fa fa-remove"></i>
|
||||
<td class="add-dashboard">
|
||||
<button class="btn btn-inverse btn-mini pull-right" ng-click="ctrl.addTagPlaylistItem(tag)">
|
||||
<i class="fa fa-plus"></i>
|
||||
Add to playlist
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -103,12 +95,8 @@
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div class="gf-form-button-row">
|
||||
<a class="btn btn-success " ng-show="ctrl.isNew"
|
||||
ng-disabled="ctrl.playlistEditForm.$invalid || ctrl.isPlaylistEmpty()"
|
||||
ng-click="ctrl.savePlaylist(ctrl.playlist, ctrl.playlistItems)">Create new playlist</a>
|
||||
<a class="btn btn-success" ng-show="!ctrl.isNew()"
|
||||
ng-disabled="ctrl.playlistEditForm.$invalid || ctrl.isPlaylistEmpty()"
|
||||
ng-click="ctrl.savePlaylist(ctrl.playlist, ctrl.playlistItems)">Save</a>
|
||||
<a class="btn btn-success" ng-show="ctrl.isNew" ng-disabled="ctrl.playlistEditForm.$invalid || ctrl.isPlaylistEmpty()" ng-click="ctrl.savePlaylist(ctrl.playlist, ctrl.playlistItems)">Create</a>
|
||||
<a class="btn btn-success" ng-show="!ctrl.isNew" ng-disabled="ctrl.playlistEditForm.$invalid || ctrl.isPlaylistEmpty()" ng-click="ctrl.savePlaylist(ctrl.playlist, ctrl.playlistItems)">Save</a>
|
||||
<a class="btn-text" ng-click="ctrl.backToList()">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,38 +10,42 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<table class="filter-table">
|
||||
<table class="filter-table filter-table--hover">
|
||||
<thead>
|
||||
<th>
|
||||
<strong>Name</strong>
|
||||
</th>
|
||||
<th>
|
||||
<strong>Start url</strong>
|
||||
</th>
|
||||
<th><strong>Name</strong></th>
|
||||
<th style="width: 100px"></th>
|
||||
<th style="width: 78px"></th>
|
||||
<th style="width: 78px"></th>
|
||||
<th style="width: 25px"></th>
|
||||
</thead>
|
||||
<tr ng-repeat="playlist in ctrl.playlists">
|
||||
<td>
|
||||
<td class="link-td">
|
||||
<a href="playlists/edit/{{playlist.id}}">{{playlist.name}}</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="playlists/play/{{playlist.id}}">playlists/play/{{playlist.id}}</a>
|
||||
<td class="dropdown">
|
||||
<button class="btn btn-inverse btn-small" data-toggle="dropdown">
|
||||
Start playlist
|
||||
<i class="fa fa-caret-down"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li>
|
||||
<a href="{{playlist.startUrl}}">
|
||||
<i class="fa fa-play"></i> In Normal mode</span>
|
||||
</a>
|
||||
<a href="{{playlist.startUrl}}?kiosk=tv">
|
||||
<i class="fa fa-play"></i> In TV mode</span>
|
||||
</a>
|
||||
<a href="{{playlist.startUrl}}?kiosk=tv&autofitpanels">
|
||||
<i class="fa fa-play"></i> In TV mode <span class="muted">(with auto fit panels)</span>
|
||||
</a>
|
||||
<a href="{{playlist.startUrl}}?kiosk">
|
||||
<i class="fa fa-play"></i> In Kiosk mode</span>
|
||||
</a>
|
||||
<a ng-href="{{playlist.startUrl}}?kiosk&autofitpanels">
|
||||
<i class="fa fa-play"></i> In Kiosk mode <span class="muted">(with auto fit panels)</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="playlists/play/{{playlist.id}}" class="btn btn-inverse btn-small">
|
||||
<i class="fa fa-play"></i>
|
||||
Play
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a href="playlists/edit/{{playlist.id}}" class="btn btn-inverse btn-small">
|
||||
<i class="fa fa-edit"></i>
|
||||
Edit
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<td class="text-right">
|
||||
<a ng-click="ctrl.removePlaylist(playlist)" class="btn btn-danger btn-small">
|
||||
<i class="fa fa-remove"></i>
|
||||
</a>
|
||||
@@ -49,18 +53,16 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.playlists.length === 0">
|
||||
<empty-list-cta model="{
|
||||
title: 'There are no playlists created yet',
|
||||
buttonIcon: 'fa fa-plus',
|
||||
buttonLink: 'playlists/create',
|
||||
buttonTitle: ' Create Playlist',
|
||||
proTip: 'You can run the playlist in Kiosk Mode.',
|
||||
proTip: 'You can use playlists to remove control TVs',
|
||||
proTipLink: 'http://docs.grafana.org/reference/playlist/',
|
||||
proTipLinkTitle: 'Learn more',
|
||||
proTipTarget: '_blank'
|
||||
}" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -19,29 +19,18 @@ export class PlaylistEditCtrl {
|
||||
/** @ngInject */
|
||||
constructor(private $scope, private backendSrv, private $location, $route, navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'playlists', 0);
|
||||
this.isNew = $route.current.params.id;
|
||||
this.isNew = !$route.current.params.id;
|
||||
|
||||
if ($route.current.params.id) {
|
||||
const playlistId = $route.current.params.id;
|
||||
|
||||
backendSrv.get('/api/playlists/' + playlistId).then(result => {
|
||||
this.playlist = result;
|
||||
this.navModel.node = {
|
||||
text: result.name,
|
||||
icon: this.navModel.node.icon,
|
||||
};
|
||||
this.navModel.breadcrumbs.push(this.navModel.node);
|
||||
});
|
||||
|
||||
backendSrv.get('/api/playlists/' + playlistId + '/items').then(result => {
|
||||
this.playlistItems = result;
|
||||
});
|
||||
} else {
|
||||
this.navModel.node = {
|
||||
text: 'New playlist',
|
||||
icon: this.navModel.node.icon,
|
||||
};
|
||||
this.navModel.breadcrumbs.push(this.navModel.node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@ function grafanaRoutes($routeProvider) {
|
||||
controller: 'PlaylistEditCtrl',
|
||||
})
|
||||
.when('/playlists/play/:id', {
|
||||
templateUrl: 'public/app/features/playlist/partials/playlists.html',
|
||||
controllerAs: 'ctrl',
|
||||
controller: 'PlaylistsCtrl',
|
||||
template: '',
|
||||
resolve: {
|
||||
init: function(playlistSrv, $route) {
|
||||
const playlistId = $route.current.params.id;
|
||||
|
||||
@@ -8,7 +8,7 @@ export class PlaylistSearchCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor($timeout, private backendSrv) {
|
||||
this.query = { query: '', tag: [], starred: false, limit: 30 };
|
||||
this.query = { query: '', tag: [], starred: false, limit: 20 };
|
||||
|
||||
$timeout(() => {
|
||||
this.query.query = '';
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import coreModule from '../../core/core_module';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import _ from 'lodash';
|
||||
import { toUrlParams } from 'app/core/utils/url';
|
||||
|
||||
class PlaylistSrv {
|
||||
private cancelPromise: any;
|
||||
@@ -11,42 +13,27 @@ class PlaylistSrv {
|
||||
public isPlaying: boolean;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $location: any, private $timeout: any, private backendSrv: any, private $routeParams: any) {}
|
||||
constructor(private $location: any, private $timeout: any, private backendSrv: any) {}
|
||||
|
||||
next() {
|
||||
this.$timeout.cancel(this.cancelPromise);
|
||||
|
||||
const playedAllDashboards = this.index > this.dashboards.length - 1;
|
||||
|
||||
if (playedAllDashboards) {
|
||||
window.location.href = this.getUrlWithKioskMode();
|
||||
window.location.href = this.startUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
const dash = this.dashboards[this.index];
|
||||
this.$location.url('dashboard/' + dash.uri);
|
||||
const queryParams = this.$location.search();
|
||||
const filteredParams = _.pickBy(queryParams, value => value !== null);
|
||||
|
||||
this.$location.url('dashboard/' + dash.uri + '?' + toUrlParams(filteredParams));
|
||||
|
||||
this.index++;
|
||||
this.cancelPromise = this.$timeout(() => this.next(), this.interval);
|
||||
}
|
||||
|
||||
getUrlWithKioskMode() {
|
||||
const inKioskMode = document.body.classList.contains('page-kiosk-mode');
|
||||
|
||||
// check if should add kiosk query param
|
||||
if (inKioskMode && this.startUrl.indexOf('kiosk') === -1) {
|
||||
return this.startUrl + '?kiosk=true';
|
||||
}
|
||||
|
||||
// check if should remove kiosk query param
|
||||
if (!inKioskMode) {
|
||||
return this.startUrl.split('?')[0];
|
||||
}
|
||||
|
||||
// already has kiosk query param, just return startUrl
|
||||
return this.startUrl;
|
||||
}
|
||||
|
||||
prev() {
|
||||
this.index = Math.max(this.index - 2, 0);
|
||||
this.next();
|
||||
@@ -59,10 +46,6 @@ class PlaylistSrv {
|
||||
this.index = 0;
|
||||
this.isPlaying = true;
|
||||
|
||||
if (this.$routeParams.kiosk) {
|
||||
appEvents.emit('toggle-kiosk-mode');
|
||||
}
|
||||
|
||||
this.backendSrv.get(`/api/playlists/${playlistId}`).then(playlist => {
|
||||
this.backendSrv.get(`/api/playlists/${playlistId}/dashboards`).then(dashboards => {
|
||||
this.dashboards = dashboards;
|
||||
@@ -73,6 +56,13 @@ class PlaylistSrv {
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.isPlaying) {
|
||||
const queryParams = this.$location.search();
|
||||
if (queryParams.kiosk) {
|
||||
appEvents.emit('toggle-kiosk-mode', { exit: true });
|
||||
}
|
||||
}
|
||||
|
||||
this.index = 0;
|
||||
this.isPlaying = false;
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ export class PlaylistsCtrl {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'playlists', 0);
|
||||
|
||||
backendSrv.get('/api/playlists').then(result => {
|
||||
this.playlists = result;
|
||||
this.playlists = result.map(item => {
|
||||
item.startUrl = `playlists/play/${item.id}`;
|
||||
return item;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user