mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-18 07:56:56 +00:00
177 lines
4.7 KiB
TypeScript
177 lines
4.7 KiB
TypeScript
import './styles.scss';
|
|
|
|
import { Button, Select, Typography } from 'antd';
|
|
import getAllChannels from 'api/channels/getAll';
|
|
import classNames from 'classnames';
|
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
|
import { Plus } from 'lucide-react';
|
|
import { useQuery } from 'react-query';
|
|
import { SuccessResponseV2 } from 'types/api';
|
|
import { Channels } from 'types/api/channels/getAll';
|
|
import APIError from 'types/api/error';
|
|
|
|
import { useCreateAlertState } from '../context';
|
|
import {
|
|
INITIAL_INFO_THRESHOLD,
|
|
INITIAL_RANDOM_THRESHOLD,
|
|
INITIAL_WARNING_THRESHOLD,
|
|
THRESHOLD_MATCH_TYPE_OPTIONS,
|
|
THRESHOLD_OPERATOR_OPTIONS,
|
|
} from '../context/constants';
|
|
import EvaluationSettings from '../EvaluationSettings/EvaluationSettings';
|
|
import { showCondensedLayout } from '../utils';
|
|
import ThresholdItem from './ThresholdItem';
|
|
import { UpdateThreshold } from './types';
|
|
import {
|
|
getCategoryByOptionId,
|
|
getCategorySelectOptionByName,
|
|
getQueryNames,
|
|
} from './utils';
|
|
|
|
function AlertThreshold(): JSX.Element {
|
|
const {
|
|
alertState,
|
|
thresholdState,
|
|
setThresholdState,
|
|
} = useCreateAlertState();
|
|
const { data, isLoading: isLoadingChannels } = useQuery<
|
|
SuccessResponseV2<Channels[]>,
|
|
APIError
|
|
>(['getChannels'], {
|
|
queryFn: () => getAllChannels(),
|
|
});
|
|
const showCondensedLayoutFlag = showCondensedLayout();
|
|
const channels = data?.data || [];
|
|
|
|
const { currentQuery } = useQueryBuilder();
|
|
|
|
const queryNames = getQueryNames(currentQuery);
|
|
|
|
const selectedCategory = getCategoryByOptionId(alertState.yAxisUnit || '');
|
|
const categorySelectOptions = getCategorySelectOptionByName(
|
|
selectedCategory || '',
|
|
);
|
|
|
|
const addThreshold = (): void => {
|
|
let newThreshold;
|
|
if (thresholdState.thresholds.length === 1) {
|
|
newThreshold = INITIAL_WARNING_THRESHOLD;
|
|
} else if (thresholdState.thresholds.length === 2) {
|
|
newThreshold = INITIAL_INFO_THRESHOLD;
|
|
} else {
|
|
newThreshold = INITIAL_RANDOM_THRESHOLD;
|
|
}
|
|
setThresholdState({
|
|
type: 'SET_THRESHOLDS',
|
|
payload: [...thresholdState.thresholds, newThreshold],
|
|
});
|
|
};
|
|
|
|
const removeThreshold = (id: string): void => {
|
|
if (thresholdState.thresholds.length > 1) {
|
|
setThresholdState({
|
|
type: 'SET_THRESHOLDS',
|
|
payload: thresholdState.thresholds.filter((t) => t.id !== id),
|
|
});
|
|
}
|
|
};
|
|
|
|
const updateThreshold: UpdateThreshold = (id, field, value) => {
|
|
setThresholdState({
|
|
type: 'SET_THRESHOLDS',
|
|
payload: thresholdState.thresholds.map((t) =>
|
|
t.id === id ? { ...t, [field]: value } : t,
|
|
),
|
|
});
|
|
};
|
|
|
|
const evaluationWindowContext = showCondensedLayoutFlag ? (
|
|
<EvaluationSettings />
|
|
) : (
|
|
<strong>Evaluation Window.</strong>
|
|
);
|
|
|
|
return (
|
|
<div
|
|
className={classNames('alert-threshold-container', {
|
|
'condensed-alert-threshold-container': showCondensedLayoutFlag,
|
|
})}
|
|
>
|
|
{/* Main condition sentence */}
|
|
<div className="alert-condition-sentences">
|
|
<div className="alert-condition-sentence">
|
|
<Typography.Text className="sentence-text">
|
|
Send a notification when
|
|
</Typography.Text>
|
|
<Select
|
|
value={thresholdState.selectedQuery}
|
|
onChange={(value): void => {
|
|
setThresholdState({
|
|
type: 'SET_SELECTED_QUERY',
|
|
payload: value,
|
|
});
|
|
}}
|
|
style={{ width: 80 }}
|
|
options={queryNames}
|
|
/>
|
|
</div>
|
|
<div className="alert-condition-sentence">
|
|
<Select
|
|
value={thresholdState.operator}
|
|
onChange={(value): void => {
|
|
setThresholdState({
|
|
type: 'SET_OPERATOR',
|
|
payload: value,
|
|
});
|
|
}}
|
|
style={{ width: 120 }}
|
|
options={THRESHOLD_OPERATOR_OPTIONS}
|
|
/>
|
|
<Typography.Text className="sentence-text">
|
|
the threshold(s)
|
|
</Typography.Text>
|
|
<Select
|
|
value={thresholdState.matchType}
|
|
onChange={(value): void => {
|
|
setThresholdState({
|
|
type: 'SET_MATCH_TYPE',
|
|
payload: value,
|
|
});
|
|
}}
|
|
style={{ width: 140 }}
|
|
options={THRESHOLD_MATCH_TYPE_OPTIONS}
|
|
/>
|
|
<Typography.Text className="sentence-text">
|
|
during the {evaluationWindowContext}
|
|
</Typography.Text>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="thresholds-section">
|
|
{thresholdState.thresholds.map((threshold, index) => (
|
|
<ThresholdItem
|
|
key={threshold.id}
|
|
threshold={threshold}
|
|
updateThreshold={updateThreshold}
|
|
removeThreshold={removeThreshold}
|
|
showRemoveButton={index !== 0 && thresholdState.thresholds.length > 1}
|
|
channels={channels}
|
|
isLoadingChannels={isLoadingChannels}
|
|
units={categorySelectOptions}
|
|
/>
|
|
))}
|
|
<Button
|
|
type="dashed"
|
|
icon={<Plus size={16} />}
|
|
onClick={addThreshold}
|
|
className="add-threshold-btn"
|
|
>
|
|
Add Threshold
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default AlertThreshold;
|