Explorar el Código

Merge remote-tracking branch 'grafana/master' into annotations-created

* grafana/master:
  docs: updated debian distro in install docs to stretch, closes #11527
  css: quick fix after IE11 changes
  fixed sidemenu icon issue created by earlier pr
  changelog: adds note for #11165
  migrated dash_class to ts
  migrated segment_srv to ts
  removed indent for manage dashboards
  created closeDropdown function, renamed appevent, added second appevent for open timepicker
  added if to onAppevent, renamed appevent, add appevent to applyCustom and setRelativeFilter
  docker: add users and groups to ldap block
  timepicker now closes without exiting edit/view mode, close order: modal, timepicker, view
  bounnd the esc key to exit timepicker
  added indent to dashboards inside folder in search dropdown, and added indent to dashboard icon in search item
ryan hace 7 años
padre
commit
39f37ff8aa

+ 1 - 0
CHANGELOG.md

@@ -14,6 +14,7 @@
 * **Prometheus**: Support POST for query and query_range [#9859](https://github.com/grafana/grafana/pull/9859), thx [@mtanda](https://github.com/mtanda)
 * **Prometheus**: Support POST for query and query_range [#9859](https://github.com/grafana/grafana/pull/9859), thx [@mtanda](https://github.com/mtanda)
 * **Alerting**: Add support for retries on alert queries [#5855](https://github.com/grafana/grafana/issues/5855), thx [@Thib17](https://github.com/Thib17)
 * **Alerting**: Add support for retries on alert queries [#5855](https://github.com/grafana/grafana/issues/5855), thx [@Thib17](https://github.com/Thib17)
 * **Table**: Table plugin value mappings [#7119](https://github.com/grafana/grafana/issues/7119), thx [infernix](https://github.com/infernix)
 * **Table**: Table plugin value mappings [#7119](https://github.com/grafana/grafana/issues/7119), thx [infernix](https://github.com/infernix)
+* **IE11**: IE 11 compatibility [#11165](https://github.com/grafana/grafana/issues/11165)
 
 
 ### Minor
 ### Minor
 * **OpsGenie**: Add triggered alerts as description [#11046](https://github.com/grafana/grafana/pull/11046), thx [@llamashoes](https://github.com/llamashoes)
 * **OpsGenie**: Add triggered alerts as description [#11046](https://github.com/grafana/grafana/pull/11046), thx [@llamashoes](https://github.com/llamashoes)

+ 1 - 0
docker/blocks/openldap/Dockerfile

@@ -17,6 +17,7 @@ EXPOSE 389
 VOLUME ["/etc/ldap", "/var/lib/ldap"]
 VOLUME ["/etc/ldap", "/var/lib/ldap"]
 
 
 COPY modules/ /etc/ldap.dist/modules
 COPY modules/ /etc/ldap.dist/modules
+COPY prepopulate/ /etc/ldap.dist/prepopulate
 
 
 COPY entrypoint.sh /entrypoint.sh
 COPY entrypoint.sh /entrypoint.sh
 
 

+ 7 - 3
docker/blocks/openldap/entrypoint.sh

@@ -65,7 +65,7 @@ EOF
     fi
     fi
 
 
     if [[ -n "$SLAPD_ADDITIONAL_SCHEMAS" ]]; then
     if [[ -n "$SLAPD_ADDITIONAL_SCHEMAS" ]]; then
-        IFS=","; declare -a schemas=($SLAPD_ADDITIONAL_SCHEMAS)
+        IFS=","; declare -a schemas=($SLAPD_ADDITIONAL_SCHEMAS); unset IFS
 
 
         for schema in "${schemas[@]}"; do
         for schema in "${schemas[@]}"; do
             slapadd -n0 -F /etc/ldap/slapd.d -l "/etc/ldap/schema/${schema}.ldif" >/dev/null 2>&1
             slapadd -n0 -F /etc/ldap/slapd.d -l "/etc/ldap/schema/${schema}.ldif" >/dev/null 2>&1
@@ -73,14 +73,18 @@ EOF
     fi
     fi
 
 
     if [[ -n "$SLAPD_ADDITIONAL_MODULES" ]]; then
     if [[ -n "$SLAPD_ADDITIONAL_MODULES" ]]; then
-        IFS=","; declare -a modules=($SLAPD_ADDITIONAL_MODULES)
+        IFS=","; declare -a modules=($SLAPD_ADDITIONAL_MODULES); unset IFS
 
 
         for module in "${modules[@]}"; do
         for module in "${modules[@]}"; do
              slapadd -n0 -F /etc/ldap/slapd.d -l "/etc/ldap/modules/${module}.ldif" >/dev/null 2>&1
              slapadd -n0 -F /etc/ldap/slapd.d -l "/etc/ldap/modules/${module}.ldif" >/dev/null 2>&1
         done
         done
     fi
     fi
 
 
-    chown -R openldap:openldap /etc/ldap/slapd.d/
+    for file in `ls /etc/ldap/prepopulate/*.ldif`; do
+        slapadd -F /etc/ldap/slapd.d -l "$file"
+    done
+
+    chown -R openldap:openldap /etc/ldap/slapd.d/ /var/lib/ldap/ /var/run/slapd/
 else
 else
     slapd_configs_in_env=`env | grep 'SLAPD_'`
     slapd_configs_in_env=`env | grep 'SLAPD_'`
 
 

+ 13 - 0
docker/blocks/openldap/notes.md

@@ -0,0 +1,13 @@
+# Notes on OpenLdap Docker Block
+
+Any ldif files added to the prepopulate subdirectory will be automatically imported into the OpenLdap database. 
+
+The ldif files add three users, `ldapviewer`, `ldapeditor` and `ldapadmin`. Two groups, `admins` and `users`, are added that correspond with the group mappings in the default conf/ldap.toml. `ldapadmin` is a member of `admins` and `ldapeditor` is a member of `users`.
+
+Note that users that are added here need to specify a `memberOf` attribute manually as well as the `member` attribute for the group. The `memberOf` module usually does this automatically (if you add a group in Apache Directory Studio for example) but this does not work in the entrypoint script as it uses the `slapadd` command to add entries before the server has started and before the `memberOf` module is loaded.
+
+After adding ldif files to `prepopulate`:
+
+1. Remove your current docker image: `docker rm docker_openldap_1`
+2. Build: `docker-compose build`
+3. `docker-compose up`

+ 10 - 0
docker/blocks/openldap/prepopulate/admin.ldif

@@ -0,0 +1,10 @@
+dn: cn=ldapadmin,dc=grafana,dc=org
+mail: ldapadmin@grafana.com
+userPassword: grafana
+objectClass: person
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+sn: ldapadmin
+cn: ldapadmin
+memberOf: cn=admins,dc=grafana,dc=org

+ 5 - 0
docker/blocks/openldap/prepopulate/adminsgroup.ldif

@@ -0,0 +1,5 @@
+dn: cn=admins,dc=grafana,dc=org
+cn: admins
+member: cn=ldapadmin,dc=grafana,dc=org
+objectClass: groupOfNames
+objectClass: top

+ 10 - 0
docker/blocks/openldap/prepopulate/editor.ldif

@@ -0,0 +1,10 @@
+dn: cn=ldapeditor,dc=grafana,dc=org
+mail: ldapeditor@grafana.com
+userPassword: grafana
+objectClass: person
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+sn: ldapeditor
+cn: ldapeditor
+memberOf: cn=users,dc=grafana,dc=org

+ 5 - 0
docker/blocks/openldap/prepopulate/usersgroup.ldif

@@ -0,0 +1,5 @@
+dn: cn=users,dc=grafana,dc=org
+cn: users
+member: cn=ldapeditor,dc=grafana,dc=org
+objectClass: groupOfNames
+objectClass: top

+ 9 - 0
docker/blocks/openldap/prepopulate/viewer.ldif

@@ -0,0 +1,9 @@
+dn: cn=ldapviewer,dc=grafana,dc=org
+mail: ldapviewer@grafana.com
+userPassword: grafana
+objectClass: person
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+sn: ldapviewer
+cn: ldapviewer

+ 2 - 2
docs/sources/installation/debian.md

@@ -34,7 +34,7 @@ sudo dpkg -i grafana_5.0.4_amd64.deb
 Add the following line to your `/etc/apt/sources.list` file.
 Add the following line to your `/etc/apt/sources.list` file.
 
 
 ```bash
 ```bash
-deb https://packagecloud.io/grafana/stable/debian/ jessie main
+deb https://packagecloud.io/grafana/stable/debian/ stretch main
 ```
 ```
 
 
 Use the above line even if you are on Ubuntu or another Debian version.
 Use the above line even if you are on Ubuntu or another Debian version.
@@ -42,7 +42,7 @@ There is also a testing repository if you want beta or release
 candidates.
 candidates.
 
 
 ```bash
 ```bash
-deb https://packagecloud.io/grafana/testing/debian/ jessie main
+deb https://packagecloud.io/grafana/testing/debian/ stretch main
 ```
 ```
 
 
 Then add the [Package Cloud](https://packagecloud.io/grafana) key. This
 Then add the [Package Cloud](https://packagecloud.io/grafana) key. This

+ 1 - 1
public/app/core/components/search/search_results.html

@@ -20,7 +20,7 @@
   <div class="search-section__header" ng-show="section.hideHeader"></div>
   <div class="search-section__header" ng-show="section.hideHeader"></div>
 
 
   <div ng-if="section.expanded">
   <div ng-if="section.expanded">
-    <a ng-repeat="item in section.items" class="search-item" ng-class="{'selected': item.selected}" ng-href="{{::item.url}}" >
+    <a ng-repeat="item in section.items" class="search-item search-item--indent" ng-class="{'selected': item.selected}" ng-href="{{::item.url}}" >
       <div ng-click="ctrl.toggleSelection(item, $event)">
       <div ng-click="ctrl.toggleSelection(item, $event)">
         <gf-form-switch
         <gf-form-switch
            ng-show="ctrl.editable"
            ng-show="ctrl.editable"

+ 0 - 36
public/app/core/directives/dash_class.js

@@ -1,36 +0,0 @@
-define([
-  'lodash',
-  'jquery',
-  '../core_module',
-],
-function (_, $, coreModule) {
-  'use strict';
-
-  coreModule.default.directive('dashClass', function() {
-    return {
-      link: function($scope, elem) {
-
-        $scope.onAppEvent('panel-fullscreen-enter', function() {
-          elem.toggleClass('panel-in-fullscreen', true);
-        });
-
-        $scope.onAppEvent('panel-fullscreen-exit', function() {
-          elem.toggleClass('panel-in-fullscreen', false);
-        });
-
-        $scope.$watch('ctrl.dashboardViewState.state.editview', function(newValue) {
-          if (newValue) {
-            elem.toggleClass('dashboard-page--settings-opening', _.isString(newValue));
-            setTimeout(function() {
-              elem.toggleClass('dashboard-page--settings-open', _.isString(newValue));
-            }, 10);
-          } else {
-            elem.removeClass('dashboard-page--settings-opening');
-            elem.removeClass('dashboard-page--settings-open');
-          }
-        });
-      }
-    };
-  });
-
-});

+ 31 - 0
public/app/core/directives/dash_class.ts

@@ -0,0 +1,31 @@
+import _ from 'lodash';
+import coreModule from '../core_module';
+
+/** @ngInject */
+export function dashClass() {
+  return {
+    link: function($scope, elem) {
+      $scope.onAppEvent('panel-fullscreen-enter', function() {
+        elem.toggleClass('panel-in-fullscreen', true);
+      });
+
+      $scope.onAppEvent('panel-fullscreen-exit', function() {
+        elem.toggleClass('panel-in-fullscreen', false);
+      });
+
+      $scope.$watch('ctrl.dashboardViewState.state.editview', function(newValue) {
+        if (newValue) {
+          elem.toggleClass('dashboard-page--settings-opening', _.isString(newValue));
+          setTimeout(function() {
+            elem.toggleClass('dashboard-page--settings-open', _.isString(newValue));
+          }, 10);
+        } else {
+          elem.removeClass('dashboard-page--settings-opening');
+          elem.removeClass('dashboard-page--settings-open');
+        }
+      });
+    },
+  };
+}
+
+coreModule.directive('dashClass', dashClass);

+ 9 - 1
public/app/core/services/keybindingSrv.ts

@@ -10,6 +10,7 @@ import 'mousetrap-global-bind';
 export class KeybindingSrv {
 export class KeybindingSrv {
   helpModal: boolean;
   helpModal: boolean;
   modalOpen = false;
   modalOpen = false;
+  timepickerOpen = false;
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private $rootScope, private $location) {
   constructor(private $rootScope, private $location) {
@@ -22,6 +23,8 @@ export class KeybindingSrv {
 
 
     this.setupGlobal();
     this.setupGlobal();
     appEvents.on('show-modal', () => (this.modalOpen = true));
     appEvents.on('show-modal', () => (this.modalOpen = true));
+    $rootScope.onAppEvent('timepickerOpen', () => (this.timepickerOpen = true));
+    $rootScope.onAppEvent('timepickerClosed', () => (this.timepickerOpen = false));
   }
   }
 
 
   setupGlobal() {
   setupGlobal() {
@@ -73,7 +76,12 @@ export class KeybindingSrv {
     appEvents.emit('hide-modal');
     appEvents.emit('hide-modal');
 
 
     if (!this.modalOpen) {
     if (!this.modalOpen) {
-      this.$rootScope.appEvent('panel-change-view', { fullscreen: false, edit: false });
+      if (this.timepickerOpen) {
+        this.$rootScope.appEvent('closeTimepicker');
+        this.timepickerOpen = false;
+      } else {
+        this.$rootScope.appEvent('panel-change-view', { fullscreen: false, edit: false });
+      }
     } else {
     } else {
       this.modalOpen = false;
       this.modalOpen = false;
     }
     }

+ 0 - 111
public/app/core/services/segment_srv.js

@@ -1,111 +0,0 @@
-define([
-  'angular',
-  'lodash',
-  '../core_module',
-],
-function (angular, _, coreModule) {
-  'use strict';
-
-  coreModule.default.service('uiSegmentSrv', function($sce, templateSrv) {
-    var self = this;
-
-    function MetricSegment(options) {
-      if (options === '*' || options.value === '*') {
-        this.value = '*';
-        this.html = $sce.trustAsHtml('<i class="fa fa-asterisk"><i>');
-        this.type = options.type;
-        this.expandable = true;
-        return;
-      }
-
-      if (_.isString(options)) {
-        this.value = options;
-        this.html = $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value));
-        return;
-      }
-
-      // temp hack to work around legacy inconsistency in segment model
-      this.text = options.value;
-
-      this.cssClass = options.cssClass;
-      this.custom = options.custom;
-      this.type = options.type;
-      this.fake = options.fake;
-      this.value = options.value;
-      this.selectMode = options.selectMode;
-      this.type = options.type;
-      this.expandable = options.expandable;
-      this.html = options.html || $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value));
-    }
-
-    this.getSegmentForValue = function(value, fallbackText) {
-      if (value) {
-        return this.newSegment(value);
-      } else {
-        return this.newSegment({value: fallbackText, fake: true});
-      }
-    };
-
-    this.newSelectMeasurement = function() {
-      return new MetricSegment({value: 'select measurement', fake: true});
-    };
-
-    this.newFake = function(text, type, cssClass) {
-      return new MetricSegment({value: text, fake: true, type: type, cssClass: cssClass});
-    };
-
-    this.newSegment = function(options) {
-      return new MetricSegment(options);
-    };
-
-    this.newKey = function(key) {
-      return new MetricSegment({value: key, type: 'key', cssClass: 'query-segment-key' });
-    };
-
-    this.newKeyValue = function(value) {
-      return new MetricSegment({value: value, type: 'value', cssClass: 'query-segment-value' });
-    };
-
-    this.newCondition = function(condition) {
-      return new MetricSegment({value: condition, type: 'condition', cssClass: 'query-keyword' });
-    };
-
-    this.newOperator = function(op) {
-      return new MetricSegment({value: op, type: 'operator', cssClass: 'query-segment-operator' });
-    };
-
-    this.newOperators = function(ops) {
-      return _.map(ops, function(op) {
-        return new MetricSegment({value: op, type: 'operator', cssClass: 'query-segment-operator' });
-      });
-    };
-
-    this.transformToSegments = function(addTemplateVars, variableTypeFilter) {
-      return function(results) {
-        var segments = _.map(results, function(segment) {
-          return self.newSegment({value: segment.text, expandable: segment.expandable});
-        });
-
-        if (addTemplateVars) {
-          _.each(templateSrv.variables, function(variable) {
-            if (variableTypeFilter === void 0 || variableTypeFilter === variable.type) {
-              segments.unshift(self.newSegment({ type: 'value', value: '$' + variable.name, expandable: true }));
-            }
-          });
-        }
-
-        return segments;
-      };
-    };
-
-    this.newSelectMetric = function() {
-      return new MetricSegment({value: 'select metric', fake: true});
-    };
-
-    this.newPlusButton = function() {
-      return new MetricSegment({fake: true, html: '<i class="fa fa-plus "></i>', type: 'plus-button', cssClass: 'query-part' });
-    };
-
-  });
-
-});

+ 111 - 0
public/app/core/services/segment_srv.ts

@@ -0,0 +1,111 @@
+import _ from 'lodash';
+import coreModule from '../core_module';
+
+/** @ngInject */
+export function uiSegmentSrv($sce, templateSrv) {
+  let self = this;
+
+  function MetricSegment(options) {
+    if (options === '*' || options.value === '*') {
+      this.value = '*';
+      this.html = $sce.trustAsHtml('<i class="fa fa-asterisk"><i>');
+      this.type = options.type;
+      this.expandable = true;
+      return;
+    }
+
+    if (_.isString(options)) {
+      this.value = options;
+      this.html = $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value));
+      return;
+    }
+
+    // temp hack to work around legacy inconsistency in segment model
+    this.text = options.value;
+
+    this.cssClass = options.cssClass;
+    this.custom = options.custom;
+    this.type = options.type;
+    this.fake = options.fake;
+    this.value = options.value;
+    this.selectMode = options.selectMode;
+    this.type = options.type;
+    this.expandable = options.expandable;
+    this.html = options.html || $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value));
+  }
+
+  this.getSegmentForValue = function(value, fallbackText) {
+    if (value) {
+      return this.newSegment(value);
+    } else {
+      return this.newSegment({ value: fallbackText, fake: true });
+    }
+  };
+
+  this.newSelectMeasurement = function() {
+    return new MetricSegment({ value: 'select measurement', fake: true });
+  };
+
+  this.newFake = function(text, type, cssClass) {
+    return new MetricSegment({ value: text, fake: true, type: type, cssClass: cssClass });
+  };
+
+  this.newSegment = function(options) {
+    return new MetricSegment(options);
+  };
+
+  this.newKey = function(key) {
+    return new MetricSegment({ value: key, type: 'key', cssClass: 'query-segment-key' });
+  };
+
+  this.newKeyValue = function(value) {
+    return new MetricSegment({ value: value, type: 'value', cssClass: 'query-segment-value' });
+  };
+
+  this.newCondition = function(condition) {
+    return new MetricSegment({ value: condition, type: 'condition', cssClass: 'query-keyword' });
+  };
+
+  this.newOperator = function(op) {
+    return new MetricSegment({ value: op, type: 'operator', cssClass: 'query-segment-operator' });
+  };
+
+  this.newOperators = function(ops) {
+    return _.map(ops, function(op) {
+      return new MetricSegment({ value: op, type: 'operator', cssClass: 'query-segment-operator' });
+    });
+  };
+
+  this.transformToSegments = function(addTemplateVars, variableTypeFilter) {
+    return function(results) {
+      let segments = _.map(results, function(segment) {
+        return self.newSegment({ value: segment.text, expandable: segment.expandable });
+      });
+
+      if (addTemplateVars) {
+        _.each(templateSrv.variables, function(variable) {
+          if (variableTypeFilter === void 0 || variableTypeFilter === variable.type) {
+            segments.unshift(self.newSegment({ type: 'value', value: '$' + variable.name, expandable: true }));
+          }
+        });
+      }
+
+      return segments;
+    };
+  };
+
+  this.newSelectMetric = function() {
+    return new MetricSegment({ value: 'select metric', fake: true });
+  };
+
+  this.newPlusButton = function() {
+    return new MetricSegment({
+      fake: true,
+      html: '<i class="fa fa-plus "></i>',
+      type: 'plus-button',
+      cssClass: 'query-part',
+    });
+  };
+}
+
+coreModule.service('uiSegmentSrv', uiSegmentSrv);

+ 10 - 4
public/app/features/dashboard/timepicker/timepicker.ts

@@ -22,7 +22,6 @@ export class TimePickerCtrl {
   refresh: any;
   refresh: any;
   isUtc: boolean;
   isUtc: boolean;
   firstDayOfWeek: number;
   firstDayOfWeek: number;
-  closeDropdown: any;
   isOpen: boolean;
   isOpen: boolean;
 
 
   /** @ngInject */
   /** @ngInject */
@@ -32,6 +31,7 @@ export class TimePickerCtrl {
     $rootScope.onAppEvent('shift-time-forward', () => this.move(1), $scope);
     $rootScope.onAppEvent('shift-time-forward', () => this.move(1), $scope);
     $rootScope.onAppEvent('shift-time-backward', () => this.move(-1), $scope);
     $rootScope.onAppEvent('shift-time-backward', () => this.move(-1), $scope);
     $rootScope.onAppEvent('refresh', this.onRefresh.bind(this), $scope);
     $rootScope.onAppEvent('refresh', this.onRefresh.bind(this), $scope);
+    $rootScope.onAppEvent('closeTimepicker', this.openDropdown.bind(this), $scope);
 
 
     // init options
     // init options
     this.panel = this.dashboard.timepicker;
     this.panel = this.dashboard.timepicker;
@@ -96,7 +96,7 @@ export class TimePickerCtrl {
 
 
   openDropdown() {
   openDropdown() {
     if (this.isOpen) {
     if (this.isOpen) {
-      this.isOpen = false;
+      this.closeDropdown();
       return;
       return;
     }
     }
 
 
@@ -112,6 +112,12 @@ export class TimePickerCtrl {
 
 
     this.refresh.options.unshift({ text: 'off' });
     this.refresh.options.unshift({ text: 'off' });
     this.isOpen = true;
     this.isOpen = true;
+    this.$rootScope.appEvent('timepickerOpen');
+  }
+
+  closeDropdown() {
+    this.isOpen = false;
+    this.$rootScope.appEvent('timepickerClosed');
   }
   }
 
 
   applyCustom() {
   applyCustom() {
@@ -120,7 +126,7 @@ export class TimePickerCtrl {
     }
     }
 
 
     this.timeSrv.setTime(this.editTimeRaw);
     this.timeSrv.setTime(this.editTimeRaw);
-    this.isOpen = false;
+    this.closeDropdown();
   }
   }
 
 
   absoluteFromChanged() {
   absoluteFromChanged() {
@@ -143,7 +149,7 @@ export class TimePickerCtrl {
     }
     }
 
 
     this.timeSrv.setTime(range);
     this.timeSrv.setTime(range);
-    this.isOpen = false;
+    this.closeDropdown();
   }
   }
 }
 }
 
 

+ 2 - 4
public/sass/base/_icons.scss

@@ -1,10 +1,8 @@
 .gicon {
 .gicon {
   line-height: 1;
   line-height: 1;
   display: inline-block;
   display: inline-block;
-  //width: 1.1057142857em;
-  //height: 1.1057142857em;
-  height: 22px;
-  width: 22px;
+  width: 1.1057142857em;
+  height: 1.1057142857em;
   text-align: center;
   text-align: center;
   background-repeat: no-repeat;
   background-repeat: no-repeat;
   background-position: center;
   background-position: center;

+ 4 - 0
public/sass/components/_search.scss

@@ -60,6 +60,10 @@
   display: flex;
   display: flex;
   flex-direction: column;
   flex-direction: column;
   flex-grow: 1;
   flex-grow: 1;
+
+  .search-item--indent {
+    margin-left: 14px;
+  }
 }
 }
 
 
 .search-dropdown__col_2 {
 .search-dropdown__col_2 {

+ 2 - 0
public/sass/components/_sidemenu.scss

@@ -123,6 +123,8 @@
     position: relative;
     position: relative;
     opacity: 0.7;
     opacity: 0.7;
     font-size: 130%;
     font-size: 130%;
+    height: 22px;
+    width: 22px;
   }
   }
 
 
   .fa {
   .fa {

+ 1 - 1
public/sass/pages/_dashboard.scss

@@ -33,7 +33,7 @@ div.flot-text {
   border: $panel-border;
   border: $panel-border;
   position: relative;
   position: relative;
   border-radius: 3px;
   border-radius: 3px;
-  //height: 100%;
+  height: 100%;
 
 
   &.panel-transparent {
   &.panel-transparent {
     background-color: transparent;
     background-color: transparent;