mirror of https://github.com/grafana/grafana.git
				
				
				
			feat: more work on #8768
This commit is contained in:
		
							parent
							
								
									23558c61d4
								
							
						
					
					
						commit
						73563d087c
					
				| 
						 | 
					@ -131,17 +131,20 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	jsonObj := map[string]interface{}{
 | 
						jsonObj := map[string]interface{}{
 | 
				
			||||||
		"defaultDatasource":  defaultDatasource,
 | 
							"defaultDatasource":       defaultDatasource,
 | 
				
			||||||
		"datasources":        datasources,
 | 
							"datasources":             datasources,
 | 
				
			||||||
		"panels":             panels,
 | 
							"panels":                  panels,
 | 
				
			||||||
		"appSubUrl":          setting.AppSubUrl,
 | 
							"appSubUrl":               setting.AppSubUrl,
 | 
				
			||||||
		"allowOrgCreate":     (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
 | 
							"allowOrgCreate":          (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
 | 
				
			||||||
		"authProxyEnabled":   setting.AuthProxyEnabled,
 | 
							"authProxyEnabled":        setting.AuthProxyEnabled,
 | 
				
			||||||
		"ldapEnabled":        setting.LdapEnabled,
 | 
							"ldapEnabled":             setting.LdapEnabled,
 | 
				
			||||||
		"alertingEnabled":    setting.AlertingEnabled,
 | 
							"alertingEnabled":         setting.AlertingEnabled,
 | 
				
			||||||
		"googleAnalyticsId":  setting.GoogleAnalyticsId,
 | 
							"googleAnalyticsId":       setting.GoogleAnalyticsId,
 | 
				
			||||||
		"disableLoginForm":   setting.DisableLoginForm,
 | 
							"disableLoginForm":        setting.DisableLoginForm,
 | 
				
			||||||
		"disableSignoutMenu": setting.DisableSignoutMenu,
 | 
							"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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,18 +90,18 @@ var (
 | 
				
			||||||
	SnapShotRemoveExpired bool
 | 
						SnapShotRemoveExpired bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// User settings
 | 
						// User settings
 | 
				
			||||||
	AllowUserSignUp     bool
 | 
						AllowUserSignUp         bool
 | 
				
			||||||
	AllowUserOrgCreate  bool
 | 
						AllowUserOrgCreate      bool
 | 
				
			||||||
	AutoAssignOrg       bool
 | 
						AutoAssignOrg           bool
 | 
				
			||||||
	AutoAssignOrgRole   string
 | 
						AutoAssignOrgRole       string
 | 
				
			||||||
	VerifyEmailEnabled  bool
 | 
						VerifyEmailEnabled      bool
 | 
				
			||||||
	LoginHint           string
 | 
						LoginHint               string
 | 
				
			||||||
	DefaultTheme        string
 | 
						DefaultTheme            string
 | 
				
			||||||
	DisableLoginForm    bool
 | 
						DisableLoginForm        bool
 | 
				
			||||||
	DisableSignoutMenu  bool
 | 
						DisableSignoutMenu      bool
 | 
				
			||||||
	ManageUsersLinkUrl  string
 | 
						ExternalUserMngLinkUrl  string
 | 
				
			||||||
	ManageUsersLinkName string
 | 
						ExternalUserMngLinkName string
 | 
				
			||||||
	ManageUsersInfo     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()
 | 
						ExternalUserMngLinkUrl = users.Key("external_manage_link_url").String()
 | 
				
			||||||
	ManageUsersLinkName = users.Key("external_manage_link_name").String()
 | 
						ExternalUserMngLinkName = users.Key("external_manage_link_name").String()
 | 
				
			||||||
	ManageUsersInfo = users.Key("external_manage_info").String()
 | 
						ExternalUserMngInfo = users.Key("external_manage_info").String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// auth
 | 
						// auth
 | 
				
			||||||
	auth := Cfg.Section("auth")
 | 
						auth := Cfg.Section("auth")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					    var src = config.disableLoginForm
 | 
				
			||||||
      ? 'public/app/features/org/partials/invite.html'
 | 
					      ? 'public/app/features/org/partials/add_user.html'
 | 
				
			||||||
      : '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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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">
 | 
					  <div class="grafana-info-box" ng-if="ctrl.externalUserMngInfo">
 | 
				
			||||||
		<table class="filter-table form-inline">
 | 
					    <span ng-bind-html="ctrl.externalUserMngInfo"></span>
 | 
				
			||||||
			<thead>
 | 
					  </div>
 | 
				
			||||||
				<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 ng-if="ctrl.editor.index === 1 && ctrl.showInviteUI">
 | 
					  <div ng-if="ctrl.editor.index === 0" class="tab-content">
 | 
				
			||||||
		<table class="filter-table form-inline">
 | 
					    <table class="filter-table form-inline">
 | 
				
			||||||
			<thead>
 | 
					      <thead>
 | 
				
			||||||
				<tr>
 | 
					        <tr>
 | 
				
			||||||
					<th>Email</th>
 | 
					          <th>Login</th>
 | 
				
			||||||
					<th>Name</th>
 | 
					          <th>Email</th>
 | 
				
			||||||
					<th></th>
 | 
					          <th>Role</th>
 | 
				
			||||||
				</tr>
 | 
					          <th style="width: 34px;"></th>
 | 
				
			||||||
			</thead>
 | 
					        </tr>
 | 
				
			||||||
			<tbody ng-repeat="invite in ctrl.pendingInvites">
 | 
					      </thead>
 | 
				
			||||||
				<tr ng-click="invite.expanded = !invite.expanded" ng-class="{'expanded': invite.expanded}">
 | 
					      <tr ng-repeat="user in ctrl.users">
 | 
				
			||||||
					<td>{{invite.email}}</td>
 | 
					        <td>{{user.login}}</td>
 | 
				
			||||||
					<td>{{invite.name}}</td>
 | 
					        <td><span class="ellipsis">{{user.email}}</span></td>
 | 
				
			||||||
					<td class="text-right">
 | 
					        <td>
 | 
				
			||||||
						<button class="btn btn-inverse btn-mini " data-clipboard-text="{{invite.url}}" clipboard-button ng-click="ctrl.copyInviteToClipboard($event)">
 | 
					          <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)">
 | 
				
			||||||
							<i class="fa fa-clipboard"></i> Copy Invite
 | 
					          </select>
 | 
				
			||||||
						</button>
 | 
					        </td>
 | 
				
			||||||
						 
 | 
					        <td>
 | 
				
			||||||
						<button class="btn btn-inverse btn-mini">
 | 
					          <a ng-click="ctrl.removeUser(user)" class="btn btn-danger btn-mini">
 | 
				
			||||||
							Details
 | 
					            <i class="fa fa-remove"></i>
 | 
				
			||||||
							<i ng-show="!invite.expanded" class="fa fa-caret-right"></i>
 | 
					          </a>
 | 
				
			||||||
							<i ng-show="invite.expanded" class="fa fa-caret-down"></i>
 | 
					        </td>
 | 
				
			||||||
						</button>
 | 
					      </tr>
 | 
				
			||||||
					</td>
 | 
					    </table>
 | 
				
			||||||
				</tr>
 | 
					  </div>
 | 
				
			||||||
				<tr ng-show="invite.expanded">
 | 
					 | 
				
			||||||
					<td colspan="3">
 | 
					 | 
				
			||||||
						<a href="{{invite.url}}">{{invite.url}}</a><br><br>
 | 
					 | 
				
			||||||
						 
 | 
					 | 
				
			||||||
						<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 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>
 | 
				
			||||||
 | 
					             
 | 
				
			||||||
 | 
					            <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>
 | 
				
			||||||
 | 
					             
 | 
				
			||||||
 | 
					            <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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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">
 | 
						<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
 | 
				
			||||||
			<h5>Shorter legend names</h5>
 | 
							<h5>Series as parameter</h5>
 | 
				
			||||||
			<ul>
 | 
							<ul>
 | 
				
			||||||
				<li>alias() function to specify a custom series name</li>
 | 
								<li>Some graphite functions allow you to have many series arguments</li>
 | 
				
			||||||
				<li>aliasByNode(2) to alias by a specific part of your metric path</li>
 | 
								<li>Use #[A-Z] to use a graphite query as parameter to a function</li>
 | 
				
			||||||
				<li>aliasByNode(2, -1) you can add multiple segment paths, and use negative index</li>
 | 
								<li>
 | 
				
			||||||
				<li>groupByNode(2, 'sum') is useful if you have 2 wildcards in your metric path and want to sumSeries and group by</li>
 | 
									Examples:
 | 
				
			||||||
			</ul>
 | 
									<ul>
 | 
				
			||||||
		</div>
 | 
										<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">
 | 
						<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
 | 
				
			||||||
			<h5>Series as parameter</h5>
 | 
							<h5>Stacking</h5>
 | 
				
			||||||
			<ul>
 | 
							<ul>
 | 
				
			||||||
				<li>Some graphite functions allow you to have many series arguments</li>
 | 
								<li>You find the stacking option under Display Styles tab</li>
 | 
				
			||||||
				<li>Use #[A-Z] to use a graphite query as parameter to a function</li>
 | 
								<li>When stacking is enabled make sure null point mode is set to 'null as zero'</li>
 | 
				
			||||||
				<li>
 | 
							</ul>
 | 
				
			||||||
					Examples:
 | 
						</div>
 | 
				
			||||||
					<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">
 | 
						<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 4">
 | 
				
			||||||
			<h5>Stacking</h5>
 | 
							<h5>Templating</h5>
 | 
				
			||||||
			<ul>
 | 
							<ul>
 | 
				
			||||||
				<li>You find the stacking option under Display Styles tab</li>
 | 
								<li>You can use a template variable in place of metric names</li>
 | 
				
			||||||
				<li>When stacking is enabled make sure null point mode is set to 'null as zero'</li>
 | 
								<li>You can use a template variable in place of function parameters</li>
 | 
				
			||||||
			</ul>
 | 
								<li>You enable the templating feature in Dashboard settings / Feature toggles </li>
 | 
				
			||||||
		</div>
 | 
							</ul>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 4">
 | 
						<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 5">
 | 
				
			||||||
			<h5>Templating</h5>
 | 
							<h5>Max data points</h5>
 | 
				
			||||||
			<ul>
 | 
							<ul>
 | 
				
			||||||
				<li>You can use a template variable in place of metric names</li>
 | 
								<li>Every graphite request is issued with a maxDataPoints parameter</li>
 | 
				
			||||||
				<li>You can use a template variable in place of function parameters</li>
 | 
								<li>Graphite uses this parameter to consolidate the real number of values down to this number</li>
 | 
				
			||||||
				<li>You enable the templating feature in Dashboard settings / Feature toggles </li>
 | 
								<li>If there are more real values, then by default they will be consolidated using averages</li>
 | 
				
			||||||
			</ul>
 | 
								<li>This could hide real peaks and max values in your series</li>
 | 
				
			||||||
		</div>
 | 
								<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>
 | 
				
			||||||
		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 5">
 | 
								<li>If you override maxDataPoint and set a high value performance can be severely effected</li>
 | 
				
			||||||
			<h5>Max data points</h5>
 | 
							</ul>
 | 
				
			||||||
			<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>
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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">
 | 
						<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
 | 
				
			||||||
			<h5>Alias patterns</h5>
 | 
							<h5>Stacking and fill</h5>
 | 
				
			||||||
			<ul>
 | 
							<ul>
 | 
				
			||||||
				<li>$m = replaced with measurement name</li>
 | 
								<li>When stacking is enabled it is important that points align</li>
 | 
				
			||||||
				<li>$measurement = replaced with measurement name</li>
 | 
								<li>If there are missing points for one series it can cause gaps or missing bars</li>
 | 
				
			||||||
				<li>$1 - $9 = replaced with part of measurement name (if you separate your measurement name with dots)</li>
 | 
								<li>You must use fill(0), and select a group by time low limit</li>
 | 
				
			||||||
				<li>$col = replaced with column name</li>
 | 
								<li>Use the group by time option below your queries and specify for example >10s if your metrics are written every 10 seconds</li>
 | 
				
			||||||
				<li>$tag_exampletag = replaced with the value of the <i>exampletag</i> tag</li>
 | 
								<li>This will insert zeros for series that are missing measurements and will make stacking work properly</li>
 | 
				
			||||||
				<li>You can also use [[tag_exampletag]] pattern replacement syntax</li>
 | 
							</ul>
 | 
				
			||||||
			</ul>
 | 
						</div>
 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
 | 
						<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
 | 
				
			||||||
			<h5>Stacking and fill</h5>
 | 
							<h5>Group by time</h5>
 | 
				
			||||||
			<ul>
 | 
							<ul>
 | 
				
			||||||
				<li>When stacking is enabled it is important that points align</li>
 | 
								<li>Group by time is important, otherwise the query could return many thousands of datapoints that will slow down Grafana</li>
 | 
				
			||||||
				<li>If there are missing points for one series it can cause gaps or missing bars</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>You must use fill(0), and select a group by time low limit</li>
 | 
								<li>If you use fill(0) or fill(null) set a low limit for the auto group by time interval</li>
 | 
				
			||||||
				<li>Use the group by time option below your queries and specify for example >10s if your metrics are written every 10 seconds</li>
 | 
								<li>The low limit can only be set in the group by time option below your queries</li>
 | 
				
			||||||
				<li>This will insert zeros for series that are missing measurements and will make stacking work properly</li>
 | 
								<li>You set a low limit by adding a greater sign before the interval</li>
 | 
				
			||||||
			</ul>
 | 
								<li>Example: >60s if you write metrics to InfluxDB every 60 seconds</li>
 | 
				
			||||||
		</div>
 | 
							</ul>
 | 
				
			||||||
 | 
					 | 
				
			||||||
		<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: >60s if you write metrics to InfluxDB every 60 seconds</li>
 | 
					 | 
				
			||||||
			</ul>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue