Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion timeserieschart/src/TimeSeriesChartPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export function TimeSeriesChartPanel(props: TimeSeriesChartProps): ReactElement
}, [props.spec.visual]);

// Use the logBase from yAxis options, defaulting to 'none' if not set
const useLogarithmicBase: LOG_BASE = yAxis?.logBase ?? 'none';
const useLogarithmicBase: LOG_BASE = yAxis?.logBase;

// convert Perses dashboard format to be ECharts compatible
const echartsYAxis = useMemo(() => {
Expand Down
9 changes: 4 additions & 5 deletions timeserieschart/src/YAxisOptionsEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import {
DEFAULT_Y_AXIS,
TimeSeriesChartYAxisOptions,
Y_AXIS_CONFIG,
LOG_BASE_OPTIONS,
LOG_BASE_CONFIG,
LOG_VALID_BASES,
LOG_BASE_OPTIONS,
} from './time-series-chart-model';

export interface YAxisOptionsEditorProps {
Expand All @@ -31,7 +30,7 @@ export interface YAxisOptionsEditorProps {
}

export function YAxisOptionsEditor({ value, onChange }: YAxisOptionsEditorProps): ReactElement {
const logBase = LOG_BASE_CONFIG[LOG_VALID_BASES[value.logBase ?? 'none']];
const logBase = value.logBase ? LOG_BASE_CONFIG[value.logBase] : undefined;

return (
<OptionsEditorGroup title="Y Axis">
Expand Down Expand Up @@ -64,13 +63,13 @@ export function YAxisOptionsEditor({ value, onChange }: YAxisOptionsEditorProps)
<SettingsAutocomplete
value={{
...logBase,
id: logBase.label,
id: logBase?.label ?? 'None',
}}
options={LOG_BASE_OPTIONS}
onChange={(__, newValue) => {
const updatedValue: TimeSeriesChartYAxisOptions = {
...value,
logBase: newValue.log,
logBase: newValue.log ?? undefined,
};
onChange(updatedValue);
}}
Expand Down
20 changes: 7 additions & 13 deletions timeserieschart/src/time-series-chart-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const DEFAULT_Y_AXIS: TimeSeriesChartYAxisOptions = {
format: DEFAULT_FORMAT,
min: undefined,
max: undefined,
logBase: 'none',
logBase: undefined,
};

export const Y_AXIS_CONFIG = {
Expand Down Expand Up @@ -187,27 +187,21 @@ export const OPACITY_CONFIG = {
};

// LogBase outlines the allowed log bases for the log-supported charts.
export type LOG_BASE_LABEL = 'none' | 'log2' | 'log10';
export type LOG_BASE = 'none' | 2 | 10;
export type LOG_BASE = undefined | 2 | 10;

// Single source of truth for log base configuration
export const LOG_BASE_CONFIG: Record<LOG_BASE_LABEL, { label: string; log: LOG_BASE }> = {
none: { label: 'None', log: 'none' },
log2: { label: '2', log: 2 },
log10: { label: '10', log: 10 },
export const LOG_BASE_CONFIG: Record<string, { label: string; log: LOG_BASE }> = {
none: { label: 'None', log: undefined },
'2': { label: '2', log: 2 },
'10': { label: '10', log: 10 },
};

// Options array for SettingsAutocomplete
export const LOG_BASE_OPTIONS = Object.entries(LOG_BASE_CONFIG).map(([id, config]) => ({
id: id as LOG_BASE_LABEL,
id: id as string,
...config,
}));

// Reverse lookup map from LOG_BASE value to LOG_BASE_LABEL
export const LOG_VALID_BASES: Record<LOG_BASE, LOG_BASE_LABEL> = Object.fromEntries(
Object.entries(LOG_BASE_CONFIG).map(([label, config]) => [config.log, label])
) as Record<LOG_BASE, LOG_BASE_LABEL>;

// Both of these constants help produce a value that is LESS THAN the initial value.
// For positive values, we multiply by a number less than 1 to get this outcome.
// For negative values, we multiply to a number greater than 1 to get this outcome.
Expand Down
38 changes: 37 additions & 1 deletion timeserieschart/src/utils/data-transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('convertPanelYAxis', () => {
min: 0.1,
max: 1,
};
const echartsAxis = convertPanelYAxis(persesAxis, 'none');
const echartsAxis = convertPanelYAxis(persesAxis, undefined);
// Axis label is handled outside of echarts since it is built with a custom React component.
expect(echartsAxis).toEqual({
show: true,
Expand All @@ -65,6 +65,42 @@ describe('convertPanelYAxis', () => {
},
});
});
it('should convert a Perses yAxis spec of type log to the ECharts equivalent', () => {
const persesAxis: TimeSeriesChartYAxisOptions = {
show: true,
label: 'Axis Label',
format: {
unit: 'percent-decimal',
decimalPlaces: 0,
},
min: 0.1,
max: 1,
};
const actualAxisLog2 = convertPanelYAxis(persesAxis, 2);
// Axis label is handled outside of echarts since it is built with a custom React component.
expect(actualAxisLog2).toEqual({
show: true,
max: 1,
min: undefined,
type: 'log',
logBase: 2,
axisLabel: {
show: true,
},
});
const actualAxisLog10 = convertPanelYAxis(persesAxis, 10);
// Axis label is handled outside of echarts since it is built with a custom React component.
expect(actualAxisLog10).toEqual({
show: true,
max: 1,
min: undefined,
type: 'log',
logBase: 10,
axisLabel: {
show: true,
},
});
});
});

const ROUND_DOWN_TESTS = [
Expand Down
13 changes: 6 additions & 7 deletions timeserieschart/src/utils/data-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,19 +234,18 @@ function findMax(data: LegacyTimeSeries[] | TimeSeries[]): number {
*/
export function convertPanelYAxis(
inputAxis: TimeSeriesChartYAxisOptions = {},
useLogarithmicBase: LOG_BASE
useLogarithmicBase: LOG_BASE | undefined
): YAXisComponentOption {
// Determine the appropriate min value based on scale type and user input
let minValue: YAXisComponentOption['min'];

if (inputAxis?.min !== undefined) {
// User explicitly set a min value - use it for both linear and log scales
minValue = inputAxis.min;
} else if (useLogarithmicBase !== 'none') {
if (useLogarithmicBase !== undefined) {
// For logarithmic scales without explicit min:
// Let ECharts auto-calculate the range based on data to avoid issues with
// function-based calculations which can result in improper ranges (e.g., 1-10)
minValue = undefined;
} else if (inputAxis?.min !== undefined) {
// User explicitly set a min value - use it for both linear and log scales
minValue = inputAxis.min;
} else {
// For linear scales without explicit min:
// Use dynamic calculation with padding for better visualization
Expand Down Expand Up @@ -278,7 +277,7 @@ export function convertPanelYAxis(
};

// Apply logarithmic scale settings if requested
if (useLogarithmicBase !== 'none') {
if (useLogarithmicBase !== undefined) {
return {
...yAxis,
type: 'log',
Expand Down