dashboard acl modal

pull/9488/head
Torkel Ödegaard 8 years ago
parent cb8b5c0d42
commit 3edd209736
  1. 6
      public/app/core/components/navbar/navbar.html
  2. 20
      public/app/core/directives/dash_edit_link.js
  3. 8
      public/app/core/nav_model_srv.ts
  4. 197
      public/app/features/dashboard/acl/acl.html
  5. 60
      public/app/features/dashboard/acl/acl.ts
  6. 135
      public/app/features/dashboard/dashnav/dashnav.html
  7. 11
      public/app/features/dashboard/dashnav/dashnav.ts
  8. 1
      public/app/features/dashboard/import/dash_import.html

@ -8,9 +8,9 @@
<i class="fa fa-chevron-left"></i> <i class="fa fa-chevron-left"></i>
</a> </a>
<!-- <a class="navbar&#45;page&#45;btn navbar&#45;page&#45;btn&#45;&#45;search" ng&#45;click="ctrl.showSearch()"> --> <a class="navbar-page-btn navbar-page-btn--search" ng-click="ctrl.showSearch()">
<!-- <i class="fa fa&#45;search"></i> --> <i class="fa fa-search"></i>
<!-- </a> --> </a>
<div ng-if="::!ctrl.hasMenu"> <div ng-if="::!ctrl.hasMenu">
<a href="{{::ctrl.section.url}}" class="navbar-page-btn"> <a href="{{::ctrl.section.url}}" class="navbar-page-btn">

