|
|
|
@ -19,7 +19,7 @@ const MIN_CARD_SIZE = 1, |
|
|
|
|
Y_AXIS_TICK_PADDING = 5, |
|
|
|
|
MIN_SELECTION_WIDTH = 2; |
|
|
|
|
|
|
|
|
|
export default function rendering(scope, elem, attrs, ctrl) { |
|
|
|
|
export default function rendering(scope: any, elem: any, attrs: any, ctrl: any) { |
|
|
|
|
return new HeatmapRenderer(scope, elem, attrs, ctrl); |
|
|
|
|
} |
|
|
|
|
export class HeatmapRenderer { |
|
|
|
@ -51,7 +51,7 @@ export class HeatmapRenderer { |
|
|
|
|
padding: any; |
|
|
|
|
margin: any; |
|
|
|
|
dataRangeWidingFactor: number; |
|
|
|
|
constructor(private scope, private elem, attrs, private ctrl) { |
|
|
|
|
constructor(private scope: any, private elem: any, attrs: any, private ctrl: any) { |
|
|
|
|
// $heatmap is JQuery object, but heatmap is D3
|
|
|
|
|
this.$heatmap = this.elem.find('.heatmap-panel'); |
|
|
|
|
this.tooltip = new HeatmapTooltip(this.$heatmap, this.scope); |
|
|
|
@ -89,7 +89,7 @@ export class HeatmapRenderer { |
|
|
|
|
this.clearCrosshair(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onGraphHover(event) { |
|
|
|
|
onGraphHover(event: { pos: any }) { |
|
|
|
|
this.drawSharedCrosshair(event.pos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -116,7 +116,7 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getYAxisWidth(elem) { |
|
|
|
|
getYAxisWidth(elem: any) { |
|
|
|
|
const axisText = elem.selectAll('.axis-y text').nodes(); |
|
|
|
|
const maxTextWidth = _.max( |
|
|
|
|
_.map(axisText, text => { |
|
|
|
@ -128,7 +128,7 @@ export class HeatmapRenderer { |
|
|
|
|
return maxTextWidth; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getXAxisHeight(elem) { |
|
|
|
|
getXAxisHeight(elem: any) { |
|
|
|
|
const axisLine = elem.select('.axis-x line'); |
|
|
|
|
if (!axisLine.empty()) { |
|
|
|
|
const axisLinePosition = parseFloat(elem.select('.axis-x line').attr('y2')); |
|
|
|
@ -244,7 +244,7 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Wide Y values range and anjust to bucket size
|
|
|
|
|
wideYAxisRange(min, max, tickInterval) { |
|
|
|
|
wideYAxisRange(min: number, max: number, tickInterval: number) { |
|
|
|
|
const yWiding = (max * (this.dataRangeWidingFactor - 1) - min * (this.dataRangeWidingFactor - 1)) / 2; |
|
|
|
|
let yMin, yMax; |
|
|
|
|
|
|
|
|
@ -349,7 +349,7 @@ export class HeatmapRenderer { |
|
|
|
|
this.ctrl.decimals = decimals; |
|
|
|
|
|
|
|
|
|
const tickValueFormatter = this.tickValueFormatter.bind(this); |
|
|
|
|
function tickFormatter(valIndex) { |
|
|
|
|
function tickFormatter(valIndex: string) { |
|
|
|
|
let valueFormatted = tsBuckets[valIndex]; |
|
|
|
|
if (!_.isNaN(_.toNumber(valueFormatted)) && valueFormatted !== '') { |
|
|
|
|
// Try to format numeric tick labels
|
|
|
|
@ -393,7 +393,7 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Adjust data range to log base
|
|
|
|
|
adjustLogRange(min, max, logBase) { |
|
|
|
|
adjustLogRange(min: number, max: number, logBase: number) { |
|
|
|
|
let yMin = this.data.heatmapStats.minLog; |
|
|
|
|
if (this.data.heatmapStats.minLog > 1 || !this.data.heatmapStats.minLog) { |
|
|
|
|
yMin = 1; |
|
|
|
@ -407,15 +407,15 @@ export class HeatmapRenderer { |
|
|
|
|
return { yMin, yMax }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
adjustLogMax(max, base) { |
|
|
|
|
adjustLogMax(max: number, base: number) { |
|
|
|
|
return Math.pow(base, Math.ceil(ticksUtils.logp(max, base))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
adjustLogMin(min, base) { |
|
|
|
|
adjustLogMin(min: number, base: number) { |
|
|
|
|
return Math.pow(base, Math.floor(ticksUtils.logp(min, base))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
logScaleTickValues(domain, base) { |
|
|
|
|
logScaleTickValues(domain: any[], base: number) { |
|
|
|
|
const domainMin = domain[0]; |
|
|
|
|
const domainMax = domain[1]; |
|
|
|
|
const tickValues = []; |
|
|
|
@ -437,9 +437,9 @@ export class HeatmapRenderer { |
|
|
|
|
return tickValues; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tickValueFormatter(decimals, scaledDecimals = null) { |
|
|
|
|
tickValueFormatter(decimals: number, scaledDecimals: any = null) { |
|
|
|
|
const format = this.panel.yAxis.format; |
|
|
|
|
return value => { |
|
|
|
|
return (value: any) => { |
|
|
|
|
try { |
|
|
|
|
return format !== 'none' ? getValueFormat(format)(value, decimals, scaledDecimals) : value; |
|
|
|
|
} catch (err) { |
|
|
|
@ -555,17 +555,17 @@ export class HeatmapRenderer { |
|
|
|
|
|
|
|
|
|
const $cards = this.$heatmap.find('.heatmap-card'); |
|
|
|
|
$cards |
|
|
|
|
.on('mouseenter', event => { |
|
|
|
|
.on('mouseenter', (event: any) => { |
|
|
|
|
this.tooltip.mouseOverBucket = true; |
|
|
|
|
this.highlightCard(event); |
|
|
|
|
}) |
|
|
|
|
.on('mouseleave', event => { |
|
|
|
|
.on('mouseleave', (event: any) => { |
|
|
|
|
this.tooltip.mouseOverBucket = false; |
|
|
|
|
this.resetCardHighLight(event); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
highlightCard(event) { |
|
|
|
|
highlightCard(event: any) { |
|
|
|
|
const color = d3.select(event.target).style('fill'); |
|
|
|
|
const highlightColor = d3.color(color).darker(2); |
|
|
|
|
const strokeColor = d3.color(color).brighter(4); |
|
|
|
@ -577,7 +577,7 @@ export class HeatmapRenderer { |
|
|
|
|
.style('stroke-width', 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
resetCardHighLight(event) { |
|
|
|
|
resetCardHighLight(event: any) { |
|
|
|
|
d3.select(event.target) |
|
|
|
|
.style('fill', this.tooltip.originalFillColor) |
|
|
|
|
.style('stroke', this.tooltip.originalFillColor) |
|
|
|
@ -599,7 +599,7 @@ export class HeatmapRenderer { |
|
|
|
|
this.cardHeight = yGridSize ? yGridSize - this.cardPadding * 2 : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getCardX(d) { |
|
|
|
|
getCardX(d: { x: any }) { |
|
|
|
|
let x; |
|
|
|
|
if (this.xScale(d.x) < 0) { |
|
|
|
|
// Cut card left to prevent overlay
|
|
|
|
@ -611,7 +611,7 @@ export class HeatmapRenderer { |
|
|
|
|
return x; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getCardWidth(d) { |
|
|
|
|
getCardWidth(d: { x: any }) { |
|
|
|
|
let w = this.cardWidth; |
|
|
|
|
if (this.xScale(d.x) < 0) { |
|
|
|
|
// Cut card left to prevent overlay
|
|
|
|
@ -626,7 +626,7 @@ export class HeatmapRenderer { |
|
|
|
|
return w; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getCardY(d) { |
|
|
|
|
getCardY(d: { y: number }) { |
|
|
|
|
let y = this.yScale(d.y) + this.chartTop - this.cardHeight - this.cardPadding; |
|
|
|
|
if (this.panel.yAxis.logBase !== 1 && d.y === 0) { |
|
|
|
|
y = this.chartBottom - this.cardHeight - this.cardPadding; |
|
|
|
@ -639,7 +639,7 @@ export class HeatmapRenderer { |
|
|
|
|
return y; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getCardHeight(d) { |
|
|
|
|
getCardHeight(d: { y: number }) { |
|
|
|
|
const y = this.yScale(d.y) + this.chartTop - this.cardHeight - this.cardPadding; |
|
|
|
|
let h = this.cardHeight; |
|
|
|
|
|
|
|
|
@ -664,7 +664,7 @@ export class HeatmapRenderer { |
|
|
|
|
return h; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getCardColor(d) { |
|
|
|
|
getCardColor(d: { count: any }) { |
|
|
|
|
if (this.panel.color.mode === 'opacity') { |
|
|
|
|
return getColorFromHexRgbOrName( |
|
|
|
|
this.panel.color.cardColor, |
|
|
|
@ -675,7 +675,7 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getCardOpacity(d) { |
|
|
|
|
getCardOpacity(d: { count: any }) { |
|
|
|
|
if (this.panel.color.mode === 'opacity') { |
|
|
|
|
return this.opacityScale(d.count); |
|
|
|
|
} else { |
|
|
|
@ -683,14 +683,14 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getEventOffset(event) { |
|
|
|
|
getEventOffset(event: any) { |
|
|
|
|
const elemOffset = this.$heatmap.offset(); |
|
|
|
|
const x = Math.floor(event.clientX - elemOffset.left); |
|
|
|
|
const y = Math.floor(event.clientY - elemOffset.top); |
|
|
|
|
return { x, y }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onMouseDown(event) { |
|
|
|
|
onMouseDown(event: any) { |
|
|
|
|
const offset = this.getEventOffset(event); |
|
|
|
|
this.selection.active = true; |
|
|
|
|
this.selection.x1 = offset.x; |
|
|
|
@ -726,7 +726,7 @@ export class HeatmapRenderer { |
|
|
|
|
this.clearCrosshair(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onMouseMove(event) { |
|
|
|
|
onMouseMove(event: any) { |
|
|
|
|
if (!this.heatmap) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -747,10 +747,10 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getEventPos(event, offset) { |
|
|
|
|
getEventPos(event: { pageX: any; pageY: any }, offset: { x: any; y: any }) { |
|
|
|
|
const x = this.xScale.invert(offset.x - this.yAxisWidth).valueOf(); |
|
|
|
|
const y = this.yScale.invert(offset.y - this.chartTop); |
|
|
|
|
const pos = { |
|
|
|
|
const pos: any = { |
|
|
|
|
pageX: event.pageX, |
|
|
|
|
pageY: event.pageY, |
|
|
|
|
x: x, |
|
|
|
@ -764,20 +764,20 @@ export class HeatmapRenderer { |
|
|
|
|
return pos; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
emitGraphHoverEvent(pos) { |
|
|
|
|
emitGraphHoverEvent(pos: { panelRelY: number; offset: { y: number } }) { |
|
|
|
|
// Set minimum offset to prevent showing legend from another panel
|
|
|
|
|
pos.panelRelY = Math.max(pos.offset.y / this.height, 0.001); |
|
|
|
|
// broadcast to other graph panels that we are hovering
|
|
|
|
|
appEvents.emit('graph-hover', { pos: pos, panel: this.panel }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
limitSelection(x2) { |
|
|
|
|
limitSelection(x2: number) { |
|
|
|
|
x2 = Math.max(x2, this.yAxisWidth); |
|
|
|
|
x2 = Math.min(x2, this.chartWidth + this.yAxisWidth); |
|
|
|
|
return x2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drawSelection(posX1, posX2) { |
|
|
|
|
drawSelection(posX1: number, posX2: number) { |
|
|
|
|
if (this.heatmap) { |
|
|
|
|
this.heatmap.selectAll('.heatmap-selection').remove(); |
|
|
|
|
const selectionX = Math.min(posX1, posX2); |
|
|
|
@ -804,7 +804,7 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drawCrosshair(position) { |
|
|
|
|
drawCrosshair(position: number) { |
|
|
|
|
if (this.heatmap) { |
|
|
|
|
this.heatmap.selectAll('.heatmap-crosshair').remove(); |
|
|
|
|
|
|
|
|
@ -825,7 +825,7 @@ export class HeatmapRenderer { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drawSharedCrosshair(pos) { |
|
|
|
|
drawSharedCrosshair(pos: { x: any }) { |
|
|
|
|
if (this.heatmap && this.ctrl.dashboard.graphTooltip !== 0) { |
|
|
|
|
const posX = this.xScale(pos.x) + this.yAxisWidth; |
|
|
|
|
this.drawCrosshair(posX); |
|
|
|
|