mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Panel menu now hides edit actions for users with role Viewer, Closes #1826
This commit is contained in:
36
'
36
'
@@ -1,36 +0,0 @@
|
|||||||
define([
|
|
||||||
'angular',
|
|
||||||
'lodash'
|
|
||||||
],
|
|
||||||
function (angular) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
angular
|
|
||||||
.module('grafana.directives')
|
|
||||||
.directive('annotationTooltip', function($sanitize, dashboardSrv) {
|
|
||||||
return {
|
|
||||||
scope: { tagColorFromName: "=" },
|
|
||||||
link: function (scope, element) {
|
|
||||||
var title = $sanitize(scope.annoation.title);
|
|
||||||
var dashboard = dashboardSrv.getCurrent();
|
|
||||||
var time = '<i>' + dashboard.formatDate(scope.annotation.time) + '</i>';
|
|
||||||
|
|
||||||
var tooltip = '<div class="graph-tooltip small"><div class="graph-tooltip-time">'+ title + ' ' + time + '</div> ' ;
|
|
||||||
|
|
||||||
if (options.tags) {
|
|
||||||
var tags = $sanitize(options.tags);
|
|
||||||
tooltip += '<span class="label label-tag" tag-color-from-name="\'asd\'">' + (tags || '') + '</span><br/>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.text) {
|
|
||||||
var text = $sanitize(options.text);
|
|
||||||
tooltip += text.replace(/\n/g, '<br/>');
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltip += "</small>";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
@@ -55,6 +55,7 @@ func GetDashboard(c *middleware.Context) {
|
|||||||
Type: m.DashTypeDB,
|
Type: m.DashTypeDB,
|
||||||
CanStar: c.IsSignedIn,
|
CanStar: c.IsSignedIn,
|
||||||
CanSave: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR,
|
CanSave: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR,
|
||||||
|
CanEdit: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type DashboardMeta struct {
|
|||||||
IsSnapshot bool `json:"isSnapshot,omitempty"`
|
IsSnapshot bool `json:"isSnapshot,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
CanSave bool `json:"canSave"`
|
CanSave bool `json:"canSave"`
|
||||||
|
CanEdit bool `json:"canEdit"`
|
||||||
CanStar bool `json:"canStar"`
|
CanStar bool `json:"canStar"`
|
||||||
Slug string `json:"slug"`
|
Slug string `json:"slug"`
|
||||||
Expires time.Time `json:"expires"`
|
Expires time.Time `json:"expires"`
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
|||||||
"defaultDatasource": defaultDatasource,
|
"defaultDatasource": defaultDatasource,
|
||||||
"datasources": datasources,
|
"datasources": datasources,
|
||||||
"appSubUrl": setting.AppSubUrl,
|
"appSubUrl": setting.AppSubUrl,
|
||||||
|
"viewerRoleMode": setting.ViewerRoleMode,
|
||||||
"buildInfo": map[string]interface{}{
|
"buildInfo": map[string]interface{}{
|
||||||
"version": setting.BuildVersion,
|
"version": setting.BuildVersion,
|
||||||
"commit": setting.BuildCommit,
|
"commit": setting.BuildCommit,
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ var (
|
|||||||
AllowUserOrgCreate bool
|
AllowUserOrgCreate bool
|
||||||
AutoAssignOrg bool
|
AutoAssignOrg bool
|
||||||
AutoAssignOrgRole string
|
AutoAssignOrgRole string
|
||||||
|
ViewerRoleMode string
|
||||||
|
|
||||||
// Http auth
|
// Http auth
|
||||||
AdminUser string
|
AdminUser string
|
||||||
@@ -383,6 +384,7 @@ func NewConfigContext(args *CommandLineArgs) {
|
|||||||
AllowUserOrgCreate = users.Key("allow_org_create").MustBool(true)
|
AllowUserOrgCreate = users.Key("allow_org_create").MustBool(true)
|
||||||
AutoAssignOrg = users.Key("auto_assign_org").MustBool(true)
|
AutoAssignOrg = users.Key("auto_assign_org").MustBool(true)
|
||||||
AutoAssignOrgRole = users.Key("auto_assign_org_role").In("Editor", []string{"Editor", "Admin", "Viewer"})
|
AutoAssignOrgRole = users.Key("auto_assign_org_role").In("Editor", []string{"Editor", "Admin", "Viewer"})
|
||||||
|
ViewerRoleMode = users.Key("viewer_role_mode").In("default", []string{"default", "strinct"})
|
||||||
|
|
||||||
// anonymous access
|
// anonymous access
|
||||||
AnonymousEnabled = Cfg.Section("auth.anonymous").Key("enabled").MustBool(false)
|
AnonymousEnabled = Cfg.Section("auth.anonymous").Key("enabled").MustBool(false)
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ function () {
|
|||||||
this.addMenuItem('view', 'icon-eye-open', 'toggleFullscreen(false); dismiss();');
|
this.addMenuItem('view', 'icon-eye-open', 'toggleFullscreen(false); dismiss();');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addMenuItem('edit', 'icon-cog', 'editPanel(); dismiss();');
|
this.addMenuItem('edit', 'icon-cog', 'editPanel(); dismiss();', 'Editor');
|
||||||
this.addMenuItem('duplicate', 'icon-copy', 'duplicatePanel()');
|
this.addMenuItem('duplicate', 'icon-copy', 'duplicatePanel()', 'Editor');
|
||||||
this.addMenuItem('share', 'icon-share', 'sharePanel(); dismiss();');
|
this.addMenuItem('share', 'icon-share', 'sharePanel(); dismiss();');
|
||||||
|
|
||||||
this.addEditorTab('General', 'app/partials/panelgeneral.html');
|
this.addEditorTab('General', 'app/partials/panelgeneral.html');
|
||||||
@@ -29,12 +29,12 @@ function () {
|
|||||||
this.addExtendedMenuItem('Panel JSON', '', 'editPanelJson(); dismiss();');
|
this.addExtendedMenuItem('Panel JSON', '', 'editPanelJson(); dismiss();');
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelMeta.prototype.addMenuItem = function(text, icon, click) {
|
PanelMeta.prototype.addMenuItem = function(text, icon, click, role) {
|
||||||
this.menu.push({text: text, icon: icon, click: click});
|
this.menu.push({text: text, icon: icon, click: click, role: role});
|
||||||
};
|
};
|
||||||
|
|
||||||
PanelMeta.prototype.addExtendedMenuItem = function(text, icon, click) {
|
PanelMeta.prototype.addExtendedMenuItem = function(text, icon, click, role) {
|
||||||
this.extendedMenu.push({text: text, icon: icon, click: click});
|
this.extendedMenu.push({text: text, icon: icon, click: click, role: role});
|
||||||
};
|
};
|
||||||
|
|
||||||
PanelMeta.prototype.addEditorTab = function(title, src) {
|
PanelMeta.prototype.addEditorTab = function(title, src) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ function (angular, $, _) {
|
|||||||
|
|
||||||
angular
|
angular
|
||||||
.module('grafana.directives')
|
.module('grafana.directives')
|
||||||
.directive('panelMenu', function($compile, linkSrv) {
|
.directive('panelMenu', function($compile, linkSrv, contextSrv) {
|
||||||
var linkTemplate =
|
var linkTemplate =
|
||||||
'<span class="panel-title drag-handle pointer">' +
|
'<span class="panel-title drag-handle pointer">' +
|
||||||
'<span class="panel-title-text drag-handle">{{panel.title | interpolateTemplateVars:this}}</span>' +
|
'<span class="panel-title-text drag-handle">{{panel.title | interpolateTemplateVars:this}}</span>' +
|
||||||
@@ -18,18 +18,26 @@ function (angular, $, _) {
|
|||||||
|
|
||||||
function createMenuTemplate($scope) {
|
function createMenuTemplate($scope) {
|
||||||
var template = '<div class="panel-menu small">';
|
var template = '<div class="panel-menu small">';
|
||||||
template += '<div class="panel-menu-inner">';
|
|
||||||
template += '<div class="panel-menu-row">';
|
if ($scope.dashboardMeta.canEdit && contextSrv.isEditor) {
|
||||||
template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(-1)"><i class="fa fa-minus"></i></a>';
|
template += '<div class="panel-menu-inner">';
|
||||||
template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(1)"><i class="fa fa-plus"></i></a>';
|
template += '<div class="panel-menu-row">';
|
||||||
template += '<a class="panel-menu-icon pull-right" ng-click="removePanel(panel)"><i class="fa fa-remove"></i></a>';
|
template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(-1)"><i class="fa fa-minus"></i></a>';
|
||||||
template += '<div class="clearfix"></div>';
|
template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(1)"><i class="fa fa-plus"></i></a>';
|
||||||
template += '</div>';
|
template += '<a class="panel-menu-icon pull-right" ng-click="removePanel(panel)"><i class="fa fa-remove"></i></a>';
|
||||||
|
template += '<div class="clearfix"></div>';
|
||||||
|
template += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
template += '<div class="panel-menu-row">';
|
template += '<div class="panel-menu-row">';
|
||||||
template += '<a class="panel-menu-link" gf-dropdown="extendedMenu"><i class="fa fa-bars"></i></a>';
|
template += '<a class="panel-menu-link" gf-dropdown="extendedMenu"><i class="fa fa-bars"></i></a>';
|
||||||
|
|
||||||
_.each($scope.panelMeta.menu, function(item) {
|
_.each($scope.panelMeta.menu, function(item) {
|
||||||
|
// skip edit actions if not editor
|
||||||
|
if (item.role === 'Editor' && (!contextSrv.isEditor || !$scope.dashboardMeta.canEdit)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
template += '<a class="panel-menu-link" ';
|
template += '<a class="panel-menu-link" ';
|
||||||
if (item.click) { template += ' ng-click="' + item.click + '"'; }
|
if (item.click) { template += ' ng-click="' + item.click + '"'; }
|
||||||
if (item.editorLink) { template += ' dash-editor-link="' + item.editorLink + '"'; }
|
if (item.editorLink) { template += ' dash-editor-link="' + item.editorLink + '"'; }
|
||||||
@@ -61,7 +69,6 @@ function (angular, $, _) {
|
|||||||
link: function($scope, elem) {
|
link: function($scope, elem) {
|
||||||
var $link = $(linkTemplate);
|
var $link = $(linkTemplate);
|
||||||
var $panelContainer = elem.parents(".panel-container");
|
var $panelContainer = elem.parents(".panel-container");
|
||||||
var menuWidth = $scope.panelMeta.menu.length === 4 ? 236 : 191;
|
|
||||||
var menuScope = null;
|
var menuScope = null;
|
||||||
var timeout = null;
|
var timeout = null;
|
||||||
var $menu = null;
|
var $menu = null;
|
||||||
@@ -111,21 +118,8 @@ function (angular, $, _) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var windowWidth = $(window).width();
|
|
||||||
var panelLeftPos = $(elem).offset().left;
|
|
||||||
var panelWidth = $(elem).width();
|
|
||||||
var menuLeftPos = (panelWidth / 2) - (menuWidth/2);
|
|
||||||
var stickingOut = panelLeftPos + menuLeftPos + menuWidth - windowWidth;
|
|
||||||
if (stickingOut > 0) {
|
|
||||||
menuLeftPos -= stickingOut + 10;
|
|
||||||
}
|
|
||||||
if (panelLeftPos + menuLeftPos < 0) {
|
|
||||||
menuLeftPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var menuTemplate = createMenuTemplate($scope);
|
var menuTemplate = createMenuTemplate($scope);
|
||||||
$menu = $(menuTemplate);
|
$menu = $(menuTemplate);
|
||||||
$menu.css('left', menuLeftPos);
|
|
||||||
$menu.mouseleave(function() {
|
$menu.mouseleave(function() {
|
||||||
dismiss(1000);
|
dismiss(1000);
|
||||||
});
|
});
|
||||||
@@ -136,15 +130,35 @@ function (angular, $, _) {
|
|||||||
dismiss(null, true);
|
dismiss(null, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
$('.panel-menu').remove();
|
|
||||||
elem.append($menu);
|
|
||||||
$scope.$apply(function() {
|
|
||||||
$compile($menu.contents())(menuScope);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".panel-container").removeClass('panel-highlight');
|
$(".panel-container").removeClass('panel-highlight');
|
||||||
$panelContainer.toggleClass('panel-highlight');
|
$panelContainer.toggleClass('panel-highlight');
|
||||||
|
|
||||||
|
$('.panel-menu').remove();
|
||||||
|
|
||||||
|
elem.append($menu);
|
||||||
|
|
||||||
|
$scope.$apply(function() {
|
||||||
|
$compile($menu.contents())(menuScope);
|
||||||
|
|
||||||
|
var menuWidth = $menu[0].offsetWidth;
|
||||||
|
var menuHeight = $menu[0].offsetHeight;
|
||||||
|
|
||||||
|
var windowWidth = $(window).width();
|
||||||
|
var panelLeftPos = $(elem).offset().left;
|
||||||
|
var panelWidth = $(elem).width();
|
||||||
|
|
||||||
|
var menuLeftPos = (panelWidth / 2) - (menuWidth/2);
|
||||||
|
var stickingOut = panelLeftPos + menuLeftPos + menuWidth - windowWidth;
|
||||||
|
if (stickingOut > 0) {
|
||||||
|
menuLeftPos -= stickingOut + 10;
|
||||||
|
}
|
||||||
|
if (panelLeftPos + menuLeftPos < 0) {
|
||||||
|
menuLeftPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$menu.css({'left': menuLeftPos, top: -menuHeight});
|
||||||
|
});
|
||||||
|
|
||||||
dismiss(2200);
|
dismiss(2200);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,6 @@ function (angular, _, store, config) {
|
|||||||
store.set('grafana.sidemenu', false);
|
store.set('grafana.sidemenu', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isEditor = this.hasRole('Editor') || this.hasRole('Admin');
|
this.isEditor = this.hasRole('Editor') || this.hasRole('Admin') || this.hasRole('Read Only Editor');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -130,7 +130,6 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
background: @grafanaTargetFuncBackground;
|
background: @grafanaTargetFuncBackground;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
top: -62px;
|
|
||||||
|
|
||||||
.panel-menu-row {
|
.panel-menu-row {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user