@ -2,8 +2,9 @@ define([
'jquery', 'jquery',
'angular', 'angular',
'../core_module', '../core_module',
'lodash',
], ],
function ($, angular, coreModule) { function ($, angular, coreModule, _) {
'use strict'; 'use strict';
var editViewMap = { var editViewMap = {
@ -12,7 +13,8 @@ function ($, angular, coreModule) {
'templating': { src: 'public/app/features/templating/partials/editor.html'}, 'templating': { src: 'public/app/features/templating/partials/editor.html'},
'history': { html: '<gf-dashboard-history dashboard="dashboard"></gf-dashboard-history>'}, 'history': { html: '<gf-dashboard-history dashboard="dashboard"></gf-dashboard-history>'},
'timepicker': { src: 'public/app/features/dashboard/timepicker/dropdown.html' }, 'timepicker': { src: 'public/app/features/dashboard/timepicker/dropdown.html' },
'import': { html: '<dash-import></dash-import>' } 'import': { html: '<dash-import dismiss="dismiss()"></dash-import>', isModal: true },
'permissions': { html: '<dash-acl-modal dismiss="dismiss()"></dash-acl-modal>', isModal: true }
}; };
coreModule.default.directive('dashEditorView', function($compile, $location, $rootScope) { coreModule.default.directive('dashEditorView', function($compile, $location, $rootScope) {
@ -31,8 +33,7 @@ function ($, angular, coreModule) {
function showEditorPane(evt, options) { function showEditorPane(evt, options) {
if (options.editview) { if (options.editview) {
options.src = editViewMap[options.editview].src; _.defaults(options, editViewMap[options.editview]);
options.html = editViewMap[options.editview].html;
} }
if (lastEditView && lastEditView === options.editview) { if (lastEditView && lastEditView === options.editview) {
@ -61,19 +62,24 @@ function ($, angular, coreModule) {
var urlParams = $location.search(); var urlParams = $location.search();
if (options.editview === urlParams.editview) { if (options.editview === urlParams.editview) {
delete urlParams.editview; delete urlParams.editview;
$location.search(urlParams); // hack for consistently updating url
setTimeout(function() {
$rootScope.$apply(function() {
$location.search(urlParams);
});
});
} }
} }
}; };
if (options.editview === 'import') { if (options.isModal) {
var modalScope = $rootScope.$new(); var modalScope = $rootScope.$new();
modalScope.$on("$destroy", function() { modalScope.$on("$destroy", function() {
editorScope.dismiss(); editorScope.dismiss();
}); });
$rootScope.appEvent('show-modal', { $rootScope.appEvent('show-modal', {
templateHtml: '<dash-import></dash-import>', templateHtml: options.html,
scope: modalScope, scope: modalScope,
backdrop: 'static' backdrop: 'static'
}); });

@ -168,6 +168,12 @@ export class NavModelSrv {
clickHandler: () => dashNavCtrl.openEditView('annotations') clickHandler: () => dashNavCtrl.openEditView('annotations')
}); });
menu.push({
title: 'Permissions...',
icon: 'fa fa-fw fa-lock',
clickHandler: () => dashNavCtrl.openEditView('permissions')
});
if (!dashboard.meta.isHome) { if (!dashboard.meta.isHome) {
menu.push({ menu.push({
title: 'Version history', title: 'Version history',
@ -199,7 +205,7 @@ export class NavModelSrv {
if (this.contextSrv.isEditor && !dashboard.meta.isFolder) { if (this.contextSrv.isEditor && !dashboard.meta.isFolder) {
menu.push({ menu.push({
title: 'Save As ...', title: 'Save As...',
icon: 'fa fa-fw fa-save', icon: 'fa fa-fw fa-save',
clickHandler: () => dashNavCtrl.saveDashboardAs() clickHandler: () => dashNavCtrl.saveDashboardAs()
}); });

@ -1,74 +1,135 @@
<div class="editor-row"> <div class="modal-body modal-body--with-overflow">
<h5 class="section-heading">Add New Permission</h5> <div class="modal-header">
<form name="addPermission" class="gf-form-group"> <h2 class="modal-header-title">
<div class="gf-form-inline"> <i class="fa fa-lock"></i>
<div class="gf-form"> <span class="p-l-1">Permissions</span>
<span class="gf-form-label">Type</span> </h2>
<select class="gf-form-input gf-size-auto" ng-model="ctrl.type" ng-options="r for r in ['User Group', 'User']"></select>
</div> <a class="modal-header-close" ng-click="ctrl.dismiss();">
<div class="gf-form" ng-show="ctrl.type === 'User'"> <i class="fa fa-remove"></i>
<span class="gf-form-label">User</span> </a>
<user-picker user-id="ctrl.userId"></user-picker> </div>
<form ng-submit="ctrl.save()" class="modal-content" novalidate>
<!-- <h5 class="section&#45;heading">Add New Permission</h5> -->
<!-- <form name="addPermission" class="gf&#45;form&#45;group"> -->
<!-- <div class="gf&#45;form&#45;inline"> -->
<!-- <div class="gf&#45;form"> -->
<!-- <span class="gf&#45;form&#45;label">Type</span> -->
<!-- <select class="gf&#45;form&#45;input gf&#45;size&#45;auto" ng&#45;model="ctrl.type" ng&#45;options="r for r in ['User Group', 'User']"></select> -->
<!-- </div> -->
<!-- <div class="gf&#45;form" ng&#45;show="ctrl.type === 'User'"> -->
<!-- <span class="gf&#45;form&#45;label">User</span> -->
<!-- <user&#45;picker user&#45;id="ctrl.userId"></user&#45;picker> -->
<!-- </div> -->
<!-- <div class="gf&#45;form" ng&#45;show="ctrl.type === 'User Group'"> -->
<!-- <span class="gf&#45;form&#45;label">User Group</span> -->
<!-- <user&#45;group&#45;picker user&#45;group&#45;id="ctrl.userGroupId"></user&#45;group&#45;picker> -->
<!-- </div> -->
<!-- <div class="gf&#45;form"> -->
<!-- <span class="gf&#45;form&#45;label">Permission</span> -->
<!-- <select class="gf&#45;form&#45;input gf&#45;size&#45;auto" ng&#45;model="ctrl.permission" ng&#45;options="p.value as p.text for p in ctrl.permissionTypeOptions"></select> -->
<!-- </div> -->
<!-- <div class="gf&#45;form"> -->
<!-- <button class="btn gf&#45;form&#45;btn btn&#45;success" ng&#45;click="ctrl.addPermission()">Add</button> -->
<!-- </div> -->
<!-- </div> -->
<!-- </form> -->
<div>
<div class="section">
<h5 class="section-heading">Groups & Users</h5>
<div class="gf-form" ng-repeat="acl in ctrl.userAcl">
<span class="gf-form-label width-15">
<i class="fa fa-fw fa-user"></i>
{{acl.userLogin}}
</span>
<div class="gf-form-select-wrapper">
<select class="gf-form-input gf-size-auto" ng-model="acl.permissions" ng-options="p.value as p.text for p in ctrl.permissionTypeOptions" ng-change="ctrl.updatePermission(permission)"></select>
</div>
<button class="btn btn-inverse gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.current.meta.mixed">
<i class="fa fa-remove"></i>
</button>
</div>
<div class="gf-form">
<button class="btn btn-inverse gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.current.meta.mixed">
<i class="fa fa-fw fa-plus"></i>
Add Permission
</button>
</div>
</div> </div>
<div class="gf-form" ng-show="ctrl.type === 'User Group'"> <div class="section pull-right">
<span class="gf-form-label">User Group</span> <h5 class="section-heading">Built-in roles</h5>
<user-group-picker user-group-id="ctrl.userGroupId"></user-group-picker> <div class="gf-form" ng-repeat="roleAcl in ctrl.roles">
<span class="gf-form-label width-5">
{{roleAcl.name}}
</span>
<div class="gf-form-select-wrapper">
<select class="gf-form-input gf-size-auto" ng-model="roleAcl.permissions" ng-options="p.value as p.text for p in ctrl.roleOptions" ng-change="ctrl.updatePermission(permission)"></select>
</div>
</div>
</div> </div>
<div class="gf-form"> </div>
<span class="gf-form-label">Permission</span>
<select class="gf-form-input gf-size-auto" ng-model="ctrl.permission" ng-options="p.value as p.text for p in ctrl.permissionTypeOptions"></select>
</div>
<div class="gf-form">
<button class="btn gf-form-btn btn-success" ng-click="ctrl.addPermission()">Add</button>
</div>
</div>
</form>
<div class="permissionlist"> <div class="clearfix"></div>
<div class="permissionlist__section">
<div class="permissionlist__section-header">
<h6>Permissions</h6>
</div>
<table class="filter-table form-inline">
<thead>
<tr>
<th style="width: 50px;"></th>
<th>Name</th>
<th style="width: 220px;">Permission</th>
<th style="width: 120px"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="permission in ctrl.userPermissions" class="permissionlist__item">
<td><i class="fa fa-fw fa-user"></i></td>
<td>{{permission.userLogin}}</td>
<td><select class="gf-form-input gf-size-auto" ng-model="permission.permissions" ng-options="p.value as p.text for p in ctrl.permissionTypeOptions" ng-change="ctrl.updatePermission(permission)"></select></td>
<td class="text-right">
<a ng-click="ctrl.removePermission(permission)" class="btn btn-danger btn-small">
<i class="fa fa-remove"></i>
</a>
</td>
</tr>
<tr ng-repeat="permission in ctrl.userGroupPermissions" class="permissionlist__item">
<td><i class="fa fa-fw fa-users"></i></td>
<td>{{permission.userGroup}}</td>
<td><select class="gf-form-input gf-size-auto" ng-model="permission.permissions" ng-options="p.value as p.text for p in ctrl.permissionTypeOptions" ng-change="ctrl.updatePermission(permission)"></select></td>
<td class="text-right">
<a ng-click="ctrl.removePermission(permission)" class="btn btn-danger btn-small">
<i class="fa fa-remove"></i>
</a>
</td>
</tr>
<tr ng-repeat="role in ctrl.roles" class="permissionlist__item">
<td></td>
<td>{{role.name}}</td>
<td><select class="gf-form-input gf-size-auto" ng-model="role.permissions" ng-options="p.value as p.text for p in ctrl.roleOptions" ng-change="ctrl.updatePermission(role)"></select></td>
<td class="text-right">
</td> <div class="gf-form-button-row text-center">
</tr> <button type="submit" class="btn btn-danger" ng-disabled="!ctrl.canUpdate">Update Permissions</button>
</tbody> <a class="btn-text" ng-click="ctrl.dismiss();">Close</a>
</table>
</div> </div>
</div>
</form>
</div> </div>
<!-- <br> -->
<!-- <br> -->
<!-- <br> -->
<!-- -->
<!-- <div class="permissionlist"> -->
<!-- <div class="permissionlist__section"> -->
<!-- <div class="permissionlist__section&#45;header"> -->
<!-- <h6>Permissions</h6> -->
<!-- </div> -->
<!-- <table class="filter&#45;table form&#45;inline"> -->
<!-- <thead> -->
<!-- <tr> -->
<!-- <th style="width: 50px;"></th> -->
<!-- <th>Name</th> -->
<!-- <th style="width: 220px;">Permission</th> -->
<!-- <th style="width: 120px"></th> -->
<!-- </tr> -->
<!-- </thead> -->
<!-- <tbody> -->
<!-- <tr ng&#45;repeat="permission in ctrl.userPermissions" class="permissionlist__item"> -->
<!-- <td><i class="fa fa&#45;fw fa&#45;user"></i></td> -->
<!-- <td>{{permission.userLogin}}</td> -->
<!-- <td><select class="gf&#45;form&#45;input gf&#45;size&#45;auto" ng&#45;model="permission.permissions" ng&#45;options="p.value as p.text for p in ctrl.permissionTypeOptions" ng&#45;change="ctrl.updatePermission(permission)"></select></td> -->
<!-- <td class="text&#45;right"> -->
<!-- <a ng&#45;click="ctrl.removePermission(permission)" class="btn btn&#45;danger btn&#45;small"> -->
<!-- <i class="fa fa&#45;remove"></i> -->
<!-- </a> -->
<!-- </td> -->
<!-- </tr> -->
<!-- <tr ng&#45;repeat="permission in ctrl.userGroupPermissions" class="permissionlist__item"> -->
<!-- <td><i class="fa fa&#45;fw fa&#45;users"></i></td> -->
<!-- <td>{{permission.userGroup}}</td> -->
<!-- <td><select class="gf&#45;form&#45;input gf&#45;size&#45;auto" ng&#45;model="permission.permissions" ng&#45;options="p.value as p.text for p in ctrl.permissionTypeOptions" ng&#45;change="ctrl.updatePermission(permission)"></select></td> -->
<!-- <td class="text&#45;right"> -->
<!-- <a ng&#45;click="ctrl.removePermission(permission)" class="btn btn&#45;danger btn&#45;small"> -->
<!-- <i class="fa fa&#45;remove"></i> -->
<!-- </a> -->
<!-- </td> -->
<!-- </tr> -->
<!-- <tr ng&#45;repeat="role in ctrl.roles" class="permissionlist__item"> -->
<!-- <td></td> -->
<!-- <td>{{role.name}}</td> -->
<!-- <td><select class="gf&#45;form&#45;input gf&#45;size&#45;auto" ng&#45;model="role.permissions" ng&#45;options="p.value as p.text for p in ctrl.roleOptions" ng&#45;change="ctrl.updatePermission(role)"></select></td> -->
<!-- <td class="text&#45;right"> -->
<!-- -->
<!-- </td> -->
<!-- </tr> -->
<!-- </tbody> -->
<!-- </table> -->
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->

@ -5,21 +5,20 @@ import appEvents from 'app/core/app_events';
import _ from 'lodash'; import _ from 'lodash';
export class AclCtrl { export class AclCtrl {
tabIndex: any;
dashboard: any; dashboard: any;
userPermissions: Permission[]; userAcl: DashboardAcl[];
userGroupPermissions: Permission[]; groupAcl: DashboardAcl[];
permissionTypeOptions = [ permissionTypeOptions = [
{value: 1, text: 'View'}, {value: 1, text: 'View'},
{value: 2, text: 'Read-only Edit'}, {value: 2, text: 'Edit'},
{value: 4, text: 'Edit'} {value: 4, text: 'Admin'}
]; ];
roleOptions = [ roleOptions = [
{value: 0, text: 'None'}, {value: 0, text: 'No Access'},
{value: 1, text: 'View'}, {value: 1, text: 'View'},
{value: 2, text: 'Read-only Edit'}, {value: 2, text: 'Edit'},
{value: 4, text: 'Edit'} {value: 4, text: 'Admin'}
]; ];
roles = []; roles = [];
@ -30,28 +29,27 @@ export class AclCtrl {
userGroupId: number; userGroupId: number;
/** @ngInject */ /** @ngInject */
constructor(private backendSrv, private $scope) { constructor(private backendSrv, private dashboardSrv) {
this.tabIndex = 0; this.userAcl = [];
this.userPermissions = []; this.groupAcl = [];
this.userGroupPermissions = []; this.dashboard = dashboardSrv.getCurrent();
this.get(this.dashboard.id); this.get(this.dashboard.id);
} }
get(dashboardId: number) { get(dashboardId: number) {
return this.backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`) return this.backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`)
.then(result => { .then(result => {
this.userPermissions = _.filter(result, p => { return p.userId > 0;}); this.userAcl = _.filter(result, p => { return p.userId > 0;});
this.userGroupPermissions = _.filter(result, p => { return p.userGroupId > 0;}); this.groupAcl = _.filter(result, p => { return p.userGroupId > 0;});
this.roles = this.setRoles(result); this.roles = this.setRoles(result);
}); });
} }
setRoles(result: any) { setRoles(result: any) {
return [ return [
{name: 'Org Viewer', permissions: 1}, {name: 'Viewer', permissions: 1},
{name: 'Org Read Only Editor', permissions: 2}, {name: 'Editor', permissions: 2},
{name: 'Org Editor', permissions: 4}, {name: 'Admin', permissions: 4}
{name: 'Org Admin', permissions: 4}
]; ];
} }
@ -76,21 +74,21 @@ export class AclCtrl {
} }
} }
addOrUpdateUserPermission(userId: number, permissionType: number) { addOrUpdateUserPermission(userId: number, permissions: number) {
return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, { return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, {
userId: userId, userId: userId,
permissions: permissionType permissions: permissions
}); });
} }
addOrUpdateUserGroupPermission(userGroupId: number, permissionType: number) { addOrUpdateUserGroupPermission(userGroupId: number, permissions: number) {
return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, { return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, {
userGroupId: userGroupId, userGroupId: userGroupId,
permissions: permissionType permissions: permissions
}); });
} }
updatePermission(permission: any) { updatePermission(permission: DashboardAcl) {
if (permission.userId > 0) { if (permission.userId > 0) {
return this.addOrUpdateUserPermission(permission.userId, permission.permissions); return this.addOrUpdateUserPermission(permission.userId, permission.permissions);
} else { } else {
@ -101,21 +99,23 @@ export class AclCtrl {
} }
} }
removePermission(permission: Permission) { removePermission(permission: DashboardAcl) {
return this.backendSrv.delete(`/api/dashboards/id/${permission.dashboardId}/acl/${permission.id}`).then(() => { return this.backendSrv.delete(`/api/dashboards/id/${permission.dashboardId}/acl/${permission.id}`).then(() => {
return this.get(permission.dashboardId); return this.get(permission.dashboardId);
}); });
} }
} }
export function aclSettings() { export function dashAclModal() {
return { return {
restrict: 'E', restrict: 'E',
templateUrl: 'public/app/features/dashboard/acl/acl.html', templateUrl: 'public/app/features/dashboard/acl/acl.html',
controller: AclCtrl, controller: AclCtrl,
bindToController: true, bindToController: true,
controllerAs: 'ctrl', controllerAs: 'ctrl',
scope: { dashboard: "=" } scope: {
dismiss: "&"
}
}; };
} }
@ -126,7 +126,7 @@ export interface FormModel {
PermissionType: number; PermissionType: number;
} }
export interface Permission { export interface DashboardAcl {
id: number; id: number;
orgId: number; orgId: number;
dashboardId: number; dashboardId: number;
@ -137,8 +137,8 @@ export interface Permission {
userEmail: string; userEmail: string;
userGroupId: number; userGroupId: number;
userGroup: string; userGroup: string;
permissions: string[]; permissions: number;
permissionType: number[]; permissionName: string;
} }
coreModule.directive('aclSettings', aclSettings); coreModule.directive('dashAclModal', dashAclModal);

@ -1,95 +1,64 @@
<div class="navbar"> <navbar model="ctrl.navModel">
<div class="navbar-inner">
<a class="navbar-brand-btn pointer" ng-click="ctrl.toggleSideMenu()">
<span class="navbar-brand-btn-background">
<img src="public/img/grafana_icon.svg"></img>
</span>
<i class="icon-gf icon-gf-grafana_wordmark"></i>
<i class="fa fa-caret-down"></i>
<i class="fa fa-chevron-left"></i>
</a>
<div class="navbar-section-wrapper"> <ul class="nav dash-playlist-actions" ng-if="ctrl.playlistSrv.isPlaying">
<a class="navbar-page-btn" ng-click="ctrl.showSearch()"> <li>
<i class="icon-gf icon-gf-dashboard"></i> <a ng-click="ctrl.playlistSrv.prev()"><i class="fa fa-step-backward"></i></a>
{{ctrl.dashboard.title}} </li>
<i class="fa fa-caret-down"></i> <li>
</a> <a ng-click="ctrl.playlistSrv.stop()"><i class="fa fa-stop"></i></a>
</div> </li>
<li>
<a ng-click="ctrl.playlistSrv.next()"><i class="fa fa-step-forward"></i></a>
</li>
</ul>
<ul class="nav dash-playlist-actions" ng-if="ctrl.playlistSrv.isPlaying"> <ul class="nav pull-left dashnav-action-icons">
<li> <li ng-show="::ctrl.dashboard.meta.canStar">
<a ng-click="ctrl.playlistSrv.prev()"><i class="fa fa-step-backward"></i></a> <a class="pointer" ng-click="ctrl.starDashboard()">
</li> <i class="fa" ng-class="{'fa-star-o': !ctrl.dashboard.meta.isStarred, 'fa-star': ctrl.dashboard.meta.isStarred}" style="color: orange;"></i>
</a>
</li>
<li ng-show="::ctrl.dashboard.meta.canShare" class="dropdown">
<a class="pointer" ng-click="ctrl.hideTooltip($event)" bs-tooltip="'Share dashboard'" data-placement="bottom" data-toggle="dropdown"><i class="fa fa-share-square-o"></i></a>
<ul class="dropdown-menu">
<li> <li>
<a ng-click="ctrl.playlistSrv.stop()"><i class="fa fa-stop"></i></a> <a class="pointer" ng-click="ctrl.shareDashboard(0)">
<i class="fa fa-link"></i> Link to Dashboard
<div class="dropdown-desc">Share an internal link to the current dashboard. Some configuration options available.</div>
</a>
</li> </li>
<li> <li>
<a ng-click="ctrl.playlistSrv.next()"><i class="fa fa-step-forward"></i></a> <a class="pointer" ng-click="ctrl.shareDashboard(1)">
</li> <i class="icon-gf icon-gf-snapshot"></i>Snapshot
</ul> <div class="dropdown-desc">Interactive, publically accessible dashboard. Sensitive data is stripped out.</div>
<ul class="nav pull-left dashnav-action-icons">
<li ng-show="::ctrl.dashboard.meta.canStar">
<a class="pointer" ng-click="ctrl.starDashboard()">
<i class="fa" ng-class="{'fa-star-o': !ctrl.dashboard.meta.isStarred, 'fa-star': ctrl.dashboard.meta.isStarred}" style="color: orange;"></i>
</a> </a>
</li> </li>
<li ng-show="::ctrl.dashboard.meta.canShare" class="dropdown"> <li>
<a class="pointer" ng-click="ctrl.hideTooltip($event)" bs-tooltip="'Share dashboard'" data-placement="bottom" data-toggle="dropdown"><i class="fa fa-share-square-o"></i></a> <a class="pointer" ng-click="ctrl.shareDashboard(2)">
<ul class="dropdown-menu"> <i class="fa fa-cloud-upload"></i>Export
<li> <div class="dropdown-desc">Export the dashboard to a JSON file for others and to share on Grafana.com</div>
<a class="pointer" ng-click="ctrl.shareDashboard(0)">
<i class="fa fa-link"></i> Link to Dashboard
<div class="dropdown-desc">Share an internal link to the current dashboard. Some configuration options available.</div>
</a>
</li>
<li>
<a class="pointer" ng-click="ctrl.shareDashboard(1)">
<i class="icon-gf icon-gf-snapshot"></i>Snapshot
<div class="dropdown-desc">Interactive, publically accessible dashboard. Sensitive data is stripped out.</div>
</a>
</li>
<li>
<a class="pointer" ng-click="ctrl.shareDashboard(2)">
<i class="fa fa-cloud-upload"></i>Export
<div class="dropdown-desc">Export the dashboard to a JSON file for others and to share on Grafana.com</div>
</a>
</li>
</ul>
</li>
<li ng-show="::ctrl.dashboard.meta.canSave">
<a ng-click="ctrl.saveDashboard()" bs-tooltip="'Save dashboard <br> CTRL+S'" data-placement="bottom"><i class="fa fa-save"></i></a>
</li>
<li ng-if="::ctrl.dashboard.snapshot.originalUrl">
<a ng-href="{{ctrl.dashboard.snapshot.originalUrl}}" bs-tooltip="'Open original dashboard'" data-placement="bottom"><i class="fa fa-link"></i></a>
</li>
<li class="dropdown">
<a class="pointer" data-toggle="dropdown">
<i class="fa fa-cog"></i>
</a> </a>
<ul class="dropdown-menu dropdown-menu--navbar">
<li ng-repeat="navItem in ::ctrl.navModel.menu" ng-class="{active: navItem.active}">
<a class="pointer" ng-href="{{::navItem.url}}" ng-click="ctrl.navItemClicked(navItem, $event)">
<i class="{{::navItem.icon}}" ng-show="::navItem.icon"></i>
{{::navItem.title}}
</a>
</li>
</ul>
</li> </li>
</ul> </ul>
</li>
<li ng-show="::ctrl.dashboard.meta.canSave">
<a ng-click="ctrl.saveDashboard()" bs-tooltip="'Save dashboard <br> CTRL+S'" data-placement="bottom"><i class="fa fa-save"></i></a>
</li>
<li ng-if="::ctrl.dashboard.snapshot.originalUrl">
<a ng-href="{{ctrl.dashboard.snapshot.originalUrl}}" bs-tooltip="'Open original dashboard'" data-placement="bottom"><i class="fa fa-link"></i></a>
</li>
</ul>
<ul class="nav pull-right"> <ul class="nav pull-right">
<li ng-show="ctrl.dashboard.meta.fullscreen" class="dashnav-back-to-dashboard"> <li ng-show="ctrl.dashboard.meta.fullscreen" class="dashnav-back-to-dashboard">
<a ng-click="ctrl.exitFullscreen()"> <a ng-click="ctrl.exitFullscreen()">
Back to dashboard Back to dashboard
</a> </a>
</li> </li>
<li> <li>
<gf-time-picker dashboard="ctrl.dashboard"></gf-time-picker> <gf-time-picker dashboard="ctrl.dashboard"></gf-time-picker>
</li> </li>
</ul> </ul>
</div>
</div> </navbar>
<dashboard-search></dashboard-search>

@ -143,17 +143,6 @@ export class DashNavCtrl {
onFolderChange(parentId) { onFolderChange(parentId) {
this.dashboard.parentId = parentId; this.dashboard.parentId = parentId;
} }
showSearch() {
this.$rootScope.appEvent('show-dash-search');
}
navItemClicked(navItem, evt) {
if (navItem.clickHandler) {
navItem.clickHandler();
evt.preventDefault();
}
}
} }
export function dashNavDirective() { export function dashNavDirective() {

@ -1,4 +1,3 @@
<div class="modal-body">
<div class="modal-header"> <div class="modal-header">
<h2 class="modal-header-title"> <h2 class="modal-header-title">

Loading…
Cancel
Save