diff --git a/frontend/src/container/FormAlertRules/ChartPreview/index.tsx b/frontend/src/container/FormAlertRules/ChartPreview/index.tsx index 7e22e3a11c..73b1f4715e 100644 --- a/frontend/src/container/FormAlertRules/ChartPreview/index.tsx +++ b/frontend/src/container/FormAlertRules/ChartPreview/index.tsx @@ -150,6 +150,8 @@ function ChartPreview({ thresholdUnit: alertDef?.condition.targetUnit, }, ], + softMax: null, + softMin: null, }), [ yAxisUnit, diff --git a/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx b/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx index db42625f1d..750cc6a707 100644 --- a/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx +++ b/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx @@ -132,6 +132,8 @@ function FullView({ thresholds: widget.thresholds, minTimeScale, maxTimeScale, + softMax: widget.softMax, + softMin: widget.softMin, }); setChartOptions(newChartOptions); diff --git a/frontend/src/container/GridCardLayout/GridCard/index.tsx b/frontend/src/container/GridCardLayout/GridCard/index.tsx index 32454bb28f..79b7d39b4d 100644 --- a/frontend/src/container/GridCardLayout/GridCard/index.tsx +++ b/frontend/src/container/GridCardLayout/GridCard/index.tsx @@ -135,11 +135,15 @@ function GridCardGraph({ thresholds: widget.thresholds, minTimeScale, maxTimeScale, + softMax: widget.softMax, + softMin: widget.softMin, }), [ widget?.id, widget?.yAxisUnit, widget.thresholds, + widget.softMax, + widget.softMin, queryResponse.data?.payload, containerDimensions, isDarkMode, diff --git a/frontend/src/container/MetricsApplication/MetricsApplication.factory.ts b/frontend/src/container/MetricsApplication/MetricsApplication.factory.ts index 9941308838..20becbb810 100644 --- a/frontend/src/container/MetricsApplication/MetricsApplication.factory.ts +++ b/frontend/src/container/MetricsApplication/MetricsApplication.factory.ts @@ -20,4 +20,6 @@ export const getWidgetQueryBuilder = ({ timePreferance: 'GLOBAL_TIME', title, yAxisUnit, + softMax: null, + softMin: null, }); diff --git a/frontend/src/container/NewDashboard/ComponentsSlider/index.tsx b/frontend/src/container/NewDashboard/ComponentsSlider/index.tsx index 1a111cf4fe..d355edfd1a 100644 --- a/frontend/src/container/NewDashboard/ComponentsSlider/index.tsx +++ b/frontend/src/container/NewDashboard/ComponentsSlider/index.tsx @@ -63,6 +63,8 @@ function DashboardGraphSlider(): JSX.Element { panelTypes: name, query: initialQueriesMap.metrics, timePreferance: 'GLOBAL_TIME', + softMax: null, + softMin: null, }, ], }, diff --git a/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphContainer.tsx b/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphContainer.tsx index 6fcbcaa8c1..c3d47880d3 100644 --- a/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphContainer.tsx +++ b/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphContainer.tsx @@ -14,6 +14,8 @@ function WidgetGraphContainer({ selectedTime, thresholds, fillSpans = false, + softMax, + softMin, }: WidgetGraphProps): JSX.Element { const { selectedDashboard } = useDashboard(); @@ -59,6 +61,8 @@ function WidgetGraphContainer({ selectedWidget={selectedWidget} thresholds={thresholds} fillSpans={fillSpans} + softMax={softMax} + softMin={softMin} /> ); } diff --git a/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphs.tsx b/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphs.tsx index cc4c146a96..08b65fa9c1 100644 --- a/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphs.tsx +++ b/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/WidgetGraphs.tsx @@ -23,6 +23,8 @@ function WidgetGraph({ yAxisUnit, thresholds, fillSpans, + softMax, + softMin, }: WidgetGraphProps): JSX.Element { const { stagedQuery } = useQueryBuilder(); @@ -83,6 +85,8 @@ function WidgetGraph({ fillSpans, minTimeScale, maxTimeScale, + softMax, + softMin, }), [ widgetId, @@ -95,6 +99,8 @@ function WidgetGraph({ fillSpans, minTimeScale, maxTimeScale, + softMax, + softMin, ], ); @@ -125,6 +131,8 @@ interface WidgetGraphProps { SuccessResponse, Error >; + softMax: number | null; + softMin: number | null; } export default WidgetGraph; diff --git a/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/index.tsx b/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/index.tsx index e92b17f90a..56846c8dec 100644 --- a/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/index.tsx +++ b/frontend/src/container/NewWidget/LeftContainer/WidgetGraph/index.tsx @@ -17,6 +17,8 @@ function WidgetGraph({ selectedTime, thresholds, fillSpans, + softMax, + softMin, }: WidgetGraphProps): JSX.Element { const { currentQuery } = useQueryBuilder(); const { selectedDashboard } = useDashboard(); @@ -53,6 +55,8 @@ function WidgetGraph({ selectedGraph={selectedGraph} yAxisUnit={yAxisUnit} fillSpans={fillSpans} + softMax={softMax} + softMin={softMin} /> ); diff --git a/frontend/src/container/NewWidget/LeftContainer/index.tsx b/frontend/src/container/NewWidget/LeftContainer/index.tsx index ad48c19a5c..0a78a084d8 100644 --- a/frontend/src/container/NewWidget/LeftContainer/index.tsx +++ b/frontend/src/container/NewWidget/LeftContainer/index.tsx @@ -11,6 +11,8 @@ function LeftContainer({ selectedTime, thresholds, fillSpans, + softMax, + softMin, }: WidgetGraphProps): JSX.Element { return ( <> @@ -20,6 +22,8 @@ function LeftContainer({ selectedGraph={selectedGraph} yAxisUnit={yAxisUnit} fillSpans={fillSpans} + softMax={softMax} + softMin={softMin} /> diff --git a/frontend/src/container/NewWidget/RightContainer/constants.ts b/frontend/src/container/NewWidget/RightContainer/constants.ts index ae12b4f3a6..0030f6927b 100644 --- a/frontend/src/container/NewWidget/RightContainer/constants.ts +++ b/frontend/src/container/NewWidget/RightContainer/constants.ts @@ -30,6 +30,15 @@ export const panelTypeVsThreshold: { [key in PANEL_TYPES]: boolean } = { [PANEL_TYPES.EMPTY_WIDGET]: false, } as const; +export const panelTypeVsSoftMinMax: { [key in PANEL_TYPES]: boolean } = { + [PANEL_TYPES.TIME_SERIES]: true, + [PANEL_TYPES.VALUE]: false, + [PANEL_TYPES.TABLE]: false, + [PANEL_TYPES.LIST]: false, + [PANEL_TYPES.TRACE]: false, + [PANEL_TYPES.EMPTY_WIDGET]: false, +} as const; + export const panelTypeVsDragAndDrop: { [key in PANEL_TYPES]: boolean } = { [PANEL_TYPES.TIME_SERIES]: false, [PANEL_TYPES.VALUE]: true, diff --git a/frontend/src/container/NewWidget/RightContainer/index.tsx b/frontend/src/container/NewWidget/RightContainer/index.tsx index c39039c04f..5ab1a965fc 100644 --- a/frontend/src/container/NewWidget/RightContainer/index.tsx +++ b/frontend/src/container/NewWidget/RightContainer/index.tsx @@ -3,6 +3,7 @@ import { Button, Divider, Input, + InputNumber, Select, Space, Switch, @@ -16,7 +17,7 @@ import useCreateAlerts from 'hooks/queryBuilder/useCreateAlerts'; import { Dispatch, SetStateAction, useCallback } from 'react'; import { Widgets } from 'types/api/dashboard/getAll'; -import { panelTypeVsThreshold } from './constants'; +import { panelTypeVsSoftMinMax, panelTypeVsThreshold } from './constants'; import { Container, Title } from './styles'; import ThresholdSelector from './Threshold/ThresholdSelector'; import { ThresholdProps } from './Threshold/types'; @@ -42,6 +43,10 @@ function RightContainer({ selectedWidget, isFillSpans, setIsFillSpans, + softMax, + softMin, + setSoftMax, + setSoftMin, }: RightContainerProps): JSX.Element { const onChangeHandler = useCallback( (setFunc: Dispatch>, value: string) => { @@ -56,6 +61,21 @@ function RightContainer({ const onCreateAlertsHandler = useCreateAlerts(selectedWidget); const allowThreshold = panelTypeVsThreshold[selectedGraph]; + const allowSoftMinMax = panelTypeVsSoftMinMax[selectedGraph]; + + const softMinHandler = useCallback( + (value: number | null) => { + setSoftMin(value); + }, + [setSoftMin], + ); + + const softMaxHandler = useCallback( + (value: number | null) => { + setSoftMax(value); + }, + [setSoftMax], + ); return ( @@ -129,6 +149,30 @@ function RightContainer({ )} + {allowSoftMinMax && ( + <> + + + Soft Min + + + + Soft Max + + + + )} + {allowThreshold && ( <> @@ -166,6 +210,10 @@ interface RightContainerProps { selectedWidget?: Widgets; isFillSpans: boolean; setIsFillSpans: Dispatch>; + softMin: number | null; + softMax: number | null; + setSoftMin: Dispatch>; + setSoftMax: Dispatch>; } RightContainer.defaultProps = { diff --git a/frontend/src/container/NewWidget/index.tsx b/frontend/src/container/NewWidget/index.tsx index 8edf04c49c..9ea47330bf 100644 --- a/frontend/src/container/NewWidget/index.tsx +++ b/frontend/src/container/NewWidget/index.tsx @@ -104,6 +104,18 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { const [saveModal, setSaveModal] = useState(false); const [discardModal, setDiscardModal] = useState(false); + const [softMin, setSoftMin] = useState( + selectedWidget?.softMin === null || selectedWidget?.softMin === undefined + ? null + : selectedWidget?.softMin || 0, + ); + + const [softMax, setSoftMax] = useState( + selectedWidget?.softMax === null || selectedWidget?.softMax === undefined + ? null + : selectedWidget?.softMax || 0, + ); + const closeModal = (): void => { setSaveModal(false); setDiscardModal(false); @@ -178,6 +190,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { yAxisUnit, panelTypes: graphType, thresholds, + softMin, + softMax, fillSpans: isFillSpans, }, ...afterWidgets, @@ -213,6 +227,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { yAxisUnit, graphType, thresholds, + softMin, + softMax, isFillSpans, afterWidgets, updateDashboardMutation, @@ -317,6 +333,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { yAxisUnit={yAxisUnit} thresholds={thresholds} fillSpans={isFillSpans} + softMax={softMax} + softMin={softMin} /> @@ -343,6 +361,10 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { selectedWidget={selectedWidget} isFillSpans={isFillSpans} setIsFillSpans={setIsFillSpans} + softMin={softMin} + setSoftMin={setSoftMin} + softMax={softMax} + setSoftMax={setSoftMax} /> diff --git a/frontend/src/container/NewWidget/types.ts b/frontend/src/container/NewWidget/types.ts index 83475c0104..21d2268d76 100644 --- a/frontend/src/container/NewWidget/types.ts +++ b/frontend/src/container/NewWidget/types.ts @@ -13,4 +13,6 @@ export interface NewWidgetProps { export interface WidgetGraphProps extends NewWidgetProps { selectedTime: timePreferance; thresholds: ThresholdProps[]; + softMin: number | null; + softMax: number | null; } diff --git a/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx b/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx index c1dd107f3f..767bf16d34 100644 --- a/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx +++ b/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx @@ -60,6 +60,8 @@ function TimeSeriesView({ isDarkMode, minTimeScale, maxTimeScale, + softMax: null, + softMin: null, }); return ( diff --git a/frontend/src/hooks/dashboard/utils.ts b/frontend/src/hooks/dashboard/utils.ts index 930fc080b2..4dfb8ce9c3 100644 --- a/frontend/src/hooks/dashboard/utils.ts +++ b/frontend/src/hooks/dashboard/utils.ts @@ -33,6 +33,8 @@ export const addEmptyWidgetInDashboardJSONWithQuery = ( title: '', timePreferance: 'GLOBAL_TIME', panelTypes: panelTypes || PANEL_TYPES.TIME_SERIES, + softMax: null, + softMin: null, }, ], }, diff --git a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts index a86c1ee49c..b6e61a2ae6 100644 --- a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts +++ b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts @@ -35,6 +35,8 @@ interface GetUPlotChartOptions { fillSpans?: boolean; minTimeScale?: number; maxTimeScale?: number; + softMin: number | null; + softMax: number | null; } export const getUPlotChartOptions = ({ @@ -51,6 +53,8 @@ export const getUPlotChartOptions = ({ setGraphsVisibilityStates, thresholds, fillSpans, + softMax, + softMin, }: GetUPlotChartOptions): uPlot.Options => { const timeScaleProps = getXAxisScale(minTimeScale, maxTimeScale); @@ -87,11 +91,13 @@ export const getUPlotChartOptions = ({ ...timeScaleProps, }, y: { - ...getYAxisScale( + ...getYAxisScale({ thresholds, - apiResponse?.data.newResult.data.result, + series: apiResponse?.data.newResult.data.result, yAxisUnit, - ), + softMax, + softMin, + }), }, }, plugins: [ diff --git a/frontend/src/lib/uPlotLib/utils/getYAxisScale.test.ts b/frontend/src/lib/uPlotLib/utils/getYAxisScale.test.ts new file mode 100644 index 0000000000..ecd70084e8 --- /dev/null +++ b/frontend/src/lib/uPlotLib/utils/getYAxisScale.test.ts @@ -0,0 +1,211 @@ +import { PANEL_TYPES } from 'constants/queryBuilder'; +import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types'; +import { QueryDataV3 } from 'types/api/widgets/getQuery'; + +import { GetYAxisScale, getYAxisScale } from './getYAxisScale'; + +describe('getYAxisScale', () => { + const mockThresholds: ThresholdProps[] = [ + { + index: '1', + keyIndex: 1, + thresholdValue: 10, + thresholdUnit: 'percentunit', + moveThreshold(dragIndex, hoverIndex): void { + console.log(dragIndex, hoverIndex); + }, + selectedGraph: PANEL_TYPES.TIME_SERIES, + }, + { + index: '2', + keyIndex: 2, + thresholdValue: 20, + thresholdUnit: 'percentunit', + moveThreshold(dragIndex, hoverIndex): void { + console.log(dragIndex, hoverIndex); + }, + selectedGraph: PANEL_TYPES.TIME_SERIES, + }, + ]; + + const mockSeriesData: QueryDataV3[] = [ + { + list: null, + queryName: 'Mock Query', + series: [ + { + labels: {}, + values: [ + { timestamp: 1, value: '15' }, + { timestamp: 2, value: '25' }, + ], + }, + ], + }, + ]; + + const mockYAxisUnit = 'percentunit'; + const mockSoftMin = 5; + const mockSoftMax = 30; + + it('threshold absent, series data absent and softmin and softmax is absent', () => { + const result = getYAxisScale({ + thresholds: [], + series: [], + yAxisUnit: undefined, + softMin: null, + softMax: null, + } as GetYAxisScale); + + expect(result).toEqual({ auto: true }); + }); + + it('Threshold absent, series data present softmin and softmax present', () => { + const result = getYAxisScale({ + thresholds: [], + series: mockSeriesData, + yAxisUnit: mockYAxisUnit, + softMin: mockSoftMin, + softMax: mockSoftMax, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [5, 30], + }); + }); + + it('Only series data present', () => { + const result = getYAxisScale({ + thresholds: [], + series: mockSeriesData, + yAxisUnit: mockYAxisUnit, + softMin: null, + softMax: null, + } as GetYAxisScale); + + expect(result).toEqual({ auto: true }); + }); + + it('Threshold absent, series data present, softmin present and softmax absent', () => { + const result = getYAxisScale({ + thresholds: [], + series: mockSeriesData, + yAxisUnit: mockYAxisUnit, + softMin: mockSoftMin, + softMax: null, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [5, 25], + }); + }); + + it('Threshold absent, series data present, softmin absent and softmax present', () => { + const result = getYAxisScale({ + thresholds: [], + series: mockSeriesData, + yAxisUnit: mockYAxisUnit, + softMin: null, + softMax: mockSoftMax, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [15, 30], + }); + }); + + it('Threshold present, series absent and softmin and softmax present', () => { + const result = getYAxisScale({ + thresholds: mockThresholds, + series: [], + yAxisUnit: mockYAxisUnit, + softMin: mockSoftMin, + softMax: mockSoftMax, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [5, 30], + }); + }); + + it('Only threshold data present', () => { + const result = getYAxisScale({ + thresholds: mockThresholds, + series: [], + yAxisUnit: mockYAxisUnit, + softMin: null, + softMax: null, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [10, 20], + }); + }); + + it('Threshold present, series absent, softmin absent and softmax present', () => { + const result = getYAxisScale({ + thresholds: mockThresholds, + series: [], + yAxisUnit: mockYAxisUnit, + softMin: null, + softMax: mockSoftMax, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [10, 30], + }); + }); + + it('Threshold data present, series data absent, softmin present and softmax absent', () => { + const result = getYAxisScale({ + thresholds: mockThresholds, + series: [], + yAxisUnit: mockYAxisUnit, + softMin: mockSoftMin, + softMax: null, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [5, 20], + }); + }); + + it('Threshold data absent, series absent, softmin and softmax present', () => { + const result = getYAxisScale({ + thresholds: [], + series: [], + yAxisUnit: mockYAxisUnit, + softMin: mockSoftMin, + softMax: mockSoftMax, + } as GetYAxisScale); + + expect(result).toEqual({ + range: { + min: { soft: mockSoftMin, mode: 2 }, + max: { soft: mockSoftMax, mode: 2 }, + }, + }); + }); + + it('All data present', () => { + const result = getYAxisScale({ + thresholds: mockThresholds, + series: mockSeriesData, + yAxisUnit: mockYAxisUnit, + softMin: mockSoftMin, + softMax: mockSoftMax, + } as GetYAxisScale); + + expect(result).toEqual({ + auto: false, + range: [5, 30], + }); + }); +}); diff --git a/frontend/src/lib/uPlotLib/utils/getYAxisScale.ts b/frontend/src/lib/uPlotLib/utils/getYAxisScale.ts index 503abd5790..42860ea8c8 100644 --- a/frontend/src/lib/uPlotLib/utils/getYAxisScale.ts +++ b/frontend/src/lib/uPlotLib/utils/getYAxisScale.ts @@ -2,6 +2,7 @@ import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/typ import { convertValue } from 'lib/getConvertedValue'; import { isFinite } from 'lodash-es'; import { QueryDataV3 } from 'types/api/widgets/getQuery'; +import uPlot from 'uplot'; function findMinMaxValues(data: QueryDataV3[]): [number, number] { let min = Number.MAX_SAFE_INTEGER; @@ -71,23 +72,167 @@ function areAllSeriesEmpty(series: QueryDataV3[]): boolean { }); } -export const getYAxisScale = ( - thresholds?: ThresholdProps[], - series?: QueryDataV3[], - yAxisUnit?: string, -): { - auto: boolean; - range?: [number, number]; -} => { - if (!thresholds || !series || thresholds.length === 0) return { auto: true }; +function configSoftMinMax( + softMin: number | null, + softMax: number | null, +): { range: uPlot.Scale.Range } { + return { + range: { + min: { + soft: softMin !== null ? softMin : undefined, + mode: 2, + }, + max: { + soft: softMax !== null ? softMax : undefined, + mode: 2, + }, + }, + }; +} - if (areAllSeriesEmpty(series)) return { auto: true }; +export const getYAxisScale = ({ + thresholds, + series, + yAxisUnit, + softMin, + softMax, +}: // eslint-disable-next-line sonarjs/cognitive-complexity +GetYAxisScale): { auto?: boolean; range?: uPlot.Scale.Range } => { + // Situation: thresholds and series data is absent + if ( + (!thresholds || thresholds.length === 0) && + (!series || areAllSeriesEmpty(series)) + ) { + // Situation: softMin is not null or softMax is null + if (softMin !== null && softMax === null) { + return configSoftMinMax(softMin, softMin + 100); + } - const [min, max] = getRange(thresholds, series, yAxisUnit); + // Situation: softMin is null softMax is not null + if (softMin === null && softMax !== null) { + return configSoftMinMax(softMax - 100, softMax); + } - // Min and Max value can be same if the value is same for all the series - if (min === max) { + // Situation: softMin is not null and softMax is not null + if (softMin !== null && softMax !== null) { + return configSoftMinMax(softMin, softMax); + } + + // Situation: softMin and softMax are null and no threshold and no series data return { auto: true }; } + + // Situation: thresholds are absent + if (!thresholds || thresholds.length === 0) { + // Situation: No thresholds data but series data is present + if (series && !areAllSeriesEmpty(series)) { + // Situation: softMin and softMax are null + if (softMin === null && softMax === null) { + return { auto: true }; + } + + // Situation: either softMin or softMax is not null + let [min, max] = findMinMaxValues(series); + + if (softMin !== null) { + // Compare with softMin if it is not null + min = Math.min(min, softMin); + } + + if (softMax !== null) { + // Compare with softMax if it is not null + max = Math.max(max, softMax); + } + + if (min === max) { + // Min and Max value can be same if the value is same for all the series + return { auto: true }; + } + + return { auto: false, range: [min, max] }; + } + + // Situation: No thresholds data and series data is absent but either soft min and soft max is present + if (softMin !== null && softMax === null) { + return configSoftMinMax(softMin, softMin + 100); + } + + if (softMin === null && softMax !== null) { + return configSoftMinMax(softMax - 100, softMax); + } + + if (softMin !== null && softMax !== null) { + return configSoftMinMax(softMin, softMax); + } + + return { auto: true }; + } + + if (!series || areAllSeriesEmpty(series)) { + // series data is absent but threshold is present + if (thresholds.length > 0) { + // Situation: thresholds are present and series data is absent + let [min, max] = findMinMaxThresholdValues(thresholds, yAxisUnit); + + if (softMin !== null) { + // Compare with softMin if it is not null + min = Math.min(min, softMin); + } + + if (softMax !== null) { + // Compare with softMax if it is not null + max = Math.max(max, softMax); + } + + if (min === max) { + // Min and Max value can be same if the value is same for all the series + return { auto: true }; + } + + return { auto: false, range: [min, max] }; + } + + // Situation: softMin or softMax is not null + if (softMin !== null && softMax === null) { + return configSoftMinMax(softMin, softMin + 100); + } + + if (softMin === null && softMax !== null) { + return configSoftMinMax(softMax - 100, softMax); + } + + if (softMin !== null && softMax !== null) { + return configSoftMinMax(softMin, softMax); + } + + return { auto: true }; + } + + // Situation: thresholds and series data are present + let [min, max] = getRange(thresholds, series, yAxisUnit); + + if (softMin !== null) { + // Compare with softMin if it is not null + min = Math.min(min, softMin); + } + + if (softMax !== null) { + // Compare with softMax if it is not null + max = Math.max(max, softMax); + } + + if (min === max) { + // Min and Max value can be same if the value is same for all the series + return { auto: true }; + } + return { auto: false, range: [min, max] }; }; + +export type GetYAxisScale = { + thresholds?: ThresholdProps[]; + series?: QueryDataV3[]; + yAxisUnit?: string; + softMin: number | null; + softMax: number | null; +}; diff --git a/frontend/src/types/api/dashboard/getAll.ts b/frontend/src/types/api/dashboard/getAll.ts index 3ad1c70f73..bb302c152b 100644 --- a/frontend/src/types/api/dashboard/getAll.ts +++ b/frontend/src/types/api/dashboard/getAll.ts @@ -73,6 +73,8 @@ export interface IBaseWidget { stepSize?: number; yAxisUnit?: string; thresholds?: ThresholdProps[]; + softMin: number | null; + softMax: number | null; fillSpans?: boolean; } export interface Widgets extends IBaseWidget {