fix bucket color, tooltip status shadow, undefined color error.

This commit is contained in:
Ivan Mikheykin
2018-09-06 13:58:22 +03:00
parent a48bbf1945
commit 4a81b3a7bb
4 changed files with 67 additions and 90 deletions
+7 -63
View File
@@ -76,7 +76,7 @@ mod.directive('statusHeatmapLegend', function() {
drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue); drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue);
} else if (panel.color.mode === 'discrete') { } else if (panel.color.mode === 'discrete') {
let colorOptions = panel.color; let colorOptions = panel.color;
drawDiscreteColorLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue); drawDiscreteColorLegend(elem, colorOptions, ctrl.discreteHelper);
} }
} }
} }
@@ -150,7 +150,7 @@ function drawOpacityLegend(elem, options, rangeFrom, rangeTo, maxValue, minValue
drawLegendValues(elem, opacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth); drawLegendValues(elem, opacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth);
} }
function drawDiscreteColorLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue) { function drawDiscreteColorLegend(elem, colorOptions, discreteHelper) {
let legendElem = $(elem).find('svg'); let legendElem = $(elem).find('svg');
let legend = d3.select(legendElem.get(0)); let legend = d3.select(legendElem.get(0));
clearLegend(elem); clearLegend(elem);
@@ -185,19 +185,18 @@ function drawDiscreteColorLegend(elem, colorOptions, rangeFrom, rangeTo, maxValu
let legendHeight = legendElem.attr("height"); let legendHeight = legendElem.attr("height");
let rangeStep = Math.floor(legendWidth / valuesNumber); let itemWidth = Math.floor(legendWidth / valuesNumber);
let valuesRange = d3.range(0, legendWidth, rangeStep); let valuesRange = d3.range(valuesNumber); // from 0 to valuesNumber-1
let colorScale = getDiscreteColorScale(colorOptions, legendWidth);
legend.selectAll(".status-heatmap-color-legend-rect") legend.selectAll(".status-heatmap-color-legend-rect")
.data(valuesRange) .data(valuesRange)
.enter().append("rect") .enter().append("rect")
.attr("x", d => d) .attr("x", d => d*itemWidth)
.attr("y", 0) .attr("y", 0)
.attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps .attr("width", itemWidth + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight) .attr("height", legendHeight)
.attr("stroke-width", 0) .attr("stroke-width", 0)
.attr("fill", d => colorScale(d)); .attr("fill", d => discreteHelper.getDiscreteColor(d));
drawDiscreteLegendValues(elem, colorOptions, legendWidth); drawDiscreteLegendValues(elem, colorOptions, legendWidth);
} }
@@ -288,31 +287,6 @@ function drawDiscreteLegendValues(elem, colorOptions, legendWidth) {
legend.select(".axis").select(".domain").remove(); legend.select(".axis").select(".domain").remove();
} }
function drawSimpleColorLegend(elem, colorScale) {
let legendElem = $(elem).find('svg');
clearLegend(elem);
let legendWidth = Math.floor(legendElem.outerWidth());
let legendHeight = legendElem.attr("height");
if (legendWidth) {
let valuesNumber = Math.floor(legendWidth / 2);
let rangeStep = Math.floor(legendWidth / valuesNumber);
let valuesRange = d3.range(0, legendWidth, rangeStep);
let legend = d3.select(legendElem.get(0));
var legendRects = legend.selectAll(".status-heatmap-color-legend-rect").data(valuesRange);
legendRects.enter().append("rect")
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", d => colorScale(d));
}
}
function drawSimpleOpacityLegend(elem, options) { function drawSimpleOpacityLegend(elem, options) {
let legendElem = $(elem).find('svg'); let legendElem = $(elem).find('svg');
let graphElem = $(elem); let graphElem = $(elem);
@@ -366,36 +340,6 @@ function getColorScale(colorScheme, maxValue, minValue = 0) {
return d3.scaleSequential(colorInterpolator).domain([start, end]); return d3.scaleSequential(colorInterpolator).domain([start, end]);
} }
// scale input range to discrete colors to draw a legend
function getDiscreteColorScale(colorOptions, maxValue, minValue = 0) {
let start = minValue;
let end = maxValue;
let thresholdValues = [];
let thresholdColors = [];
for (let i = 0; i < colorOptions.thresholds.length; i++) {
thresholdColors.push(colorOptions.thresholds[i].color);
thresholdValues.push(colorOptions.thresholds[i].value);
}
// TODO sort colors by value and index?
let thresholdScaler = (d) => {
let color = thresholdColors[Math.floor(d)];
if (color != undefined) {
return color
}
return 'rgba(0,0,0,0)';
};
let inputRangeScaler = d3.scaleLinear().domain([start, end]).range([0, thresholdColors.length+1]);
// scale min-max to 0 - max-thrs-value
return function(d) {
return thresholdScaler(inputRangeScaler(d));
}
}
function getOpacityScale(options, maxValue, minValue = 0) { function getOpacityScale(options, maxValue, minValue = 0) {
let legendOpacityScale; let legendOpacityScale;
if (options.colorScale === 'linear') { if (options.colorScale === 'linear') {
+46 -10
View File
@@ -17,7 +17,7 @@ export class ColorModeDiscrete {
for (let j = 0; j < values.length; j++) { for (let j = 0; j < values.length; j++) {
if (values[j] == thresholds[i].value) { if (values[j] == thresholds[i].value) {
tooltips.push({ tooltips.push({
"tooltip": thresholds[i].tooltip, "tooltip": thresholds[i].tooltip?thresholds[i].tooltip:values[j],
"color": thresholds[i].color "color": thresholds[i].color
}); });
} }
@@ -37,25 +37,49 @@ export class ColorModeDiscrete {
return notMatched; return notMatched;
} }
getDiscreteColorScale() { getNotColoredValues(values) {
return (d) => { let notMatched = [];
let threshold = this.getMatchedThreshold(d); for (let j = 0; j < values.length; j++) {
if (!threshold) { let threshold = this.getMatchedThreshold(values[j]);
// Error if value not in thresholds if (!threshold || !threshold.color || threshold.color == "") {
notMatched.push(values[j]);
}
}
return notMatched;
}
getDiscreteColor(index) {
let color = this.getThreshold(index).color;
if (!color || color == "") {
return 'rgba(0,0,0,1)'; return 'rgba(0,0,0,1)';
} }
else { return color;
return threshold.color;
} }
};
// returns color from first matched thresold in order from 0 to thresholds.length
getBucketColor(values) {
let thresholds = this.panel.color.thresholds;
for (let i = 0; i < thresholds.length; i++) {
for (let j = 0; j < values.length; j++) {
if (values[j] == thresholds[i].value) {
return this.getDiscreteColor(i);
}
}
}
return 'rgba(0,0,0,1)';
} }
updateCardsValuesHasColorInfo() { updateCardsValuesHasColorInfo() {
this.panelCtrl.cardsData.noColorDefined = false;
let cards = this.panelCtrl.cardsData.cards; let cards = this.panelCtrl.cardsData.cards;
for (let i=0; i<cards.length; i++) { for (let i=0; i<cards.length; i++) {
cards[i].noColorDefined = false;
let values = cards[i].values; let values = cards[i].values;
for (let j=0; j<values.length; j++) { for (let j=0; j<values.length; j++) {
if (!this.getMatchedThreshold(values[j])) { let threshold = this.getMatchedThreshold(values[j]);
if (!threshold || !threshold.color || threshold.color == "") {
cards[i].noColorDefined = true; cards[i].noColorDefined = true;
this.panelCtrl.cardsData.noColorDefined = true; this.panelCtrl.cardsData.noColorDefined = true;
break; break;
@@ -88,6 +112,18 @@ export class ColorModeDiscrete {
return null; return null;
} }
getThreshold(index) {
let thresholds = this.panel.color.thresholds;
if (index < 0 || index >= thresholds.length == null) {
return {
"color": "rgba(0,0,0,0)",
"value": "null",
"tooltip": "null",
}
}
return thresholds[index];
}
roundIntervalCeil(interval) { roundIntervalCeil(interval) {
switch (true) { switch (true) {
case interval <= 10: case interval <= 10:
+2 -4
View File
@@ -266,9 +266,7 @@ export default function link(scope, elem, attrs, ctrl) {
let maxValue = panel.color.max || cardsData.maxValue; let maxValue = panel.color.max || cardsData.maxValue;
let minValue = panel.color.min || cardsData.minValue; let minValue = panel.color.min || cardsData.minValue;
if (panel.color.mode === 'discrete') { if (panel.color.mode !== 'discrete') {
colorScale = ctrl.discreteHelper.getDiscreteColorScale();
} else {
colorScale = getColorScale(maxValue, minValue); colorScale = getColorScale(maxValue, minValue);
} }
setOpacityScale(maxValue); setOpacityScale(maxValue);
@@ -421,7 +419,7 @@ export default function link(scope, elem, attrs, ctrl) {
} else if (panel.color.mode === 'spectrum') { } else if (panel.color.mode === 'spectrum') {
return colorScale(d.value); return colorScale(d.value);
} else if (panel.color.mode === 'discrete') { } else if (panel.color.mode === 'discrete') {
return colorScale(d.value); return ctrl.discreteHelper.getBucketColor(d.values);
} }
} }
+9 -10
View File
@@ -85,18 +85,17 @@ export class StatusHeatmapTooltip {
let statuses = this.panelCtrl.discreteHelper.convertValuesToTooltips(values); let statuses = this.panelCtrl.discreteHelper.convertValuesToTooltips(values);
let statusesHtml = ''; let statusesHtml = '';
if (statuses.length === 1) { if (statuses.length === 1) {
statusesHtml = ` statusesHtml = "status:";
status: <b style="background-color: ${statuses[0].color}; padding: 1px;">${statuses[0].tooltip}</b>`;
} else if (statuses.length > 1) { } else if (statuses.length > 1) {
statusesHtml = ` statusesHtml = "statuses:";
statuses:
<ul>
${_.join(_.map(statuses, v => `<li style="background-color: ${v.color}; padding: 1px; text-shadow: 0 0 0.2em #FFF, 0 0 0.2em #FFF, 0 0 0.2em #FFF">${v.tooltip}</li>`), "")}
</ul>`;
} }
tooltipHtml += `<div> tooltipHtml += `
<div>
name: <b>${y}</b> <br> name: <b>${y}</b> <br>
${statusesHtml} ${statusesHtml}
<ul>
${_.join(_.map(statuses, v => `<li style="background-color: ${v.color}; padding: 1px; font-weight: bold; text-shadow: 0 0 0.2em #FFF, 0 0 0.2em #FFF, 0 0 0.2em #FFF">${v.tooltip}</li>`), "")}
</ul>
</div>`; </div>`;
} else { } else {
if (values.length === 1) { if (values.length === 1) {
@@ -123,9 +122,9 @@ export class StatusHeatmapTooltip {
// Discrete mode errors // Discrete mode errors
if (this.panel.color.mode === 'discrete') { if (this.panel.color.mode === 'discrete') {
if (card.noColorDefined) { if (card.noColorDefined) {
let badValues = this.panelCtrl.discreteHelper.getNotMatchedValues(values); let badValues = this.panelCtrl.discreteHelper.getNotColoredValues(values);
tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.noColorDefined.title} tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.noColorDefined.title}
<br>bad values: <br>not colored values:
<ul> <ul>
${_.join(_.map(badValues, v => `<li>${v}</li>`), "")} ${_.join(_.map(badValues, v => `<li>${v}</li>`), "")}
</ul> </ul>