Alerting: Fix notification templates layout (#101232)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { Route, Routes } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import DuplicateMessageTemplate from './components/contact-points/DuplicateMessageTemplate';
|
||||
import EditMessageTemplate from './components/contact-points/EditMessageTemplate';
|
||||
import NewMessageTemplate from './components/contact-points/NewMessageTemplate';
|
||||
@@ -8,21 +7,11 @@ import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
function NotificationTemplates() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: 'Notification templates',
|
||||
subTitle: 'Create and edit a group of notification templates',
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route path=":name/edit" element={<EditMessageTemplate />} />
|
||||
<Route path="new" element={<NewMessageTemplate />} />
|
||||
<Route path=":name/duplicate" element={<DuplicateMessageTemplate />} />
|
||||
</Routes>
|
||||
</AlertmanagerPageWrapper>
|
||||
<Routes>
|
||||
<Route path="new" element={<NewMessageTemplate />} />
|
||||
<Route path=":name/edit" element={<EditMessageTemplate />} />
|
||||
<Route path=":name/duplicate" element={<DuplicateMessageTemplate />} />
|
||||
</Routes>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+33
-6
@@ -2,16 +2,19 @@ import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { Alert, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
import { isNotFoundError } from '../../api/util';
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { generateCopiedName } from '../../utils/duplicate';
|
||||
import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { updateDefinesWithUniqueValue } from '../../utils/templates';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
import { ActiveTab } from './ContactPoints';
|
||||
import { useGetNotificationTemplate, useNotificationTemplates } from './useNotificationTemplates';
|
||||
|
||||
const notFoundComponent = <EntityNotFound entity="Notification template" />;
|
||||
@@ -23,16 +26,19 @@ const DuplicateMessageTemplateComponent = () => {
|
||||
|
||||
const {
|
||||
currentData: template,
|
||||
isLoading,
|
||||
error,
|
||||
isLoading: isLoadingTemplate,
|
||||
error: templateFetchError,
|
||||
} = useGetNotificationTemplate({ alertmanager: selectedAlertmanager ?? '', uid: templateUid ?? '' });
|
||||
|
||||
const {
|
||||
currentData: templates,
|
||||
isLoading: templatesLoading,
|
||||
error: templatesError,
|
||||
error: templatesFetchError,
|
||||
} = useNotificationTemplates({ alertmanager: selectedAlertmanager ?? '' });
|
||||
|
||||
const isLoading = isLoadingTemplate || templatesLoading;
|
||||
const error = templateFetchError || templatesFetchError;
|
||||
|
||||
if (!selectedAlertmanager) {
|
||||
return <EntityNotFound entity="Alertmanager" />;
|
||||
}
|
||||
@@ -41,11 +47,11 @@ const DuplicateMessageTemplateComponent = () => {
|
||||
return <EntityNotFound entity="Notification template" />;
|
||||
}
|
||||
|
||||
if (isLoading || templatesLoading) {
|
||||
if (isLoading) {
|
||||
return <LoadingPlaceholder text="Loading notification template" />;
|
||||
}
|
||||
|
||||
if (error || templatesError || !template || !templates) {
|
||||
if (error) {
|
||||
return isNotFoundError(error) ? (
|
||||
notFoundComponent
|
||||
) : (
|
||||
@@ -55,6 +61,10 @@ const DuplicateMessageTemplateComponent = () => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!template) {
|
||||
return notFoundComponent;
|
||||
}
|
||||
|
||||
const duplicatedName = generateCopiedName(template.title, templates?.map((t) => t.title) ?? []);
|
||||
|
||||
return (
|
||||
@@ -67,7 +77,24 @@ const DuplicateMessageTemplateComponent = () => {
|
||||
|
||||
function DuplicateMessageTemplate() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: t('alerting.notification-templates.duplicate.title', 'Duplicate notification template group'),
|
||||
subTitle: t(
|
||||
'alerting.notification-templates.duplicate.subTitle',
|
||||
'Duplicate a group of notification templates'
|
||||
),
|
||||
parentItem: {
|
||||
text: t('alerting.common.titles.notification-templates', 'Notification Templates'),
|
||||
url: createRelativeUrl('/alerting/notifications', {
|
||||
tab: ActiveTab.NotificationTemplates,
|
||||
}),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DuplicateMessageTemplateComponent />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
|
||||
+20
-3
@@ -2,14 +2,17 @@ import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { Alert, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
import { isNotFoundError } from '../../api/util';
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
import { ActiveTab } from './ContactPoints';
|
||||
import { useGetNotificationTemplate } from './useNotificationTemplates';
|
||||
|
||||
const notFoundComponent = <EntityNotFound entity="Notification template" />;
|
||||
@@ -19,7 +22,7 @@ const EditMessageTemplateComponent = () => {
|
||||
const templateUid = name ? decodeURIComponent(name) : undefined;
|
||||
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
const { currentData, isLoading, error } = useGetNotificationTemplate({
|
||||
const { currentData, isLoading, error, isUninitialized } = useGetNotificationTemplate({
|
||||
alertmanager: selectedAlertmanager ?? '',
|
||||
uid: templateUid ?? '',
|
||||
});
|
||||
@@ -28,7 +31,7 @@ const EditMessageTemplateComponent = () => {
|
||||
return <EntityNotFound entity="Notification template" />;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
if (isLoading || isUninitialized) {
|
||||
return <LoadingPlaceholder text="Loading template..." />;
|
||||
}
|
||||
|
||||
@@ -51,7 +54,21 @@ const EditMessageTemplateComponent = () => {
|
||||
|
||||
function EditMessageTemplate() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: t('alerting.notification-templates.edit.title', 'Edit notification template group'),
|
||||
subTitle: t('alerting.notification-templates.edit.subTitle', 'Edit a group of notification templates'),
|
||||
parentItem: {
|
||||
text: t('alerting.common.titles.notification-templates', 'Notification Templates'),
|
||||
url: createRelativeUrl('/alerting/notifications', {
|
||||
tab: ActiveTab.NotificationTemplates,
|
||||
}),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<EditMessageTemplateComponent />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
|
||||
+27
-5
@@ -1,16 +1,38 @@
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
function NewMessageTemplate() {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
import { ActiveTab } from './ContactPoints';
|
||||
|
||||
function NewMessageTemplatePage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<TemplateForm alertmanager={selectedAlertmanager ?? ''} />
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: t('alerting.notification-templates.new.title', 'New notification template group'),
|
||||
subTitle: t('alerting.notification-templates.new.subTitle', 'Create a new group of notification templates'),
|
||||
parentItem: {
|
||||
text: t('alerting.common.titles.notification-templates', 'Notification Templates'),
|
||||
url: createRelativeUrl('/alerting/notifications', {
|
||||
tab: ActiveTab.NotificationTemplates,
|
||||
}),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<NewMessageTemplate />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(NewMessageTemplate);
|
||||
function NewMessageTemplate() {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
return <TemplateForm alertmanager={selectedAlertmanager ?? ''} />;
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(NewMessageTemplatePage);
|
||||
|
||||
@@ -25,17 +25,14 @@ import {
|
||||
useStyles2,
|
||||
} from '@grafana/ui';
|
||||
import { useAppNotification } from 'app/core/copy/appNotification';
|
||||
import { useCleanup } from 'app/core/hooks/useCleanup';
|
||||
import { Trans, t } from 'app/core/internationalization';
|
||||
import { ActiveTab as ContactPointsActiveTabs } from 'app/features/alerting/unified/components/contact-points/ContactPoints';
|
||||
import { TestTemplateAlert } from 'app/plugins/datasource/alertmanager/types';
|
||||
|
||||
import { AppChromeUpdate } from '../../../../../core/components/AppChrome/AppChromeUpdate';
|
||||
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { makeAMLink, stringifyErrorLike } from '../../utils/misc';
|
||||
import { initialAsyncRequestState } from '../../utils/redux';
|
||||
import { ProvisionedResource, ProvisioningAlert } from '../Provisioning';
|
||||
import { Spacer } from '../Spacer';
|
||||
import { EditorColumnHeader } from '../contact-points/templates/EditorColumnHeader';
|
||||
import {
|
||||
NotificationTemplate,
|
||||
@@ -95,15 +92,14 @@ export const TemplateForm = ({ originalTemplate, prefill, alertmanager }: Props)
|
||||
|
||||
const appNotification = useAppNotification();
|
||||
|
||||
const [createNewTemplate] = useCreateNotificationTemplate({ alertmanager });
|
||||
const [updateTemplate] = useUpdateNotificationTemplate({ alertmanager });
|
||||
const [createNewTemplate, { error: createTemplateError }] = useCreateNotificationTemplate({ alertmanager });
|
||||
const [updateTemplate, { error: updateTemplateError }] = useUpdateNotificationTemplate({ alertmanager });
|
||||
const { titleIsUnique } = useValidateNotificationTemplate({ alertmanager, originalTemplate });
|
||||
|
||||
useCleanup((state) => (state.unifiedAlerting.saveAMConfig = initialAsyncRequestState));
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const isGrafanaAlertManager = alertmanager === GRAFANA_RULES_SOURCE_NAME;
|
||||
|
||||
const { error } = useUnifiedAlertingSelector((state) => state.saveAMConfig);
|
||||
const error = updateTemplateError ?? createTemplateError;
|
||||
|
||||
const [cheatsheetOpened, toggleCheatsheetOpened] = useToggle(false);
|
||||
|
||||
@@ -168,28 +164,9 @@ export const TemplateForm = ({ originalTemplate, prefill, alertmanager }: Props)
|
||||
setValue('content', newValue);
|
||||
};
|
||||
|
||||
const actionButtons = (
|
||||
<Stack>
|
||||
<Button onClick={() => formRef.current?.requestSubmit()} variant="primary" size="sm" disabled={isSubmitting}>
|
||||
<Trans i18nKey="common.save">Save</Trans>
|
||||
</Button>
|
||||
<LinkButton
|
||||
disabled={isSubmitting}
|
||||
href={makeAMLink('alerting/notifications', alertmanager, {
|
||||
tab: ContactPointsActiveTabs.NotificationTemplates,
|
||||
})}
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
>
|
||||
<Trans i18nKey="common.cancel">Cancel</Trans>
|
||||
</LinkButton>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormProvider {...formApi}>
|
||||
<AppChromeUpdate actions={actionButtons} />
|
||||
<form onSubmit={handleSubmit(submit)} ref={formRef} className={styles.form} aria-label="Template form">
|
||||
{/* error message */}
|
||||
{error && (
|
||||
@@ -206,136 +183,155 @@ export const TemplateForm = ({ originalTemplate, prefill, alertmanager }: Props)
|
||||
|
||||
{/* name field for the template */}
|
||||
<FieldSet disabled={isProvisioned} className={styles.fieldset}>
|
||||
<InlineField
|
||||
label="Template group name"
|
||||
error={errors?.title?.message}
|
||||
invalid={!!errors.title?.message}
|
||||
required
|
||||
className={styles.nameField}
|
||||
>
|
||||
<Input
|
||||
{...register('title', {
|
||||
required: { value: true, message: 'Required.' },
|
||||
validate: { titleIsUnique },
|
||||
})}
|
||||
placeholder="Give your template group a name"
|
||||
width={42}
|
||||
autoFocus={true}
|
||||
id="new-template-name"
|
||||
/>
|
||||
</InlineField>
|
||||
<Stack direction="column" gap={1} alignItems="stretch" minHeight="100%">
|
||||
{/* name and save buttons */}
|
||||
<Stack direction="row" alignItems="center">
|
||||
<InlineField
|
||||
label="Template group name"
|
||||
error={errors?.title?.message}
|
||||
invalid={!!errors.title?.message}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
{...register('title', {
|
||||
required: { value: true, message: 'Required.' },
|
||||
validate: { titleIsUnique },
|
||||
})}
|
||||
placeholder="Give your template group a name"
|
||||
width={42}
|
||||
autoFocus={true}
|
||||
id="new-template-name"
|
||||
/>
|
||||
</InlineField>
|
||||
<Spacer />
|
||||
<Stack>
|
||||
<Button onClick={() => formRef.current?.requestSubmit()} variant="primary" disabled={isSubmitting}>
|
||||
<Trans i18nKey="common.save">Save</Trans>
|
||||
</Button>
|
||||
<LinkButton
|
||||
disabled={isSubmitting}
|
||||
href={makeAMLink('alerting/notifications', alertmanager, {
|
||||
tab: ContactPointsActiveTabs.NotificationTemplates,
|
||||
})}
|
||||
variant="secondary"
|
||||
>
|
||||
<Trans i18nKey="common.cancel">Cancel</Trans>
|
||||
</LinkButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* editor layout */}
|
||||
<div {...rowSplitter.containerProps} className={styles.contentContainer}>
|
||||
<div {...rowSplitter.primaryProps}>
|
||||
{/* template content and payload editor column – full height and half-width */}
|
||||
<div {...columnSplitter.containerProps} className={styles.contentField}>
|
||||
{/* template editor */}
|
||||
<div {...columnSplitter.primaryProps}>
|
||||
{/* primaryProps will set "minHeight: min-content;" so we have to make sure to apply minHeight to the child */}
|
||||
<div className={cx(styles.flexColumn, styles.containerWithBorderAndRadius, styles.minEditorSize)}>
|
||||
<div>
|
||||
<EditorColumnHeader
|
||||
label="Template group"
|
||||
actions={
|
||||
<>
|
||||
{/* examples dropdown – only available for Grafana Alertmanager */}
|
||||
{isGrafanaAlertManager && (
|
||||
<Dropdown
|
||||
overlay={
|
||||
<Menu>
|
||||
{GlobalTemplateDataExamples.map((item, index) => (
|
||||
{/* editor layout */}
|
||||
<div {...rowSplitter.containerProps} className={styles.contentContainer}>
|
||||
<div {...rowSplitter.primaryProps}>
|
||||
{/* template content and payload editor column – full height and half-width */}
|
||||
<div {...columnSplitter.containerProps} className={styles.contentField}>
|
||||
{/* template editor */}
|
||||
<div {...columnSplitter.primaryProps}>
|
||||
{/* primaryProps will set "minHeight: min-content;" so we have to make sure to apply minHeight to the child */}
|
||||
<div className={cx(styles.flexColumn, styles.containerWithBorderAndRadius, styles.minEditorSize)}>
|
||||
<div>
|
||||
<EditorColumnHeader
|
||||
label="Template group"
|
||||
actions={
|
||||
<>
|
||||
{/* examples dropdown – only available for Grafana Alertmanager */}
|
||||
{isGrafanaAlertManager && (
|
||||
<Dropdown
|
||||
overlay={
|
||||
<Menu>
|
||||
{GlobalTemplateDataExamples.map((item, index) => (
|
||||
<Menu.Item
|
||||
key={index}
|
||||
label={item.description}
|
||||
onClick={() => appendExample(item.example)}
|
||||
/>
|
||||
))}
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key={index}
|
||||
label={item.description}
|
||||
onClick={() => appendExample(item.example)}
|
||||
label={'Examples documentation'}
|
||||
url="https://grafana.com/docs/grafana/latest/alerting/configure-notifications/template-notifications/examples/"
|
||||
target="_blank"
|
||||
icon="external-link-alt"
|
||||
/>
|
||||
))}
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
label={'Examples documentation'}
|
||||
url="https://grafana.com/docs/grafana/latest/alerting/configure-notifications/template-notifications/examples/"
|
||||
target="_blank"
|
||||
icon="external-link-alt"
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button variant="secondary" size="sm" icon="angle-down">
|
||||
<Trans i18nKey="alerting.templates.editor.add-example">Add example</Trans>
|
||||
</Button>
|
||||
</Dropdown>
|
||||
)}
|
||||
<Button
|
||||
icon="question-circle"
|
||||
size="sm"
|
||||
fill="outline"
|
||||
variant="secondary"
|
||||
onClick={toggleCheatsheetOpened}
|
||||
>
|
||||
<Button variant="secondary" size="sm" icon="angle-down">
|
||||
<Trans i18nKey="alerting.templates.editor.add-example">Add example</Trans>
|
||||
</Button>
|
||||
</Dropdown>
|
||||
)}
|
||||
<Button
|
||||
icon="question-circle"
|
||||
size="sm"
|
||||
fill="outline"
|
||||
variant="secondary"
|
||||
onClick={toggleCheatsheetOpened}
|
||||
>
|
||||
<Trans i18nKey="common.help">Help</Trans>
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Box flex={1}>
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
<TemplateEditor
|
||||
value={getValues('content')}
|
||||
onBlur={(value) => setValue('content', value)}
|
||||
containerStyles={styles.editorContainer}
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</Box>
|
||||
</div>
|
||||
</div>
|
||||
{/* payload editor – only available for Grafana Alertmanager */}
|
||||
{isGrafanaAlertManager && (
|
||||
<>
|
||||
<div {...columnSplitter.splitterProps} />
|
||||
<div {...columnSplitter.secondaryProps}>
|
||||
<div
|
||||
className={cx(
|
||||
styles.containerWithBorderAndRadius,
|
||||
styles.minEditorSize,
|
||||
styles.payloadEditor,
|
||||
styles.flexFull
|
||||
)}
|
||||
>
|
||||
<PayloadEditor
|
||||
payload={payload}
|
||||
defaultPayload={defaultPayloadString}
|
||||
setPayload={setPayload}
|
||||
setPayloadFormatError={setPayloadFormatError}
|
||||
payloadFormatError={payloadFormatError}
|
||||
<Trans i18nKey="common.help">Help</Trans>
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Box flex={1}>
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
<TemplateEditor
|
||||
value={getValues('content')}
|
||||
onBlur={(value) => setValue('content', value)}
|
||||
containerStyles={styles.editorContainer}
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</Box>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* preview column – full height and half-width */}
|
||||
{isGrafanaAlertManager && (
|
||||
<>
|
||||
<div {...rowSplitter.secondaryProps}>
|
||||
<div {...rowSplitter.splitterProps} />
|
||||
<TemplatePreview
|
||||
payload={payload}
|
||||
templateName={watch('title')}
|
||||
setPayloadFormatError={setPayloadFormatError}
|
||||
payloadFormatError={payloadFormatError}
|
||||
className={cx(styles.templatePreview, styles.minEditorSize)}
|
||||
/>
|
||||
</div>
|
||||
{/* payload editor – only available for Grafana Alertmanager */}
|
||||
{isGrafanaAlertManager && (
|
||||
<>
|
||||
<div {...columnSplitter.splitterProps} />
|
||||
<div {...columnSplitter.secondaryProps}>
|
||||
<div
|
||||
className={cx(
|
||||
styles.containerWithBorderAndRadius,
|
||||
styles.minEditorSize,
|
||||
styles.payloadEditor,
|
||||
styles.flexFull
|
||||
)}
|
||||
>
|
||||
<PayloadEditor
|
||||
payload={payload}
|
||||
defaultPayload={defaultPayloadString}
|
||||
setPayload={setPayload}
|
||||
setPayloadFormatError={setPayloadFormatError}
|
||||
payloadFormatError={payloadFormatError}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* preview column – full height and half-width */}
|
||||
{isGrafanaAlertManager && (
|
||||
<>
|
||||
<div {...rowSplitter.secondaryProps}>
|
||||
<div {...rowSplitter.splitterProps} />
|
||||
<TemplatePreview
|
||||
payload={payload}
|
||||
templateName={watch('title')}
|
||||
setPayloadFormatError={setPayloadFormatError}
|
||||
payloadFormatError={payloadFormatError}
|
||||
className={cx(styles.templatePreview, styles.minEditorSize)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</FieldSet>
|
||||
</form>
|
||||
</FormProvider>
|
||||
@@ -439,9 +435,6 @@ export const getStyles = (theme: GrafanaTheme2) => {
|
||||
label: css({
|
||||
margin: 0,
|
||||
}),
|
||||
nameField: css({
|
||||
marginBottom: theme.spacing(1),
|
||||
}),
|
||||
contentContainer: css({
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
|
||||
@@ -295,6 +295,9 @@
|
||||
"export-all": "Export all",
|
||||
"loading": "Loading...",
|
||||
"search-by-matchers": "Search by matchers",
|
||||
"titles": {
|
||||
"notification-templates": "Notification Templates"
|
||||
},
|
||||
"view": "View"
|
||||
},
|
||||
"contact-points": {
|
||||
@@ -404,6 +407,20 @@
|
||||
"title": "Alert instance routing preview",
|
||||
"uninitialized": "When you have your folder selected and your query and labels are configured, click \"Preview routing\" to see the results here."
|
||||
},
|
||||
"notification-templates": {
|
||||
"duplicate": {
|
||||
"subTitle": "Duplicate a group of notification templates",
|
||||
"title": "Duplicate notification template group"
|
||||
},
|
||||
"edit": {
|
||||
"subTitle": "Edit a group of notification templates",
|
||||
"title": "Edit notification template group"
|
||||
},
|
||||
"new": {
|
||||
"subTitle": "Create a new group of notification templates",
|
||||
"title": "New notification template group"
|
||||
}
|
||||
},
|
||||
"policies": {
|
||||
"default-policy": {
|
||||
"description": "All alert instances will be handled by the default policy if no other matching policies are found.",
|
||||
|
||||
@@ -295,6 +295,9 @@
|
||||
"export-all": "Ēχpőřŧ äľľ",
|
||||
"loading": "Ŀőäđįʼnģ...",
|
||||
"search-by-matchers": "Ŝęäřčĥ þy mäŧčĥęřş",
|
||||
"titles": {
|
||||
"notification-templates": "Ńőŧįƒįčäŧįőʼn Ŧęmpľäŧęş"
|
||||
},
|
||||
"view": "Vįęŵ"
|
||||
},
|
||||
"contact-points": {
|
||||
@@ -404,6 +407,20 @@
|
||||
"title": "Åľęřŧ įʼnşŧäʼnčę řőūŧįʼnģ přęvįęŵ",
|
||||
"uninitialized": "Ŵĥęʼn yőū ĥävę yőūř ƒőľđęř şęľęčŧęđ äʼnđ yőūř qūęřy äʼnđ ľäþęľş äřę čőʼnƒįģūřęđ, čľįčĸ \"Přęvįęŵ řőūŧįʼnģ\" ŧő şęę ŧĥę řęşūľŧş ĥęřę."
|
||||
},
|
||||
"notification-templates": {
|
||||
"duplicate": {
|
||||
"subTitle": "Đūpľįčäŧę ä ģřőūp őƒ ʼnőŧįƒįčäŧįőʼn ŧęmpľäŧęş",
|
||||
"title": "Đūpľįčäŧę ʼnőŧįƒįčäŧįőʼn ŧęmpľäŧę ģřőūp"
|
||||
},
|
||||
"edit": {
|
||||
"subTitle": "Ēđįŧ ä ģřőūp őƒ ʼnőŧįƒįčäŧįőʼn ŧęmpľäŧęş",
|
||||
"title": "Ēđįŧ ʼnőŧįƒįčäŧįőʼn ŧęmpľäŧę ģřőūp"
|
||||
},
|
||||
"new": {
|
||||
"subTitle": "Cřęäŧę ä ʼnęŵ ģřőūp őƒ ʼnőŧįƒįčäŧįőʼn ŧęmpľäŧęş",
|
||||
"title": "Ńęŵ ʼnőŧįƒįčäŧįőʼn ŧęmpľäŧę ģřőūp"
|
||||
}
|
||||
},
|
||||
"policies": {
|
||||
"default-policy": {
|
||||
"description": "Åľľ äľęřŧ įʼnşŧäʼnčęş ŵįľľ þę ĥäʼnđľęđ þy ŧĥę đęƒäūľŧ pőľįčy įƒ ʼnő őŧĥęř mäŧčĥįʼnģ pőľįčįęş äřę ƒőūʼnđ.",
|
||||
|
||||
Reference in New Issue
Block a user