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:
@@ -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"]
|
||||
],
|
||||
|
||||
+5
-24
@@ -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)}`,
|
||||
}),
|
||||
});
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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": "Ŗęşŧőřę Đäşĥþőäřđş"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user