diff --git a/public/app/features/alerting/unified/components/rule-editor/QueryWrapper.tsx b/public/app/features/alerting/unified/components/rule-editor/QueryWrapper.tsx index 8a95fa6087c..0538ea7a3bd 100644 --- a/public/app/features/alerting/unified/components/rule-editor/QueryWrapper.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/QueryWrapper.tsx @@ -1,6 +1,6 @@ import { css } from '@emotion/css'; import { cloneDeep } from 'lodash'; -import React, { FC, ReactNode, useState } from 'react'; +import React, { FC, useState } from 'react'; import { CoreApp, @@ -13,7 +13,7 @@ import { RelativeTimeRange, ThresholdsConfig, } from '@grafana/data'; -import { RelativeTimeRangePicker, useStyles2 } from '@grafana/ui'; +import { RelativeTimeRangePicker, useStyles2, Tooltip, Icon } from '@grafana/ui'; import { isExpressionQuery } from 'app/features/expressions/guards'; import { QueryEditorRow } from 'app/features/query/components/QueryEditorRow'; import { AlertQuery } from 'app/types/unified-alerting-dto'; @@ -58,18 +58,49 @@ export const QueryWrapper: FC = ({ const isExpression = isExpressionQuery(query.model); const [pluginId, changePluginId] = useState(isExpression ? TABLE : TIMESERIES); - const renderTimePicker = (query: AlertQuery, index: number): ReactNode => { - if (isExpressionQuery(query.model) || !onChangeTimeRange) { - return null; - } - + function SelectingDataSourceTooltip() { + const styles = useStyles2(getStyles); return ( - onChangeTimeRange(range, index)} - /> +
+ + Not finding the data source you want? Some data sources are not supported for alerting. Click on the icon + for more information. + + } + > + + window.open( + ' https://grafana.com/docs/grafana/latest/alerting/fundamentals/data-source-alerting/', + '_blank' + ) + } + /> + +
); - }; + } + + function HeaderExtras({ query, index }: { query: AlertQuery; index: number }) { + if (isExpressionQuery(query.model)) { + return null; + } else { + return ( + <> + + {onChangeTimeRange && ( + onChangeTimeRange(range, index)} + /> + )} + + ); + } + } return (
@@ -87,7 +118,7 @@ export const QueryWrapper: FC = ({ onAddQuery={() => onDuplicateQuery(cloneDeep(query))} onRunQuery={onRunQueries} queries={queries} - renderHeaderExtras={() => renderTimePicker(query, index)} + renderHeaderExtras={() => } app={CoreApp.UnifiedAlerting} visualization={ data.state !== LoadingState.NotStarted ? ( @@ -118,4 +149,13 @@ const getStyles = (theme: GrafanaTheme2) => ({ border: 1px solid ${theme.colors.border.medium}; border-radius: ${theme.shape.borderRadius(1)}; `, + dsTooltip: css` + display: flex; + align-items: center; + margin-right: ${theme.spacing(2)}; + &:hover { + opacity: 0.85; + cursor: pointer; + } + `, }); diff --git a/public/app/features/datasources/components/BasicSettings.tsx b/public/app/features/datasources/components/BasicSettings.tsx index bd99284cb29..bdcf896f3da 100644 --- a/public/app/features/datasources/components/BasicSettings.tsx +++ b/public/app/features/datasources/components/BasicSettings.tsx @@ -1,7 +1,10 @@ +import { css } from '@emotion/css'; import React from 'react'; +import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { InlineField, InlineSwitch, Input } from '@grafana/ui'; +import { getDataSourceSrv } from '@grafana/runtime'; +import { InlineField, InlineSwitch, Input, Badge, useStyles2 } from '@grafana/ui'; export interface Props { dataSourceName: string; @@ -11,40 +14,65 @@ export interface Props { } export function BasicSettings({ dataSourceName, isDefault, onDefaultChange, onNameChange }: Props) { + const ds = getDataSourceSrv()?.getInstanceSettings(dataSourceName); + const hasAlertingEnabled = Boolean(ds?.meta?.alerting ?? false); + return ( -
-
- {/* Name */} -
- +
+ {/* Name */} +
+ - onNameChange(event.currentTarget.value)} - required - aria-label={selectors.pages.DataSource.name} + grow + > + onNameChange(event.currentTarget.value)} + required + aria-label={selectors.pages.DataSource.name} + /> + +
+ + {/* Is Default */} + + ) => { + onDefaultChange(event.currentTarget.checked); + }} />
- - {/* Is Default */} - - ) => { - onDefaultChange(event.currentTarget.checked); - }} - /> -
+ + ); +} + +export function AlertingEnabled({ enabled }: { enabled: boolean }) { + const styles = useStyles2(getStyles); + return ( +
+ {enabled ? ( + + ) : ( + + )}
); } + +const getStyles = (theme: GrafanaTheme2) => ({ + badge: css` + margin-bottom: ${theme.spacing(2)}; + `, +});