|
@@ -19,56 +19,91 @@ let MIN_CARD_SIZE = 1,
|
|
|
Y_AXIS_TICK_PADDING = 5,
|
|
Y_AXIS_TICK_PADDING = 5,
|
|
|
MIN_SELECTION_WIDTH = 2;
|
|
MIN_SELECTION_WIDTH = 2;
|
|
|
|
|
|
|
|
-export default function link(scope, elem, attrs, ctrl) {
|
|
|
|
|
- let data, timeRange, panel, heatmap;
|
|
|
|
|
-
|
|
|
|
|
- // $heatmap is JQuery object, but heatmap is D3
|
|
|
|
|
- let $heatmap = elem.find('.heatmap-panel');
|
|
|
|
|
- let tooltip = new HeatmapTooltip($heatmap, scope);
|
|
|
|
|
-
|
|
|
|
|
- let width,
|
|
|
|
|
- height,
|
|
|
|
|
- yScale,
|
|
|
|
|
- xScale,
|
|
|
|
|
- chartWidth,
|
|
|
|
|
- chartHeight,
|
|
|
|
|
- chartTop,
|
|
|
|
|
- chartBottom,
|
|
|
|
|
- yAxisWidth,
|
|
|
|
|
- xAxisHeight,
|
|
|
|
|
- cardPadding,
|
|
|
|
|
- cardRound,
|
|
|
|
|
- cardWidth,
|
|
|
|
|
- cardHeight,
|
|
|
|
|
- colorScale,
|
|
|
|
|
- opacityScale,
|
|
|
|
|
- mouseUpHandler;
|
|
|
|
|
-
|
|
|
|
|
- let selection = {
|
|
|
|
|
- active: false,
|
|
|
|
|
- x1: -1,
|
|
|
|
|
- x2: -1,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- let padding = { left: 0, right: 0, top: 0, bottom: 0 },
|
|
|
|
|
- margin = { left: 25, right: 15, top: 10, bottom: 20 },
|
|
|
|
|
- dataRangeWidingFactor = DATA_RANGE_WIDING_FACTOR;
|
|
|
|
|
-
|
|
|
|
|
- ctrl.events.on('render', () => {
|
|
|
|
|
- render();
|
|
|
|
|
- ctrl.renderingCompleted();
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- function setElementHeight() {
|
|
|
|
|
|
|
+export default class Link {
|
|
|
|
|
+ width: number;
|
|
|
|
|
+ height: number;
|
|
|
|
|
+ yScale: any;
|
|
|
|
|
+ xScale: any;
|
|
|
|
|
+ chartWidth: number;
|
|
|
|
|
+ chartHeight: number;
|
|
|
|
|
+ chartTop: number;
|
|
|
|
|
+ chartBottom: number;
|
|
|
|
|
+ yAxisWidth: number;
|
|
|
|
|
+ xAxisHeight: number;
|
|
|
|
|
+ cardPadding: number;
|
|
|
|
|
+ cardRound: number;
|
|
|
|
|
+ cardWidth: number;
|
|
|
|
|
+ cardHeight: number;
|
|
|
|
|
+ colorScale: any;
|
|
|
|
|
+ opacityScale: any;
|
|
|
|
|
+ mouseUpHandler: any;
|
|
|
|
|
+ data: any;
|
|
|
|
|
+ panel: any;
|
|
|
|
|
+ $heatmap: any;
|
|
|
|
|
+ tooltip: HeatmapTooltip;
|
|
|
|
|
+ heatmap: any;
|
|
|
|
|
+ timeRange: any;
|
|
|
|
|
+
|
|
|
|
|
+ selection: any;
|
|
|
|
|
+ padding: any;
|
|
|
|
|
+ margin: any;
|
|
|
|
|
+ dataRangeWidingFactor: number;
|
|
|
|
|
+ constructor(private scope, private elem, attrs, private ctrl) {
|
|
|
|
|
+ // $heatmap is JQuery object, but heatmap is D3
|
|
|
|
|
+ this.$heatmap = elem.find('.heatmap-panel');
|
|
|
|
|
+ this.tooltip = new HeatmapTooltip(this.$heatmap, this.scope);
|
|
|
|
|
+
|
|
|
|
|
+ this.selection = {
|
|
|
|
|
+ active: false,
|
|
|
|
|
+ x1: -1,
|
|
|
|
|
+ x2: -1,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ this.padding = { left: 0, right: 0, top: 0, bottom: 0 };
|
|
|
|
|
+ this.margin = { left: 25, right: 15, top: 10, bottom: 20 };
|
|
|
|
|
+ this.dataRangeWidingFactor = DATA_RANGE_WIDING_FACTOR;
|
|
|
|
|
+
|
|
|
|
|
+ this.ctrl.events.on('render', this.onRender.bind(this));
|
|
|
|
|
+
|
|
|
|
|
+ this.ctrl.tickValueFormatter = this.tickValueFormatter;
|
|
|
|
|
+ /////////////////////////////
|
|
|
|
|
+ // Selection and crosshair //
|
|
|
|
|
+ /////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+ // Shared crosshair and tooltip
|
|
|
|
|
+ appEvents.on('graph-hover', this.onGraphHover.bind(this), this.scope);
|
|
|
|
|
+
|
|
|
|
|
+ appEvents.on('graph-hover-clear', this.onGraphHoverClear.bind(this), this.scope);
|
|
|
|
|
+
|
|
|
|
|
+ // Register selection listeners
|
|
|
|
|
+ this.$heatmap.on('mousedown', this.onMouseDown.bind(this));
|
|
|
|
|
+ this.$heatmap.on('mousemove', this.onMouseMove.bind(this));
|
|
|
|
|
+ this.$heatmap.on('mouseleave', this.onMouseLeave.bind(this));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onGraphHoverClear() {
|
|
|
|
|
+ this.clearCrosshair();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onGraphHover(event) {
|
|
|
|
|
+ this.drawSharedCrosshair(event.pos);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onRender() {
|
|
|
|
|
+ this.render();
|
|
|
|
|
+ this.ctrl.renderingCompleted();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setElementHeight() {
|
|
|
try {
|
|
try {
|
|
|
- var height = ctrl.height || panel.height || ctrl.row.height;
|
|
|
|
|
|
|
+ var height = this.ctrl.height || this.panel.height || this.ctrl.row.height;
|
|
|
if (_.isString(height)) {
|
|
if (_.isString(height)) {
|
|
|
height = parseInt(height.replace('px', ''), 10);
|
|
height = parseInt(height.replace('px', ''), 10);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- height -= panel.legend.show ? 28 : 11; // bottom padding and space for legend
|
|
|
|
|
|
|
+ height -= this.panel.legend.show ? 28 : 11; // bottom padding and space for legend
|
|
|
|
|
|
|
|
- $heatmap.css('height', height + 'px');
|
|
|
|
|
|
|
+ this.$heatmap.css('height', height + 'px');
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
@@ -77,7 +112,7 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getYAxisWidth(elem) {
|
|
|
|
|
|
|
+ getYAxisWidth(elem) {
|
|
|
let axis_text = elem.selectAll('.axis-y text').nodes();
|
|
let axis_text = elem.selectAll('.axis-y text').nodes();
|
|
|
let max_text_width = _.max(
|
|
let max_text_width = _.max(
|
|
|
_.map(axis_text, text => {
|
|
_.map(axis_text, text => {
|
|
@@ -89,7 +124,7 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
return max_text_width;
|
|
return max_text_width;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getXAxisHeight(elem) {
|
|
|
|
|
|
|
+ getXAxisHeight(elem) {
|
|
|
let axis_line = elem.select('.axis-x line');
|
|
let axis_line = elem.select('.axis-x line');
|
|
|
if (!axis_line.empty()) {
|
|
if (!axis_line.empty()) {
|
|
|
let axis_line_position = parseFloat(elem.select('.axis-x line').attr('y2'));
|
|
let axis_line_position = parseFloat(elem.select('.axis-x line').attr('y2'));
|
|
@@ -101,16 +136,16 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function addXAxis() {
|
|
|
|
|
- scope.xScale = xScale = d3
|
|
|
|
|
|
|
+ addXAxis() {
|
|
|
|
|
+ this.scope.xScale = this.xScale = d3
|
|
|
.scaleTime()
|
|
.scaleTime()
|
|
|
- .domain([timeRange.from, timeRange.to])
|
|
|
|
|
- .range([0, chartWidth]);
|
|
|
|
|
|
|
+ .domain([this.timeRange.from, this.timeRange.to])
|
|
|
|
|
+ .range([0, this.chartWidth]);
|
|
|
|
|
|
|
|
- let ticks = chartWidth / DEFAULT_X_TICK_SIZE_PX;
|
|
|
|
|
- let grafanaTimeFormatter = ticksUtils.grafanaTimeFormat(ticks, timeRange.from, timeRange.to);
|
|
|
|
|
|
|
+ let ticks = this.chartWidth / DEFAULT_X_TICK_SIZE_PX;
|
|
|
|
|
+ let grafanaTimeFormatter = ticksUtils.grafanaTimeFormat(ticks, this.timeRange.from, this.timeRange.to);
|
|
|
let timeFormat;
|
|
let timeFormat;
|
|
|
- let dashboardTimeZone = ctrl.dashboard.getTimezone();
|
|
|
|
|
|
|
+ let dashboardTimeZone = this.ctrl.dashboard.getTimezone();
|
|
|
if (dashboardTimeZone === 'utc') {
|
|
if (dashboardTimeZone === 'utc') {
|
|
|
timeFormat = d3.utcFormat(grafanaTimeFormatter);
|
|
timeFormat = d3.utcFormat(grafanaTimeFormatter);
|
|
|
} else {
|
|
} else {
|
|
@@ -118,100 +153,100 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let xAxis = d3
|
|
let xAxis = d3
|
|
|
- .axisBottom(xScale)
|
|
|
|
|
|
|
+ .axisBottom(this.xScale)
|
|
|
.ticks(ticks)
|
|
.ticks(ticks)
|
|
|
.tickFormat(timeFormat)
|
|
.tickFormat(timeFormat)
|
|
|
.tickPadding(X_AXIS_TICK_PADDING)
|
|
.tickPadding(X_AXIS_TICK_PADDING)
|
|
|
- .tickSize(chartHeight);
|
|
|
|
|
|
|
+ .tickSize(this.chartHeight);
|
|
|
|
|
|
|
|
- let posY = margin.top;
|
|
|
|
|
- let posX = yAxisWidth;
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ let posY = this.margin.top;
|
|
|
|
|
+ let posX = this.yAxisWidth;
|
|
|
|
|
+ this.heatmap
|
|
|
.append('g')
|
|
.append('g')
|
|
|
.attr('class', 'axis axis-x')
|
|
.attr('class', 'axis axis-x')
|
|
|
.attr('transform', 'translate(' + posX + ',' + posY + ')')
|
|
.attr('transform', 'translate(' + posX + ',' + posY + ')')
|
|
|
.call(xAxis);
|
|
.call(xAxis);
|
|
|
|
|
|
|
|
// Remove horizontal line in the top of axis labels (called domain in d3)
|
|
// Remove horizontal line in the top of axis labels (called domain in d3)
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-x')
|
|
.select('.axis-x')
|
|
|
.select('.domain')
|
|
.select('.domain')
|
|
|
.remove();
|
|
.remove();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function addYAxis() {
|
|
|
|
|
- let ticks = Math.ceil(chartHeight / DEFAULT_Y_TICK_SIZE_PX);
|
|
|
|
|
- let tick_interval = ticksUtils.tickStep(data.heatmapStats.min, data.heatmapStats.max, ticks);
|
|
|
|
|
- let { y_min, y_max } = wideYAxisRange(data.heatmapStats.min, data.heatmapStats.max, tick_interval);
|
|
|
|
|
|
|
+ addYAxis() {
|
|
|
|
|
+ let ticks = Math.ceil(this.chartHeight / DEFAULT_Y_TICK_SIZE_PX);
|
|
|
|
|
+ let tick_interval = ticksUtils.tickStep(this.data.heatmapStats.min, this.data.heatmapStats.max, ticks);
|
|
|
|
|
+ let { y_min, y_max } = this.wideYAxisRange(this.data.heatmapStats.min, this.data.heatmapStats.max, tick_interval);
|
|
|
|
|
|
|
|
// Rewrite min and max if it have been set explicitly
|
|
// Rewrite min and max if it have been set explicitly
|
|
|
- y_min = panel.yAxis.min !== null ? panel.yAxis.min : y_min;
|
|
|
|
|
- y_max = panel.yAxis.max !== null ? panel.yAxis.max : y_max;
|
|
|
|
|
|
|
+ y_min = this.panel.yAxis.min !== null ? this.panel.yAxis.min : y_min;
|
|
|
|
|
+ y_max = this.panel.yAxis.max !== null ? this.panel.yAxis.max : y_max;
|
|
|
|
|
|
|
|
// Adjust ticks after Y range widening
|
|
// Adjust ticks after Y range widening
|
|
|
tick_interval = ticksUtils.tickStep(y_min, y_max, ticks);
|
|
tick_interval = ticksUtils.tickStep(y_min, y_max, ticks);
|
|
|
ticks = Math.ceil((y_max - y_min) / tick_interval);
|
|
ticks = Math.ceil((y_max - y_min) / tick_interval);
|
|
|
|
|
|
|
|
let decimalsAuto = ticksUtils.getPrecision(tick_interval);
|
|
let decimalsAuto = ticksUtils.getPrecision(tick_interval);
|
|
|
- let decimals = panel.yAxis.decimals === null ? decimalsAuto : panel.yAxis.decimals;
|
|
|
|
|
|
|
+ let decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;
|
|
|
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
|
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
|
|
let flot_tick_size = ticksUtils.getFlotTickSize(y_min, y_max, ticks, decimalsAuto);
|
|
let flot_tick_size = ticksUtils.getFlotTickSize(y_min, y_max, ticks, decimalsAuto);
|
|
|
let scaledDecimals = ticksUtils.getScaledDecimals(decimals, flot_tick_size);
|
|
let scaledDecimals = ticksUtils.getScaledDecimals(decimals, flot_tick_size);
|
|
|
- ctrl.decimals = decimals;
|
|
|
|
|
- ctrl.scaledDecimals = scaledDecimals;
|
|
|
|
|
|
|
+ this.ctrl.decimals = decimals;
|
|
|
|
|
+ this.ctrl.scaledDecimals = scaledDecimals;
|
|
|
|
|
|
|
|
// Set default Y min and max if no data
|
|
// Set default Y min and max if no data
|
|
|
- if (_.isEmpty(data.buckets)) {
|
|
|
|
|
|
|
+ if (_.isEmpty(this.data.buckets)) {
|
|
|
y_max = 1;
|
|
y_max = 1;
|
|
|
y_min = -1;
|
|
y_min = -1;
|
|
|
ticks = 3;
|
|
ticks = 3;
|
|
|
decimals = 1;
|
|
decimals = 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- data.yAxis = {
|
|
|
|
|
|
|
+ this.data.yAxis = {
|
|
|
min: y_min,
|
|
min: y_min,
|
|
|
max: y_max,
|
|
max: y_max,
|
|
|
ticks: ticks,
|
|
ticks: ticks,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- scope.yScale = yScale = d3
|
|
|
|
|
|
|
+ this.scope.yScale = this.yScale = d3
|
|
|
.scaleLinear()
|
|
.scaleLinear()
|
|
|
.domain([y_min, y_max])
|
|
.domain([y_min, y_max])
|
|
|
- .range([chartHeight, 0]);
|
|
|
|
|
|
|
+ .range([this.chartHeight, 0]);
|
|
|
|
|
|
|
|
let yAxis = d3
|
|
let yAxis = d3
|
|
|
- .axisLeft(yScale)
|
|
|
|
|
|
|
+ .axisLeft(this.yScale)
|
|
|
.ticks(ticks)
|
|
.ticks(ticks)
|
|
|
- .tickFormat(tickValueFormatter(decimals, scaledDecimals))
|
|
|
|
|
- .tickSizeInner(0 - width)
|
|
|
|
|
|
|
+ .tickFormat(this.tickValueFormatter(decimals, scaledDecimals))
|
|
|
|
|
+ .tickSizeInner(0 - this.width)
|
|
|
.tickSizeOuter(0)
|
|
.tickSizeOuter(0)
|
|
|
.tickPadding(Y_AXIS_TICK_PADDING);
|
|
.tickPadding(Y_AXIS_TICK_PADDING);
|
|
|
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.append('g')
|
|
.append('g')
|
|
|
.attr('class', 'axis axis-y')
|
|
.attr('class', 'axis axis-y')
|
|
|
.call(yAxis);
|
|
.call(yAxis);
|
|
|
|
|
|
|
|
// Calculate Y axis width first, then move axis into visible area
|
|
// Calculate Y axis width first, then move axis into visible area
|
|
|
- let posY = margin.top;
|
|
|
|
|
- let posX = getYAxisWidth(heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
- heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
|
|
|
|
|
|
+ let posY = this.margin.top;
|
|
|
|
|
+ let posX = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
+ this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
|
|
|
|
|
|
|
// Remove vertical line in the right of axis labels (called domain in d3)
|
|
// Remove vertical line in the right of axis labels (called domain in d3)
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-y')
|
|
.select('.axis-y')
|
|
|
.select('.domain')
|
|
.select('.domain')
|
|
|
.remove();
|
|
.remove();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Wide Y values range and anjust to bucket size
|
|
// Wide Y values range and anjust to bucket size
|
|
|
- function wideYAxisRange(min, max, tickInterval) {
|
|
|
|
|
- let y_widing = (max * (dataRangeWidingFactor - 1) - min * (dataRangeWidingFactor - 1)) / 2;
|
|
|
|
|
|
|
+ wideYAxisRange(min, max, tickInterval) {
|
|
|
|
|
+ let y_widing = (max * (this.dataRangeWidingFactor - 1) - min * (this.dataRangeWidingFactor - 1)) / 2;
|
|
|
let y_min, y_max;
|
|
let y_min, y_max;
|
|
|
|
|
|
|
|
if (tickInterval === 0) {
|
|
if (tickInterval === 0) {
|
|
|
- y_max = max * dataRangeWidingFactor;
|
|
|
|
|
- y_min = min - min * (dataRangeWidingFactor - 1);
|
|
|
|
|
|
|
+ y_max = max * this.dataRangeWidingFactor;
|
|
|
|
|
+ y_min = min - min * (this.dataRangeWidingFactor - 1);
|
|
|
tickInterval = (y_max - y_min) / 2;
|
|
tickInterval = (y_max - y_min) / 2;
|
|
|
} else {
|
|
} else {
|
|
|
y_max = Math.ceil((max + y_widing) / tickInterval) * tickInterval;
|
|
y_max = Math.ceil((max + y_widing) / tickInterval) * tickInterval;
|
|
@@ -226,152 +261,153 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
return { y_min, y_max };
|
|
return { y_min, y_max };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function addLogYAxis() {
|
|
|
|
|
- let log_base = panel.yAxis.logBase;
|
|
|
|
|
- let { y_min, y_max } = adjustLogRange(data.heatmapStats.minLog, data.heatmapStats.max, log_base);
|
|
|
|
|
|
|
+ addLogYAxis() {
|
|
|
|
|
+ let log_base = this.panel.yAxis.logBase;
|
|
|
|
|
+ let { y_min, y_max } = this.adjustLogRange(this.data.heatmapStats.minLog, this.data.heatmapStats.max, log_base);
|
|
|
|
|
|
|
|
- y_min = panel.yAxis.min && panel.yAxis.min !== '0' ? adjustLogMin(panel.yAxis.min, log_base) : y_min;
|
|
|
|
|
- y_max = panel.yAxis.max !== null ? adjustLogMax(panel.yAxis.max, log_base) : y_max;
|
|
|
|
|
|
|
+ y_min =
|
|
|
|
|
+ this.panel.yAxis.min && this.panel.yAxis.min !== '0' ? this.adjustLogMin(this.panel.yAxis.min, log_base) : y_min;
|
|
|
|
|
+ y_max = this.panel.yAxis.max !== null ? this.adjustLogMax(this.panel.yAxis.max, log_base) : y_max;
|
|
|
|
|
|
|
|
// Set default Y min and max if no data
|
|
// Set default Y min and max if no data
|
|
|
- if (_.isEmpty(data.buckets)) {
|
|
|
|
|
|
|
+ if (_.isEmpty(this.data.buckets)) {
|
|
|
y_max = Math.pow(log_base, 2);
|
|
y_max = Math.pow(log_base, 2);
|
|
|
y_min = 1;
|
|
y_min = 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- scope.yScale = yScale = d3
|
|
|
|
|
|
|
+ this.scope.yScale = this.yScale = d3
|
|
|
.scaleLog()
|
|
.scaleLog()
|
|
|
- .base(panel.yAxis.logBase)
|
|
|
|
|
|
|
+ .base(this.panel.yAxis.logBase)
|
|
|
.domain([y_min, y_max])
|
|
.domain([y_min, y_max])
|
|
|
- .range([chartHeight, 0]);
|
|
|
|
|
|
|
+ .range([this.chartHeight, 0]);
|
|
|
|
|
|
|
|
- let domain = yScale.domain();
|
|
|
|
|
- let tick_values = logScaleTickValues(domain, log_base);
|
|
|
|
|
|
|
+ let domain = this.yScale.domain();
|
|
|
|
|
+ let tick_values = this.logScaleTickValues(domain, log_base);
|
|
|
|
|
|
|
|
let decimalsAuto = ticksUtils.getPrecision(y_min);
|
|
let decimalsAuto = ticksUtils.getPrecision(y_min);
|
|
|
- let decimals = panel.yAxis.decimals || decimalsAuto;
|
|
|
|
|
|
|
+ let decimals = this.panel.yAxis.decimals || decimalsAuto;
|
|
|
|
|
|
|
|
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
|
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
|
|
let flot_tick_size = ticksUtils.getFlotTickSize(y_min, y_max, tick_values.length, decimalsAuto);
|
|
let flot_tick_size = ticksUtils.getFlotTickSize(y_min, y_max, tick_values.length, decimalsAuto);
|
|
|
let scaledDecimals = ticksUtils.getScaledDecimals(decimals, flot_tick_size);
|
|
let scaledDecimals = ticksUtils.getScaledDecimals(decimals, flot_tick_size);
|
|
|
- ctrl.decimals = decimals;
|
|
|
|
|
- ctrl.scaledDecimals = scaledDecimals;
|
|
|
|
|
|
|
+ this.ctrl.decimals = decimals;
|
|
|
|
|
+ this.ctrl.scaledDecimals = scaledDecimals;
|
|
|
|
|
|
|
|
- data.yAxis = {
|
|
|
|
|
|
|
+ this.data.yAxis = {
|
|
|
min: y_min,
|
|
min: y_min,
|
|
|
max: y_max,
|
|
max: y_max,
|
|
|
ticks: tick_values.length,
|
|
ticks: tick_values.length,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
let yAxis = d3
|
|
let yAxis = d3
|
|
|
- .axisLeft(yScale)
|
|
|
|
|
|
|
+ .axisLeft(this.yScale)
|
|
|
.tickValues(tick_values)
|
|
.tickValues(tick_values)
|
|
|
- .tickFormat(tickValueFormatter(decimals, scaledDecimals))
|
|
|
|
|
- .tickSizeInner(0 - width)
|
|
|
|
|
|
|
+ .tickFormat(this.tickValueFormatter(decimals, scaledDecimals))
|
|
|
|
|
+ .tickSizeInner(0 - this.width)
|
|
|
.tickSizeOuter(0)
|
|
.tickSizeOuter(0)
|
|
|
.tickPadding(Y_AXIS_TICK_PADDING);
|
|
.tickPadding(Y_AXIS_TICK_PADDING);
|
|
|
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.append('g')
|
|
.append('g')
|
|
|
.attr('class', 'axis axis-y')
|
|
.attr('class', 'axis axis-y')
|
|
|
.call(yAxis);
|
|
.call(yAxis);
|
|
|
|
|
|
|
|
// Calculate Y axis width first, then move axis into visible area
|
|
// Calculate Y axis width first, then move axis into visible area
|
|
|
- let posY = margin.top;
|
|
|
|
|
- let posX = getYAxisWidth(heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
- heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
|
|
|
|
|
|
+ let posY = this.margin.top;
|
|
|
|
|
+ let posX = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
+ this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
|
|
|
|
|
|
|
// Set first tick as pseudo 0
|
|
// Set first tick as pseudo 0
|
|
|
if (y_min < 1) {
|
|
if (y_min < 1) {
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-y')
|
|
.select('.axis-y')
|
|
|
.select('.tick text')
|
|
.select('.tick text')
|
|
|
.text('0');
|
|
.text('0');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Remove vertical line in the right of axis labels (called domain in d3)
|
|
// Remove vertical line in the right of axis labels (called domain in d3)
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-y')
|
|
.select('.axis-y')
|
|
|
.select('.domain')
|
|
.select('.domain')
|
|
|
.remove();
|
|
.remove();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function addYAxisFromBuckets() {
|
|
|
|
|
- const tsBuckets = data.tsBuckets;
|
|
|
|
|
|
|
+ addYAxisFromBuckets() {
|
|
|
|
|
+ const tsBuckets = this.data.tsBuckets;
|
|
|
|
|
|
|
|
- scope.yScale = yScale = d3
|
|
|
|
|
|
|
+ this.scope.yScale = this.yScale = d3
|
|
|
.scaleLinear()
|
|
.scaleLinear()
|
|
|
.domain([0, tsBuckets.length - 1])
|
|
.domain([0, tsBuckets.length - 1])
|
|
|
- .range([chartHeight, 0]);
|
|
|
|
|
|
|
+ .range([this.chartHeight, 0]);
|
|
|
|
|
|
|
|
const tick_values = _.map(tsBuckets, (b, i) => i);
|
|
const tick_values = _.map(tsBuckets, (b, i) => i);
|
|
|
const decimalsAuto = _.max(_.map(tsBuckets, ticksUtils.getStringPrecision));
|
|
const decimalsAuto = _.max(_.map(tsBuckets, ticksUtils.getStringPrecision));
|
|
|
- const decimals = panel.yAxis.decimals === null ? decimalsAuto : panel.yAxis.decimals;
|
|
|
|
|
- ctrl.decimals = decimals;
|
|
|
|
|
|
|
+ const decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;
|
|
|
|
|
+ this.ctrl.decimals = decimals;
|
|
|
|
|
|
|
|
function tickFormatter(valIndex) {
|
|
function tickFormatter(valIndex) {
|
|
|
let valueFormatted = tsBuckets[valIndex];
|
|
let valueFormatted = tsBuckets[valIndex];
|
|
|
if (!_.isNaN(_.toNumber(valueFormatted)) && valueFormatted !== '') {
|
|
if (!_.isNaN(_.toNumber(valueFormatted)) && valueFormatted !== '') {
|
|
|
// Try to format numeric tick labels
|
|
// Try to format numeric tick labels
|
|
|
- valueFormatted = tickValueFormatter(decimals)(_.toNumber(valueFormatted));
|
|
|
|
|
|
|
+ valueFormatted = this.tickValueFormatter(decimals)(_.toNumber(valueFormatted));
|
|
|
}
|
|
}
|
|
|
return valueFormatted;
|
|
return valueFormatted;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const tsBucketsFormatted = _.map(tsBuckets, (v, i) => tickFormatter(i));
|
|
const tsBucketsFormatted = _.map(tsBuckets, (v, i) => tickFormatter(i));
|
|
|
- data.tsBucketsFormatted = tsBucketsFormatted;
|
|
|
|
|
|
|
+ this.data.tsBucketsFormatted = tsBucketsFormatted;
|
|
|
|
|
|
|
|
let yAxis = d3
|
|
let yAxis = d3
|
|
|
- .axisLeft(yScale)
|
|
|
|
|
|
|
+ .axisLeft(this.yScale)
|
|
|
.tickValues(tick_values)
|
|
.tickValues(tick_values)
|
|
|
.tickFormat(tickFormatter)
|
|
.tickFormat(tickFormatter)
|
|
|
- .tickSizeInner(0 - width)
|
|
|
|
|
|
|
+ .tickSizeInner(0 - this.width)
|
|
|
.tickSizeOuter(0)
|
|
.tickSizeOuter(0)
|
|
|
.tickPadding(Y_AXIS_TICK_PADDING);
|
|
.tickPadding(Y_AXIS_TICK_PADDING);
|
|
|
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.append('g')
|
|
.append('g')
|
|
|
.attr('class', 'axis axis-y')
|
|
.attr('class', 'axis axis-y')
|
|
|
.call(yAxis);
|
|
.call(yAxis);
|
|
|
|
|
|
|
|
// Calculate Y axis width first, then move axis into visible area
|
|
// Calculate Y axis width first, then move axis into visible area
|
|
|
- const posY = margin.top;
|
|
|
|
|
- const posX = getYAxisWidth(heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
- heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
|
|
|
|
|
|
+ const posY = this.margin.top;
|
|
|
|
|
+ const posX = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
+ this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
|
|
|
|
|
|
|
// Remove vertical line in the right of axis labels (called domain in d3)
|
|
// Remove vertical line in the right of axis labels (called domain in d3)
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-y')
|
|
.select('.axis-y')
|
|
|
.select('.domain')
|
|
.select('.domain')
|
|
|
.remove();
|
|
.remove();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Adjust data range to log base
|
|
// Adjust data range to log base
|
|
|
- function adjustLogRange(min, max, logBase) {
|
|
|
|
|
|
|
+ adjustLogRange(min, max, logBase) {
|
|
|
let y_min, y_max;
|
|
let y_min, y_max;
|
|
|
|
|
|
|
|
- y_min = data.heatmapStats.minLog;
|
|
|
|
|
- if (data.heatmapStats.minLog > 1 || !data.heatmapStats.minLog) {
|
|
|
|
|
|
|
+ y_min = this.data.heatmapStats.minLog;
|
|
|
|
|
+ if (this.data.heatmapStats.minLog > 1 || !this.data.heatmapStats.minLog) {
|
|
|
y_min = 1;
|
|
y_min = 1;
|
|
|
} else {
|
|
} else {
|
|
|
- y_min = adjustLogMin(data.heatmapStats.minLog, logBase);
|
|
|
|
|
|
|
+ y_min = this.adjustLogMin(this.data.heatmapStats.minLog, logBase);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Adjust max Y value to log base
|
|
// Adjust max Y value to log base
|
|
|
- y_max = adjustLogMax(data.heatmapStats.max, logBase);
|
|
|
|
|
|
|
+ y_max = this.adjustLogMax(this.data.heatmapStats.max, logBase);
|
|
|
|
|
|
|
|
return { y_min, y_max };
|
|
return { y_min, y_max };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function adjustLogMax(max, base) {
|
|
|
|
|
|
|
+ adjustLogMax(max, base) {
|
|
|
return Math.pow(base, Math.ceil(ticksUtils.logp(max, base)));
|
|
return Math.pow(base, Math.ceil(ticksUtils.logp(max, base)));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function adjustLogMin(min, base) {
|
|
|
|
|
|
|
+ adjustLogMin(min, base) {
|
|
|
return Math.pow(base, Math.floor(ticksUtils.logp(min, base)));
|
|
return Math.pow(base, Math.floor(ticksUtils.logp(min, base)));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function logScaleTickValues(domain, base) {
|
|
|
|
|
|
|
+ logScaleTickValues(domain, base) {
|
|
|
let domainMin = domain[0];
|
|
let domainMin = domain[0];
|
|
|
let domainMax = domain[1];
|
|
let domainMax = domain[1];
|
|
|
let tickValues = [];
|
|
let tickValues = [];
|
|
@@ -393,8 +429,8 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
return tickValues;
|
|
return tickValues;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function tickValueFormatter(decimals, scaledDecimals = null) {
|
|
|
|
|
- let format = panel.yAxis.format;
|
|
|
|
|
|
|
+ tickValueFormatter(decimals, scaledDecimals = null) {
|
|
|
|
|
+ let format = this.panel.yAxis.format;
|
|
|
return function(value) {
|
|
return function(value) {
|
|
|
try {
|
|
try {
|
|
|
return format !== 'none' ? kbn.valueFormats[format](value, decimals, scaledDecimals) : value;
|
|
return format !== 'none' ? kbn.valueFormats[format](value, decimals, scaledDecimals) : value;
|
|
@@ -405,181 +441,179 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ctrl.tickValueFormatter = tickValueFormatter;
|
|
|
|
|
-
|
|
|
|
|
- function fixYAxisTickSize() {
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ fixYAxisTickSize() {
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-y')
|
|
.select('.axis-y')
|
|
|
.selectAll('.tick line')
|
|
.selectAll('.tick line')
|
|
|
- .attr('x2', chartWidth);
|
|
|
|
|
|
|
+ .attr('x2', this.chartWidth);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function addAxes() {
|
|
|
|
|
- chartHeight = height - margin.top - margin.bottom;
|
|
|
|
|
- chartTop = margin.top;
|
|
|
|
|
- chartBottom = chartTop + chartHeight;
|
|
|
|
|
|
|
+ addAxes() {
|
|
|
|
|
+ this.chartHeight = this.height - this.margin.top - this.margin.bottom;
|
|
|
|
|
+ this.chartTop = this.margin.top;
|
|
|
|
|
+ this.chartBottom = this.chartTop + this.chartHeight;
|
|
|
|
|
|
|
|
- if (panel.dataFormat === 'tsbuckets') {
|
|
|
|
|
- addYAxisFromBuckets();
|
|
|
|
|
|
|
+ if (this.panel.dataFormat === 'tsbuckets') {
|
|
|
|
|
+ this.addYAxisFromBuckets();
|
|
|
} else {
|
|
} else {
|
|
|
- if (panel.yAxis.logBase === 1) {
|
|
|
|
|
- addYAxis();
|
|
|
|
|
|
|
+ if (this.panel.yAxis.logBase === 1) {
|
|
|
|
|
+ this.addYAxis();
|
|
|
} else {
|
|
} else {
|
|
|
- addLogYAxis();
|
|
|
|
|
|
|
+ this.addLogYAxis();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- yAxisWidth = getYAxisWidth(heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
- chartWidth = width - yAxisWidth - margin.right;
|
|
|
|
|
- fixYAxisTickSize();
|
|
|
|
|
|
|
+ this.yAxisWidth = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;
|
|
|
|
|
+ this.chartWidth = this.width - this.yAxisWidth - this.margin.right;
|
|
|
|
|
+ this.fixYAxisTickSize();
|
|
|
|
|
|
|
|
- addXAxis();
|
|
|
|
|
- xAxisHeight = getXAxisHeight(heatmap);
|
|
|
|
|
|
|
+ this.addXAxis();
|
|
|
|
|
+ this.xAxisHeight = this.getXAxisHeight(this.heatmap);
|
|
|
|
|
|
|
|
- if (!panel.yAxis.show) {
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ if (!this.panel.yAxis.show) {
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-y')
|
|
.select('.axis-y')
|
|
|
.selectAll('line')
|
|
.selectAll('line')
|
|
|
.style('opacity', 0);
|
|
.style('opacity', 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (!panel.xAxis.show) {
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ if (!this.panel.xAxis.show) {
|
|
|
|
|
+ this.heatmap
|
|
|
.select('.axis-x')
|
|
.select('.axis-x')
|
|
|
.selectAll('line')
|
|
.selectAll('line')
|
|
|
.style('opacity', 0);
|
|
.style('opacity', 0);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function addHeatmapCanvas() {
|
|
|
|
|
- let heatmap_elem = $heatmap[0];
|
|
|
|
|
|
|
+ addHeatmapCanvas() {
|
|
|
|
|
+ let heatmap_elem = this.$heatmap[0];
|
|
|
|
|
|
|
|
- width = Math.floor($heatmap.width()) - padding.right;
|
|
|
|
|
- height = Math.floor($heatmap.height()) - padding.bottom;
|
|
|
|
|
|
|
+ this.width = Math.floor(this.$heatmap.width()) - this.padding.right;
|
|
|
|
|
+ this.height = Math.floor(this.$heatmap.height()) - this.padding.bottom;
|
|
|
|
|
|
|
|
- cardPadding = panel.cards.cardPadding !== null ? panel.cards.cardPadding : CARD_PADDING;
|
|
|
|
|
- cardRound = panel.cards.cardRound !== null ? panel.cards.cardRound : CARD_ROUND;
|
|
|
|
|
|
|
+ this.cardPadding = this.panel.cards.cardPadding !== null ? this.panel.cards.cardPadding : CARD_PADDING;
|
|
|
|
|
+ this.cardRound = this.panel.cards.cardRound !== null ? this.panel.cards.cardRound : CARD_ROUND;
|
|
|
|
|
|
|
|
- if (heatmap) {
|
|
|
|
|
- heatmap.remove();
|
|
|
|
|
|
|
+ if (this.heatmap) {
|
|
|
|
|
+ this.heatmap.remove();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- heatmap = d3
|
|
|
|
|
|
|
+ this.heatmap = d3
|
|
|
.select(heatmap_elem)
|
|
.select(heatmap_elem)
|
|
|
.append('svg')
|
|
.append('svg')
|
|
|
- .attr('width', width)
|
|
|
|
|
- .attr('height', height);
|
|
|
|
|
|
|
+ .attr('width', this.width)
|
|
|
|
|
+ .attr('height', this.height);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function addHeatmap() {
|
|
|
|
|
- addHeatmapCanvas();
|
|
|
|
|
- addAxes();
|
|
|
|
|
|
|
+ addHeatmap() {
|
|
|
|
|
+ this.addHeatmapCanvas();
|
|
|
|
|
+ this.addAxes();
|
|
|
|
|
|
|
|
- if (panel.yAxis.logBase !== 1 && panel.dataFormat !== 'tsbuckets') {
|
|
|
|
|
- let log_base = panel.yAxis.logBase;
|
|
|
|
|
- let domain = yScale.domain();
|
|
|
|
|
- let tick_values = logScaleTickValues(domain, log_base);
|
|
|
|
|
- data.buckets = mergeZeroBuckets(data.buckets, _.min(tick_values));
|
|
|
|
|
|
|
+ if (this.panel.yAxis.logBase !== 1 && this.panel.dataFormat !== 'tsbuckets') {
|
|
|
|
|
+ let log_base = this.panel.yAxis.logBase;
|
|
|
|
|
+ let domain = this.yScale.domain();
|
|
|
|
|
+ let tick_values = this.logScaleTickValues(domain, log_base);
|
|
|
|
|
+ this.data.buckets = mergeZeroBuckets(this.data.buckets, _.min(tick_values));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- let cardsData = data.cards;
|
|
|
|
|
- let maxValueAuto = data.cardStats.max;
|
|
|
|
|
- let maxValue = panel.color.max || maxValueAuto;
|
|
|
|
|
- let minValue = panel.color.min || 0;
|
|
|
|
|
|
|
+ let cardsData = this.data.cards;
|
|
|
|
|
+ let maxValueAuto = this.data.cardStats.max;
|
|
|
|
|
+ let maxValue = this.panel.color.max || maxValueAuto;
|
|
|
|
|
+ let minValue = this.panel.color.min || 0;
|
|
|
|
|
|
|
|
- let colorScheme = _.find(ctrl.colorSchemes, {
|
|
|
|
|
- value: panel.color.colorScheme,
|
|
|
|
|
|
|
+ let colorScheme = _.find(this.ctrl.colorSchemes, {
|
|
|
|
|
+ value: this.panel.color.colorScheme,
|
|
|
});
|
|
});
|
|
|
- colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, maxValue, minValue);
|
|
|
|
|
- opacityScale = getOpacityScale(panel.color, maxValue);
|
|
|
|
|
- setCardSize();
|
|
|
|
|
|
|
+ this.colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, maxValue, minValue);
|
|
|
|
|
+ this.opacityScale = getOpacityScale(this.panel.color, maxValue);
|
|
|
|
|
+ this.setCardSize();
|
|
|
|
|
|
|
|
- let cards = heatmap.selectAll('.heatmap-card').data(cardsData);
|
|
|
|
|
|
|
+ let cards = this.heatmap.selectAll('.heatmap-card').data(cardsData);
|
|
|
cards.append('title');
|
|
cards.append('title');
|
|
|
cards = cards
|
|
cards = cards
|
|
|
.enter()
|
|
.enter()
|
|
|
.append('rect')
|
|
.append('rect')
|
|
|
- .attr('x', getCardX)
|
|
|
|
|
- .attr('width', getCardWidth)
|
|
|
|
|
- .attr('y', getCardY)
|
|
|
|
|
- .attr('height', getCardHeight)
|
|
|
|
|
- .attr('rx', cardRound)
|
|
|
|
|
- .attr('ry', cardRound)
|
|
|
|
|
|
|
+ .attr('x', this.getCardX)
|
|
|
|
|
+ .attr('width', this.getCardWidth)
|
|
|
|
|
+ .attr('y', this.getCardY)
|
|
|
|
|
+ .attr('height', this.getCardHeight)
|
|
|
|
|
+ .attr('rx', this.cardRound)
|
|
|
|
|
+ .attr('ry', this.cardRound)
|
|
|
.attr('class', 'bordered heatmap-card')
|
|
.attr('class', 'bordered heatmap-card')
|
|
|
- .style('fill', getCardColor)
|
|
|
|
|
- .style('stroke', getCardColor)
|
|
|
|
|
|
|
+ .style('fill', this.getCardColor)
|
|
|
|
|
+ .style('stroke', this.getCardColor)
|
|
|
.style('stroke-width', 0)
|
|
.style('stroke-width', 0)
|
|
|
- .style('opacity', getCardOpacity);
|
|
|
|
|
|
|
+ .style('opacity', this.getCardOpacity);
|
|
|
|
|
|
|
|
- let $cards = $heatmap.find('.heatmap-card');
|
|
|
|
|
|
|
+ let $cards = this.$heatmap.find('.heatmap-card');
|
|
|
$cards
|
|
$cards
|
|
|
.on('mouseenter', event => {
|
|
.on('mouseenter', event => {
|
|
|
- tooltip.mouseOverBucket = true;
|
|
|
|
|
- highlightCard(event);
|
|
|
|
|
|
|
+ this.tooltip.mouseOverBucket = true;
|
|
|
|
|
+ this.highlightCard(event);
|
|
|
})
|
|
})
|
|
|
.on('mouseleave', event => {
|
|
.on('mouseleave', event => {
|
|
|
- tooltip.mouseOverBucket = false;
|
|
|
|
|
- resetCardHighLight(event);
|
|
|
|
|
|
|
+ this.tooltip.mouseOverBucket = false;
|
|
|
|
|
+ this.resetCardHighLight(event);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function highlightCard(event) {
|
|
|
|
|
|
|
+ highlightCard(event) {
|
|
|
let color = d3.select(event.target).style('fill');
|
|
let color = d3.select(event.target).style('fill');
|
|
|
let highlightColor = d3.color(color).darker(2);
|
|
let highlightColor = d3.color(color).darker(2);
|
|
|
let strokeColor = d3.color(color).brighter(4);
|
|
let strokeColor = d3.color(color).brighter(4);
|
|
|
let current_card = d3.select(event.target);
|
|
let current_card = d3.select(event.target);
|
|
|
- tooltip.originalFillColor = color;
|
|
|
|
|
|
|
+ this.tooltip.originalFillColor = color;
|
|
|
current_card
|
|
current_card
|
|
|
.style('fill', highlightColor.toString())
|
|
.style('fill', highlightColor.toString())
|
|
|
.style('stroke', strokeColor.toString())
|
|
.style('stroke', strokeColor.toString())
|
|
|
.style('stroke-width', 1);
|
|
.style('stroke-width', 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function resetCardHighLight(event) {
|
|
|
|
|
|
|
+ resetCardHighLight(event) {
|
|
|
d3
|
|
d3
|
|
|
.select(event.target)
|
|
.select(event.target)
|
|
|
- .style('fill', tooltip.originalFillColor)
|
|
|
|
|
- .style('stroke', tooltip.originalFillColor)
|
|
|
|
|
|
|
+ .style('fill', this.tooltip.originalFillColor)
|
|
|
|
|
+ .style('stroke', this.tooltip.originalFillColor)
|
|
|
.style('stroke-width', 0);
|
|
.style('stroke-width', 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function setCardSize() {
|
|
|
|
|
- let xGridSize = Math.floor(xScale(data.xBucketSize) - xScale(0));
|
|
|
|
|
- let yGridSize = Math.floor(yScale(yScale.invert(0) - data.yBucketSize));
|
|
|
|
|
|
|
+ setCardSize() {
|
|
|
|
|
+ let xGridSize = Math.floor(this.xScale(this.data.xBucketSize) - this.xScale(0));
|
|
|
|
|
+ let yGridSize = Math.floor(this.yScale(this.yScale.invert(0) - this.data.yBucketSize));
|
|
|
|
|
|
|
|
- if (panel.yAxis.logBase !== 1) {
|
|
|
|
|
- let base = panel.yAxis.logBase;
|
|
|
|
|
- let splitFactor = data.yBucketSize || 1;
|
|
|
|
|
- yGridSize = Math.floor((yScale(1) - yScale(base)) / splitFactor);
|
|
|
|
|
|
|
+ if (this.panel.yAxis.logBase !== 1) {
|
|
|
|
|
+ let base = this.panel.yAxis.logBase;
|
|
|
|
|
+ let splitFactor = this.data.yBucketSize || 1;
|
|
|
|
|
+ yGridSize = Math.floor((this.yScale(1) - this.yScale(base)) / splitFactor);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- cardWidth = xGridSize - cardPadding * 2;
|
|
|
|
|
- cardHeight = yGridSize ? yGridSize - cardPadding * 2 : 0;
|
|
|
|
|
|
|
+ this.cardWidth = xGridSize - this.cardPadding * 2;
|
|
|
|
|
+ this.cardHeight = yGridSize ? yGridSize - this.cardPadding * 2 : 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getCardX(d) {
|
|
|
|
|
|
|
+ getCardX(d) {
|
|
|
let x;
|
|
let x;
|
|
|
- if (xScale(d.x) < 0) {
|
|
|
|
|
|
|
+ if (this.xScale(d.x) < 0) {
|
|
|
// Cut card left to prevent overlay
|
|
// Cut card left to prevent overlay
|
|
|
- x = yAxisWidth + cardPadding;
|
|
|
|
|
|
|
+ x = this.yAxisWidth + this.cardPadding;
|
|
|
} else {
|
|
} else {
|
|
|
- x = xScale(d.x) + yAxisWidth + cardPadding;
|
|
|
|
|
|
|
+ x = this.xScale(d.x) + this.yAxisWidth + this.cardPadding;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return x;
|
|
return x;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getCardWidth(d) {
|
|
|
|
|
|
|
+ getCardWidth(d) {
|
|
|
let w;
|
|
let w;
|
|
|
- if (xScale(d.x) < 0) {
|
|
|
|
|
|
|
+ if (this.xScale(d.x) < 0) {
|
|
|
// Cut card left to prevent overlay
|
|
// Cut card left to prevent overlay
|
|
|
- let cutted_width = xScale(d.x) + cardWidth;
|
|
|
|
|
|
|
+ let cutted_width = this.xScale(d.x) + this.cardWidth;
|
|
|
w = cutted_width > 0 ? cutted_width : 0;
|
|
w = cutted_width > 0 ? cutted_width : 0;
|
|
|
- } else if (xScale(d.x) + cardWidth > chartWidth) {
|
|
|
|
|
|
|
+ } else if (this.xScale(d.x) + this.cardWidth > this.chartWidth) {
|
|
|
// Cut card right to prevent overlay
|
|
// Cut card right to prevent overlay
|
|
|
- w = chartWidth - xScale(d.x) - cardPadding;
|
|
|
|
|
|
|
+ w = this.chartWidth - this.xScale(d.x) - this.cardPadding;
|
|
|
} else {
|
|
} else {
|
|
|
- w = cardWidth;
|
|
|
|
|
|
|
+ w = this.cardWidth;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Card width should be MIN_CARD_SIZE at least
|
|
// Card width should be MIN_CARD_SIZE at least
|
|
@@ -587,138 +621,117 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
return w;
|
|
return w;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getCardY(d) {
|
|
|
|
|
- let y = yScale(d.y) + chartTop - cardHeight - cardPadding;
|
|
|
|
|
- if (panel.yAxis.logBase !== 1 && d.y === 0) {
|
|
|
|
|
- y = chartBottom - cardHeight - cardPadding;
|
|
|
|
|
|
|
+ getCardY(d) {
|
|
|
|
|
+ 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;
|
|
|
} else {
|
|
} else {
|
|
|
- if (y < chartTop) {
|
|
|
|
|
- y = chartTop;
|
|
|
|
|
|
|
+ if (y < this.chartTop) {
|
|
|
|
|
+ y = this.chartTop;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return y;
|
|
return y;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getCardHeight(d) {
|
|
|
|
|
- let y = yScale(d.y) + chartTop - cardHeight - cardPadding;
|
|
|
|
|
- let h = cardHeight;
|
|
|
|
|
|
|
+ getCardHeight(d) {
|
|
|
|
|
+ let y = this.yScale(d.y) + this.chartTop - this.cardHeight - this.cardPadding;
|
|
|
|
|
+ let h = this.cardHeight;
|
|
|
|
|
|
|
|
- if (panel.yAxis.logBase !== 1 && d.y === 0) {
|
|
|
|
|
- return cardHeight;
|
|
|
|
|
|
|
+ if (this.panel.yAxis.logBase !== 1 && d.y === 0) {
|
|
|
|
|
+ return this.cardHeight;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Cut card height to prevent overlay
|
|
// Cut card height to prevent overlay
|
|
|
- if (y < chartTop) {
|
|
|
|
|
- h = yScale(d.y) - cardPadding;
|
|
|
|
|
- } else if (yScale(d.y) > chartBottom) {
|
|
|
|
|
- h = chartBottom - y;
|
|
|
|
|
- } else if (y + cardHeight > chartBottom) {
|
|
|
|
|
- h = chartBottom - y;
|
|
|
|
|
|
|
+ if (y < this.chartTop) {
|
|
|
|
|
+ h = this.yScale(d.y) - this.cardPadding;
|
|
|
|
|
+ } else if (this.yScale(d.y) > this.chartBottom) {
|
|
|
|
|
+ h = this.chartBottom - y;
|
|
|
|
|
+ } else if (y + this.cardHeight > this.chartBottom) {
|
|
|
|
|
+ h = this.chartBottom - y;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Height can't be more than chart height
|
|
// Height can't be more than chart height
|
|
|
- h = Math.min(h, chartHeight);
|
|
|
|
|
|
|
+ h = Math.min(h, this.chartHeight);
|
|
|
// Card height should be MIN_CARD_SIZE at least
|
|
// Card height should be MIN_CARD_SIZE at least
|
|
|
h = Math.max(h, MIN_CARD_SIZE);
|
|
h = Math.max(h, MIN_CARD_SIZE);
|
|
|
|
|
|
|
|
return h;
|
|
return h;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getCardColor(d) {
|
|
|
|
|
- if (panel.color.mode === 'opacity') {
|
|
|
|
|
- return panel.color.cardColor;
|
|
|
|
|
|
|
+ getCardColor(d) {
|
|
|
|
|
+ if (this.panel.color.mode === 'opacity') {
|
|
|
|
|
+ return this.panel.color.cardColor;
|
|
|
} else {
|
|
} else {
|
|
|
- return colorScale(d.count);
|
|
|
|
|
|
|
+ return this.colorScale(d.count);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function getCardOpacity(d) {
|
|
|
|
|
- if (panel.color.mode === 'opacity') {
|
|
|
|
|
- return opacityScale(d.count);
|
|
|
|
|
|
|
+ getCardOpacity(d) {
|
|
|
|
|
+ if (this.panel.color.mode === 'opacity') {
|
|
|
|
|
+ return this.opacityScale(d.count);
|
|
|
} else {
|
|
} else {
|
|
|
return 1;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /////////////////////////////
|
|
|
|
|
- // Selection and crosshair //
|
|
|
|
|
- /////////////////////////////
|
|
|
|
|
-
|
|
|
|
|
- // Shared crosshair and tooltip
|
|
|
|
|
- appEvents.on(
|
|
|
|
|
- 'graph-hover',
|
|
|
|
|
- event => {
|
|
|
|
|
- drawSharedCrosshair(event.pos);
|
|
|
|
|
- },
|
|
|
|
|
- scope
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- appEvents.on(
|
|
|
|
|
- 'graph-hover-clear',
|
|
|
|
|
- () => {
|
|
|
|
|
- clearCrosshair();
|
|
|
|
|
- },
|
|
|
|
|
- scope
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ onMouseDown(event) {
|
|
|
|
|
+ this.selection.active = true;
|
|
|
|
|
+ this.selection.x1 = event.offsetX;
|
|
|
|
|
|
|
|
- function onMouseDown(event) {
|
|
|
|
|
- selection.active = true;
|
|
|
|
|
- selection.x1 = event.offsetX;
|
|
|
|
|
-
|
|
|
|
|
- mouseUpHandler = function() {
|
|
|
|
|
- onMouseUp();
|
|
|
|
|
|
|
+ this.mouseUpHandler = () => {
|
|
|
|
|
+ this.onMouseUp();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- $(document).one('mouseup', mouseUpHandler);
|
|
|
|
|
|
|
+ $(document).one('mouseup', this.mouseUpHandler);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function onMouseUp() {
|
|
|
|
|
- $(document).unbind('mouseup', mouseUpHandler);
|
|
|
|
|
- mouseUpHandler = null;
|
|
|
|
|
- selection.active = false;
|
|
|
|
|
|
|
+ onMouseUp() {
|
|
|
|
|
+ $(document).unbind('mouseup', this.mouseUpHandler);
|
|
|
|
|
+ this.mouseUpHandler = null;
|
|
|
|
|
+ this.selection.active = false;
|
|
|
|
|
|
|
|
- let selectionRange = Math.abs(selection.x2 - selection.x1);
|
|
|
|
|
- if (selection.x2 >= 0 && selectionRange > MIN_SELECTION_WIDTH) {
|
|
|
|
|
- let timeFrom = xScale.invert(Math.min(selection.x1, selection.x2) - yAxisWidth);
|
|
|
|
|
- let timeTo = xScale.invert(Math.max(selection.x1, selection.x2) - yAxisWidth);
|
|
|
|
|
|
|
+ let selectionRange = Math.abs(this.selection.x2 - this.selection.x1);
|
|
|
|
|
+ if (this.selection.x2 >= 0 && selectionRange > MIN_SELECTION_WIDTH) {
|
|
|
|
|
+ let timeFrom = this.xScale.invert(Math.min(this.selection.x1, this.selection.x2) - this.yAxisWidth);
|
|
|
|
|
+ let timeTo = this.xScale.invert(Math.max(this.selection.x1, this.selection.x2) - this.yAxisWidth);
|
|
|
|
|
|
|
|
- ctrl.timeSrv.setTime({
|
|
|
|
|
|
|
+ this.ctrl.timeSrv.setTime({
|
|
|
from: moment.utc(timeFrom),
|
|
from: moment.utc(timeFrom),
|
|
|
to: moment.utc(timeTo),
|
|
to: moment.utc(timeTo),
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- clearSelection();
|
|
|
|
|
|
|
+ this.clearSelection();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function onMouseLeave() {
|
|
|
|
|
|
|
+ onMouseLeave() {
|
|
|
appEvents.emit('graph-hover-clear');
|
|
appEvents.emit('graph-hover-clear');
|
|
|
- clearCrosshair();
|
|
|
|
|
|
|
+ this.clearCrosshair();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function onMouseMove(event) {
|
|
|
|
|
- if (!heatmap) {
|
|
|
|
|
|
|
+ onMouseMove(event) {
|
|
|
|
|
+ if (!this.heatmap) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (selection.active) {
|
|
|
|
|
|
|
+ if (this.selection.active) {
|
|
|
// Clear crosshair and tooltip
|
|
// Clear crosshair and tooltip
|
|
|
- clearCrosshair();
|
|
|
|
|
- tooltip.destroy();
|
|
|
|
|
|
|
+ this.clearCrosshair();
|
|
|
|
|
+ this.tooltip.destroy();
|
|
|
|
|
|
|
|
- selection.x2 = limitSelection(event.offsetX);
|
|
|
|
|
- drawSelection(selection.x1, selection.x2);
|
|
|
|
|
|
|
+ this.selection.x2 = this.limitSelection(event.offsetX);
|
|
|
|
|
+ this.drawSelection(this.selection.x1, this.selection.x2);
|
|
|
} else {
|
|
} else {
|
|
|
- emitGraphHoverEvent(event);
|
|
|
|
|
- drawCrosshair(event.offsetX);
|
|
|
|
|
- tooltip.show(event, data);
|
|
|
|
|
|
|
+ this.emitGraphHoverEvent(event);
|
|
|
|
|
+ this.drawCrosshair(event.offsetX);
|
|
|
|
|
+ this.tooltip.show(event, this.data);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function emitGraphHoverEvent(event) {
|
|
|
|
|
- let x = xScale.invert(event.offsetX - yAxisWidth).valueOf();
|
|
|
|
|
- let y = yScale.invert(event.offsetY);
|
|
|
|
|
|
|
+ emitGraphHoverEvent(event) {
|
|
|
|
|
+ let x = this.xScale.invert(event.offsetX - this.yAxisWidth).valueOf();
|
|
|
|
|
+ let y = this.yScale.invert(event.offsetY);
|
|
|
let pos = {
|
|
let pos = {
|
|
|
pageX: event.pageX,
|
|
pageX: event.pageX,
|
|
|
pageY: event.pageY,
|
|
pageY: event.pageY,
|
|
@@ -730,105 +743,100 @@ export default function link(scope, elem, attrs, ctrl) {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// Set minimum offset to prevent showing legend from another panel
|
|
// Set minimum offset to prevent showing legend from another panel
|
|
|
- pos.panelRelY = Math.max(event.offsetY / height, 0.001);
|
|
|
|
|
|
|
+ pos.panelRelY = Math.max(event.offsetY / this.height, 0.001);
|
|
|
|
|
|
|
|
// broadcast to other graph panels that we are hovering
|
|
// broadcast to other graph panels that we are hovering
|
|
|
- appEvents.emit('graph-hover', { pos: pos, panel: panel });
|
|
|
|
|
|
|
+ appEvents.emit('graph-hover', { pos: pos, panel: this.panel });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function limitSelection(x2) {
|
|
|
|
|
- x2 = Math.max(x2, yAxisWidth);
|
|
|
|
|
- x2 = Math.min(x2, chartWidth + yAxisWidth);
|
|
|
|
|
|
|
+ limitSelection(x2) {
|
|
|
|
|
+ x2 = Math.max(x2, this.yAxisWidth);
|
|
|
|
|
+ x2 = Math.min(x2, this.chartWidth + this.yAxisWidth);
|
|
|
return x2;
|
|
return x2;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function drawSelection(posX1, posX2) {
|
|
|
|
|
- if (heatmap) {
|
|
|
|
|
- heatmap.selectAll('.heatmap-selection').remove();
|
|
|
|
|
|
|
+ drawSelection(posX1, posX2) {
|
|
|
|
|
+ if (this.heatmap) {
|
|
|
|
|
+ this.heatmap.selectAll('.heatmap-selection').remove();
|
|
|
let selectionX = Math.min(posX1, posX2);
|
|
let selectionX = Math.min(posX1, posX2);
|
|
|
let selectionWidth = Math.abs(posX1 - posX2);
|
|
let selectionWidth = Math.abs(posX1 - posX2);
|
|
|
|
|
|
|
|
if (selectionWidth > MIN_SELECTION_WIDTH) {
|
|
if (selectionWidth > MIN_SELECTION_WIDTH) {
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.append('rect')
|
|
.append('rect')
|
|
|
.attr('class', 'heatmap-selection')
|
|
.attr('class', 'heatmap-selection')
|
|
|
.attr('x', selectionX)
|
|
.attr('x', selectionX)
|
|
|
.attr('width', selectionWidth)
|
|
.attr('width', selectionWidth)
|
|
|
- .attr('y', chartTop)
|
|
|
|
|
- .attr('height', chartHeight);
|
|
|
|
|
|
|
+ .attr('y', this.chartTop)
|
|
|
|
|
+ .attr('height', this.chartHeight);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function clearSelection() {
|
|
|
|
|
- selection.x1 = -1;
|
|
|
|
|
- selection.x2 = -1;
|
|
|
|
|
|
|
+ clearSelection() {
|
|
|
|
|
+ this.selection.x1 = -1;
|
|
|
|
|
+ this.selection.x2 = -1;
|
|
|
|
|
|
|
|
- if (heatmap) {
|
|
|
|
|
- heatmap.selectAll('.heatmap-selection').remove();
|
|
|
|
|
|
|
+ if (this.heatmap) {
|
|
|
|
|
+ this.heatmap.selectAll('.heatmap-selection').remove();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function drawCrosshair(position) {
|
|
|
|
|
- if (heatmap) {
|
|
|
|
|
- heatmap.selectAll('.heatmap-crosshair').remove();
|
|
|
|
|
|
|
+ drawCrosshair(position) {
|
|
|
|
|
+ if (this.heatmap) {
|
|
|
|
|
+ this.heatmap.selectAll('.heatmap-crosshair').remove();
|
|
|
|
|
|
|
|
let posX = position;
|
|
let posX = position;
|
|
|
- posX = Math.max(posX, yAxisWidth);
|
|
|
|
|
- posX = Math.min(posX, chartWidth + yAxisWidth);
|
|
|
|
|
|
|
+ posX = Math.max(posX, this.yAxisWidth);
|
|
|
|
|
+ posX = Math.min(posX, this.chartWidth + this.yAxisWidth);
|
|
|
|
|
|
|
|
- heatmap
|
|
|
|
|
|
|
+ this.heatmap
|
|
|
.append('g')
|
|
.append('g')
|
|
|
.attr('class', 'heatmap-crosshair')
|
|
.attr('class', 'heatmap-crosshair')
|
|
|
.attr('transform', 'translate(' + posX + ',0)')
|
|
.attr('transform', 'translate(' + posX + ',0)')
|
|
|
.append('line')
|
|
.append('line')
|
|
|
.attr('x1', 1)
|
|
.attr('x1', 1)
|
|
|
- .attr('y1', chartTop)
|
|
|
|
|
|
|
+ .attr('y1', this.chartTop)
|
|
|
.attr('x2', 1)
|
|
.attr('x2', 1)
|
|
|
- .attr('y2', chartBottom)
|
|
|
|
|
|
|
+ .attr('y2', this.chartBottom)
|
|
|
.attr('stroke-width', 1);
|
|
.attr('stroke-width', 1);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function drawSharedCrosshair(pos) {
|
|
|
|
|
- if (heatmap && ctrl.dashboard.graphTooltip !== 0) {
|
|
|
|
|
- let posX = xScale(pos.x) + yAxisWidth;
|
|
|
|
|
- drawCrosshair(posX);
|
|
|
|
|
|
|
+ drawSharedCrosshair(pos) {
|
|
|
|
|
+ if (this.heatmap && this.ctrl.dashboard.graphTooltip !== 0) {
|
|
|
|
|
+ let posX = this.xScale(pos.x) + this.yAxisWidth;
|
|
|
|
|
+ this.drawCrosshair(posX);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function clearCrosshair() {
|
|
|
|
|
- if (heatmap) {
|
|
|
|
|
- heatmap.selectAll('.heatmap-crosshair').remove();
|
|
|
|
|
|
|
+ clearCrosshair() {
|
|
|
|
|
+ if (this.heatmap) {
|
|
|
|
|
+ this.heatmap.selectAll('.heatmap-crosshair').remove();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function render() {
|
|
|
|
|
- data = ctrl.data;
|
|
|
|
|
- panel = ctrl.panel;
|
|
|
|
|
- timeRange = ctrl.range;
|
|
|
|
|
|
|
+ render() {
|
|
|
|
|
+ this.data = this.ctrl.data;
|
|
|
|
|
+ this.panel = this.ctrl.panel;
|
|
|
|
|
+ this.timeRange = this.ctrl.range;
|
|
|
|
|
|
|
|
- if (!setElementHeight() || !data) {
|
|
|
|
|
|
|
+ if (!this.setElementHeight() || !this.data) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Draw default axes and return if no data
|
|
// Draw default axes and return if no data
|
|
|
- if (_.isEmpty(data.buckets)) {
|
|
|
|
|
- addHeatmapCanvas();
|
|
|
|
|
- addAxes();
|
|
|
|
|
|
|
+ if (_.isEmpty(this.data.buckets)) {
|
|
|
|
|
+ this.addHeatmapCanvas();
|
|
|
|
|
+ this.addAxes();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- addHeatmap();
|
|
|
|
|
- scope.yAxisWidth = yAxisWidth;
|
|
|
|
|
- scope.xAxisHeight = xAxisHeight;
|
|
|
|
|
- scope.chartHeight = chartHeight;
|
|
|
|
|
- scope.chartWidth = chartWidth;
|
|
|
|
|
- scope.chartTop = chartTop;
|
|
|
|
|
|
|
+ this.addHeatmap();
|
|
|
|
|
+ this.scope.yAxisWidth = this.yAxisWidth;
|
|
|
|
|
+ this.scope.xAxisHeight = this.xAxisHeight;
|
|
|
|
|
+ this.scope.chartHeight = this.chartHeight;
|
|
|
|
|
+ this.scope.chartWidth = this.chartWidth;
|
|
|
|
|
+ this.scope.chartTop = this.chartTop;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // Register selection listeners
|
|
|
|
|
- $heatmap.on('mousedown', onMouseDown);
|
|
|
|
|
- $heatmap.on('mousemove', onMouseMove);
|
|
|
|
|
- $heatmap.on('mouseleave', onMouseLeave);
|
|
|
|
|
}
|
|
}
|