mirror of
https://github.com/timberjoegithub/grafana-statusmap.git
synced 2026-07-23 16:13:09 +00:00
feat: use grafana-toolkit to build a plugin
- fix linter warnings - use yarn: remove Gruntfile.js and package-lock.json ++
This commit is contained in:
+91
-83
@@ -9,22 +9,21 @@ import { tooltipEditorCtrl } from './tooltip_editor';
|
||||
import { migratePanelConfig } from './panel_config_migration';
|
||||
|
||||
// Utils
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import {loadPluginCss} from 'app/plugins/sdk';
|
||||
import kbn from 'grafana/app/core/utils/kbn';
|
||||
import { loadPluginCss } from 'grafana/app/plugins/sdk';
|
||||
|
||||
// Types
|
||||
import { MetricsPanelCtrl } from 'app/plugins/sdk';
|
||||
import { AnnotationsSrv } from 'app/features/annotations/annotations_srv';
|
||||
import { MetricsPanelCtrl } from 'grafana/app/plugins/sdk';
|
||||
import { AnnotationsSrv } from 'grafana/app/features/annotations/annotations_srv';
|
||||
import { CoreEvents, PanelEvents } from './libs/grafana/events/index';
|
||||
import {Bucket, BucketMatrix, BucketMatrixPager } from './statusmap_data';
|
||||
import { Bucket, BucketMatrix, BucketMatrixPager } from './statusmap_data';
|
||||
import rendering from './rendering';
|
||||
import { Polygrafill } from './libs/polygrafill/index';
|
||||
|
||||
|
||||
import {ColorModeDiscrete} from "./color_mode_discrete";
|
||||
import { ColorModeDiscrete } from './color_mode_discrete';
|
||||
|
||||
const VALUE_INDEX = 0,
|
||||
TIME_INDEX = 1;
|
||||
TIME_INDEX = 1;
|
||||
|
||||
const colorSchemes = [
|
||||
// Diverging
|
||||
@@ -52,18 +51,18 @@ const colorSchemes = [
|
||||
{ name: 'YlGnBu', value: 'interpolateYlGnBu', invert: 'dark' },
|
||||
{ name: 'YlGn', value: 'interpolateYlGn', invert: 'dark' },
|
||||
{ name: 'YlOrBr', value: 'interpolateYlOrBr', invert: 'dark' },
|
||||
{ name: 'YlOrRd', value: 'interpolateYlOrRd', invert: 'dark' }
|
||||
{ name: 'YlOrRd', value: 'interpolateYlOrRd', invert: 'dark' },
|
||||
];
|
||||
|
||||
let colorModes = ['opacity', 'spectrum', 'discrete'];
|
||||
let opacityScales = ['linear', 'sqrt'];
|
||||
|
||||
loadPluginCss({
|
||||
dark: 'plugins/flant-statusmap-panel/css/statusmap.dark.css',
|
||||
light: 'plugins/flant-statusmap-panel/css/statusmap.light.css'
|
||||
dark: 'plugins/flant-statusmap-panel/styles/dark.css',
|
||||
light: 'plugins/flant-statusmap-panel/styles/light.css',
|
||||
});
|
||||
|
||||
export var renderComplete:any = {name:'statusmap-render-complete'};
|
||||
export var renderComplete: any = { name: 'statusmap-render-complete' };
|
||||
|
||||
class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
static templateUrl = 'module.html';
|
||||
@@ -79,7 +78,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
colorSchemes: any = [];
|
||||
unitFormats: any;
|
||||
|
||||
dataWarnings: {[warningId: string]: {title: string, tip: string}} = {};
|
||||
dataWarnings: { [warningId: string]: { title: string; tip: string } } = {};
|
||||
multipleValues: boolean;
|
||||
noColorDefined: boolean;
|
||||
noDatapoints: boolean;
|
||||
@@ -90,7 +89,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
annotationsPromise: any;
|
||||
|
||||
// TODO remove this transient variable: use ng-model-options="{ getterSetter: true }"
|
||||
pageSizeViewer: number = 15;
|
||||
pageSizeViewer = 15;
|
||||
|
||||
panelDefaults: any = {
|
||||
// datasource name, null = default datasource
|
||||
@@ -104,22 +103,22 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
colorScheme: 'interpolateGnYlRd',
|
||||
// discrete mode settings
|
||||
defaultColor: '#757575',
|
||||
thresholds: [] // manual colors
|
||||
thresholds: [], // manual colors
|
||||
},
|
||||
// buckets settings
|
||||
cards: {
|
||||
cardMinWidth: 5,
|
||||
cardVSpacing: 2,
|
||||
cardHSpacing: 2,
|
||||
cardRound: null
|
||||
cardRound: null,
|
||||
},
|
||||
xAxis: {
|
||||
show: true
|
||||
show: true,
|
||||
},
|
||||
yAxis: {
|
||||
show: true,
|
||||
minWidth: -1,
|
||||
maxWidth: -1
|
||||
maxWidth: -1,
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
@@ -127,15 +126,15 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
showItems: false,
|
||||
items: [], // see tooltip_editor.ts
|
||||
showExtraInfo: false,
|
||||
extraInfo: "",
|
||||
extraInfo: '',
|
||||
},
|
||||
legend: {
|
||||
show: true
|
||||
show: true,
|
||||
},
|
||||
yLabel: {
|
||||
usingSplitLabel: false,
|
||||
delimiter: "",
|
||||
labelTemplate: "",
|
||||
delimiter: '',
|
||||
labelTemplate: '',
|
||||
},
|
||||
// how null points should be handled
|
||||
nullPointMode: 'as empty',
|
||||
@@ -147,21 +146,21 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
|
||||
// Pagination options
|
||||
usingPagination: false,
|
||||
pageSize: 15
|
||||
pageSize: 15,
|
||||
};
|
||||
|
||||
/** @ngInject */
|
||||
constructor($scope: any, $injector: auto.IInjectorService, private annotationsSrv: AnnotationsSrv) {
|
||||
super($scope, $injector);
|
||||
|
||||
if(!Polygrafill.hasAppEventCompatibleEmitter(this.events)){
|
||||
if (!Polygrafill.hasAppEventCompatibleEmitter(this.events)) {
|
||||
CoreEvents.fallbackToStringEvents();
|
||||
PanelEvents.fallbackToStringEvents();
|
||||
renderComplete = 'statusmap-render-complete';
|
||||
}
|
||||
|
||||
// Grafana 7.2 workaround
|
||||
if (typeof kbn["intervalToMs"] === "function") {
|
||||
if (typeof kbn['intervalToMs'] === 'function') {
|
||||
kbn.interval_to_ms = kbn.intervalToMs;
|
||||
}
|
||||
|
||||
@@ -183,7 +182,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
|
||||
// default graph width for discrete card width calculation
|
||||
this.graph = {
|
||||
"chartWidth" : -1
|
||||
chartWidth: -1,
|
||||
};
|
||||
|
||||
this.multipleValues = false;
|
||||
@@ -203,7 +202,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
noDatapoints: {
|
||||
title: 'No data points',
|
||||
tip: 'No datapoints returned from data query',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.annotations = [];
|
||||
@@ -221,7 +220,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
this.onCardColorChange = this.onCardColorChange.bind(this);
|
||||
}
|
||||
|
||||
onRenderComplete(data: any):void {
|
||||
onRenderComplete(data: any): void {
|
||||
this.graph.chartWidth = data.chartWidth;
|
||||
this.renderingCompleted();
|
||||
}
|
||||
@@ -256,10 +255,9 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
||||
// getChartWidth returns an approximation of chart canvas width or
|
||||
// a saved value calculated during a render.
|
||||
getChartWidth():number {
|
||||
getChartWidth(): number {
|
||||
if (this.graph.chartWidth > 0) {
|
||||
return this.graph.chartWidth;
|
||||
}
|
||||
@@ -272,10 +270,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
// - y axis ticks are not rendered yet on first data receive,
|
||||
// so choose 200 as a decent value for y legend width
|
||||
// - chartWidth can not be lower than the half of the panel width.
|
||||
const chartWidth = _.max([
|
||||
panelWidth - 200,
|
||||
panelWidth/2
|
||||
]);
|
||||
const chartWidth = _.max([panelWidth - 200, panelWidth / 2]);
|
||||
|
||||
return chartWidth!;
|
||||
}
|
||||
@@ -283,7 +278,9 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
// Quick workaround for 6.7 and 7.0+. There is no call to
|
||||
// calculateInterval in updateTimeRange in those versions.
|
||||
// TODO ts type has no argument for this method.
|
||||
//
|
||||
updateTimeRange(datasource?: any) {
|
||||
// @ts-ignore
|
||||
let ret = super.updateTimeRange(datasource);
|
||||
this.calculateInterval();
|
||||
return ret;
|
||||
@@ -297,7 +294,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
|
||||
let minCardWidth = this.panel.cards.cardMinWidth;
|
||||
let minSpacing = this.panel.cards.cardHSpacing;
|
||||
let maxCardsCount = Math.ceil((chartWidth-minCardWidth) / (minCardWidth + minSpacing));
|
||||
let maxCardsCount = Math.ceil((chartWidth - minCardWidth) / (minCardWidth + minSpacing));
|
||||
|
||||
let intervalMs;
|
||||
let rangeMs = this.range.to.valueOf() - this.range.from.valueOf();
|
||||
@@ -307,7 +304,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
|
||||
// Calculate low limit of interval
|
||||
let lowLimitMs = 1; // 1 millisecond default low limit
|
||||
|
||||
|
||||
let intervalOverride = this.panel.interval;
|
||||
|
||||
// if no panel interval check datasource
|
||||
@@ -351,7 +348,9 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
* issue 11806.
|
||||
*/
|
||||
// 5.x before 5.4 doesn't have datasourcePromises.
|
||||
if ("undefined" !== typeof(this.annotationsSrv.datasourcePromises)) {
|
||||
// @ts-ignore
|
||||
if ('undefined' !== typeof this.annotationsSrv.datasourcePromises) {
|
||||
// @ts-ignore
|
||||
return this.annotationsSrv.datasourcePromises.then(r => {
|
||||
return this.issueQueriesWithInterval(datasource, this.interval);
|
||||
});
|
||||
@@ -372,14 +371,20 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
}
|
||||
|
||||
onDataReceived(dataList: any) {
|
||||
this.data = dataList;
|
||||
this.data = dataList;
|
||||
// Quick workaround for 7.0+. There is no call to
|
||||
// calculateInterval when enter Edit mode.
|
||||
if (!this.intervalMs) {
|
||||
this.calculateInterval();
|
||||
}
|
||||
|
||||
let newBucketMatrix = this.convertDataToBuckets(dataList, this.range.from.valueOf(), this.range.to.valueOf(), this.intervalMs, true);
|
||||
let newBucketMatrix = this.convertDataToBuckets(
|
||||
dataList,
|
||||
this.range.from.valueOf(),
|
||||
this.range.to.valueOf(),
|
||||
this.intervalMs,
|
||||
true
|
||||
);
|
||||
|
||||
this.bucketMatrix = newBucketMatrix;
|
||||
this.bucketMatrixPager.bucketMatrix = newBucketMatrix;
|
||||
@@ -437,7 +442,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
|
||||
this.noColorDefined = false;
|
||||
if (this.panel.color.mode === 'discrete') {
|
||||
if (this.panel.seriesFilterIndex == -1) {
|
||||
if (this.panel.seriesFilterIndex === -1) {
|
||||
this.discreteExtraSeries.updateCardsValuesHasColorInfo();
|
||||
} else {
|
||||
this.discreteExtraSeries.updateCardsValuesHasColorInfoSingle();
|
||||
@@ -514,26 +519,30 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
to and from — a time range of the panel.
|
||||
intervalMs — a calculated interval. It is used to split a time range.
|
||||
*/
|
||||
convertDataToBuckets(data:any, from:number, to:number, intervalMs: number, mostRecentBucket: boolean):BucketMatrix {
|
||||
convertDataToBuckets(
|
||||
data: any,
|
||||
from: number,
|
||||
to: number,
|
||||
intervalMs: number,
|
||||
mostRecentBucket: boolean
|
||||
): BucketMatrix {
|
||||
let bucketMatrix = new BucketMatrix();
|
||||
bucketMatrix.rangeMs = to - from;
|
||||
bucketMatrix.intervalMs = intervalMs;
|
||||
|
||||
if (!data || data.length == 0) {
|
||||
if (!data || data.length === 0) {
|
||||
// Mimic heatmap and graph 'no data' labels.
|
||||
bucketMatrix.targets = [
|
||||
"1.0", "0.0", "-1.0"
|
||||
];
|
||||
bucketMatrix.buckets["1.0"] = [];
|
||||
bucketMatrix.buckets["0.0"] = [];
|
||||
bucketMatrix.buckets["-1.0"] = [];
|
||||
bucketMatrix.targets = ['1.0', '0.0', '-1.0'];
|
||||
bucketMatrix.buckets['1.0'] = [];
|
||||
bucketMatrix.buckets['0.0'] = [];
|
||||
bucketMatrix.buckets['-1.0'] = [];
|
||||
bucketMatrix.xBucketSize = 42;
|
||||
bucketMatrix.noDatapoints = true;
|
||||
return bucketMatrix;
|
||||
}
|
||||
|
||||
let targetIndex: {[target: string]: number[]} = {};
|
||||
let targetPartials: {[target: string]: string[]} = {};
|
||||
let targetIndex: { [target: string]: number[] } = {};
|
||||
let targetPartials: { [target: string]: string[] } = {};
|
||||
|
||||
// Group indicies of elements in data by target (y label).
|
||||
|
||||
@@ -547,22 +556,22 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
let yLabel = queryResult.target;
|
||||
|
||||
// Check if there is some labelTemplate configured
|
||||
if (this.panel.yLabel.usingSplitLabel && this.panel.yLabel.delimiter != "" ) {
|
||||
if (this.panel.yLabel.usingSplitLabel && this.panel.yLabel.delimiter !== '') {
|
||||
let pLabels = queryResult.target.split(this.panel.yLabel.delimiter);
|
||||
|
||||
// Load all possible values as scoped vars and load them into targetPartials
|
||||
// to be used on different components as Bucket and BucketMatrix props
|
||||
let scopedVars = []
|
||||
scopedVars[`__y_label`] = {value: yLabel}
|
||||
let scopedVars = [];
|
||||
scopedVars[`__y_label`] = { value: yLabel };
|
||||
for (let i in pLabels) {
|
||||
scopedVars[`__y_label_${i}`] = {value: pLabels[i]};
|
||||
scopedVars[`__y_label_${i}`] = { value: pLabels[i] };
|
||||
}
|
||||
|
||||
if (this.panel.yLabel.labelTemplate != "") {
|
||||
yLabel = this.templateSrv.replace(this.panel.yLabel.labelTemplate, scopedVars)
|
||||
if (this.panel.yLabel.labelTemplate !== '') {
|
||||
yLabel = this.templateSrv.replace(this.panel.yLabel.labelTemplate, scopedVars);
|
||||
}
|
||||
|
||||
targetPartials[yLabel] = pLabels
|
||||
targetPartials[yLabel] = pLabels;
|
||||
}
|
||||
|
||||
//reset if it already exists
|
||||
@@ -576,18 +585,18 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
|
||||
//console.log ("targetIndex: ", targetIndex, "targetKeys: ", targetKeys);
|
||||
|
||||
let targetTimestampRanges: {[target: string]: {[timestamp: number]: number[]}} = {};
|
||||
let targetTimestampRanges: { [target: string]: { [timestamp: number]: number[] } } = {};
|
||||
|
||||
// Collect all timestamps for each target.
|
||||
// Make map timestamp => [from, to]. from == previous ts, to == ts from datapoint.
|
||||
targetKeys.map((target) => {
|
||||
targetKeys.map(target => {
|
||||
let targetTimestamps: any[] = [];
|
||||
|
||||
for (let si = 0; si < targetIndex[target].length; si++) {
|
||||
let s = data[targetIndex[target][si]];
|
||||
_.map(s.datapoints, (datapoint, idx) => {
|
||||
targetTimestamps.push(datapoint[TIME_INDEX]-from);
|
||||
})
|
||||
targetTimestamps.push(datapoint[TIME_INDEX] - from);
|
||||
});
|
||||
}
|
||||
|
||||
//console.log("timestamps['"+target+"'] = ", targetTimestamps);
|
||||
@@ -597,15 +606,15 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
//console.log("uniq timestamps['"+target+"'] = ", targetTimestamps);
|
||||
|
||||
targetTimestampRanges[target] = [];
|
||||
for (let i = targetTimestamps.length-1 ; i>=0; i-- ) {
|
||||
for (let i = targetTimestamps.length - 1; i >= 0; i--) {
|
||||
let tsTo = targetTimestamps[i];
|
||||
let tsFrom = 0;
|
||||
if (tsTo < 0) {
|
||||
tsFrom = tsTo - intervalMs;
|
||||
} else {
|
||||
if (i-1 >= 0) {
|
||||
if (i - 1 >= 0) {
|
||||
// Set from to previous timestamp + 1ms;
|
||||
tsFrom = targetTimestamps[i-1]+1;
|
||||
tsFrom = targetTimestamps[i - 1] + 1;
|
||||
// tfTo - tfFrom should not be more than intervalMs
|
||||
let minFrom = tsTo - intervalMs;
|
||||
if (tsFrom < minFrom) {
|
||||
@@ -622,10 +631,10 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
// Create empty buckets using intervalMs to calculate ranges.
|
||||
// If mostRecentBucket is set, create a bucket with a range "to":"to"
|
||||
// to store most recent values.
|
||||
targetKeys.map((target) => {
|
||||
targetKeys.map(target => {
|
||||
let targetEmptyBuckets: any[] = [];
|
||||
|
||||
let lastTs = to-from;
|
||||
let lastTs = to - from;
|
||||
|
||||
if (mostRecentBucket) {
|
||||
let topBucket = new Bucket();
|
||||
@@ -638,21 +647,21 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
topBucket.relFrom = targetTimestampRanges[target][lastTs][0];
|
||||
lastTs = topBucket.relFrom;
|
||||
}
|
||||
topBucket.to = topBucket.relTo+from;
|
||||
topBucket.from = topBucket.relFrom+from;
|
||||
topBucket.to = topBucket.relTo + from;
|
||||
topBucket.from = topBucket.relFrom + from;
|
||||
targetEmptyBuckets.push(topBucket);
|
||||
}
|
||||
|
||||
let idx = 0;
|
||||
let bucketFrom: number = 0;
|
||||
let bucketFrom = 0;
|
||||
while (bucketFrom >= 0) {
|
||||
let b = new Bucket();
|
||||
b.yLabel = target;
|
||||
b.pLabels = targetPartials[target]
|
||||
b.relTo = lastTs - idx*intervalMs;
|
||||
b.relFrom = lastTs - ((idx+1) * intervalMs);
|
||||
b.to = b.relTo+from;
|
||||
b.from = b.relFrom+from;
|
||||
b.pLabels = targetPartials[target];
|
||||
b.relTo = lastTs - idx * intervalMs;
|
||||
b.relFrom = lastTs - (idx + 1) * intervalMs;
|
||||
b.to = b.relTo + from;
|
||||
b.from = b.relFrom + from;
|
||||
b.values = [];
|
||||
bucketFrom = b.relFrom;
|
||||
targetEmptyBuckets.push(b);
|
||||
@@ -671,8 +680,8 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
// Put values into buckets.
|
||||
bucketMatrix.minValue = Number.MAX_VALUE;
|
||||
bucketMatrix.maxValue = Number.MIN_SAFE_INTEGER;
|
||||
targetKeys.map((target) => {
|
||||
targetIndex[target].map((dataIndex) => {
|
||||
targetKeys.map(target => {
|
||||
targetIndex[target].map(dataIndex => {
|
||||
let s = data[dataIndex];
|
||||
s.datapoints.map((dp: any) => {
|
||||
for (let i = 0; i < bucketMatrix.buckets[target].length; i++) {
|
||||
@@ -682,7 +691,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
}
|
||||
});
|
||||
});
|
||||
bucketMatrix.buckets[target].map((bucket) => {
|
||||
bucketMatrix.buckets[target].map(bucket => {
|
||||
bucket.minValue = _.min(bucket.values);
|
||||
bucket.maxValue = _.max(bucket.values);
|
||||
if (bucket.minValue < bucketMatrix.minValue) {
|
||||
@@ -696,13 +705,14 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
bucketMatrix.multipleValues = true;
|
||||
bucket.multipleValues = true;
|
||||
|
||||
bucket.value = this.panel.seriesFilterIndex != -1 ? bucket.values[this.panel.seriesFilterIndex] : bucket.maxValue;
|
||||
bucket.value =
|
||||
this.panel.seriesFilterIndex !== -1 ? bucket.values[this.panel.seriesFilterIndex] : bucket.maxValue;
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
bucketMatrix.xBucketSize = Number.MIN_SAFE_INTEGER;
|
||||
targetKeys.map((target) => {
|
||||
targetKeys.map(target => {
|
||||
let bucketsLen: number = bucketMatrix.buckets[target].length;
|
||||
if (bucketsLen > bucketMatrix.xBucketSize) {
|
||||
bucketMatrix.xBucketSize = bucketsLen;
|
||||
@@ -717,6 +727,4 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
StatusHeatmapCtrl, StatusHeatmapCtrl as PanelCtrl
|
||||
};
|
||||
export { StatusHeatmapCtrl, StatusHeatmapCtrl as PanelCtrl };
|
||||
|
||||
Reference in New Issue
Block a user