mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-30 17:23:29 -05:00
Rework timeSeries in chart viewer (#2987)
* rework timeSeries in chart viewer * rework important to fix tests
This commit is contained in:
committed by
Karl Burtram
parent
724c49f5c4
commit
7dfcd89a04
@@ -18,7 +18,8 @@ export enum ControlType {
|
||||
combo,
|
||||
numberInput,
|
||||
input,
|
||||
checkbox
|
||||
checkbox,
|
||||
dateInput
|
||||
}
|
||||
|
||||
export interface IChartOption {
|
||||
@@ -115,6 +116,20 @@ const xAxisMaxInput: IChartOption = {
|
||||
default: undefined
|
||||
};
|
||||
|
||||
const xAxisMinDateInput: IChartOption = {
|
||||
label: localize('xAxisMinDate', 'X Axis Minimum Date'),
|
||||
type: ControlType.dateInput,
|
||||
configEntry: 'xAxisMin',
|
||||
default: undefined
|
||||
};
|
||||
|
||||
const xAxisMaxDateInput: IChartOption = {
|
||||
label: localize('xAxisMaxDate', 'X Axis Maximum Date'),
|
||||
type: ControlType.dateInput,
|
||||
configEntry: 'xAxisMax',
|
||||
default: undefined
|
||||
};
|
||||
|
||||
const dataTypeInput: IChartOption = {
|
||||
label: localize('dataTypeLabel', 'Data Type'),
|
||||
type: ControlType.combo,
|
||||
@@ -150,7 +165,11 @@ export const ChartOptions: IChartOptions = {
|
||||
[ChartType.TimeSeries]: [
|
||||
legendInput,
|
||||
yAxisLabelInput,
|
||||
xAxisLabelInput
|
||||
yAxisMinInput,
|
||||
yAxisMaxInput,
|
||||
xAxisLabelInput,
|
||||
xAxisMinDateInput,
|
||||
xAxisMaxDateInput,
|
||||
],
|
||||
[ChartType.Bar]: [
|
||||
dataDirectionOption,
|
||||
|
||||
@@ -275,7 +275,7 @@ export class ChartView implements IPanelView {
|
||||
dropdown.render(optionContainer);
|
||||
dropdown.onDidSelect(e => {
|
||||
if (this.options[option.configEntry] !== option.options[e.index]) {
|
||||
this.options[option.configEntry] = option.options[e.index] === 'timeSeries' ? 'line' : option.options[e.index];
|
||||
this.options[option.configEntry] = option.options[e.index];
|
||||
if (this.insight) {
|
||||
this.insight.options = this.options;
|
||||
}
|
||||
@@ -324,6 +324,24 @@ export class ChartView implements IPanelView {
|
||||
};
|
||||
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
||||
break;
|
||||
case ControlType.dateInput:
|
||||
let dateInput = new InputBox(optionContainer, this._contextViewService, { type: 'date' });
|
||||
dateInput.value = value || '';
|
||||
dateInput.onDidChange(e => {
|
||||
if (this.options[option.configEntry] !== e) {
|
||||
this.options[option.configEntry] = e;
|
||||
if (this.insight) {
|
||||
this.insight.options = this.options;
|
||||
}
|
||||
}
|
||||
});
|
||||
setFunc = (val: string) => {
|
||||
if (!isUndefinedOrNull(val)) {
|
||||
dateInput.value = val;
|
||||
}
|
||||
};
|
||||
this.optionDisposables.push(attachInputBoxStyler(dateInput, this._themeService));
|
||||
break;
|
||||
}
|
||||
this.optionMap[option.configEntry] = { element: optionContainer, set: setFunc };
|
||||
container.appendChild(optionContainer);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Chart as ChartJs } from 'chart.js';
|
||||
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { mixin } from 'sql/base/common/objects';
|
||||
import { localize } from 'vs/nls';
|
||||
import * as colors from 'vs/platform/theme/common/colorRegistry';
|
||||
import { editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry';
|
||||
@@ -15,10 +15,28 @@ import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||
import { IInsightOptions, IInsight } from './interfaces';
|
||||
import { ChartType, DataDirection, LegendPosition } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ChartType, DataDirection, LegendPosition, DataType, IPointDataSet, customMixin } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
|
||||
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
||||
|
||||
const timeSeriesScales = {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
display: true,
|
||||
ticks: {
|
||||
autoSkip: false,
|
||||
maxRotation: 45,
|
||||
minRotation: 45
|
||||
}
|
||||
}],
|
||||
|
||||
yAxes: [{
|
||||
display: true,
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
const defaultOptions: IInsightOptions = {
|
||||
type: ChartType.Bar,
|
||||
dataDirection: DataDirection.Horizontal
|
||||
@@ -30,6 +48,8 @@ export class Graph implements IInsight {
|
||||
private chartjs: ChartJs;
|
||||
private _data: IInsightData;
|
||||
|
||||
private originalType: ChartType;
|
||||
|
||||
public static readonly types = [ChartType.Bar, ChartType.Doughnut, ChartType.HorizontalBar, ChartType.Line, ChartType.Pie, ChartType.Scatter, ChartType.TimeSeries];
|
||||
public readonly types = Graph.types;
|
||||
|
||||
@@ -83,37 +103,51 @@ export class Graph implements IInsight {
|
||||
labels = data.rows.map(row => row[0]);
|
||||
}
|
||||
|
||||
if (this.options.dataDirection === DataDirection.Horizontal) {
|
||||
if (this.options.labelFirstColumn) {
|
||||
chartData = data.rows.map((row) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)).slice(1),
|
||||
label: row[0]
|
||||
};
|
||||
});
|
||||
} else {
|
||||
chartData = data.rows.map((row, i) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)),
|
||||
label: localize('series', 'Series {0}', i)
|
||||
};
|
||||
});
|
||||
}
|
||||
if (this.originalType === ChartType.TimeSeries) {
|
||||
let dataSetMap: { [label: string]: IPointDataSet } = {};
|
||||
this._data.rows.map(row => {
|
||||
if (row && row.length >= 3) {
|
||||
let legend = row[0];
|
||||
if (!dataSetMap[legend]) {
|
||||
dataSetMap[legend] = { label: legend, data: [], fill: false };
|
||||
}
|
||||
dataSetMap[legend].data.push({ x: row[1], y: Number(row[2]) });
|
||||
}
|
||||
});
|
||||
chartData = Object.values(dataSetMap);
|
||||
} else {
|
||||
if (this.options.columnsAsLabels) {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: data.columns[i + 1]
|
||||
};
|
||||
});
|
||||
if (this.options.dataDirection === DataDirection.Horizontal) {
|
||||
if (this.options.labelFirstColumn) {
|
||||
chartData = data.rows.map((row) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)).slice(1),
|
||||
label: row[0]
|
||||
};
|
||||
});
|
||||
} else {
|
||||
chartData = data.rows.map((row, i) => {
|
||||
return {
|
||||
data: row.map(item => Number(item)),
|
||||
label: localize('series', 'Series {0}', i)
|
||||
};
|
||||
});
|
||||
}
|
||||
} else {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: localize('series', 'Series {0}', i + 1)
|
||||
};
|
||||
});
|
||||
if (this.options.columnsAsLabels) {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: data.columns[i + 1]
|
||||
};
|
||||
});
|
||||
} else {
|
||||
chartData = data.rows[0].slice(1).map((row, i) => {
|
||||
return {
|
||||
data: data.rows.map(row => Number(row[i + 1])),
|
||||
label: localize('series', 'Series {0}', i + 1)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +221,35 @@ export class Graph implements IInsight {
|
||||
color: gridLines
|
||||
}
|
||||
}];
|
||||
|
||||
if (this.originalType === ChartType.TimeSeries) {
|
||||
retval = mixin(retval, timeSeriesScales, true, customMixin);
|
||||
if (options.xAxisMax) {
|
||||
retval = mixin(retval, {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
max: options.xAxisMax
|
||||
}
|
||||
}],
|
||||
}
|
||||
}, true, customMixin);
|
||||
}
|
||||
|
||||
if (options.xAxisMin) {
|
||||
retval = mixin(retval, {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
min: options.xAxisMin
|
||||
}
|
||||
}],
|
||||
}
|
||||
}, true, customMixin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval.legend = <ChartJs.ChartLegendOptions>{
|
||||
@@ -208,6 +271,12 @@ export class Graph implements IInsight {
|
||||
|
||||
public set options(options: IInsightOptions) {
|
||||
this._options = options;
|
||||
this.originalType = options.type as ChartType;
|
||||
if (this.options.type === ChartType.TimeSeries) {
|
||||
this.options.type = ChartType.Line;
|
||||
this.options.dataType = DataType.Point;
|
||||
this.options.dataDirection = DataDirection.Horizontal;
|
||||
}
|
||||
this.data = this._data;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Graph } from './graphInsight';
|
||||
import { IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||
import { DataDirection, ChartType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { DataDirection, ChartType, DataType } from 'sql/parts/dashboard/widgets/insights/views/charts/interfaces';
|
||||
import { ImageInsight } from './imageInsight';
|
||||
import { TableInsight } from './tableInsight';
|
||||
import { IInsightOptions, IInsight, InsightType, IInsightCtor } from './interfaces';
|
||||
@@ -16,6 +16,7 @@ import { CountInsight } from './countInsight';
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Dimension } from 'vs/base/browser/dom';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
|
||||
const defaultOptions: IInsightOptions = {
|
||||
type: ChartType.Bar,
|
||||
@@ -47,13 +48,13 @@ export class Insight {
|
||||
}
|
||||
|
||||
public set options(val: IInsightOptions) {
|
||||
this._options = val;
|
||||
this._options = deepClone(val);
|
||||
if (this.insight) {
|
||||
// check to see if we need to change the insight type
|
||||
if (!this.insight.types.includes(val.type)) {
|
||||
if (!this.insight.types.includes(this.options.type)) {
|
||||
this.buildInsight();
|
||||
} else {
|
||||
this.insight.options = val;
|
||||
this.insight.options = this.options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user