diff --git a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx index 146b21f9e68..c5d2e188c34 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx @@ -180,8 +180,7 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => { text-overflow: ellipsis; `, content: css` - margin-top: ${theme.spacing.inlineFormMargin}; - margin-left: ${theme.spacing.lg}; + margin: ${theme.spacing.md}; `, disabled: css` color: ${theme.colors.textWeak}; diff --git a/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx b/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx index 1bd3a6598f1..9db88e23170 100644 --- a/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx @@ -1,4 +1,4 @@ -import React, { PureComponent } from 'react'; +import React, { PureComponent, useState } from 'react'; import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd'; import { DataQuery, @@ -10,10 +10,13 @@ import { ThresholdsMode, } from '@grafana/data'; import { config, getDataSourceSrv } from '@grafana/runtime'; -import { QueryWrapper } from './QueryWrapper'; -import { AlertQuery } from 'app/types/unified-alerting-dto'; +import { EmptyQueryWrapper, QueryWrapper } from './QueryWrapper'; +import { AlertDataQuery, AlertQuery } from 'app/types/unified-alerting-dto'; import { isExpressionQuery } from 'app/features/expressions/guards'; import { queriesWithUpdatedReferences } from './util'; +import { Button, Card, Icon } from '@grafana/ui'; +import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow'; +import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; interface Props { // The query configuration @@ -100,30 +103,26 @@ export class QueryRows extends PureComponent { onChangeDataSource = (settings: DataSourceInstanceSettings, index: number) => { const { queries, onQueriesChange } = this.props; - onQueriesChange( - queries.map((item, itemIndex) => { - if (itemIndex !== index) { - return item; - } + const updatedQueries = queries.map((item, itemIndex) => { + if (itemIndex !== index) { + return item; + } - const previous = getDataSourceSrv().getInstanceSettings(item.datasourceUid); - - if (previous?.type === settings.uid) { - return { - ...item, - datasourceUid: settings.uid, - }; - } - - const { refId, hide } = item.model; + const previous = getDataSourceSrv().getInstanceSettings(item.datasourceUid); + if (previous?.type === settings.uid) { return { ...item, datasourceUid: settings.uid, - model: { refId, hide }, }; - }) - ); + } + + return { + ...item, + datasourceUid: settings.uid, + }; + }); + onQueriesChange(updatedQueries); }; onChangeQuery = (query: DataQuery, index: number) => { @@ -245,8 +244,24 @@ export class QueryRows extends PureComponent { const dsSettings = this.getDataSourceSettings(query); if (!dsSettings) { - return null; + return ( + { + const defaultDataSource = getDatasourceSrv().getInstanceSettings(null); + if (defaultDataSource) { + this.onChangeDataSource(defaultDataSource, index); + } + }} + onRemoveQuery={() => { + this.onRemoveQuery(query); + }} + /> + ); } + return ( { ); } } + +interface DatasourceNotFoundProps { + index: number; + model: AlertDataQuery; + onUpdateDatasource: () => void; + onRemoveQuery: () => void; +} + +const DatasourceNotFound = ({ index, onUpdateDatasource, onRemoveQuery, model }: DatasourceNotFoundProps) => { + const refId = model.refId; + + const [showDetails, setShowDetails] = useState(false); + + const toggleDetails = () => { + setShowDetails((show) => !show); + }; + + const handleUpdateDatasource = () => { + onUpdateDatasource(); + }; + + return ( + + + + + + + + + + + + + + + {showDetails && ( +
+
+              {JSON.stringify(model, null, 2)}
+            
+
+ )} +
+
+ ); +}; diff --git a/public/app/features/alerting/unified/components/rule-editor/QueryStep.tsx b/public/app/features/alerting/unified/components/rule-editor/QueryStep.tsx index a77c592c4d6..e55f4d5d549 100644 --- a/public/app/features/alerting/unified/components/rule-editor/QueryStep.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/QueryStep.tsx @@ -14,6 +14,7 @@ export const QueryStep: FC = () => { } = useFormContext(); const type = watch('type'); const dataSourceName = watch('dataSourceName'); + return ( = ({ ); }; +export const EmptyQueryWrapper: FC<{}> = ({ children }) => { + const styles = useStyles2(getStyles); + return
{children}
; +}; + const getStyles = (theme: GrafanaTheme2) => ({ wrapper: css` label: AlertingQueryWrapper; margin-bottom: ${theme.spacing(1)}; border: 1px solid ${theme.colors.border.medium}; border-radius: ${theme.shape.borderRadius(1)}; - padding-bottom: ${theme.spacing(1)}; `, }); diff --git a/public/app/types/unified-alerting-dto.ts b/public/app/types/unified-alerting-dto.ts index 94ffff70b43..155ff4f9790 100644 --- a/public/app/types/unified-alerting-dto.ts +++ b/public/app/types/unified-alerting-dto.ts @@ -102,7 +102,7 @@ export enum GrafanaAlertStateDecision { Error = 'Error', } -interface AlertDataQuery extends DataQuery { +export interface AlertDataQuery extends DataQuery { maxDataPoints?: number; intervalMs?: number; }