Alerting: show deleted datasource (#43891)

This commit is contained in:
Gilles De Mey 2022-01-17 14:30:00 +01:00 committed by GitHub
parent f6b70e0a69
commit bd9df4f829
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 109 additions and 26 deletions

View File

@ -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};

View File

@ -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<Props, State> {
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<Props, State> {
const dsSettings = this.getDataSourceSettings(query);
if (!dsSettings) {
return null;
return (
<DatasourceNotFound
key={`${query.refId}-${index}`}
index={index}
model={query.model}
onUpdateDatasource={() => {
const defaultDataSource = getDatasourceSrv().getInstanceSettings(null);
if (defaultDataSource) {
this.onChangeDataSource(defaultDataSource, index);
}
}}
onRemoveQuery={() => {
this.onRemoveQuery(query);
}}
/>
);
}
return (
<QueryWrapper
index={index}
@ -275,3 +290,67 @@ export class QueryRows extends PureComponent<Props, State> {
);
}
}
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<boolean>(false);
const toggleDetails = () => {
setShowDetails((show) => !show);
};
const handleUpdateDatasource = () => {
onUpdateDatasource();
};
return (
<EmptyQueryWrapper>
<QueryOperationRow title={refId} draggable index={index} id={refId} isOpen>
<Card
heading="This datasource has been removed"
description={
'The datasource for this query was not found, it was either removed or is not installed correctly.'
}
>
<Card.Figure>
<Icon name="question-circle" />
</Card.Figure>
<Card.Actions>
<Button key="update" variant="secondary" onClick={handleUpdateDatasource}>
Update datasource
</Button>
<Button key="remove" variant="destructive" onClick={onRemoveQuery}>
Remove query
</Button>
</Card.Actions>
<Card.SecondaryActions>
<Button
key="details"
onClick={toggleDetails}
icon={showDetails ? 'angle-up' : 'angle-down'}
fill="text"
size="sm"
>
Show details
</Button>
</Card.SecondaryActions>
</Card>
{showDetails && (
<div>
<pre>
<code>{JSON.stringify(model, null, 2)}</code>
</pre>
</div>
)}
</QueryOperationRow>
</EmptyQueryWrapper>
);
};

View File

@ -14,6 +14,7 @@ export const QueryStep: FC = () => {
} = useFormContext<RuleFormValues>();
const type = watch('type');
const dataSourceName = watch('dataSourceName');
return (
<RuleEditorSection
stepNo={2}

View File

@ -103,12 +103,16 @@ export const QueryWrapper: FC<Props> = ({
);
};
export const EmptyQueryWrapper: FC<{}> = ({ children }) => {
const styles = useStyles2(getStyles);
return <div className={styles.wrapper}>{children}</div>;
};
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)};
`,
});

View File

@ -102,7 +102,7 @@ export enum GrafanaAlertStateDecision {
Error = 'Error',
}
interface AlertDataQuery extends DataQuery {
export interface AlertDataQuery extends DataQuery {
maxDataPoints?: number;
intervalMs?: number;
}