瀏覽代碼

Unified Color picker fixes (#9466)

* colorpicker: fix opening error when color is undefined

* colorpicker: replace spectrum picker by new color picker

* colorpicker: remove old spectrum picker directive

* annotations: use tinycolor for working with region colors
Alexander Zobnin 8 年之前
父節點
當前提交
a174ad4c9a

+ 2 - 1
package.json

@@ -123,6 +123,7 @@
     "remarkable": "^1.7.1",
     "rxjs": "^5.4.3",
     "tether": "^1.4.0",
-    "tether-drop": "https://github.com/torkelo/drop"
+    "tether-drop": "https://github.com/torkelo/drop",
+    "tinycolor2": "^1.4.1"
   }
 }

+ 4 - 1
public/app/core/components/colorpicker/ColorPicker.tsx

@@ -77,5 +77,8 @@ export class ColorPicker extends React.Component<IProps, any> {
 }
 
 coreModule.directive('colorPicker', function (reactDirective) {
-  return reactDirective(ColorPicker, ['color', 'onChange']);
+  return reactDirective(ColorPicker, [
+    'color',
+    ['onChange', { watchDepth: 'reference', wrapApply: true }]
+  ]);
 });

+ 4 - 4
public/app/core/components/colorpicker/ColorPickerPopover.tsx

@@ -1,11 +1,11 @@
 import React from 'react';
 import $ from 'jquery';
+import tinycolor from 'tinycolor2';
 import coreModule from 'app/core/core_module';
 import { GfColorPalette } from './ColorPalette';
 import { GfSpectrumPicker } from './SpectrumPicker';
 
