浏览代码

Panel menu now hides edit actions for users with role Viewer, Closes #1826

Torkel Ödegaard 10 年之前
父节点
当前提交
85c3a0aa14

+ 0 - 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>";
-      }
-    };
-  });
-
-});
-

+ 1 - 0
pkg/api/dashboard.go

@@ -55,6 +55,7 @@ func GetDashboard(c *middleware.Context) {
 			Type:      m.DashTypeDB,
 			CanStar:   c.IsSignedIn,
 			CanSave:   c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR,
+			CanEdit:   c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR,
 		},
 	}
 

+ 1 - 0
pkg/api/dtos/models.go

@@ -34,6 +34,7 @@ type DashboardMeta struct {
 	IsSnapshot bool      `json:"isSnapshot,omitempty"`
 	Type       string    `json:"type,omitempty"`
 	CanSave    bool      `json:"canSave"`
+	CanEdit    bool      `json:"canEdit"`
 	CanStar    bool      `json:"canStar"`
 	Slug       string    `json:"slug"`
 	Expires    time.Time `json:"expires"`

+ 1 - 0
pkg/api/frontendsettings.go

@@ -99,6 +99,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
 		"defaultDatasource": defaultDatasource,
 		"datasources":       datasources,
 		"appSubUrl":         setting.AppSubUrl,
+		"viewerRoleMode":    setting.ViewerRoleMode,
 		"buildInfo": map[string]interface{}{
 			"version":    setting.BuildVersion,
 			"commit":     setting.BuildCommit,

+ 2 - 0
pkg/setting/setting.go

@@ -79,6 +79,7 @@ var (
 	AllowUserOrgCreate bool
 	AutoAssignOrg      bool
 	AutoAssignOrgRole  string
+	ViewerRoleMode     string
 
 	// Http auth
 	AdminUser     string
@@ -383,6 +384,7 @@ func NewConfigContext(args *CommandLineArgs) {
 	AllowUserOrgCreate = users.Key("allow_org_create").MustBool(true)
 	AutoAssignOrg = users.Key("auto_assign_org").MustBool(true)
 	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
 	AnonymousEnabled = Cfg.Section("auth.anonymous").Key("enabled").MustBool(false)

+ 6 - 6
public/app/components/panelmeta.js

@@ -16,8 +16,8 @@ function () {
       this.addMenuItem('view', 'icon-eye-open', 'toggleFullscreen(false); dismiss();');
     }
 
-    this.addMenuItem('edit', 'icon-cog', 'editPanel(); dismiss();');
-    this.addMenuItem('duplicate', 'icon-copy', 'duplicatePanel()');
+    this.addMenuItem('edit', 'icon-cog', 'editPanel(); dismiss();', 'Editor');
+    this.addMenuItem('duplicate', 'icon-copy', 'duplicatePanel()', 'Editor');
     this.addMenuItem('share', 'icon-share', 'sharePanel(); dismiss();');
 
     this.addEditorTab('General', 'app/partials/panelgeneral.html');
@@ -29,12 +29,12 @@ function () {
     this.addExtendedMenuItem('Panel JSON', '', 'editPanelJson(); dismiss();');
   }
 
-  PanelMeta.prototype.addMenuItem = function(text, icon, click) {
-    this.menu.push({text: text, icon: icon, click: click});
+  PanelMeta.prototype.addMenuItem = function(text, icon, click, role) {
+    this.menu.push({text: text, icon: icon, click: click, role: role});
   };
 
-  PanelMeta.prototype.addExtendedMenuItem = function(text, icon, click) {
-    this.extendedMenu.push({text: text, icon: icon, click: click});
+  PanelMeta.prototype.addExtendedMenuItem = function(text, icon, click, role) {
+    this.extendedMenu.push({text: text, icon: icon, click: click, role: role});
   };
 
   PanelMeta.prototype.addEditorTab = function(title, src) {

+ 39 - 25
public/app/features/panel/panelMenu.js

@@ -8,7 +8,7 @@ function (angular, $, _) {
 
   angular
     .module('grafana.directives')
-    .directive('panelMenu', function($compile, linkSrv) {
+    .directive('panelMenu', function($compile, linkSrv, contextSrv) {
       var linkTemplate =
           '<span class="panel-title drag-handle pointer">' +
             '<span class="panel-title-text drag-handle">{{panel.title | interpolateTemplateVars:this}}</span>' +
@@ -18,18 +18,26 @@ function (angular, $, _) {
 
       function createMenuTemplate($scope) {
         var template = '<div class="panel-menu small">';
-        template += '<div class="panel-menu-inner">';
-        template += '<div class="panel-menu-row">';
-        template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(-1)"><i class="fa fa-minus"></i></a>';
-        template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(1)"><i class="fa fa-plus"></i></a>';
-        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>';
+
+        if ($scope.dashboardMeta.canEdit && contextSrv.isEditor) {
+          template += '<div class="panel-menu-inner">';
+          template += '<div class="panel-menu-row">';
+          template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(-1)"><i class="fa fa-minus"></i></a>';
+          template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(1)"><i class="fa fa-plus"></i></a>';
+          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 += '<a class="panel-menu-link" gf-dropdown="extendedMenu"><i class="fa fa-bars"></i></a>';
 
         _.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" ';
           if (item.click) { template += ' ng-click="' + item.click + '"'; }
           if (item.editorLink) { template += ' dash-editor-link="' + item.editorLink + '"'; }
@@ -61,7 +69,6 @@ function (angular, $, _) {
         link: function($scope, elem) {
           var $link = $(linkTemplate);
           var $panelContainer = elem.parents(".panel-container");
-          var menuWidth = $scope.panelMeta.menu.length === 4 ? 236 : 191;
           var menuScope = null;
           var timeout = null;
           var $menu = null;
@@ -111,21 +118,8 @@ function (angular, $, _) {
               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);
             $menu = $(menuTemplate);
-            $menu.css('left', menuLeftPos);
             $menu.mouseleave(function() {
               dismiss(1000);
             });
@@ -136,14 +130,34 @@ function (angular, $, _) {
               dismiss(null, true);
             };
 
+            $(".panel-container").removeClass('panel-highlight');
+            $panelContainer.toggleClass('panel-highlight');
+
             $('.panel-menu').remove();
+
             elem.append($menu);
+
             $scope.$apply(function() {
               $compile($menu.contents())(menuScope);
-            });
 
-            $(".panel-container").removeClass('panel-highlight');
-            $panelContainer.toggleClass('panel-highlight');
+              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);
           };

+ 1 - 1
public/app/services/contextSrv.js

@@ -60,6 +60,6 @@ function (angular, _, store, config) {
       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');
   });
 });

+ 0 - 1
public/css/less/panel.less

@@ -130,7 +130,6 @@
   position: absolute;
   background: @grafanaTargetFuncBackground;
   border: 1px solid black;
-  top: -62px;
 
   .panel-menu-row {
     white-space: nowrap;