mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Use monaco editor for admin page (#69514)
This commit is contained in:
@@ -78,7 +78,7 @@ const ui = {
|
||||
confirmButton: byRole('button', { name: /Yes, reset configuration/ }),
|
||||
resetButton: byRole('button', { name: /Reset configuration/ }),
|
||||
saveButton: byRole('button', { name: /Save/ }),
|
||||
configInput: byLabelText<HTMLTextAreaElement>(/Configuration/),
|
||||
configInput: byLabelText(/Code editor container/),
|
||||
readOnlyConfig: byTestId('readonly-config'),
|
||||
};
|
||||
|
||||
@@ -107,37 +107,29 @@ describe('Admin config', () => {
|
||||
expect(ui.confirmButton.query()).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Edit and save alertmanager config', async () => {
|
||||
it('Editable alertmanager config', async () => {
|
||||
let savedConfig: AlertManagerCortexConfig | undefined = undefined;
|
||||
|
||||
const defaultConfig = {
|
||||
template_files: {
|
||||
foo: 'bar',
|
||||
template_files: {},
|
||||
alertmanager_config: {
|
||||
route: {
|
||||
receiver: 'old one',
|
||||
},
|
||||
},
|
||||
alertmanager_config: {},
|
||||
};
|
||||
|
||||
const newConfig = {
|
||||
template_files: {
|
||||
bar: 'baz',
|
||||
},
|
||||
alertmanager_config: {},
|
||||
};
|
||||
|
||||
mocks.api.fetchConfig.mockImplementation(() => Promise.resolve(savedConfig ?? defaultConfig));
|
||||
mocks.api.updateAlertManagerConfig.mockResolvedValue();
|
||||
renderAdminPage(dataSources.alertManager.name);
|
||||
const input = await ui.configInput.find();
|
||||
expect(input.value).toEqual(JSON.stringify(defaultConfig, null, 2));
|
||||
await userEvent.clear(input);
|
||||
// What is this regex replace doing? in userEvent v13, '{' and '[' are special characters.
|
||||
// To get the literal character, you have to escape them by typing '{{' or '[['.
|
||||
// See https://github.com/testing-library/user-event/issues/584.
|
||||
await userEvent.type(input, JSON.stringify(newConfig, null, 2).replace(/[{[]/g, '$&$&'));
|
||||
|
||||
await ui.configInput.find();
|
||||
await userEvent.click(ui.saveButton.get());
|
||||
|
||||
await waitFor(() => expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalled());
|
||||
expect(mocks.api.updateAlertManagerConfig.mock.lastCall).toMatchSnapshot();
|
||||
|
||||
await waitFor(() => expect(mocks.api.fetchConfig).toHaveBeenCalledTimes(3));
|
||||
expect(input.value).toEqual(JSON.stringify(newConfig, null, 2));
|
||||
});
|
||||
|
||||
it('Read-only when using Prometheus Alertmanager', async () => {
|
||||
@@ -148,7 +140,6 @@ describe('Admin config', () => {
|
||||
renderAdminPage(dataSources.promAlertManager.name);
|
||||
|
||||
await ui.readOnlyConfig.find();
|
||||
expect(ui.configInput.query()).not.toBeInTheDocument();
|
||||
expect(ui.resetButton.query()).not.toBeInTheDocument();
|
||||
expect(ui.saveButton.query()).not.toBeInTheDocument();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Button, ConfirmModal, Field, Form, HorizontalGroup, TextArea } from '@grafana/ui';
|
||||
import { Button, CodeEditor, ConfirmModal, Field, Form, HorizontalGroup } from '@grafana/ui';
|
||||
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
|
||||
@@ -31,33 +31,46 @@ export const ConfigEditor = ({
|
||||
}: ConfigEditorProps) => {
|
||||
return (
|
||||
<Form defaultValues={defaultValues} onSubmit={onSubmit} key={defaultValues.configJSON}>
|
||||
{({ register, errors }) => (
|
||||
<>
|
||||
{!readOnly && (
|
||||
<>
|
||||
<Field
|
||||
disabled={loading}
|
||||
label="Configuration"
|
||||
invalid={!!errors.configJSON}
|
||||
error={errors.configJSON?.message}
|
||||
>
|
||||
<TextArea
|
||||
{...register('configJSON', {
|
||||
required: { value: true, message: 'Required.' },
|
||||
validate: (v) => {
|
||||
try {
|
||||
JSON.parse(v);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return e instanceof Error ? e.message : 'Invalid JSON.';
|
||||
}
|
||||
},
|
||||
})}
|
||||
id="configuration"
|
||||
rows={25}
|
||||
/>
|
||||
</Field>
|
||||
{({ errors, setValue, register }) => {
|
||||
register('configJSON', {
|
||||
required: { value: true, message: 'Required' },
|
||||
validate: (value: string) => {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return e instanceof Error ? e.message : 'JSON is invalid';
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Field
|
||||
disabled={loading}
|
||||
label="Configuration"
|
||||
invalid={!!errors.configJSON}
|
||||
error={errors.configJSON?.message}
|
||||
data-testid={readOnly ? 'readonly-config' : 'config'}
|
||||
>
|
||||
<CodeEditor
|
||||
language="json"
|
||||
width="100%"
|
||||
height={500}
|
||||
showLineNumbers={true}
|
||||
value={defaultValues.configJSON}
|
||||
showMiniMap={false}
|
||||
onSave={(value) => {
|
||||
setValue('configJSON', value);
|
||||
}}
|
||||
onBlur={(value) => {
|
||||
setValue('configJSON', value);
|
||||
}}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
{!readOnly && (
|
||||
<HorizontalGroup>
|
||||
<Button type="submit" variant="primary" disabled={loading}>
|
||||
Save configuration
|
||||
@@ -68,29 +81,25 @@ export const ConfigEditor = ({
|
||||
</Button>
|
||||
)}
|
||||
</HorizontalGroup>
|
||||
</>
|
||||
)}
|
||||
{readOnly && (
|
||||
<Field label="Configuration">
|
||||
<pre data-testid="readonly-config">{defaultValues.configJSON}</pre>
|
||||
</Field>
|
||||
)}
|
||||
{Boolean(showConfirmDeleteAMConfig) && onConfirmReset && onDismiss && (
|
||||
<ConfirmModal
|
||||
isOpen={true}
|
||||
title="Reset Alertmanager configuration"
|
||||
body={`Are you sure you want to reset configuration ${
|
||||
alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME
|
||||
? 'for the Grafana Alertmanager'
|
||||
: `for "${alertManagerSourceName}"`
|
||||
}? Contact points and notification policies will be reset to their defaults.`}
|
||||
confirmText="Yes, reset configuration"
|
||||
onConfirm={onConfirmReset}
|
||||
onDismiss={onDismiss}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
)}
|
||||
|
||||
{Boolean(showConfirmDeleteAMConfig) && onConfirmReset && onDismiss && (
|
||||
<ConfirmModal
|
||||
isOpen={true}
|
||||
title="Reset Alertmanager configuration"
|
||||
body={`Are you sure you want to reset configuration ${
|
||||
alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME
|
||||
? 'for the Grafana Alertmanager'
|
||||
: `for "${alertManagerSourceName}"`
|
||||
}? Contact points and notification policies will be reset to their defaults.`}
|
||||
confirmText="Yes, reset configuration"
|
||||
onConfirm={onConfirmReset}
|
||||
onDismiss={onDismiss}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Admin config Editable alertmanager config 1`] = `
|
||||
[
|
||||
"CloudManager",
|
||||
{
|
||||
"alertmanager_config": {
|
||||
"receivers": [
|
||||
{
|
||||
"name": "default ",
|
||||
},
|
||||
],
|
||||
"route": {
|
||||
"receiver": "old one",
|
||||
},
|
||||
},
|
||||
"template_files": {},
|
||||
},
|
||||
]
|
||||
`;
|
||||
Reference in New Issue
Block a user