import { css, cx } from '@emotion/css'; import { compact, uniqueId } from 'lodash'; import * as React from 'react'; import { useFormContext } from 'react-hook-form'; import AutoSizer from 'react-virtualized-auto-sizer'; import { GrafanaTheme2 } from '@grafana/data'; import { Alert, Box, Button, useStyles2 } from '@grafana/ui'; import { TemplatePreviewErrors, TemplatePreviewResponse, TemplatePreviewResult } from '../../api/templateApi'; import { stringifyErrorLike } from '../../utils/misc'; import { EditorColumnHeader } from '../contact-points/templates/EditorColumnHeader'; import type { TemplateFormValues } from './TemplateForm'; import { usePreviewTemplate } from './usePreviewTemplate'; export function TemplatePreview({ payload, templateName, payloadFormatError, setPayloadFormatError, className, }: { payload: string; templateName: string; payloadFormatError: string | null; setPayloadFormatError: (value: React.SetStateAction) => void; className?: string; }) { const styles = useStyles2(getStyles); const { watch } = useFormContext(); const templateContent = watch('content'); const { data, isLoading, onPreview, error: previewError, } = usePreviewTemplate(templateContent, templateName, payload, setPayloadFormatError); const previewToRender = getPreviewResults(previewError, payloadFormatError, data); return (
Refresh } /> {({ height }) =>
{previewToRender}
}
); } function PreviewResultViewer({ previews }: { previews: TemplatePreviewResult[] }) { const styles = useStyles2(getStyles); // If there is only one template, we don't need to show the name const singleTemplate = previews.length === 1; return ( ); } function PreviewErrorViewer({ errors }: { errors: TemplatePreviewErrors[] }) { return errors.map((error) => ( {error.message} )); } const getStyles = (theme: GrafanaTheme2) => ({ container: css({ label: 'template-preview-container', display: 'flex', flexDirection: 'column', borderRadius: theme.shape.radius.default, border: `1px solid ${theme.colors.border.medium}`, }), viewerContainer: ({ height }: { height: number }) => css({ height, overflow: 'auto', backgroundColor: theme.colors.background.primary, }), viewer: { container: css({ display: 'flex', flexDirection: 'column', height: 'inherit', }), box: css({ display: 'flex', flexDirection: 'column', borderBottom: `1px solid ${theme.colors.border.medium}`, height: 'inherit', }), header: css({ fontSize: theme.typography.bodySmall.fontSize, padding: theme.spacing(1, 2), borderBottom: `1px solid ${theme.colors.border.medium}`, backgroundColor: theme.colors.background.secondary, }), errorText: css({ color: theme.colors.error.text, }), pre: css({ backgroundColor: 'transparent', margin: 0, border: 'none', padding: theme.spacing(2), }), }, }); export function getPreviewResults( previewError: unknown | undefined, payloadFormatError: string | null, data: TemplatePreviewResponse | undefined ): JSX.Element { // ERRORS IN JSON OR IN REQUEST (endpoint not available, for example) const previewErrorRequest = previewError ? stringifyErrorLike(previewError) : undefined; const errorToRender = payloadFormatError || previewErrorRequest; //PREVIEW : RESULTS AND ERRORS const previewResponseResults = data?.results ?? []; const previewResponseErrors = data?.errors; return ( <> {errorToRender && ( {errorToRender} )} {previewResponseErrors && } {previewResponseResults && } ); }