Browse Source

Merge branch 'models-to-parse-data' into 'main'

Models to parse data

See merge request chartwerk/grafana-chartwerk-panel!3
merge-requests/4/merge
Alexander Velikiy 2 years ago
parent
commit
dad58c5226
  1. 55
      src/components/Panel.tsx
  2. 27
      src/models/options.ts
  3. 59
      src/models/series.ts
  4. 39
      src/module.ts
  5. 15
      src/types.ts

55
src/components/Panel.tsx

@ -1,4 +1,5 @@
import { DataProcessor } from '../grafana/data_processor';
import { Options } from '../models/options';
import { Series } from '../models/series';
import { PanelOptions } from '../types';
@ -14,40 +15,19 @@ interface Props extends PanelProps<PanelOptions> {}
export function Panel({ options, data, width, height, timeZone, timeRange, onChangeTimeRange }: Props) {
console.log('options', options);
console.log('data', data);
const processor = new DataProcessor({});
const seriesList = processor.getSeriesList({
dataList: data.series,
range: timeRange,
});
const chwSeriesList = updateSeriesListWithChartwerkParams(seriesList);
console.log('seriesList', chwSeriesList);
let chartContainer = useRef(null);
// TODO: use models to parse options and series
const series = new Series(data, timeRange, options.gauge.value).getChartwerkSeries();
console.log('series', series);
const chartwerkOptions = new Options(options).getChartwerkOptions();
// we request animation frame here because at the moment we need an existing DOM-element at the moment we render the pod
let chartContainer = useRef(null);
// we request animation frame here because we need an existing DOM-element at the moment we render the pod
window.requestAnimationFrame(() => {
// TODO: pass datapoints
// TODO: pass options
// TODO: switch / case pod type
const pod = new ChartwerkGaugePod((chartContainer as any).current, chwSeriesList, {
maxValue: options.gauge.max,
minValue: options.gauge.min,
valueFormatter: (val) => val.toFixed(2),
defaultColor: 'green',
stops: [
{
color: 'green',
value: 100,
},
{
color: 'orange',
value: 140,
},
],
// @ts-ignore
icons: [{ src: 'https://cityhost.ua/upload_img/blog5ef308ea5529c_trash2-01.jpg', position: 'middle', size: 30 }],
});
const pod = new ChartwerkGaugePod(
(chartContainer as any).current,
series,
chartwerkOptions
);
pod.render();
});
return (
@ -60,14 +40,3 @@ export function Panel({ options, data, width, height, timeZone, timeRange, onCha
></div>
);
}
function updateSeriesListWithChartwerkParams(series: any[]): any[] {
return _.map(series, (serie: any, idx: number) => {
return {
target: serie.alias,
color: serie.color,
datapoints: _.map(serie.datapoints, (row) => _.reverse(row)),
alias: serie.label,
};
});
}

27
src/models/options.ts

@ -0,0 +1,27 @@
import { PanelOptions } from 'types';
// Convert Grafana options into Chartwerk options
export class Options {
constructor(private grafanaOptions: PanelOptions) {}
public getChartwerkOptions(): any {
return {
maxValue: this.grafanaOptions.gauge.max.value || 0,
minValue: this.grafanaOptions.gauge.min.value || 0,
valueFormatter: (val: any) => val.toFixed(2),
defaultColor: 'green',
stops: [
{
color: 'green',
value: 100,
},
{
color: 'orange',
value: 140,
},
],
// @ts-ignore
icons: [{ src: 'https://cityhost.ua/upload_img/blog5ef308ea5529c_trash2-01.jpg', position: 'middle', size: 30 }],
};
}
}

59
src/models/series.ts

@ -0,0 +1,59 @@
import { PanelData, TimeRange } from '@grafana/data';
import { DataProcessor } from '../grafana/data_processor';
import { ExtremumOptions } from 'types';
import * as _ from 'lodash';
// Convert Grafana options into Chartwerk options
export class Series {
private processor;
private _seriesList;
private _selectedSerieName;
constructor(grafanaData: PanelData, timeRange: TimeRange, private gaugeValueOptions: ExtremumOptions) {
if(this._isSerieOneValue()) {
this._seriesList = [{ datapoints: [[0, gaugeValueOptions.value]] }];
return;
}
if(this.gaugeValueOptions.useMetric && _.isEmpty(this.gaugeValueOptions.metricName)) {
throw new Error(`Value or metric is not selected.`);
}
this._selectedSerieName = this.gaugeValueOptions.metricName;
this.processor = new DataProcessor({});
const seriesList = this.processor.getSeriesList({
dataList: grafanaData.series,
range: timeRange,
});
const filteredSeries = _.filter(seriesList, serie => serie.alias === this._selectedSerieName);
if(filteredSeries.length === 0) {
throw new Error(`Can't find metric for ${this._selectedSerieName} name`);
}
if(filteredSeries.length > 1) {
throw new Error(`Get ${filteredSeries.length} metrics for ${this._selectedSerieName} name. Please choose one`);
}
this._seriesList = this._updateSeriesListWithChartwerkParams(filteredSeries);
}
public getChartwerkSeries(): any[] {
return this._seriesList;
}
private _updateSeriesListWithChartwerkParams(series: any[]): any[] {
return _.map(series, (serie: any, idx: number) => {
return {
target: serie.alias,
color: serie.color,
datapoints: _.map(serie.datapoints, (row) => _.reverse(row)),
alias: serie.label,
};
});
}
private _isSerieOneValue(): boolean {
return !this.gaugeValueOptions.useMetric;
}
}

39
src/module.ts

@ -30,38 +30,57 @@ export const plugin = new PanelPlugin<PanelOptions>(Panel).setPanelOptions((buil
},
})
.addNumberInput({
path: 'gauge.min',
name: 'Value',
path: 'gauge.value.value',
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.value.useMetric,
})
.addFieldNamePicker({
name: 'Value',
path: 'gauge.value.metricName',
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.value.useMetric,
})
.addBooleanSwitch({
path: 'gauge.value.useMetric',
name: 'Use metric',
defaultValue: false,
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE,
})
.addNumberInput({
path: 'gauge.min.value',
name: 'Min',
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.useMetricForMin,
showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.min.useMetric,
})
.addFieldNamePicker({
name: 'Min',
path: 'gauge.minMetricName',
path: 'gauge.min.metricName',
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.useMetricForMin,
showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.min.useMetric,
})
.addBooleanSwitch({
path: 'gauge.useMetricForMin',
path: 'gauge.min.useMetric',
name: 'Use metric',
defaultValue: false,
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE,
})
.addNumberInput({
path: 'gauge.max',
path: 'gauge.max.value',
name: 'Max',
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.useMetricForMax,
showIf: (config) => config.visualizationType === Pod.GAUGE && !config.gauge.max.useMetric,
})
.addFieldNamePicker({
name: 'Max',
path: 'gauge.maxMetricName',
path: 'gauge.max.metricName',
category: ['Extremum'],
showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.useMetricForMax,
showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.max.useMetric,
})
.addBooleanSwitch({
path: 'gauge.useMetricForMax',
path: 'gauge.max.useMetric',
name: 'Use metric',
defaultValue: false,
category: ['Extremum'],

15
src/types.ts

@ -1,15 +1,18 @@
export interface PanelOptions {
visualizationType: Pod;
gauge: {
min?: number;
useMetricForMin: boolean;
minMetricName: string;
max?: number;
useMetricForMax: boolean;
maxMetricName: string;
min: ExtremumOptions;
max: ExtremumOptions;
value: ExtremumOptions;
};
}
export type ExtremumOptions = {
value?: number;
useMetric: false;
metricName: string;
};
export enum Pod {
LINE = 'Line',
BAR = 'Bar',

Loading…
Cancel
Save