Commit a174ad4c by Alexander Zobnin Committed by Torkel Ödegaard

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
parent 6ce990af
......@@ -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"
}
}
......@@ -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 }]
]);
});
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
};
}
......
......@@ -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";
......
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');
});
}
};
});
});
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",
......
......@@ -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();
}
......
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;
}
}
......@@ -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>
......
......@@ -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>
......
......@@ -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,
......
......@@ -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">
......
......@@ -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>
......
......@@ -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};
......
......@@ -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>
......
......@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment