[Fix]: threshold in alerts (#4074)

This commit is contained in:
Rajat Dabade 2023-12-01 18:16:25 +05:30 committed by GitHub
parent aad44a1037
commit 0b991331d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 147 additions and 14 deletions

View File

@ -2,6 +2,7 @@ import { InfoCircleOutlined } from '@ant-design/icons';
import Spinner from 'components/Spinner'; import Spinner from 'components/Spinner';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import GridPanelSwitch from 'container/GridPanelSwitch'; import GridPanelSwitch from 'container/GridPanelSwitch';
import { getFormatNameByOptionId } from 'container/NewWidget/RightContainer/alertFomatCategories';
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems'; import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
import { Time } from 'container/TopNav/DateTimeSelection/config'; import { Time } from 'container/TopNav/DateTimeSelection/config';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange'; import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
@ -19,7 +20,7 @@ import { EQueryType } from 'types/common/dashboard';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { ChartContainer, FailedMessageContainer } from './styles'; import { ChartContainer, FailedMessageContainer } from './styles';
import { covertIntoDataFormats } from './utils'; import { getThresholdLabel } from './utils';
export interface ChartPreviewProps { export interface ChartPreviewProps {
name: string; name: string;
@ -50,12 +51,6 @@ function ChartPreview({
(state) => state.globalTime, (state) => state.globalTime,
); );
const thresholdValue = covertIntoDataFormats({
value: threshold,
sourceUnit: alertDef?.condition.targetUnit,
targetUnit: query?.unit,
});
const canQuery = useMemo((): boolean => { const canQuery = useMemo((): boolean => {
if (!query || query == null) { if (!query || query == null) {
return false; return false;
@ -110,6 +105,9 @@ function ChartPreview({
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
const optionName =
getFormatNameByOptionId(alertDef?.condition.targetUnit || '') || '';
const options = useMemo( const options = useMemo(
() => () =>
getUPlotChartOptions({ getUPlotChartOptions({
@ -124,10 +122,16 @@ function ChartPreview({
keyIndex: 0, keyIndex: 0,
moveThreshold: (): void => {}, moveThreshold: (): void => {},
selectedGraph: PANEL_TYPES.TIME_SERIES, // no impact selectedGraph: PANEL_TYPES.TIME_SERIES, // no impact
thresholdValue, thresholdValue: threshold,
thresholdLabel: `${t( thresholdLabel: `${t(
'preview_chart_threshold_label', 'preview_chart_threshold_label',
)} (y=${thresholdValue} ${query?.unit || ''})`, )} (y=${getThresholdLabel(
optionName,
threshold,
alertDef?.condition.targetUnit,
query?.unit,
)})`,
thresholdUnit: alertDef?.condition.targetUnit,
}, },
], ],
}), }),
@ -136,8 +140,10 @@ function ChartPreview({
queryResponse?.data?.payload, queryResponse?.data?.payload,
containerDimensions, containerDimensions,
isDarkMode, isDarkMode,
threshold,
t, t,
thresholdValue, optionName,
alertDef?.condition.targetUnit,
], ],
); );

View File

@ -51,6 +51,21 @@ export function covertIntoDataFormats({
return Number.isNaN(result) ? 0 : result; return Number.isNaN(result) ? 0 : result;
} }
export const getThresholdLabel = (
optionName: string,
value: number,
unit?: string,
yAxisUnit?: string,
): string => {
if (
unit === MiscellaneousFormats.PercentUnit ||
yAxisUnit === MiscellaneousFormats.PercentUnit
) {
return `${value * 100}%`;
}
return `${value} ${optionName}`;
};
interface IUnit { interface IUnit {
value: number; value: number;
sourceUnit?: string; sourceUnit?: string;

View File

@ -6,6 +6,8 @@ import {
CategoryNames, CategoryNames,
DataFormats, DataFormats,
DataRateFormats, DataRateFormats,
HelperCategory,
HelperFormat,
MiscellaneousFormats, MiscellaneousFormats,
ThroughputFormats, ThroughputFormats,
TimeFormats, TimeFormats,
@ -119,3 +121,10 @@ export const getCategoryByOptionId = (id: string): Category | undefined =>
export const isCategoryName = (name: string): name is CategoryNames => export const isCategoryName = (name: string): name is CategoryNames =>
alertsCategory.some((category) => category.name === name); alertsCategory.some((category) => category.name === name);
const allFormats: HelperFormat[] = alertsCategory.flatMap(
(category: HelperCategory) => category.formats,
);
export const getFormatNameByOptionId = (id: string): string | undefined =>
allFormats.find((format) => format.id === id)?.name;

View File

@ -362,3 +362,13 @@ export type Category = {
}; };
export type DataTypeCategories = Category[]; export type DataTypeCategories = Category[];
export interface HelperFormat {
name: string;
id: string;
}
export interface HelperCategory {
name: string;
formats: Format[];
}

View File

@ -265,10 +265,15 @@ function findUnitObject(
export function convertValue( export function convertValue(
value: number, value: number,
currentUnit: string, currentUnit?: string,
targetUnit: string, targetUnit?: string,
): number | null { ): number | null {
if (targetUnit === 'none') { if (
targetUnit === 'none' ||
!currentUnit ||
!targetUnit ||
currentUnit === targetUnit
) {
return value; return value;
} }
const currentUnitObj = findUnitObject(currentUnit); const currentUnitObj = findUnitObject(currentUnit);

View File

@ -15,6 +15,7 @@ import onClickPlugin, { OnClickPluginOpts } from './plugins/onClickPlugin';
import tooltipPlugin from './plugins/tooltipPlugin'; import tooltipPlugin from './plugins/tooltipPlugin';
import getAxes from './utils/getAxes'; import getAxes from './utils/getAxes';
import getSeries from './utils/getSeriesData'; import getSeries from './utils/getSeriesData';
import { getYAxisScale } from './utils/getYAxisScale';
interface GetUPlotChartOptions { interface GetUPlotChartOptions {
id?: string; id?: string;
@ -79,7 +80,11 @@ export const getUPlotChartOptions = ({
auto: true, // Automatically adjust scale range auto: true, // Automatically adjust scale range
}, },
y: { y: {
auto: true, ...getYAxisScale(
thresholds,
apiResponse?.data.newResult.data.result,
yAxisUnit,
),
}, },
}, },
plugins: [ plugins: [

View File

@ -0,0 +1,83 @@
import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types';
import { convertValue } from 'lib/getConvertedValue';
import { QueryDataV3 } from 'types/api/widgets/getQuery';
function findMinMaxValues(data: QueryDataV3[]): [number, number] {
let min = 0;
let max = 0;
data?.forEach((entry) => {
entry.series?.forEach((series) => {
series.values.forEach((valueObj) => {
const value = parseFloat(valueObj.value);
if (!value) return;
min = Math.min(min, value);
max = Math.max(max, value);
});
});
});
return [min, max];
}
function findMinMaxThresholdValues(
thresholds: ThresholdProps[],
yAxisUnit?: string,
): [number, number] {
let minThresholdValue = 0;
let maxThresholdValue = 0;
thresholds.forEach((entry) => {
const { thresholdValue, thresholdUnit } = entry;
if (thresholdValue === undefined) return;
minThresholdValue = Math.min(
minThresholdValue,
convertValue(thresholdValue, thresholdUnit, yAxisUnit) || 0,
);
maxThresholdValue = Math.max(
maxThresholdValue,
convertValue(thresholdValue, thresholdUnit, yAxisUnit) || 0,
);
});
return [minThresholdValue, maxThresholdValue];
}
function getRange(
thresholds: ThresholdProps[],
series: QueryDataV3[],
yAxisUnit?: string,
): [number, number] {
const [minThresholdValue, maxThresholdValue] = findMinMaxThresholdValues(
thresholds,
yAxisUnit,
);
const [minSeriesValue, maxSeriesValue] = findMinMaxValues(series);
const min = Math.min(minThresholdValue, minSeriesValue);
const max = Math.max(maxThresholdValue, maxSeriesValue);
return [min, max];
}
function areAllSeriesEmpty(series: QueryDataV3[]): boolean {
return series.every((entry) => {
if (!entry.series) return true;
return entry.series.every((series) => series.values.length === 0);
});
}
export const getYAxisScale = (
thresholds?: ThresholdProps[],
series?: QueryDataV3[],
yAxisUnit?: string,
): {
auto: boolean;
range?: [number, number];
} => {
if (!thresholds || !series) return { auto: true };
if (areAllSeriesEmpty(series)) return { auto: true };
const [min, max] = getRange(thresholds, series, yAxisUnit);
return { auto: false, range: [min, max] };
};