瀏覽代碼

feat: more work on #8768

Torkel Ödegaard 8 年之前
父節點
當前提交
73563d087c

+ 14 - 11
pkg/api/frontendsettings.go

@@ -131,17 +131,20 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
 	}
 	}
 
 
 	jsonObj := map[string]interface{}{
 	jsonObj := map[string]interface{}{
-		"defaultDatasource":  defaultDatasource,
-		"datasources":        datasources,
-		"panels":             panels,
-		"appSubUrl":          setting.AppSubUrl,
-		"allowOrgCreate":     (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
-		"authProxyEnabled":   setting.AuthProxyEnabled,
-		"ldapEnabled":        setting.LdapEnabled,
-		"alertingEnabled":    setting.AlertingEnabled,
-		"googleAnalyticsId":  setting.GoogleAnalyticsId,
-		"disableLoginForm":   setting.DisableLoginForm,
-		"disableSignoutMenu": setting.DisableSignoutMenu,
+		"defaultDatasource":       defaultDatasource,
+		"datasources":             datasources,
+		"panels":                  panels,
+		"appSubUrl":               setting.AppSubUrl,
+		"allowOrgCreate":          (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
+		"authProxyEnabled":        setting.AuthProxyEnabled,
+		"ldapEnabled":             setting.LdapEnabled,
+		"alertingEnabled":         setting.AlertingEnabled,
+		"googleAnalyticsId":       setting.GoogleAnalyticsId,
+		"disableLoginForm":        setting.DisableLoginForm,
+		"disableSignoutMenu":      setting.DisableSignoutMenu,
+		"externalUserMngInfo":     setting.ExternalUserMngInfo,
+		"externalUserMngLinkUrl":  setting.ExternalUserMngLinkUrl,
+		"externalUserMngLinkName": setting.ExternalUserMngLinkName,
 		"buildInfo": map[string]interface{}{
 		"buildInfo": map[string]interface{}{
 			"version":       setting.BuildVersion,
 			"version":       setting.BuildVersion,
 			"commit":        setting.BuildCommit,
 			"commit":        setting.BuildCommit,

+ 15 - 15
pkg/setting/setting.go

@@ -90,18 +90,18 @@ var (
 	SnapShotRemoveExpired bool
 	SnapShotRemoveExpired bool
 
 
 	// User settings
 	// User settings
-	AllowUserSignUp     bool
-	AllowUserOrgCreate  bool
-	AutoAssignOrg       bool
-	AutoAssignOrgRole   string
-	VerifyEmailEnabled  bool
-	LoginHint           string
-	DefaultTheme        string
-	DisableLoginForm    bool
-	DisableSignoutMenu  bool
-	ManageUsersLinkUrl  string
-	ManageUsersLinkName string
-	ManageUsersInfo     string
+	AllowUserSignUp         bool
+	AllowUserOrgCreate      bool
+	AutoAssignOrg           bool
+	AutoAssignOrgRole       string
+	VerifyEmailEnabled      bool
+	LoginHint               string
+	DefaultTheme            string
+	DisableLoginForm        bool
+	DisableSignoutMenu      bool
+	ExternalUserMngLinkUrl  string
+	ExternalUserMngLinkName string
+	ExternalUserMngInfo     string
 
 
 	// Http auth
 	// Http auth
 	AdminUser     string
 	AdminUser     string
@@ -534,9 +534,9 @@ func NewConfigContext(args *CommandLineArgs) error {
 	VerifyEmailEnabled = users.Key("verify_email_enabled").MustBool(false)
 	VerifyEmailEnabled = users.Key("verify_email_enabled").MustBool(false)
 	LoginHint = users.Key("login_hint").String()
 	LoginHint = users.Key("login_hint").String()
 	DefaultTheme = users.Key("default_theme").String()
 	DefaultTheme = users.Key("default_theme").String()
-	ManageUsersLinkUrl = users.Key("external_manage_link_url").String()
-	ManageUsersLinkName = users.Key("external_manage_link_name").String()
-	ManageUsersInfo = users.Key("external_manage_info").String()
+	ExternalUserMngLinkUrl = users.Key("external_manage_link_url").String()
+	ExternalUserMngLinkName = users.Key("external_manage_link_name").String()
+	ExternalUserMngInfo = users.Key("external_manage_info").String()
 
 
 	// auth
 	// auth
 	auth := Cfg.Section("auth")
 	auth := Cfg.Section("auth")

+ 31 - 7
public/app/features/org/org_users_ctrl.ts

@@ -3,6 +3,7 @@
 import config from 'app/core/config';
 import config from 'app/core/config';
 import _ from 'lodash';
 import _ from 'lodash';
 import coreModule from 'app/core/core_module';
 import coreModule from 'app/core/core_module';
+import Remarkable from 'remarkable';
 
 
 export class OrgUsersCtrl {
 export class OrgUsersCtrl {
 
 
@@ -10,11 +11,14 @@ export class OrgUsersCtrl {
   users: any;
   users: any;
   pendingInvites: any;
   pendingInvites: any;
   editor: any;
   editor: any;
-  showInviteUI: boolean;
   navModel: any;
   navModel: any;
+  externalUserMngLinkUrl: string;
+  externalUserMngLinkName: string;
+  externalUserMngInfo: string;
+  addUsersBtnName: string;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private $scope, private $http, private backendSrv, navModelSrv) {
+  constructor(private $scope, private $http, private backendSrv, navModelSrv, $sce) {
     this.user = {
     this.user = {
       loginOrEmail: '',
       loginOrEmail: '',
       role: 'Viewer',
       role: 'Viewer',
@@ -23,7 +27,27 @@ export class OrgUsersCtrl {
 
 
     this.get();
     this.get();
     this.editor = { index: 0 };
     this.editor = { index: 0 };
-    this.showInviteUI = config.disableLoginForm === false;
+    this.externalUserMngLinkUrl = config.externalUserMngLinkUrl;
+    this.externalUserMngLinkName = config.externalUserMngLinkName;
+
+    // render external user management info markdown
+    if (config.externalUserMngInfo) {
+      this.externalUserMngInfo = new Remarkable({
+        linkTarget: '__blank',
+      }).render(config.externalUserMngInfo);
+    }
+
+    this.addUsersBtnName = this.getAddUserBtnName();
+  }
+
+  getAddUserBtnName(): string {
+    if (this.externalUserMngLinkName) {
+      return this.externalUserMngLinkName;
+    } else if (config.disableLoginForm) {
+      return "Add Users";
+    } else {
+      return "Add or Invite";
+    }
   }
   }
 
 
   get() {
   get() {
@@ -68,13 +92,13 @@ export class OrgUsersCtrl {
     evt.stopPropagation();
     evt.stopPropagation();
   }
   }
 
 
-  openInviteModal() {
+  openAddUsersView() {
     var modalScope = this.$scope.$new();
     var modalScope = this.$scope.$new();
     modalScope.invitesSent = this.get.bind(this);
     modalScope.invitesSent = this.get.bind(this);
 
 
-    var src = this.showInviteUI
-      ? 'public/app/features/org/partials/invite.html'
-      : 'public/app/features/org/partials/add_user.html';
+    var src = config.disableLoginForm
+      ? 'public/app/features/org/partials/add_user.html'
+      : 'public/app/features/org/partials/invite.html';
 
 
     this.$scope.appEvent('show-modal', {
     this.$scope.appEvent('show-modal', {
       src: src,
       src: src,

+ 77 - 67
public/app/features/org/partials/orgUsers.html

@@ -5,11 +5,17 @@
 		<h1>Organization users</h1>
 		<h1>Organization users</h1>
 
 
 		<div class="page-header-tabs">
 		<div class="page-header-tabs">
-			<button class="btn btn-success" ng-click="ctrl.openInviteModal()">
+
+			<button class="btn btn-success" ng-click="ctrl.openAddUsersView()" ng-hide="ctrl.externalUserMngLinkUrl">
 				<i class="fa fa-plus"></i>
 				<i class="fa fa-plus"></i>
-        Add <span ng-show="ctrl.showInviteUI"> or Invite</span>
+        <span>{{ctrl.addUsersBtnName}}</span>
 			</button>
 			</button>
 
 
+      <a class="btn btn-inverse" ng-href="{{ctrl.externalUserMngLinkUrl}}" target="_blank" ng-if="ctrl.externalUserMngLinkUrl">
+				<i class="fa fa-external-link-square"></i>
+        {{ctrl.addUsersBtnName}}
+      </a>
+
 			<ul class="gf-tabs">
 			<ul class="gf-tabs">
 				<li class="gf-tabs-item">
 				<li class="gf-tabs-item">
 					<a class="gf-tabs-link" ng-click="ctrl.editor.index = 0" ng-class="{active: ctrl.editor.index === 0}">
 					<a class="gf-tabs-link" ng-click="ctrl.editor.index = 0" ng-class="{active: ctrl.editor.index === 0}">
@@ -25,72 +31,76 @@
 		</div>
 		</div>
 	</div>
 	</div>
 
 
-	<div ng-if="ctrl.editor.index === 0" class="tab-content">
-		<table class="filter-table form-inline">
-			<thead>
-				<tr>
-					<th>Login</th>
-					<th>Email</th>
-					<th>Role</th>
-					<th style="width: 34px;"></th>
-				</tr>
-			</thead>
-			<tr ng-repeat="user in ctrl.users">
-				<td>{{user.login}}</td>
-				<td><span class="ellipsis">{{user.email}}</span></td>
-				<td>
-					<select type="text" ng-model="user.role" class="input-medium" ng-options="f for f in ['Viewer', 'Editor', 'Read Only Editor', 'Admin']" ng-change="ctrl.updateOrgUser(user)">
-					</select>
-				</td>
-				<td>
-					<a ng-click="ctrl.removeUser(user)" class="btn btn-danger btn-mini">
-						<i class="fa fa-remove"></i>
-					</a>
-				</td>
-			</tr>
-		</table>
-	</div>
+  <div class="grafana-info-box" ng-if="ctrl.externalUserMngInfo">
+    <span ng-bind-html="ctrl.externalUserMngInfo"></span>
+  </div>
 
 
-	<div ng-if="ctrl.editor.index === 1 && ctrl.showInviteUI">
-		<table class="filter-table form-inline">
-			<thead>
-				<tr>
-					<th>Email</th>
-					<th>Name</th>
-					<th></th>
-				</tr>
-			</thead>
-			<tbody ng-repeat="invite in ctrl.pendingInvites">
-				<tr ng-click="invite.expanded = !invite.expanded" ng-class="{'expanded': invite.expanded}">
-					<td>{{invite.email}}</td>
-					<td>{{invite.name}}</td>
-					<td class="text-right">
-						<button class="btn btn-inverse btn-mini " data-clipboard-text="{{invite.url}}" clipboard-button ng-click="ctrl.copyInviteToClipboard($event)">
-							<i class="fa fa-clipboard"></i> Copy Invite
-						</button>
-						&nbsp;
-						<button class="btn btn-inverse btn-mini">
-							Details
-							<i ng-show="!invite.expanded" class="fa fa-caret-right"></i>
-							<i ng-show="invite.expanded" class="fa fa-caret-down"></i>
-						</button>
-					</td>
-				</tr>
-				<tr ng-show="invite.expanded">
-					<td colspan="3">
-						<a href="{{invite.url}}">{{invite.url}}</a><br><br>
-						&nbsp;
-						<button class="btn btn-inverse btn-mini" ng-click="ctrl.revokeInvite(invite, $event)">
-							<i class="fa fa-remove" style="color: red"></i> Revoke invite
-						</button>
-						<span style="padding-left: 15px">
-							Invited: <em> {{invite.createdOn | date: 'shortDate'}} by {{invite.invitedBy}} </em>
-						</span>
-					</td>
-				</tr>
-			</tbody>
-		</table>
+  <div ng-if="ctrl.editor.index === 0" class="tab-content">
+    <table class="filter-table form-inline">
+      <thead>
+        <tr>
+          <th>Login</th>
+          <th>Email</th>
+          <th>Role</th>
+          <th style="width: 34px;"></th>
+        </tr>
+      </thead>
+      <tr ng-repeat="user in ctrl.users">
+        <td>{{user.login}}</td>
+        <td><span class="ellipsis">{{user.email}}</span></td>
+        <td>
+          <select type="text" ng-model="user.role" class="input-medium" ng-options="f for f in ['Viewer', 'Editor', 'Read Only Editor', 'Admin']" ng-change="ctrl.updateOrgUser(user)">
+          </select>
+        </td>
+        <td>
+          <a ng-click="ctrl.removeUser(user)" class="btn btn-danger btn-mini">
+            <i class="fa fa-remove"></i>
+          </a>
+        </td>
+      </tr>
+    </table>
+  </div>
 
 
-	</div>
+  <div ng-if="ctrl.editor.index === 1 && ctrl.showInviteUI">
+    <table class="filter-table form-inline">
+      <thead>
+        <tr>
+          <th>Email</th>
+          <th>Name</th>
+          <th></th>
+        </tr>
+      </thead>
+      <tbody ng-repeat="invite in ctrl.pendingInvites">
+        <tr ng-click="invite.expanded = !invite.expanded" ng-class="{'expanded': invite.expanded}">
+          <td>{{invite.email}}</td>
+          <td>{{invite.name}}</td>
+          <td class="text-right">
+            <button class="btn btn-inverse btn-mini " data-clipboard-text="{{invite.url}}" clipboard-button ng-click="ctrl.copyInviteToClipboard($event)">
+              <i class="fa fa-clipboard"></i> Copy Invite
+            </button>
+            &nbsp;
+            <button class="btn btn-inverse btn-mini">
+              Details
+              <i ng-show="!invite.expanded" class="fa fa-caret-right"></i>
+              <i ng-show="invite.expanded" class="fa fa-caret-down"></i>
+            </button>
+          </td>
+        </tr>
+        <tr ng-show="invite.expanded">
+          <td colspan="3">
+            <a href="{{invite.url}}">{{invite.url}}</a><br><br>
+            &nbsp;
+            <button class="btn btn-inverse btn-mini" ng-click="ctrl.revokeInvite(invite, $event)">
+              <i class="fa fa-remove" style="color: red"></i> Revoke invite
+            </button>
+            <span style="padding-left: 15px">
+              Invited: <em> {{invite.createdOn | date: 'shortDate'}} by {{invite.invitedBy}} </em>
+            </span>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+
+  </div>
 </div>
 </div>
 
 

+ 52 - 55
public/app/plugins/datasource/graphite/partials/query.options.html

@@ -63,64 +63,61 @@
 </section>
 </section>
 
 
 <div class="editor-row">
 <div class="editor-row">
-	<div class="pull-left">
-
-		<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
-			<h5>Shorter legend names</h5>
-			<ul>
-				<li>alias() function to specify a custom series name</li>
-				<li>aliasByNode(2) to alias by a specific part of your metric path</li>
-				<li>aliasByNode(2, -1) you can add multiple segment paths, and use negative index</li>
-				<li>groupByNode(2, 'sum') is useful if you have 2 wildcards in your metric path and want to sumSeries and group by</li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
+		<h5>Shorter legend names</h5>
+		<ul>
+			<li>alias() function to specify a custom series name</li>
+			<li>aliasByNode(2) to alias by a specific part of your metric path</li>
+			<li>aliasByNode(2, -1) you can add multiple segment paths, and use negative index</li>
+			<li>groupByNode(2, 'sum') is useful if you have 2 wildcards in your metric path and want to sumSeries and group by</li>
+		</ul>
+	</div>
 
 
-		<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
-			<h5>Series as parameter</h5>
-			<ul>
-				<li>Some graphite functions allow you to have many series arguments</li>
-				<li>Use #[A-Z] to use a graphite query as parameter to a function</li>
-				<li>
-					Examples:
-					<ul>
-						<li>asPercent(#A, #B)</li>
-						<li>prod.srv-01.counters.count - asPercent(#A) : percentage of count in comparison with A query</li>
-						<li>prod.srv-01.counters.count - sumSeries(#A) : sum count and series A </li>
-						<li>divideSeries(#A, #B)</li>
-					</ul>
-				</li>
-				<li>If a query is added only to be used as a parameter, hide it from the graph with the eye icon</li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
+		<h5>Series as parameter</h5>
+		<ul>
+			<li>Some graphite functions allow you to have many series arguments</li>
+			<li>Use #[A-Z] to use a graphite query as parameter to a function</li>
+			<li>
+				Examples:
+				<ul>
+					<li>asPercent(#A, #B)</li>
+					<li>prod.srv-01.counters.count - asPercent(#A) : percentage of count in comparison with A query</li>
+					<li>prod.srv-01.counters.count - sumSeries(#A) : sum count and series A </li>
+					<li>divideSeries(#A, #B)</li>
+				</ul>
+			</li>
+			<li>If a query is added only to be used as a parameter, hide it from the graph with the eye icon</li>
+		</ul>
+	</div>
 
 
-		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
-			<h5>Stacking</h5>
-			<ul>
-				<li>You find the stacking option under Display Styles tab</li>
-				<li>When stacking is enabled make sure null point mode is set to 'null as zero'</li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
+		<h5>Stacking</h5>
+		<ul>
+			<li>You find the stacking option under Display Styles tab</li>
+			<li>When stacking is enabled make sure null point mode is set to 'null as zero'</li>
+		</ul>
+	</div>
 
 
-		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 4">
-			<h5>Templating</h5>
-			<ul>
-				<li>You can use a template variable in place of metric names</li>
-				<li>You can use a template variable in place of function parameters</li>
-				<li>You enable the templating feature in Dashboard settings / Feature toggles </li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 4">
+		<h5>Templating</h5>
+		<ul>
+			<li>You can use a template variable in place of metric names</li>
+			<li>You can use a template variable in place of function parameters</li>
+			<li>You enable the templating feature in Dashboard settings / Feature toggles </li>
+		</ul>
+	</div>
 
 
-		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 5">
-			<h5>Max data points</h5>
-			<ul>
-				<li>Every graphite request is issued with a maxDataPoints parameter</li>
-				<li>Graphite uses this parameter to consolidate the real number of values down to this number</li>
-				<li>If there are more real values, then by default they will be consolidated using averages</li>
-				<li>This could hide real peaks and max values in your series</li>
-				<li>You can change how point consolidation is made using the consolidateBy graphite function</li>
-				<li>Point consolidation will effect series legend values (min,max,total,current)</li>
-				<li>If you override maxDataPoint and set a high value performance can be severely effected</li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 5">
+		<h5>Max data points</h5>
+		<ul>
+			<li>Every graphite request is issued with a maxDataPoints parameter</li>
+			<li>Graphite uses this parameter to consolidate the real number of values down to this number</li>
+			<li>If there are more real values, then by default they will be consolidated using averages</li>
+			<li>This could hide real peaks and max values in your series</li>
+			<li>You can change how point consolidation is made using the consolidateBy graphite function</li>
+			<li>Point consolidation will effect series legend values (min,max,total,current)</li>
+			<li>If you override maxDataPoint and set a high value performance can be severely effected</li>
+		</ul>
 	</div>
 	</div>
 </div>
 </div>

+ 31 - 34
public/app/plugins/datasource/influxdb/partials/query.options.html

@@ -37,42 +37,39 @@
 </section>
 </section>
 
 
 <div class="editor-row">
 <div class="editor-row">
-	<div class="pull-left">
-
-		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
-			<h5>Alias patterns</h5>
-			<ul>
-				<li>$m = replaced with measurement name</li>
-				<li>$measurement = replaced with measurement name</li>
-				<li>$1 - $9 = replaced with part of measurement name (if you separate your measurement name with dots)</li>
-				<li>$col = replaced with column name</li>
-				<li>$tag_exampletag = replaced with the value of the <i>exampletag</i> tag</li>
-				<li>You can also use [[tag_exampletag]] pattern replacement syntax</li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
+		<h5>Alias patterns</h5>
+		<ul>
+			<li>$m = replaced with measurement name</li>
+			<li>$measurement = replaced with measurement name</li>
+			<li>$1 - $9 = replaced with part of measurement name (if you separate your measurement name with dots)</li>
+			<li>$col = replaced with column name</li>
+			<li>$tag_exampletag = replaced with the value of the <i>exampletag</i> tag</li>
+			<li>You can also use [[tag_exampletag]] pattern replacement syntax</li>
+		</ul>
+	</div>
 
 
-		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
-			<h5>Stacking and fill</h5>
-			<ul>
-				<li>When stacking is enabled it is important that points align</li>
-				<li>If there are missing points for one series it can cause gaps or missing bars</li>
-				<li>You must use fill(0), and select a group by time low limit</li>
-				<li>Use the group by time option below your queries and specify for example &gt;10s if your metrics are written every 10 seconds</li>
-				<li>This will insert zeros for series that are missing measurements and will make stacking work properly</li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
+		<h5>Stacking and fill</h5>
+		<ul>
+			<li>When stacking is enabled it is important that points align</li>
+			<li>If there are missing points for one series it can cause gaps or missing bars</li>
+			<li>You must use fill(0), and select a group by time low limit</li>
+			<li>Use the group by time option below your queries and specify for example &gt;10s if your metrics are written every 10 seconds</li>
+			<li>This will insert zeros for series that are missing measurements and will make stacking work properly</li>
+		</ul>
+	</div>
 
 
-		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
-			<h5>Group by time</h5>
-			<ul>
-				<li>Group by time is important, otherwise the query could return many thousands of datapoints that will slow down Grafana</li>
-				<li>Leave the group by time field empty for each query and it will be calculated based on time range and pixel width of the graph</li>
-				<li>If you use fill(0) or fill(null) set a low limit for the auto group by time interval</li>
-				<li>The low limit can only be set in the group by time option below your queries</li>
-				<li>You set a low limit by adding a greater sign before the interval</li>
-				<li>Example: &gt;60s if you write metrics to InfluxDB every 60 seconds</li>
-			</ul>
-		</div>
+	<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
+		<h5>Group by time</h5>
+		<ul>
+			<li>Group by time is important, otherwise the query could return many thousands of datapoints that will slow down Grafana</li>
+			<li>Leave the group by time field empty for each query and it will be calculated based on time range and pixel width of the graph</li>
+			<li>If you use fill(0) or fill(null) set a low limit for the auto group by time interval</li>
+			<li>The low limit can only be set in the group by time option below your queries</li>
+			<li>You set a low limit by adding a greater sign before the interval</li>
+			<li>Example: &gt;60s if you write metrics to InfluxDB every 60 seconds</li>
+		</ul>
 	</div>
 	</div>
 </div>
 </div>
 
 

+ 3 - 1
public/sass/_variables.dark.scss

@@ -258,7 +258,6 @@ $popover-border-color:    $gray-1;
 $popover-help-bg:         $btn-secondary-bg;
 $popover-help-bg:         $btn-secondary-bg;
 $popover-help-color:      $text-color;
 $popover-help-color:      $text-color;
 
 
-
 // Tooltips and popovers
 // Tooltips and popovers
 // -------------------------
 // -------------------------
 $tooltipColor:            $popover-help-color;
 $tooltipColor:            $popover-help-color;
@@ -276,6 +275,9 @@ $card-background: linear-gradient(135deg, #2f2f2f, #262626);
 $card-background-hover: linear-gradient(135deg, #343434, #262626);
 $card-background-hover: linear-gradient(135deg, #343434, #262626);
 $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .3);
 $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .3);
 
 
+// info box
+$info-box-background: linear-gradient(120deg, #142749, #0e203e);
+
 // footer
 // footer
 $footer-link-color:   $gray-1;
 $footer-link-color:   $gray-1;
 $footer-link-hover:   $gray-4;
 $footer-link-hover:   $gray-4;

+ 3 - 0
public/sass/_variables.light.scss

@@ -300,6 +300,9 @@ $card-background: linear-gradient(135deg, $gray-5, $gray-6);
 $card-background-hover: linear-gradient(135deg, $gray-6, $gray-7);
 $card-background-hover: linear-gradient(135deg, $gray-6, $gray-7);
 $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .1);
 $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .1);
 
 
+// info box
+$info-box-background: linear-gradient(135deg, #f1fbff, #d7ebff);
+
 // footer
 // footer
 $footer-link-color:   $gray-3;
 $footer-link-color:   $gray-3;
 $footer-link-hover:   $dark-5;
 $footer-link-hover:   $dark-5;

+ 7 - 2
public/sass/components/_infobox.scss

@@ -5,15 +5,16 @@
   top: -13px;
   top: -13px;
   left: -8px;
   left: -8px;
   font-size: 20px;
   font-size: 20px;
-  color: $blue;
+  color: $text-color;
 }
 }
 
 
 .grafana-info-box {
 .grafana-info-box {
   position: relative;
   position: relative;
-  background: $card-background;
+  background: $info-box-background;
   box-shadow: $card-shadow;
   box-shadow: $card-shadow;
   padding: 1rem;
   padding: 1rem;
   border-radius: 4px;
   border-radius: 4px;
+  margin-bottom: $spacer;
 
 
   h5 {
   h5 {
     margin-bottom: $spacer;
     margin-bottom: $spacer;
@@ -21,5 +22,9 @@
   ul {
   ul {
     padding-left: $spacer;
     padding-left: $spacer;
   }
   }
+
+  a {
+    @extend .external-link;
+  }
 }
 }