Commit 8e9a0edd by Torkel Ödegaard

Custom snapshot topnav header, new custom dashboard snapshot icon, #1623

parent 80c771c9
......@@ -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"
)
......@@ -27,10 +28,12 @@ type CurrentUser struct {
}
type DashboardMeta struct {
IsStarred bool `json:"isStarred"`
IsHome bool `json:"isHome"`
IsSnapshot bool `json:"isSnapshot"`
Slug string `json:"slug"`
IsStarred bool `json:"isStarred"`
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>' +
......
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;
......
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>
......
<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">&nbsp;&nbsp;(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>
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: &nbsp;' + moment(meta.created).calendar();
if (meta.expires) {
$scope.titleTooltip += '<br>Expires: &nbsp;' + 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(),
});
};
});
});
<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">
......
@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,12 +90,12 @@
position: relative;
top: 4px;
}
}
.dashboard-title {
padding: 0px 6px 5px 5px;
color: @linkColorHover;
font-size: 17px;
}
.dashboard-title {
padding: 0px 6px 5px 5px;
color: @linkColorHover;
font-size: 17px;
}
.top-nav-icon {
......@@ -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;
}
......@@ -11,6 +11,7 @@
font-weight: normal;
font-style: normal;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
......
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