Alerting: Create reusable components for threshold (#94045)

* Create reusable components for threshold

* update translations

* do not use capital letters for keys in translations
This commit is contained in:
Sonia Aguilar
2024-11-08 18:15:29 +02:00
committed by GitHub
parent acf119a12c
commit d92e17ee55
7 changed files with 99 additions and 92 deletions
-5
View File
@@ -3502,11 +3502,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "8"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "9"]
],
"public/app/features/expressions/components/Threshold.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/expressions/guards.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -4,13 +4,15 @@ import { Dispatch, FormEvent } from 'react';
import { UnknownAction } from 'redux';
import { GrafanaTheme2, PanelData, ReducerID, SelectableValue } from '@grafana/data';
import { ButtonSelect, InlineField, InlineFieldRow, Input, Select, Stack, Text, useStyles2 } from '@grafana/ui';
import { InlineField, InlineFieldRow, Input, Select, Stack, Text, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { EvalFunction } from 'app/features/alerting/state/alertDef';
import { ThresholdSelect } from 'app/features/expressions/components/ThresholdSelect';
import { ExpressionQuery, ExpressionQueryType, reducerTypes, thresholdFunctions } from 'app/features/expressions/types';
import { getReducerType } from 'app/features/expressions/utils/expressionTypes';
import { AlertQuery } from 'app/types/unified-alerting-dto';
import { ToLabel } from '../../../../../expressions/components/ToLabel';
import { ExpressionResult } from '../../expressions/Expression';
import { updateExpression } from './reducer';
@@ -114,12 +116,7 @@ export const SimpleConditionEditor = ({
</InlineField>
<InlineField label="OF QUERY">
<Stack direction="row" gap={1} alignItems="center">
<ButtonSelect
className={styles.buttonSelectText}
options={thresholdFunctions}
onChange={onEvalFunctionChange}
value={thresholdFunction}
/>
<ThresholdSelect onChange={onEvalFunctionChange} value={thresholdFunction} />
{isRange ? (
<>
<Input
@@ -128,9 +125,7 @@ export const SimpleConditionEditor = ({
value={simpleCondition.evaluator.params[0]}
onChange={(event) => onEvaluateValueChange(event, 0)}
/>
<div className={styles.condition.button}>
<Trans i18nKey="alerting.simpleCondition.ofQuery.To">TO</Trans>
</div>
<ToLabel />
<Input
type="number"
width={10}
@@ -261,19 +256,5 @@ const getStyles = (theme: GrafanaTheme2) => ({
borderBottom: `solid 1px ${theme.colors.border.weak}`,
flex: 1,
}),
button: css({
height: '32px',
color: theme.colors.primary.text,
fontSize: theme.typography.bodySmall.fontSize,
textTransform: 'uppercase',
display: 'flex',
alignItems: 'center',
borderRadius: theme.shape.radius.default,
fontWeight: theme.typography.fontWeightBold,
border: `1px solid ${theme.colors.border.medium}`,
whiteSpace: 'nowrap',
padding: `0 ${theme.spacing(1)}`,
backgroundColor: theme.colors.background.primary,
}),
},
});
@@ -1,16 +1,18 @@
import { css } from '@emotion/css';
import { AnyAction } from '@reduxjs/toolkit';
import { FormEvent, useEffect, useReducer } from 'react';
import * as React from 'react';
import { FormEvent, useEffect, useReducer } from 'react';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { Stack } from '@grafana/experimental';
import { ButtonSelect, InlineField, InlineFieldRow, InlineSwitch, Input, Select, useStyles2 } from '@grafana/ui';
import { InlineField, InlineFieldRow, InlineSwitch, Input, Select, useStyles2 } from '@grafana/ui';
import { config } from 'app/core/config';
import { EvalFunction } from 'app/features/alerting/state/alertDef';
import { ClassicCondition, ExpressionQuery, thresholdFunctions } from '../types';
import { ThresholdSelect } from './ThresholdSelect';
import { ToLabel } from './ToLabel';
import {
isInvalid,
thresholdReducer,
@@ -91,12 +93,8 @@ export const Threshold = ({ labelWidth, onChange, refIds, query, onError, useHys
</InlineField>
</InlineFieldRow>
<InlineFieldRow>
<ButtonSelect
className={styles.buttonSelectText}
options={thresholdFunctions}
onChange={onEvalFunctionChange}
value={thresholdFunction}
/>
<ThresholdSelect onChange={onEvalFunctionChange} value={thresholdFunction} />
{isRange ? (
<>
<Input
@@ -105,7 +103,7 @@ export const Threshold = ({ labelWidth, onChange, refIds, query, onError, useHys
onChange={(event) => onEvaluateValueChange(event, 0)}
defaultValue={conditionInState.evaluator.params[0]}
/>
<div className={styles.button}>TO</div>
<ToLabel />
<Input
type="number"
width={10}
@@ -226,7 +224,7 @@ function RecoveryThresholdRow({ isRange, condition, onError, dispatch, allowOnbl
/>
</InlineField>
</div>
<div className={styles.button}>TO</div>
<ToLabel />
<div className={styles.range}>
<InlineField invalid={Boolean(errorMsgTo)} error={errorMsgTo}>
<Input
@@ -257,7 +255,7 @@ function RecoveryThresholdRow({ isRange, condition, onError, dispatch, allowOnbl
</InlineField>
</div>
<div className={styles.button}>TO</div>
<ToLabel />
<div className={styles.range}>
<InlineField invalid={Boolean(errorMsgTo)} error={errorMsgTo}>
<Input
@@ -321,26 +319,6 @@ function RecoveryThresholdRow({ isRange, condition, onError, dispatch, allowOnbl
}
const getStyles = (theme: GrafanaTheme2) => ({
buttonSelectText: css({
color: theme.colors.primary.text,
fontSize: theme.typography.bodySmall.fontSize,
textTransform: 'uppercase',
padding: `0 ${theme.spacing(1)}`,
}),
button: css({
height: '32px',
color: theme.colors.primary.text,
fontSize: theme.typography.bodySmall.fontSize,
textTransform: 'uppercase',
display: 'flex',
alignItems: 'center',
borderRadius: theme.shape.radius.default,
fontWeight: theme.typography.fontWeightBold,
border: `1px solid ${theme.colors.border.medium}`,
whiteSpace: 'nowrap',
padding: `0 ${theme.spacing(1)}`,
backgroundColor: theme.colors.background.primary,
}),
range: css({
width: 'min-content',
}),
@@ -0,0 +1,27 @@
import { css } from '@emotion/css';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { ButtonSelect, useStyles2 } from '@grafana/ui';
import { EvalFunction } from 'app/features/alerting/state/alertDef';
import { thresholdFunctions } from '../types';
export interface ThresholdSelectProps {
onChange: (value: SelectableValue<EvalFunction>) => void;
value: SelectableValue<EvalFunction> | undefined;
}
export function ThresholdSelect({ onChange, value }: ThresholdSelectProps) {
const styles = useStyles2(getStyles);
return (
<ButtonSelect className={styles.buttonSelectText} options={thresholdFunctions} onChange={onChange} value={value} />
);
}
const getStyles = (theme: GrafanaTheme2) => ({
buttonSelectText: css({
color: theme.colors.primary.text,
fontSize: theme.typography.bodySmall.fontSize,
textTransform: 'uppercase',
padding: `0 ${theme.spacing(1)}`,
}),
});
@@ -0,0 +1,26 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
export function ToLabel() {
const styles = useStyles2(getStyles);
return (
<div className={styles.button}>
<Trans i18nKey="alerting.threshold.to">TO</Trans>
</div>
);
}
const getStyles = (theme: GrafanaTheme2) => ({
button: css({
height: '32px',
color: theme.colors.primary.text,
fontSize: theme.typography.bodySmall.fontSize,
display: 'flex',
alignItems: 'center',
fontWeight: theme.typography.fontWeightBold,
padding: `0 ${theme.spacing(1)}`,
}),
});
+16 -16
View File
@@ -163,9 +163,9 @@
"parse-mode-warning-title": "Telegram messages are limited to 4096 UTF-8 characters."
},
"used-by_one": "Used by {{ count }} notification policy",
"used-by_other": "Used by {{ count }} notification policies",
"used-by_other": "Used by {{ count }} notification policy",
"used-by-rules_one": "Used by {{ count }} alert rule",
"used-by-rules_other": "Used by {{ count }} alert rules"
"used-by-rules_other": "Used by {{ count }} alert rule"
},
"contactPointFilter": {
"label": "Contact point"
@@ -233,7 +233,7 @@
"inherited": "Inherited",
"mute-time": "Muted when",
"n-instances_one": "instance",
"n-instances_other": "instances",
"n-instances_other": "instance",
"timingOptions": {
"groupInterval": {
"description": "How long to wait before sending a notification about new alerts that are added to a group of alerts for which an initial notification has already been sent.",
@@ -249,7 +249,7 @@
}
}
},
"n-more-policies_one": "{{count}} additional policy",
"n-more-policies_one": "{{count}} additional policies",
"n-more-policies_other": "{{count}} additional policies",
"new-child": "New child policy",
"new-policy": "Add new policy",
@@ -323,15 +323,15 @@
"save-query": "Save current search"
},
"simpleCondition": {
"alertCondition": "Alert condition",
"ofQuery": {
"To": "TO"
}
"alertCondition": "Alert condition"
},
"templates": {
"misconfigured-badge-text": "Misconfigured",
"misconfigured-warning": "This template is misconfigured.",
"misconfigured-warning-details": "Templates must be defined in both the <1></1> and <4></4> sections of your alertmanager configuration."
},
"threshold": {
"to": "TO"
}
},
"annotations": {
@@ -382,15 +382,15 @@
},
"counts": {
"alertRule_one": "{{count}} alert rule",
"alertRule_other": "{{count}} alert rules",
"alertRule_other": "{{count}} alert rule",
"dashboard_one": "{{count}} dashboard",
"dashboard_other": "{{count}} dashboards",
"dashboard_other": "{{count}} dashboard",
"folder_one": "{{count}} folder",
"folder_other": "{{count}} folders",
"folder_other": "{{count}} folder",
"libraryPanel_one": "{{count}} library panel",
"libraryPanel_other": "{{count}} library panels",
"libraryPanel_other": "{{count}} library panel",
"total_one": "{{count}} item",
"total_other": "{{count}} items"
"total_other": "{{count}} item"
},
"dashboards-tree": {
"collapse-folder-button": "Collapse folder {{title}}",
@@ -2445,16 +2445,16 @@
"confirm-text": "Delete",
"delete-button": "Delete",
"delete-loading": "Deleting...",
"text_one": "This action will delete {{numberOfDashboards}} dashboard.",
"text_one": "This action will delete {{numberOfDashboards}} dashboards.",
"text_other": "This action will delete {{numberOfDashboards}} dashboards.",
"title": "Permanently Delete Dashboards"
},
"restore-modal": {
"folder-picker-text_one": "Please choose a folder where your dashboard will be restored.",
"folder-picker-text_one": "Please choose a folder where your dashboards will be restored.",
"folder-picker-text_other": "Please choose a folder where your dashboards will be restored.",
"restore-button": "Restore",
"restore-loading": "Restoring...",
"text_one": "This action will restore {{numberOfDashboards}} dashboard.",
"text_one": "This action will restore {{numberOfDashboards}} dashboards.",
"text_other": "This action will restore {{numberOfDashboards}} dashboards.",
"title": "Restore Dashboards"
}
+16 -16
View File
@@ -163,9 +163,9 @@
"parse-mode-warning-title": "Ŧęľęģřäm męşşäģęş äřę ľįmįŧęđ ŧő 4096 ŮŦF-8 čĥäřäčŧęřş."
},
"used-by_one": "Ůşęđ þy {{ count }} ʼnőŧįƒįčäŧįőʼn pőľįčy",
"used-by_other": "Ůşęđ þy {{ count }} ʼnőŧįƒįčäŧįőʼn pőľįčįęş",
"used-by_other": "Ůşęđ þy {{ count }} ʼnőŧįƒįčäŧįőʼn pőľįčy",
"used-by-rules_one": "Ůşęđ þy {{ count }} äľęřŧ řūľę",
"used-by-rules_other": "Ůşęđ þy {{ count }} äľęřŧ řūľęş"
"used-by-rules_other": "Ůşęđ þy {{ count }} äľęřŧ řūľę"
},
"contactPointFilter": {
"label": "Cőʼnŧäčŧ pőįʼnŧ"
@@ -233,7 +233,7 @@
"inherited": "Ĩʼnĥęřįŧęđ",
"mute-time": "Mūŧęđ ŵĥęʼn",
"n-instances_one": "įʼnşŧäʼnčę",
"n-instances_other": "įʼnşŧäʼnčęş",
"n-instances_other": "įʼnşŧäʼnčę",
"timingOptions": {
"groupInterval": {
"description": "Ħőŵ ľőʼnģ ŧő ŵäįŧ þęƒőřę şęʼnđįʼnģ ä ʼnőŧįƒįčäŧįőʼn äþőūŧ ʼnęŵ äľęřŧş ŧĥäŧ äřę äđđęđ ŧő ä ģřőūp őƒ äľęřŧş ƒőř ŵĥįčĥ äʼn įʼnįŧįäľ ʼnőŧįƒįčäŧįőʼn ĥäş äľřęäđy þęęʼn şęʼnŧ.",
@@ -249,7 +249,7 @@
}
}
},
"n-more-policies_one": "{{count}} äđđįŧįőʼnäľ pőľįčy",
"n-more-policies_one": "{{count}} äđđįŧįőʼnäľ pőľįčįęş",
"n-more-policies_other": "{{count}} äđđįŧįőʼnäľ pőľįčįęş",
"new-child": "Ńęŵ čĥįľđ pőľįčy",
"new-policy": "Åđđ ʼnęŵ pőľįčy",
@@ -323,15 +323,15 @@
"save-query": "Ŝävę čūřřęʼnŧ şęäřčĥ"
},
"simpleCondition": {
"alertCondition": "Åľęřŧ čőʼnđįŧįőʼn",
"ofQuery": {
"To": "ŦØ"
}
"alertCondition": "Åľęřŧ čőʼnđįŧįőʼn"
},
"templates": {
"misconfigured-badge-text": "Mįşčőʼnƒįģūřęđ",
"misconfigured-warning": "Ŧĥįş ŧęmpľäŧę įş mįşčőʼnƒįģūřęđ.",
"misconfigured-warning-details": "Ŧęmpľäŧęş mūşŧ þę đęƒįʼnęđ įʼn þőŧĥ ŧĥę <1></1> äʼnđ <4></4> şęčŧįőʼnş őƒ yőūř äľęřŧmäʼnäģęř čőʼnƒįģūřäŧįőʼn."
},
"threshold": {
"to": "ŦØ"
}
},
"annotations": {
@@ -382,15 +382,15 @@
},
"counts": {
"alertRule_one": "{{count}} äľęřŧ řūľę",
"alertRule_other": "{{count}} äľęřŧ řūľęş",
"alertRule_other": "{{count}} äľęřŧ řūľę",
"dashboard_one": "{{count}} đäşĥþőäřđ",
"dashboard_other": "{{count}} đäşĥþőäřđş",
"dashboard_other": "{{count}} đäşĥþőäřđ",
"folder_one": "{{count}} ƒőľđęř",
"folder_other": "{{count}} ƒőľđęřş",
"folder_other": "{{count}} ƒőľđęř",
"libraryPanel_one": "{{count}} ľįþřäřy päʼnęľ",
"libraryPanel_other": "{{count}} ľįþřäřy päʼnęľş",
"libraryPanel_other": "{{count}} ľįþřäřy päʼnęľ",
"total_one": "{{count}} įŧęm",
"total_other": "{{count}} įŧęmş"
"total_other": "{{count}} įŧęm"
},
"dashboards-tree": {
"collapse-folder-button": "Cőľľäpşę ƒőľđęř {{title}}",
@@ -2445,16 +2445,16 @@
"confirm-text": "Đęľęŧę",
"delete-button": "Đęľęŧę",
"delete-loading": "Đęľęŧįʼnģ...",
"text_one": "Ŧĥįş äčŧįőʼn ŵįľľ đęľęŧę {{numberOfDashboards}} đäşĥþőäřđ.",
"text_one": "Ŧĥįş äčŧįőʼn ŵįľľ đęľęŧę {{numberOfDashboards}} đäşĥþőäřđş.",
"text_other": "Ŧĥįş äčŧįőʼn ŵįľľ đęľęŧę {{numberOfDashboards}} đäşĥþőäřđş.",
"title": "Pęřmäʼnęʼnŧľy Đęľęŧę Đäşĥþőäřđş"
},
"restore-modal": {
"folder-picker-text_one": "Pľęäşę čĥőőşę ä ƒőľđęř ŵĥęřę yőūř đäşĥþőäřđ ŵįľľ þę řęşŧőřęđ.",
"folder-picker-text_one": "Pľęäşę čĥőőşę ä ƒőľđęř ŵĥęřę yőūř đäşĥþőäřđş ŵįľľ þę řęşŧőřęđ.",
"folder-picker-text_other": "Pľęäşę čĥőőşę ä ƒőľđęř ŵĥęřę yőūř đäşĥþőäřđş ŵįľľ þę řęşŧőřęđ.",
"restore-button": "Ŗęşŧőřę",
"restore-loading": "Ŗęşŧőřįʼnģ...",
"text_one": "Ŧĥįş äčŧįőʼn ŵįľľ řęşŧőřę {{numberOfDashboards}} đäşĥþőäřđ.",
"text_one": "Ŧĥįş äčŧįőʼn ŵįľľ řęşŧőřę {{numberOfDashboards}} đäşĥþőäřđş.",
"text_other": "Ŧĥįş äčŧįőʼn ŵįľľ řęşŧőřę {{numberOfDashboards}} đäşĥþőäřđş.",
"title": "Ŗęşŧőřę Đäşĥþőäřđş"
}