mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Custom snapshot topnav header, new custom dashboard snapshot icon, #1623
This commit is contained in:
@@ -65,7 +65,11 @@ func GetDashboardSnapshot(c *middleware.Context) {
|
||||
|
||||
dto := dtos.Dashboard{
|
||||
Model: snapshot.Dashboard,
|
||||
Meta: dtos.DashboardMeta{IsSnapshot: true},
|
||||
Meta: dtos.DashboardMeta{
|
||||
IsSnapshot: true,
|
||||
Created: snapshot.Created,
|
||||
Expires: snapshot.Expires,
|
||||
},
|
||||
}
|
||||
|
||||
metrics.M_Api_Dashboard_Snapshot_Get.Inc(1)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
@@ -31,6 +32,8 @@ type DashboardMeta struct {
|
||||
IsHome bool `json:"isHome"`
|
||||
IsSnapshot bool `json:"isSnapshot"`
|
||||
Slug string `json:"slug"`
|
||||
Expires time.Time `json:"expires"`
|
||||
Created time.Time `json:"created"`
|
||||
}
|
||||
|
||||
type Dashboard struct {
|
||||
|
||||
@@ -25,7 +25,7 @@ function (angular) {
|
||||
'<i class="fa fa-bars"></i>' +
|
||||
'</a>' +
|
||||
|
||||
'<span class="icon-circle top-nav-icon"">' +
|
||||
'<span class="icon-circle top-nav-icon">' +
|
||||
'<i ng-class="icon"></i>' +
|
||||
'</span>' +
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
define([
|
||||
'./dashboardCtrl',
|
||||
'./dashboardNavCtrl',
|
||||
'./snapshotTopNavCtrl',
|
||||
'./saveDashboardAsCtrl',
|
||||
'./playlistCtrl',
|
||||
'./rowCtrl',
|
||||
|
||||
@@ -21,6 +21,7 @@ function (angular, $, config) {
|
||||
$timeout) {
|
||||
|
||||
$scope.editor = { index: 0 };
|
||||
$scope.topNavPartial = 'app/features/dashboard/partials/dashboardTopNav.html';
|
||||
$scope.panels = config.panels;
|
||||
|
||||
var resizeEventTimeout;
|
||||
@@ -76,10 +77,7 @@ function (angular, $, config) {
|
||||
}
|
||||
|
||||
if (dashboard.snapshot) {
|
||||
meta.canEdit = false;
|
||||
meta.canSave = false;
|
||||
meta.canStar = false;
|
||||
meta.canShare = false;
|
||||
$scope.topNavPartial = 'app/features/dashboard/partials/snapshotTopNav.html';
|
||||
}
|
||||
|
||||
$scope.dashboardMeta = meta;
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
define([
|
||||
'angular',
|
||||
'lodash',
|
||||
'moment',
|
||||
'config',
|
||||
'store',
|
||||
'filesaver'
|
||||
],
|
||||
function (angular, _, moment) {
|
||||
function (angular, _) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.controllers');
|
||||
|
||||
module.controller('DashboardNavCtrl', function($scope, $rootScope, alertSrv, $location, playlistSrv, backendSrv, timeSrv, $timeout) {
|
||||
module.controller('DashboardNavCtrl', function($scope, $rootScope, alertSrv, $location, playlistSrv, backendSrv, $timeout) {
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.onAppEvent('save-dashboard', $scope.saveDashboard);
|
||||
$scope.onAppEvent('delete-dashboard', $scope.deleteDashboard);
|
||||
|
||||
$scope.onAppEvent('zoom-out', function() {
|
||||
$scope.zoom(2);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openEditView = function(editview) {
|
||||
@@ -136,27 +131,6 @@ function (angular, _, moment) {
|
||||
window.saveAs(blob, $scope.dashboard.title + '-' + new Date().getTime());
|
||||
};
|
||||
|
||||
$scope.zoom = function(factor) {
|
||||
var range = timeSrv.timeRange();
|
||||
|
||||
var timespan = (range.to.valueOf() - range.from.valueOf());
|
||||
var center = range.to.valueOf() - timespan/2;
|
||||
|
||||
var to = (center + (timespan*factor)/2);
|
||||
var from = (center - (timespan*factor)/2);
|
||||
|
||||
if(to > Date.now() && range.to <= Date.now()) {
|
||||
var offset = to - Date.now();
|
||||
from = from - offset;
|
||||
to = Date.now();
|
||||
}
|
||||
|
||||
timeSrv.setTime({
|
||||
from: moment.utc(from).toDate(),
|
||||
to: moment.utc(to).toDate(),
|
||||
});
|
||||
};
|
||||
|
||||
$scope.snapshot = function() {
|
||||
$scope.dashboard.snapshot = true;
|
||||
$rootScope.$broadcast('refresh');
|
||||
|
||||
@@ -47,8 +47,12 @@
|
||||
|
||||
<div class="gf-box-body share-snapshot ng-cloak" ng-cloak ng-if="editor.index === 1" ng-controller="ShareSnapshotCtrl">
|
||||
|
||||
<div class="share-snapshot-header" ng-if="step === 1">
|
||||
<div style="margin: 10px 0">
|
||||
<i ng-if="loading" class="fa fa-spinner fa-spin"></i>
|
||||
<i ng-if="!loading" class="gf-icon gf-icon-snapshot"></i>
|
||||
</div>
|
||||
|
||||
<div class="share-snapshot-header" ng-if="step === 1">
|
||||
<p class="share-snapshot-info-text">
|
||||
A snapshot is an instant way to share an interactive dashboard publicly.
|
||||
When created, we <strong>strip sensitive data</strong> like queries (metric, template and annotation) and panel links,
|
||||
@@ -86,7 +90,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-if="step === 2" style="margin-top: 55px">
|
||||
<div class="gf-form" ng-if="step === 2" style="margin-top: 40px">
|
||||
<div class="gf-form-row">
|
||||
<a href="{{snapshotUrl}}" class="large share-snapshot-link" target="_blank">
|
||||
<i class="fa fa-external-link-square"></i>
|
||||
|
||||
31
src/app/features/dashboard/partials/snapshotTopNav.html
Normal file
31
src/app/features/dashboard/partials/snapshotTopNav.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<div class="navbar navbar-static-top" ng-controller='SnapshotTopNavCtrl' ng-init="init()">
|
||||
<div class="navbar-inner">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="top-nav">
|
||||
<a class="pointer top-nav-menu-btn" ng-if="!contextSrv.sidemenu" ng-click="contextSrv.toggleSideMenu()">
|
||||
<img class="logo-icon" src="img/fav32.png"></img>
|
||||
<i class="fa fa-bars"></i>
|
||||
</a>
|
||||
|
||||
<div class="top-nav-snapshot-title">
|
||||
<a class="pointer" bs-tooltip="titleTooltip" data-placement="bottom">
|
||||
<i class="gf-icon gf-icon-snapshot"></i>
|
||||
<span class="dashboard-title">
|
||||
{{dashboard.title}}
|
||||
<em class="small"> (snapshot)</em>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav pull-right">
|
||||
<li ng-repeat="pulldown in dashboard.nav" ng-controller="PulldownCtrl" ng-show="pulldown.enable">
|
||||
<grafana-simple-panel type="pulldown.type" ng-cloak>
|
||||
</grafana-simple-panel>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
22
src/app/features/dashboard/snapshotTopNavCtrl.js
Normal file
22
src/app/features/dashboard/snapshotTopNavCtrl.js
Normal file
@@ -0,0 +1,22 @@
|
||||
define([
|
||||
'angular',
|
||||
'moment',
|
||||
],
|
||||
function (angular, moment) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.controllers');
|
||||
|
||||
module.controller('SnapshotTopNavCtrl', function($scope) {
|
||||
|
||||
$scope.init = function() {
|
||||
var meta = $scope.dashboardMeta;
|
||||
$scope.titleTooltip = 'Created: ' + moment(meta.created).calendar();
|
||||
if (meta.expires) {
|
||||
$scope.titleTooltip += '<br>Expires: ' + moment(meta.expires).fromNow() + '<br>';
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -66,6 +66,10 @@ function (angular, app, _, moment, kbn) {
|
||||
}
|
||||
|
||||
$scope.time = getScopeTimeObj(time.from, time.to);
|
||||
|
||||
$scope.onAppEvent('zoom-out', function() {
|
||||
$scope.zoom(2);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.customTime = function() {
|
||||
@@ -213,5 +217,26 @@ function (angular, app, _, moment, kbn) {
|
||||
return moment(new Date(date.getTime() + date.getTimezoneOffset() * 60000)).toDate();
|
||||
};
|
||||
|
||||
$scope.zoom = function(factor) {
|
||||
var range = timeSrv.timeRange();
|
||||
|
||||
var timespan = (range.to.valueOf() - range.from.valueOf());
|
||||
var center = range.to.valueOf() - timespan/2;
|
||||
|
||||
var to = (center + (timespan*factor)/2);
|
||||
var from = (center - (timespan*factor)/2);
|
||||
|
||||
if(to > Date.now() && range.to <= Date.now()) {
|
||||
var offset = to - Date.now();
|
||||
from = from - offset;
|
||||
to = Date.now();
|
||||
}
|
||||
|
||||
timeSrv.setTime({
|
||||
from: moment.utc(from).toDate(),
|
||||
to: moment.utc(to).toDate(),
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<div body-class class="dashboard" ng-class="{'dashboard-fullscreen': dashboardViewState.fullscreen}">
|
||||
|
||||
<div ng-include="'app/partials/dashboard_topnav.html'">
|
||||
<div ng-include src="topNavPartial">
|
||||
</div>
|
||||
|
||||
|
||||
<div dash-editor-view></div>
|
||||
<div dash-search-view></div>
|
||||
|
||||
<div ng-if="submenuEnabled" ng-include="'app/partials/submenu.html'">
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div class="main-view-container">
|
||||
|
||||
22
src/css/less/fonts.less
Normal file
22
src/css/less/fonts.less
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
@font-face {
|
||||
font-family: 'raintank';
|
||||
src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SAyoAAAC8AAAAYGNtYXAaVcxXAAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5Zjk9uEcAAAFwAAACLGhlYWQFNCNwAAADnAAAADZoaGVhB14DxgAAA9QAAAAkaG10eAWdAAAAAAP4AAAAFGxvY2EAKAEqAAAEDAAAAAxtYXhwABUAvAAABBgAAAAgbmFtZflvA+cAAAQ4AAABTnBvc3QAAwAAAAAFiAAAACAAAwQAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADmAAPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIOYA//3//wAAAAAAIOYA//3//wAB/+MaBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAADwAA/7YDnAO3AAMAHQAhACUAKgAuADEAQgBTAGQAdQCGAJcAqAC5AAA3FyUnJTUTJzUjJwcjJwcjFQcTBxcVIQ0BNzM1NycTAxEXJTkCByERIREHFSc3NzEzAxQWOwEyNj0BNCYrASIGHQE3MzIWHQEUBisBIiY9ATQ2MxcVFBY7ATI2PQE0JisBIgYVMxUUBisBIiY9ATQ2OwE2FhUHNCYrASIGHQEUFjsBMjY9AQc1NDY7ATIWHQEUBisBIiY1BTMyNj0BNCYrASIGHQEUFjM3FRQGKwEiJj0BNDY7ATYWFXsKAS9VAbOKkFsDmDvbEZhXTjY/Alj+wQFGGT4mIU5TU/3CmgJU/awxICDLAWUbE40TGxsTjRMbLo0LERELjQwQEAzQHBONExsbE40UG9cQC40MEBAMjQsQ7BsTjRMbGxONExvXEAuNDBAQDIwMEAEbjRMbGxONFBsbFKgQC40MEBAMjQsQDkMvFvQEAfYoVRcXPDxGDf4JwhFKBFpdHAbPAdn+zwFIF54x/ZsCZUbPygV3/s4TGxsTjBQbHBOMqRAMjQsQEAuMDBEdjBQbHBOMFBsbFIwMEBAMjAwQAREM+RQbHBONExscEo2MjAwQEAyNCxARCy4bE4wUGxwTjRIbuo0LEBALjQwQAREMAAEAAAABAABhLqkRXw889QALBAAAAAAA0TxvgwAAAADRPG+DAAD/tgOcA7cAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAAA5wAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAACAAAAA50AAAAAAAAACgAUAB4BFgABAAAABQC6AA8AAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEAEAAAAAEAAAAAAAIADgBOAAEAAAAAAAMAEAAmAAEAAAAAAAQAEABcAAEAAAAAAAUAFgAQAAEAAAAAAAYACAA2AAEAAAAAAAoANABsAAMAAQQJAAEAEAAAAAMAAQQJAAIADgBOAAMAAQQJAAMAEAAmAAMAAQQJAAQAEABcAAMAAQQJAAUAFgAQAAMAAQQJAAYAEAA+AAMAAQQJAAoANABsAHIAYQBpAG4AdABhAG4AawBWAGUAcgBzAGkAbwBuACAAMQAuADAAcgBhAGkAbgB0AGEAbgBrcmFpbnRhbmsAcgBhAGkAbgB0AGEAbgBrAFIAZQBnAHUAbABhAHIAcgBhAGkAbgB0AGEAbgBrAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('truetype'),
|
||||
url(data:application/font-woff;charset=utf-8;base64,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) format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.gf-icon {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 'raintank';
|
||||
font-size: inherit;
|
||||
text-rendering: auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.gf-icon-snapshot:before {
|
||||
content: "\e600";
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
@import "dashlist.less";
|
||||
@import "admin.less";
|
||||
@import "validation.less";
|
||||
@import "fonts.less";
|
||||
|
||||
.row-control-inner {
|
||||
padding:0px;
|
||||
@@ -298,6 +299,14 @@
|
||||
.share-snapshot {
|
||||
text-align: center;
|
||||
|
||||
.gf-icon-snapshot {
|
||||
font-size: 70px;
|
||||
}
|
||||
|
||||
.fa-spinner {
|
||||
font-size: 70px;
|
||||
}
|
||||
|
||||
.share-snapshot-info-text {
|
||||
margin: 10px 105px;
|
||||
strong {
|
||||
@@ -307,16 +316,6 @@
|
||||
}
|
||||
|
||||
.share-snapshot-header {
|
||||
.fa-spinner {
|
||||
position: absolute;
|
||||
font-size: 600%;
|
||||
left: 44%;
|
||||
color: @grafanaTargetFuncBackground;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
margin: 20px 0 22px 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,13 +90,13 @@
|
||||
position: relative;
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
padding: 0px 6px 5px 5px;
|
||||
color: @linkColorHover;
|
||||
font-size: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
.top-nav-icon {
|
||||
margin: 5px 0px 0 11px;
|
||||
@@ -122,3 +122,19 @@
|
||||
color: @linkColor;
|
||||
}
|
||||
|
||||
.top-nav-snapshot-title {
|
||||
.gf-icon {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 3px 15px 5px 10px;
|
||||
}
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 1.4em;
|
||||
margin: 9px 18px 5px 14px;
|
||||
color: @linkColor;
|
||||
}
|
||||
|
||||
|
||||
1
src/vendor/css/font-awesome.min.css
vendored
1
src/vendor/css/font-awesome.min.css
vendored
@@ -11,6 +11,7 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome;
|
||||
|
||||
Reference in New Issue
Block a user