Annotations: Disable "Add annotation" button when annotations are disabled (#57481)

This commit is contained in:
Ryan McKinley
2022-10-24 13:24:33 -07:00
committed by GitHub
parent e59ddd6bc5
commit 37b011d79e
4 changed files with 60 additions and 16 deletions

View File

@@ -121,9 +121,11 @@ export const AnnotationSettingsEdit = ({ editIdx, dashboard }: Props) => {
{ds && !ds.annotations && <AngularEditorLoader datasource={ds} annotation={annotation} onChange={onUpdate} />} {ds && !ds.annotations && <AngularEditorLoader datasource={ds} annotation={annotation} onChange={onUpdate} />}
</FieldSet> </FieldSet>
<Stack> <Stack>
<Button variant="destructive" onClick={onDelete}> {!annotation.builtIn && (
Delete <Button variant="destructive" onClick={onDelete}>
</Button> Delete
</Button>
)}
<Button variant="secondary" onClick={onPreview}> <Button variant="secondary" onClick={onPreview}>
Preview in dashboard Preview in dashboard
</Button> </Button>

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { arrayUtils } from '@grafana/data'; import { arrayUtils, AnnotationQuery } from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime'; import { getDataSourceSrv } from '@grafana/runtime';
import { DeleteButton, Icon, IconButton, VerticalGroup } from '@grafana/ui'; import { DeleteButton, Icon, IconButton, VerticalGroup } from '@grafana/ui';
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
@@ -29,6 +29,30 @@ export const AnnotationSettingsList = ({ dashboard, onNew, onEdit }: Props) => {
const showEmptyListCTA = annotations.length === 0 || (annotations.length === 1 && annotations[0].builtIn); const showEmptyListCTA = annotations.length === 0 || (annotations.length === 1 && annotations[0].builtIn);
const getAnnotationName = (anno: AnnotationQuery) => {
if (anno.enable === false) {
return (
<>
<Icon name="times" /> &nbsp;<em className="muted">(Disabled) &nbsp; {anno.name}</em>
</>
);
}
if (anno.builtIn) {
return (
<>
<Icon name="comment-alt" /> &nbsp;<em className="muted">{anno.name} (Built-in)</em>
</>
);
}
return (
<>
<Icon name="comment-alt" /> &nbsp;{anno.name}
</>
);
};
const dataSourceSrv = getDataSourceSrv(); const dataSourceSrv = getDataSourceSrv();
return ( return (
<VerticalGroup> <VerticalGroup>
@@ -46,11 +70,11 @@ export const AnnotationSettingsList = ({ dashboard, onNew, onEdit }: Props) => {
<tr key={`${annotation.name}-${idx}`}> <tr key={`${annotation.name}-${idx}`}>
{annotation.builtIn ? ( {annotation.builtIn ? (
<td style={{ width: '90%' }} className="pointer" onClick={() => onEdit(idx)}> <td style={{ width: '90%' }} className="pointer" onClick={() => onEdit(idx)}>
<Icon name="comment-alt" /> &nbsp; <em className="muted">{annotation.name} (Built-in)</em> {getAnnotationName(annotation)}
</td> </td>
) : ( ) : (
<td className="pointer" onClick={() => onEdit(idx)}> <td className="pointer" onClick={() => onEdit(idx)}>
<Icon name="comment-alt" /> &nbsp; {annotation.name} {getAnnotationName(annotation)}
</td> </td>
)} )}
<td className="pointer" onClick={() => onEdit(idx)}> <td className="pointer" onClick={() => onEdit(idx)}>
@@ -65,11 +89,13 @@ export const AnnotationSettingsList = ({ dashboard, onNew, onEdit }: Props) => {
) : null} ) : null}
</td> </td>
<td style={{ width: '1%' }}> <td style={{ width: '1%' }}>
<DeleteButton {!annotation.builtIn && (
size="sm" <DeleteButton
onConfirm={() => onDelete(idx)} size="sm"
aria-label={`Delete query with title "${annotation.name}"`} onConfirm={() => onDelete(idx)}
/> aria-label={`Delete query with title "${annotation.name}"`}
/>
)}
</td> </td>
</tr> </tr>
))} ))}

View File

@@ -230,11 +230,23 @@ describe('AnnotationsSettings', () => {
}); });
test('Deleting annotation', async () => { test('Deleting annotation', async () => {
setup(dashboard, 0); dashboard.annotations.list = [
...dashboard.annotations.list,
{
builtIn: 0,
datasource: { uid: 'uid3', type: 'prometheus' },
enable: true,
hide: true,
iconColor: 'rgba(0, 211, 255, 1)',
name: 'Annotation 2',
type: 'dashboard',
},
];
setup(dashboard, 1); // Edit the not built-in annotations
await userEvent.click(screen.getByRole('button', { name: 'Delete' })); await userEvent.click(screen.getByRole('button', { name: 'Delete' }));
expect(locationService.getSearchObject().editIndex).toBe(undefined); expect(locationService.getSearchObject().editIndex).toBe(undefined);
expect(dashboard.annotations.list.length).toBe(0); expect(dashboard.annotations.list.length).toBe(1); // started with two
}); });
}); });

View File

@@ -1114,10 +1114,14 @@ export class DashboardModel implements TimeModel {
} }
canAddAnnotations() { canAddAnnotations() {
// If RBAC is enabled there are additional conditions to check. // When the builtin annotations are disabled, we should not add any in the UI
const canAdd = !contextSrv.accessControlEnabled() || Boolean(this.meta.annotationsPermissions?.dashboard.canAdd); const found = this.annotations.list.find((item) => item.builtIn === 1);
if (found?.enable === false || !this.canEditDashboard()) {
return false;
}
return this.canEditDashboard() && canAdd; // If RBAC is enabled there are additional conditions to check.
return !contextSrv.accessControlEnabled() || Boolean(this.meta.annotationsPermissions?.dashboard.canAdd);
} }
canEditDashboard() { canEditDashboard() {