mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
TimeSeries: Add per-axis grid visibility toggle (#38502)
* Allow grid lines visibility control to XYChart and TimeSeries * Move grid lines config to field config (axis) * Fix merge * Auto grid mode * Fix ts * Align naming * Update packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com> * Update packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com> * remove 'grid' from props diff array since field.config.custom.* is handled by structureRev diffing Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com> Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
parent
b5e4a0a39a
commit
1be53b4f3b
@ -144,6 +144,7 @@ export interface AxisConfig {
|
|||||||
axisWidth?: number; // pixels ideally auto?
|
axisWidth?: number; // pixels ideally auto?
|
||||||
axisSoftMin?: number;
|
axisSoftMin?: number;
|
||||||
axisSoftMax?: number;
|
axisSoftMax?: number;
|
||||||
|
axisGridShow?: boolean;
|
||||||
scaleDistribution?: ScaleDistributionConfig;
|
scaleDistribution?: ScaleDistributionConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import {
|
|||||||
TimeZone,
|
TimeZone,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { preparePlotFrame as defaultPreparePlotFrame } from './utils';
|
import { preparePlotFrame as defaultPreparePlotFrame } from './utils';
|
||||||
|
|
||||||
import { VizLegendOptions } from '@grafana/schema';
|
import { VizLegendOptions } from '@grafana/schema';
|
||||||
import { PanelContext, PanelContextRoot } from '../PanelChrome/PanelContext';
|
import { PanelContext, PanelContextRoot } from '../PanelChrome/PanelContext';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
@ -19,7 +19,16 @@ export class UnthemedTimeSeries extends React.Component<TimeSeriesProps> {
|
|||||||
prepConfig = (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => {
|
prepConfig = (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => {
|
||||||
const { eventBus, sync } = this.context;
|
const { eventBus, sync } = this.context;
|
||||||
const { theme, timeZone } = this.props;
|
const { theme, timeZone } = this.props;
|
||||||
return preparePlotConfigBuilder({ frame: alignedFrame, theme, timeZone, getTimeRange, eventBus, sync, allFrames });
|
|
||||||
|
return preparePlotConfigBuilder({
|
||||||
|
frame: alignedFrame,
|
||||||
|
theme,
|
||||||
|
timeZone,
|
||||||
|
getTimeRange,
|
||||||
|
eventBus,
|
||||||
|
sync,
|
||||||
|
allFrames,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
renderLegend = (config: UPlotConfigBuilder) => {
|
renderLegend = (config: UPlotConfigBuilder) => {
|
||||||
|
@ -79,6 +79,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
|||||||
placement: AxisPlacement.Bottom,
|
placement: AxisPlacement.Bottom,
|
||||||
timeZone,
|
timeZone,
|
||||||
theme,
|
theme,
|
||||||
|
grid: { show: xField.config.custom?.axisGridShow },
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Not time!
|
// Not time!
|
||||||
@ -96,6 +97,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
|||||||
scaleKey: xScaleKey,
|
scaleKey: xScaleKey,
|
||||||
placement: AxisPlacement.Bottom,
|
placement: AxisPlacement.Bottom,
|
||||||
theme,
|
theme,
|
||||||
|
grid: { show: xField.config.custom?.axisGridShow },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +149,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
|||||||
placement: customConfig.axisPlacement ?? AxisPlacement.Auto,
|
placement: customConfig.axisPlacement ?? AxisPlacement.Auto,
|
||||||
formatValue: (v) => formattedValueToString(fmt(v)),
|
formatValue: (v) => formattedValueToString(fmt(v)),
|
||||||
theme,
|
theme,
|
||||||
|
grid: { show: customConfig.axisGridShow },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export interface AxisProps {
|
|||||||
size?: number | null;
|
size?: number | null;
|
||||||
gap?: number;
|
gap?: number;
|
||||||
placement?: AxisPlacement;
|
placement?: AxisPlacement;
|
||||||
grid?: boolean;
|
grid?: Axis.Grid;
|
||||||
ticks?: boolean;
|
ticks?: boolean;
|
||||||
formatValue?: (v: any) => string;
|
formatValue?: (v: any) => string;
|
||||||
incrs?: Axis.Incrs;
|
incrs?: Axis.Incrs;
|
||||||
@ -43,7 +43,7 @@ export class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {
|
|||||||
label,
|
label,
|
||||||
show = true,
|
show = true,
|
||||||
placement = AxisPlacement.Auto,
|
placement = AxisPlacement.Auto,
|
||||||
grid = true,
|
grid = { show: true },
|
||||||
ticks = true,
|
ticks = true,
|
||||||
gap = 5,
|
gap = 5,
|
||||||
formatValue,
|
formatValue,
|
||||||
@ -74,7 +74,7 @@ export class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {
|
|||||||
labelGap: 0,
|
labelGap: 0,
|
||||||
|
|
||||||
grid: {
|
grid: {
|
||||||
show: grid,
|
show: grid.show,
|
||||||
stroke: gridColor,
|
stroke: gridColor,
|
||||||
width: 1 / devicePixelRatio,
|
width: 1 / devicePixelRatio,
|
||||||
},
|
},
|
||||||
|
@ -329,7 +329,7 @@ describe('UPlotConfigBuilder', () => {
|
|||||||
placement: AxisPlacement.Bottom,
|
placement: AxisPlacement.Bottom,
|
||||||
isTime: false,
|
isTime: false,
|
||||||
formatValue: () => 'test value',
|
formatValue: () => 'test value',
|
||||||
grid: false,
|
grid: { show: false },
|
||||||
show: true,
|
show: true,
|
||||||
theme: darkTheme,
|
theme: darkTheme,
|
||||||
values: [],
|
values: [],
|
||||||
@ -411,7 +411,6 @@ describe('UPlotConfigBuilder', () => {
|
|||||||
|
|
||||||
expect(builder.getAxisPlacement('y1')).toBe(AxisPlacement.Left);
|
expect(builder.getAxisPlacement('y1')).toBe(AxisPlacement.Left);
|
||||||
expect(builder.getAxisPlacement('y2')).toBe(AxisPlacement.Right);
|
expect(builder.getAxisPlacement('y2')).toBe(AxisPlacement.Right);
|
||||||
expect(builder.getConfig().axes![1].grid!.show).toBe(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('when fillColor is not set fill', () => {
|
it('when fillColor is not set fill', () => {
|
||||||
@ -709,4 +708,95 @@ describe('UPlotConfigBuilder', () => {
|
|||||||
expect(addHookFn).toHaveBeenCalledTimes(1);
|
expect(addHookFn).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Grid lines visibility', () => {
|
||||||
|
it('handles auto behaviour', () => {
|
||||||
|
const builder = new UPlotConfigBuilder();
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'x',
|
||||||
|
placement: AxisPlacement.Bottom,
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y1',
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y2',
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y3',
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
const axesConfig = builder.getConfig().axes!;
|
||||||
|
|
||||||
|
expect(axesConfig[0].grid!.show).toBe(true);
|
||||||
|
expect(axesConfig[1].grid!.show).toBe(true);
|
||||||
|
expect(axesConfig[2].grid!.show).toBe(false);
|
||||||
|
expect(axesConfig[3].grid!.show).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles auto behaviour with explicite grid settings', () => {
|
||||||
|
const builder = new UPlotConfigBuilder();
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'x',
|
||||||
|
placement: AxisPlacement.Bottom,
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y1',
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y2',
|
||||||
|
grid: { show: true },
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y3',
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
const axesConfig = builder.getConfig().axes!;
|
||||||
|
|
||||||
|
expect(axesConfig[0].grid!.show).toBe(true);
|
||||||
|
expect(axesConfig[1].grid!.show).toBe(true);
|
||||||
|
expect(axesConfig[2].grid!.show).toBe(true);
|
||||||
|
expect(axesConfig[3].grid!.show).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles explicit grid settings', () => {
|
||||||
|
const builder = new UPlotConfigBuilder();
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'x',
|
||||||
|
grid: { show: false },
|
||||||
|
placement: AxisPlacement.Bottom,
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y1',
|
||||||
|
grid: { show: false },
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.addAxis({
|
||||||
|
scaleKey: 'y2',
|
||||||
|
grid: { show: true },
|
||||||
|
theme: darkTheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
const axesConfig = builder.getConfig().axes!;
|
||||||
|
|
||||||
|
expect(axesConfig[0].grid!.show).toBe(false);
|
||||||
|
expect(axesConfig[1].grid!.show).toBe(false);
|
||||||
|
expect(axesConfig[2].grid!.show).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -42,7 +42,6 @@ export class UPlotConfigBuilder {
|
|||||||
private isStacking = false;
|
private isStacking = false;
|
||||||
private select: uPlot.Select | undefined;
|
private select: uPlot.Select | undefined;
|
||||||
private hasLeftAxis = false;
|
private hasLeftAxis = false;
|
||||||
private hasBottomAxis = false;
|
|
||||||
private hooks: Hooks.Arrays = {};
|
private hooks: Hooks.Arrays = {};
|
||||||
private tz: string | undefined = undefined;
|
private tz: string | undefined = undefined;
|
||||||
private sync = false;
|
private sync = false;
|
||||||
@ -80,7 +79,7 @@ export class UPlotConfigBuilder {
|
|||||||
|
|
||||||
addAxis(props: AxisProps) {
|
addAxis(props: AxisProps) {
|
||||||
props.placement = props.placement ?? AxisPlacement.Auto;
|
props.placement = props.placement ?? AxisPlacement.Auto;
|
||||||
|
props.grid = props.grid ?? {};
|
||||||
if (this.axes[props.scaleKey]) {
|
if (this.axes[props.scaleKey]) {
|
||||||
this.axes[props.scaleKey].merge(props);
|
this.axes[props.scaleKey].merge(props);
|
||||||
return;
|
return;
|
||||||
@ -91,17 +90,12 @@ export class UPlotConfigBuilder {
|
|||||||
props.placement = this.hasLeftAxis ? AxisPlacement.Right : AxisPlacement.Left;
|
props.placement = this.hasLeftAxis ? AxisPlacement.Right : AxisPlacement.Left;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (props.placement) {
|
if (props.placement === AxisPlacement.Left) {
|
||||||
case AxisPlacement.Left:
|
this.hasLeftAxis = true;
|
||||||
this.hasLeftAxis = true;
|
|
||||||
break;
|
|
||||||
case AxisPlacement.Bottom:
|
|
||||||
this.hasBottomAxis = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.placement === AxisPlacement.Hidden) {
|
if (props.placement === AxisPlacement.Hidden) {
|
||||||
props.show = false;
|
props.grid.show = false;
|
||||||
props.size = 0;
|
props.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,24 +227,30 @@ export class UPlotConfigBuilder {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ensureNonOverlappingAxes(axes: UPlotAxisBuilder[]): UPlotAxisBuilder[] {
|
|
||||||
for (const axis of axes) {
|
|
||||||
if (axis.props.placement === AxisPlacement.Right && this.hasLeftAxis) {
|
|
||||||
axis.props.grid = false;
|
|
||||||
}
|
|
||||||
if (axis.props.placement === AxisPlacement.Top && this.hasBottomAxis) {
|
|
||||||
axis.props.grid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return axes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private tzDate = (ts: number) => {
|
private tzDate = (ts: number) => {
|
||||||
let date = new Date(ts);
|
let date = new Date(ts);
|
||||||
|
|
||||||
return this.tz ? uPlot.tzDate(date, this.tz) : date;
|
return this.tz ? uPlot.tzDate(date, this.tz) : date;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private ensureNonOverlappingAxes(axes: UPlotAxisBuilder[]): UPlotAxisBuilder[] {
|
||||||
|
const xAxis = axes.find((a) => a.props.scaleKey === 'x');
|
||||||
|
const axesWithoutGridSet = axes.filter((a) => a.props.grid?.show === undefined);
|
||||||
|
const firstValueAxisIdx = axesWithoutGridSet.findIndex(
|
||||||
|
(a) => a.props.placement === AxisPlacement.Left || (a.props.placement === AxisPlacement.Bottom && a !== xAxis)
|
||||||
|
);
|
||||||
|
|
||||||
|
// For all axes with no grid set, set the grid automatically (grid only for first left axis )
|
||||||
|
for (let i = 0; i < axesWithoutGridSet.length; i++) {
|
||||||
|
if (axesWithoutGridSet[i] === xAxis || i === firstValueAxisIdx) {
|
||||||
|
axesWithoutGridSet[i].props.grid!.show = true;
|
||||||
|
} else {
|
||||||
|
axesWithoutGridSet[i].props.grid!.show = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return axes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @alpha */
|
/** @alpha */
|
||||||
|
@ -17,11 +17,12 @@ export function addAxisConfig(
|
|||||||
defaultConfig: AxisConfig,
|
defaultConfig: AxisConfig,
|
||||||
hideScale?: boolean
|
hideScale?: boolean
|
||||||
) {
|
) {
|
||||||
|
const category = ['Axis'];
|
||||||
builder
|
builder
|
||||||
.addRadio({
|
.addRadio({
|
||||||
path: 'axisPlacement',
|
path: 'axisPlacement',
|
||||||
name: 'Placement',
|
name: 'Placement',
|
||||||
category: ['Axis'],
|
category,
|
||||||
defaultValue: graphFieldOptions.axisPlacement[0].value,
|
defaultValue: graphFieldOptions.axisPlacement[0].value,
|
||||||
settings: {
|
settings: {
|
||||||
options: graphFieldOptions.axisPlacement,
|
options: graphFieldOptions.axisPlacement,
|
||||||
@ -30,7 +31,7 @@ export function addAxisConfig(
|
|||||||
.addTextInput({
|
.addTextInput({
|
||||||
path: 'axisLabel',
|
path: 'axisLabel',
|
||||||
name: 'Label',
|
name: 'Label',
|
||||||
category: ['Axis'],
|
category,
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
settings: {
|
settings: {
|
||||||
placeholder: 'Optional text',
|
placeholder: 'Optional text',
|
||||||
@ -42,7 +43,7 @@ export function addAxisConfig(
|
|||||||
.addNumberInput({
|
.addNumberInput({
|
||||||
path: 'axisWidth',
|
path: 'axisWidth',
|
||||||
name: 'Width',
|
name: 'Width',
|
||||||
category: ['Axis'],
|
category,
|
||||||
settings: {
|
settings: {
|
||||||
placeholder: 'Auto',
|
placeholder: 'Auto',
|
||||||
},
|
},
|
||||||
@ -52,7 +53,7 @@ export function addAxisConfig(
|
|||||||
path: 'axisSoftMin',
|
path: 'axisSoftMin',
|
||||||
name: 'Soft min',
|
name: 'Soft min',
|
||||||
defaultValue: defaultConfig.axisSoftMin,
|
defaultValue: defaultConfig.axisSoftMin,
|
||||||
category: ['Axis'],
|
category,
|
||||||
settings: {
|
settings: {
|
||||||
placeholder: 'See: Standard options > Min',
|
placeholder: 'See: Standard options > Min',
|
||||||
},
|
},
|
||||||
@ -61,17 +62,31 @@ export function addAxisConfig(
|
|||||||
path: 'axisSoftMax',
|
path: 'axisSoftMax',
|
||||||
name: 'Soft max',
|
name: 'Soft max',
|
||||||
defaultValue: defaultConfig.axisSoftMax,
|
defaultValue: defaultConfig.axisSoftMax,
|
||||||
category: ['Axis'],
|
category,
|
||||||
settings: {
|
settings: {
|
||||||
placeholder: 'See: Standard options > Max',
|
placeholder: 'See: Standard options > Max',
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
.addRadio({
|
||||||
|
path: 'axisGridShow',
|
||||||
|
name: 'Show grid lines',
|
||||||
|
category,
|
||||||
|
defaultValue: undefined,
|
||||||
|
settings: {
|
||||||
|
options: [
|
||||||
|
{ value: undefined, label: 'Auto' },
|
||||||
|
{ value: true, label: 'On' },
|
||||||
|
{ value: false, label: 'Off' },
|
||||||
|
],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!hideScale) {
|
if (!hideScale) {
|
||||||
builder.addCustomEditor<void, ScaleDistributionConfig>({
|
builder.addCustomEditor<void, ScaleDistributionConfig>({
|
||||||
id: 'scaleDistribution',
|
id: 'scaleDistribution',
|
||||||
path: 'scaleDistribution',
|
path: 'scaleDistribution',
|
||||||
name: 'Scale',
|
name: 'Scale',
|
||||||
category: ['Axis'],
|
category,
|
||||||
editor: ScaleDistributionEditor,
|
editor: ScaleDistributionEditor,
|
||||||
override: ScaleDistributionEditor,
|
override: ScaleDistributionEditor,
|
||||||
defaultValue: { type: ScaleDistribution.Linear },
|
defaultValue: { type: ScaleDistribution.Linear },
|
||||||
|
@ -99,7 +99,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
|
|||||||
placement: vizOrientation.xOri === 0 ? AxisPlacement.Bottom : AxisPlacement.Left,
|
placement: vizOrientation.xOri === 0 ? AxisPlacement.Bottom : AxisPlacement.Left,
|
||||||
splits: config.xSplits,
|
splits: config.xSplits,
|
||||||
values: config.xValues,
|
values: config.xValues,
|
||||||
grid: false,
|
grid: { show: false },
|
||||||
ticks: false,
|
ticks: false,
|
||||||
gap: 15,
|
gap: 15,
|
||||||
theme,
|
theme,
|
||||||
@ -174,6 +174,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
|
|||||||
placement,
|
placement,
|
||||||
formatValue: (v) => formattedValueToString(field.display!(v)),
|
formatValue: (v) => formattedValueToString(field.display!(v)),
|
||||||
theme,
|
theme,
|
||||||
|
grid: { show: customConfig.axisGridShow },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
|||||||
placement: AxisPlacement.Bottom,
|
placement: AxisPlacement.Bottom,
|
||||||
timeZone,
|
timeZone,
|
||||||
theme,
|
theme,
|
||||||
|
grid: { show: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.addAxis({
|
builder.addAxis({
|
||||||
@ -175,7 +176,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
|||||||
placement: AxisPlacement.Left,
|
placement: AxisPlacement.Left,
|
||||||
splits: coreConfig.ySplits,
|
splits: coreConfig.ySplits,
|
||||||
values: coreConfig.yValues,
|
values: coreConfig.yValues,
|
||||||
grid: false,
|
grid: { show: false },
|
||||||
ticks: false,
|
ticks: false,
|
||||||
gap: 16,
|
gap: 16,
|
||||||
theme,
|
theme,
|
||||||
|
@ -40,6 +40,7 @@ export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const enableAnnotationCreation = Boolean(canAddAnnotations && canAddAnnotations());
|
const enableAnnotationCreation = Boolean(canAddAnnotations && canAddAnnotations());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TimeSeries
|
<TimeSeries
|
||||||
frames={frames}
|
frames={frames}
|
||||||
|
@ -36,6 +36,7 @@ export const defaultGraphConfig: GraphFieldConfig = {
|
|||||||
mode: StackingMode.None,
|
mode: StackingMode.None,
|
||||||
group: 'A',
|
group: 'A',
|
||||||
},
|
},
|
||||||
|
axisGridShow: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const categoryStyles = ['Graph styles'];
|
const categoryStyles = ['Graph styles'];
|
||||||
|
Loading…
Reference in New Issue
Block a user