-// Spectrum picker uses TinyColor and loads it as a global variable, so we can use it here also
-declare var tinycolor;
+const DEFAULT_COLOR = '#000000';
 
 export interface IProps {
   color: string;
@@ -19,8 +19,8 @@ export class ColorPickerPopover extends React.Component<IProps, any> {
     super(props);
     this.state = {
       tab: 'palette',
-      color: this.props.color,
-      colorString: this.props.color
+      color: this.props.color || DEFAULT_COLOR,
+      colorString: this.props.color || DEFAULT_COLOR
     };
   }
 

+ 0 - 1
public/app/core/core.ts

@@ -5,7 +5,6 @@ import "./directives/dropdown_typeahead";
 import "./directives/metric_segment";
 import "./directives/misc";
 import "./directives/ng_model_on_blur";
-import "./directives/spectrum_picker";
 import "./directives/tags";
 import "./directives/value_select_dropdown";
 import "./directives/rebuild_on_change";

+ 0 - 41
public/app/core/directives/spectrum_picker.js

@@ -1,41 +0,0 @@
-define([
-  'angular',
-  '../core_module',
-  'vendor/spectrum',
-],
-function (angular, coreModule) {
-  'use strict';
-
-  coreModule.default.directive('spectrumPicker', function() {
-    return {
-      restrict: 'E',
-      require: 'ngModel',
-      scope: false,
-      replace: true,
-      template: "<span><input class='input-small' /></span>",
-      link: function(scope, element, attrs, ngModel) {
-        var input = element.find('input');
-        var options = angular.extend({
-          showAlpha: true,
-          showButtons: false,
-          color: ngModel.$viewValue,
-          change: function(color) {
-            scope.$apply(function() {
-              ngModel.$setViewValue(color.toRgbString());
-            });
-          }
-        }, scope.$eval(attrs.options));
-
-        ngModel.$render = function() {
-          input.spectrum('set', ngModel.$viewValue || '');
-        };
-
-        input.spectrum(options);
-
-        scope.$on('$destroy', function() {
-          input.spectrum('destroy');
-        });
-      }
-    };
-  });
-});

+ 2 - 3
public/app/core/utils/colors.ts

@@ -1,7 +1,5 @@
 import _ from 'lodash';
-
-// Spectrum picker uses TinyColor and loads it as a global variable, so we can use it here also
-declare var tinycolor;
+import tinycolor from 'tinycolor2';
 
 export const PALETTE_ROWS = 4;
 export const PALETTE_COLUMNS = 14;
@@ -9,6 +7,7 @@ export const DEFAULT_ANNOTATION_COLOR = 'rgba(0, 211, 255, 1)';
 export const OK_COLOR = "rgba(11, 237, 50, 1)";
 export const ALERTING_COLOR = "rgba(237, 46, 24, 1)";
 export const NO_DATA_COLOR = "rgba(150, 150, 150, 1)";
+export const REGION_FILL_ALPHA = 0.09;
 
 let colors = [
   "#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0",

+ 6 - 0
public/app/features/annotations/editor_ctrl.ts

@@ -33,6 +33,8 @@ export class AnnotationsEditorCtrl {
     this.datasources = datasourceSrv.getAnnotationSources();
     this.annotations = $scope.dashboard.annotations.list;
     this.reset();
+
+    this.onColorChange = this.onColorChange.bind(this);
   }
 
   datasourceChanged() {
@@ -83,6 +85,10 @@ export class AnnotationsEditorCtrl {
     this.$scope.broadcastRefresh();
   }
 
+  onColorChange(newColor) {
+    this.currentAnnotation.iconColor = newColor;
+  }
+
   annotationEnabledChange() {
     this.$scope.broadcastRefresh();
   }

+ 9 - 27
public/app/features/annotations/event_manager.ts

@@ -1,8 +1,9 @@
 import _ from 'lodash';
 import moment from 'moment';
+import tinycolor from 'tinycolor2';
 import {MetricsPanelCtrl} from 'app/plugins/sdk';
 import {AnnotationEvent} from './event';
-import {OK_COLOR, ALERTING_COLOR, NO_DATA_COLOR, DEFAULT_ANNOTATION_COLOR} from 'app/core/utils/colors';
+import {OK_COLOR, ALERTING_COLOR, NO_DATA_COLOR, DEFAULT_ANNOTATION_COLOR, REGION_FILL_ALPHA} from 'app/core/utils/colors';
 
 export class EventManager {
   event: AnnotationEvent;
@@ -151,36 +152,17 @@ function addRegionMarking(regions, flotOptions) {
       fillColor = defaultColor;
     }
 
-    // Convert #FFFFFF to rgb(255, 255, 255)
-    // because panels with alerting use this format
-    let hexPattern = /^#[\da-fA-f]{3,6}/;
-    if (hexPattern.test(fillColor)) {
-      fillColor = convertToRGB(fillColor);
-    }
-
-    fillColor = addAlphaToRGB(fillColor, 0.09);
+    fillColor = addAlphaToRGB(fillColor, REGION_FILL_ALPHA);
     markings.push({xaxis: {from: region.min, to: region.timeEnd}, color: fillColor});
   });
 }
 
-function addAlphaToRGB(rgb: string, alpha: number): string {
-  let rgbPattern = /^rgb\(/;
-  if (rgbPattern.test(rgb)) {
-    return rgb.replace(')', `, ${alpha})`).replace('rgb', 'rgba');
-  } else {
-    return rgb.replace(/[\d\.]+\)/, `${alpha})`);
-  }
-}
-
-function convertToRGB(hex: string): string {
-  let hexPattern = /#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})/g;
-  let match = hexPattern.exec(hex);
-  if (match) {
-    let rgb = _.map(match.slice(1), hex_val => {
-      return parseInt(hex_val, 16);
-    });
-    return 'rgb(' + rgb.join(',') + ')';
+function addAlphaToRGB(colorString: string, alpha: number): string {
+  let color = tinycolor(colorString);
+  if (color.isValid()) {
+    color.setAlpha(alpha);
+    return color.toRgbString();
   } else {
-    return '';
+    return colorString;
   }
 }

+ 4 - 2
public/app/features/annotations/partials/editor.html

@@ -119,8 +119,10 @@
 														label-class="width-7">
 						</gf-form-switch>
 						<div class="gf-form">
-							<label class="gf-form-label">Color</label>
-							<spectrum-picker class="gf-form-input width-3" ng-model="ctrl.currentAnnotation.iconColor"></spectrum-picker>
+							<label class="gf-form-label width-9">Color</label>
+							<span class="gf-form-label">
+								<color-picker color="ctrl.currentAnnotation.iconColor" onChange="ctrl.onColorChange"></color-picker>
+							</span>
 						</div>
 					</div>
 				</div>

+ 16 - 2
public/app/plugins/panel/graph/thresholds_form.ts

@@ -37,6 +37,20 @@ export class ThresholdFormCtrl {
   render() {
     this.panelCtrl.render();
   }
+
+  onFillColorChange(index) {
+    return (newColor) => {
+      this.panel.thresholds[index].fillColor = newColor;
+      this.render();
+    };
+  }
+
+  onLineColorChange(index) {
+    return (newColor) => {
+      this.panel.thresholds[index].lineColor = newColor;
+      this.render();
+    };
+  }
 }
 
 var template = `
@@ -77,7 +91,7 @@ var template = `
       <div class="gf-form" ng-if="threshold.fill && threshold.colorMode === 'custom'">
         <label class="gf-form-label">Fill color</label>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="threshold.fillColor" ng-change="ctrl.render()" ></spectrum-picker>
+          <color-picker color="threshold.fillColor" onChange="ctrl.onFillColorChange($index)"></color-picker>
         </span>
       </div>
 
@@ -87,7 +101,7 @@ var template = `
       <div class="gf-form" ng-if="threshold.line && threshold.colorMode === 'custom'">
         <label class="gf-form-label">Line color</label>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="threshold.lineColor" ng-change="ctrl.render()" ></spectrum-picker>
+          <color-picker color="threshold.lineColor" onChange="ctrl.onLineColorChange($index)"></color-picker>
         </span>
       </div>
 

+ 7 - 0
public/app/plugins/panel/heatmap/heatmap_ctrl.ts

@@ -119,6 +119,8 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
     this.events.on('data-error', this.onDataError.bind(this));
     this.events.on('data-snapshot-load', this.onDataReceived.bind(this));
     this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
+
+    this.onCardColorChange = this.onCardColorChange.bind(this);
   }
 
   onInitEditMode() {
@@ -236,6 +238,11 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
     this.render();
   }
 
+  onCardColorChange(newColor) {
+    this.panel.color.cardColor = newColor;
+    this.render();
+  }
+
   seriesHandler(seriesData) {
     let series = new TimeSeries({
       datapoints: seriesData.datapoints,

+ 1 - 1
public/app/plugins/panel/heatmap/partials/display_editor.html

@@ -12,7 +12,7 @@
       <div class="gf-form">
         <label class="gf-form-label width-9">Color</label>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="ctrl.panel.color.cardColor" ng-change="ctrl.render()" ></spectrum-picker>
+          <color-picker color="ctrl.panel.color.cardColor" onChange="ctrl.onCardColorChange"></color-picker>
         </span>
       </div>
       <div class="gf-form">

+ 4 - 10
public/app/plugins/panel/singlestat/editor.html

@@ -68,14 +68,8 @@
     </div>
     <div class="gf-form">
       <label class="gf-form-label width-8">Colors</label>
-      <span class="gf-form-label">
-        <color-picker color="ctrl.panel.colors[0]" onChange="ctrl.onColorChange(0)"></color-picker>
-      </span>
-      <span class="gf-form-label">
-        <color-picker color="ctrl.panel.colors[1]" onChange="ctrl.onColorChange(1)"></color-picker>
-      </span>
-      <span class="gf-form-label">
-        <color-picker color="ctrl.panel.colors[2]" onChange="ctrl.onColorChange(2)"></color-picker>
+      <span class="gf-form-label" ng-repeat="color in ctrl.panel.colors track by $index">
+        <color-picker color="color" onChange="ctrl.onColorChange($index)"></color-picker>
       </span>
       <span class="gf-form-label">
         <a  ng-click="ctrl.invertColorOrder()">
@@ -93,13 +87,13 @@
       <div class="gf-form">
         <label class="gf-form-label width-9">Line Color</label>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="ctrl.panel.sparkline.lineColor" ng-change="ctrl.render()" ></spectrum-picker>
+          <color-picker color="ctrl.panel.sparkline.lineColor" onChange="ctrl.onSparklineColorChange"></color-picker>
         </span>
       </div>
       <div class="gf-form">
         <label class="gf-form-label width-9">Fill Color</label>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="ctrl.panel.sparkline.fillColor" ng-change="ctrl.render()" ></spectrum-picker>
+          <color-picker color="ctrl.panel.sparkline.fillColor" onChange="ctrl.onSparklineFillChange"></color-picker>
         </span>
       </div>
     </div>

+ 13 - 0
public/app/plugins/panel/singlestat/module.ts

@@ -92,6 +92,9 @@ class SingleStatCtrl extends MetricsPanelCtrl {
     this.events.on('data-error', this.onDataError.bind(this));
     this.events.on('data-snapshot-load', this.onDataReceived.bind(this));
     this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
+
+    this.onSparklineColorChange = this.onSparklineColorChange.bind(this);
+    this.onSparklineFillChange = this.onSparklineFillChange.bind(this);
   }
 
   onInitEditMode() {
@@ -221,6 +224,16 @@ class SingleStatCtrl extends MetricsPanelCtrl {
     };
   }
 
+  onSparklineColorChange(newColor) {
+    this.panel.sparkline.lineColor = newColor;
+    this.render();
+  }
+
+  onSparklineFillChange(newColor) {
+    this.panel.sparkline.fillColor = newColor;
+    this.render();
+  }
+
   getDecimalsForValue(value) {
     if (_.isNumber(this.panel.decimals)) {
       return {decimals: this.panel.decimals, scaledDecimals: null};

+ 3 - 3
public/app/plugins/panel/table/column_options.html

@@ -80,13 +80,13 @@
       <div class="gf-form">
         <label class="gf-form-label width-8">Colors</label>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="style.colors[0]" ng-change="editor.render()"></spectrum-picker>
+          <color-picker color="style.colors[0]" onChange="editor.onColorChange($index, 0)"></color-picker>
         </span>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="style.colors[1]" ng-change="editor.render()"></spectrum-picker>
+          <color-picker color="style.colors[1]" onChange="editor.onColorChange($index, 1)"></color-picker>
         </span>
         <span class="gf-form-label">
-          <spectrum-picker ng-model="style.colors[2]" ng-change="editor.render()"></spectrum-picker>
+          <color-picker color="style.colors[2]" onChange="editor.onColorChange($index, 2)"></color-picker>
         </span>
         <div class="gf-form-label">
           <a class="pointer" ng-click="editor.invertColorOrder($index)">Invert</a>

+ 9 - 0
public/app/plugins/panel/table/column_options.ts

@@ -53,6 +53,8 @@ export class ColumnOptionsCtrl {
         return col.text;
       });
     };
+
+    this.onColorChange = this.onColorChange.bind(this);
   }
 
   render() {
@@ -104,6 +106,13 @@ export class ColumnOptionsCtrl {
     ref[2] = copy;
     this.panelCtrl.render();
   }
+
+  onColorChange(styleIndex, colorIndex) {
+    return (newColor) => {
+      this.panel.styles[styleIndex].colors[colorIndex] = newColor;
+      this.render();
+    };
+  }
 }
 
 /** @ngInject */