add custom messages to Notification Detail

This commit is contained in:
Keith Grant 2020-09-08 12:49:59 -07:00
parent 7042542e6a
commit e0e48bf922
6 changed files with 228 additions and 49 deletions

View File

@ -1,11 +1,11 @@
import 'styled-components/macro';
import React from 'react';
import { shape, node, number } from 'prop-types';
import { shape, node, number, oneOf } from 'prop-types';
import { TextListItemVariants } from '@patternfly/react-core';
import { DetailName, DetailValue } from './Detail';
import CodeMirrorInput from '../CodeMirrorInput';
function ObjectDetail({ value, label, rows, fullHeight }) {
function CodeDetail({ value, label, mode, rows, fullHeight }) {
return (
<>
<DetailName
@ -28,8 +28,8 @@ function ObjectDetail({ value, label, rows, fullHeight }) {
css="grid-column: 1 / -1; margin-top: -20px"
>
<CodeMirrorInput
mode="json"
value={JSON.stringify(value)}
mode={mode}
value={value}
readOnly
rows={rows}
fullHeight={fullHeight}
@ -39,13 +39,14 @@ function ObjectDetail({ value, label, rows, fullHeight }) {
</>
);
}
ObjectDetail.propTypes = {
CodeDetail.propTypes = {
value: shape.isRequired,
label: node.isRequired,
rows: number,
mode: oneOf(['json', 'yaml', 'jinja2']).isRequired,
};
ObjectDetail.defaultProps = {
CodeDetail.defaultProps = {
rows: null,
};
export default ObjectDetail;
export default CodeDetail;

View File

@ -5,7 +5,7 @@ export { default as UserDateDetail } from './UserDateDetail';
export { default as DetailBadge } from './DetailBadge';
export { default as ArrayDetail } from './ArrayDetail';
/*
NOTE: ObjectDetail cannot be imported here, as it causes circular
NOTE: CodeDetail cannot be imported here, as it causes circular
dependencies in testing environment. Import it directly from
DetailList/ObjectDetail
*/

View File

@ -106,6 +106,7 @@ function NotificationTemplate({ setBreadcrumb, i18n }) {
<Route path="/notification_templates/:id/details">
<NotificationTemplateDetail
template={template}
defaultMessages={defaultMessages}
isLoading={isLoading}
/>
</Route>

View File

@ -11,19 +11,21 @@ import {
DetailList,
DeletedDetail,
} from '../../../components/DetailList';
import ObjectDetail from '../../../components/DetailList/ObjectDetail';
import CodeDetail from '../../../components/DetailList/CodeDetail';
import DeleteButton from '../../../components/DeleteButton';
import ErrorDetail from '../../../components/ErrorDetail';
import { NotificationTemplatesAPI } from '../../../api';
import useRequest, { useDismissableError } from '../../../util/useRequest';
import hasCustomMessages from '../shared/hasCustomMessages';
import { NOTIFICATION_TYPES } from '../constants';
function NotificationTemplateDetail({ i18n, template }) {
function NotificationTemplateDetail({ i18n, template, defaultMessages }) {
const history = useHistory();
const {
notification_configuration: configuration,
summary_fields,
messages,
} = template;
const { request: deleteTemplate, isLoading, error: deleteError } = useRequest(
@ -34,6 +36,7 @@ function NotificationTemplateDetail({ i18n, template }) {
);
const { error, dismissError } = useDismissableError(deleteError);
const typeMessageDefaults = defaultMessages[template.notification_type];
return (
<CardBody>
@ -275,7 +278,7 @@ function NotificationTemplateDetail({ i18n, template }) {
dataCy="nt-detail-twilio-source-phone"
/>
<ArrayDetail
label={i18n._(t`Destination SMS Number`)}
label={i18n._(t`Destination SMS Number(s)`)}
value={configuration.to_numbers}
dataCy="nt-detail-twilio-destination-numbers"
/>
@ -312,14 +315,23 @@ function NotificationTemplateDetail({ i18n, template }) {
value={configuration.http_method}
dataCy="nt-detail-webhook-http-method"
/>
<ObjectDetail
<CodeDetail
label={i18n._(t`HTTP Headers`)}
value={configuration.headers}
value={JSON.stringify(configuration.headers)}
mode="json"
rows="6"
dataCy="nt-detail-webhook-headers"
/>
</>
)}
{hasCustomMessages(messages, typeMessageDefaults) && (
<CustomMessageDetails
messages={messages}
defaults={typeMessageDefaults}
type={template.notification_type}
i18n={i18n}
/>
)}
</DetailList>
<CardActionsRow>
{summary_fields.user_capabilities &&
@ -359,4 +371,164 @@ function NotificationTemplateDetail({ i18n, template }) {
);
}
function CustomMessageDetails({ messages, defaults, type, i18n }) {
const showMessages = type !== 'webhook';
const showBodies = ['email', 'pagerduty', 'webhook'].includes(type);
return (
<>
{showMessages && (
<CodeDetail
label={i18n._(t`Start message`)}
value={messages.started.message || defaults.started.message}
mode="jinja2"
rows="2"
fullWidth
/>
)}
{showBodies && (
<CodeDetail
label={i18n._(t`Start message body`)}
value={messages.started.body || defaults.started.body}
mode="jinja2"
rows="6"
fullWidth
/>
)}
{showMessages && (
<CodeDetail
label={i18n._(t`Success message`)}
value={messages.success.message || defaults.success.message}
mode="jinja2"
rows="2"
fullWidth
/>
)}
{showBodies && (
<CodeDetail
label={i18n._(t`Success message body`)}
value={messages.success.body || defaults.success.body}
mode="jinja2"
rows="6"
fullWidth
/>
)}
{showMessages && (
<CodeDetail
label={i18n._(t`Error message`)}
value={messages.error.message || defaults.error.message}
mode="jinja2"
rows="2"
fullWidth
/>
)}
{showBodies && (
<CodeDetail
label={i18n._(t`Error message body`)}
value={messages.error.body || defaults.error.body}
mode="jinja2"
rows="6"
fullWidth
/>
)}
{showMessages && (
<CodeDetail
label={i18n._(t`Workflow approved message`)}
value={
messages.workflow_approval.approved.message ||
defaults.workflow_approval.approved.message
}
mode="jinja2"
rows="2"
fullWidth
/>
)}
{showBodies && (
<CodeDetail
label={i18n._(t`Workflow approved message body`)}
value={
messages.workflow_approval.approved.body ||
defaults.workflow_approval.approved.body
}
mode="jinja2"
rows="6"
fullWidth
/>
)}
{showMessages && (
<CodeDetail
label={i18n._(t`Workflow denied message`)}
value={
messages.workflow_approval.denied.message ||
defaults.workflow_approval.denied.message
}
mode="jinja2"
rows="2"
fullWidth
/>
)}
{showBodies && (
<CodeDetail
label={i18n._(t`Workflow denied message body`)}
value={
messages.workflow_approval.denied.body ||
defaults.workflow_approval.denied.body
}
mode="jinja2"
rows="6"
fullWidth
/>
)}
{showMessages && (
<CodeDetail
label={i18n._(t`Workflow pending message`)}
value={
messages.workflow_approval.running.message ||
defaults.workflow_approval.running.message
}
mode="jinja2"
rows="2"
fullWidth
/>
)}
{showBodies && (
<CodeDetail
label={i18n._(t`Workflow pending message body`)}
value={
messages.workflow_approval.running.body ||
defaults.workflow_approval.running.body
}
mode="jinja2"
rows="6"
fullWidth
/>
)}
{showMessages && (
<CodeDetail
label={i18n._(t`Workflow timed out message`)}
value={
messages.workflow_approval.timed_out.message ||
defaults.workflow_approval.timed_out.message
}
mode="jinja2"
rows="2"
fullWidth
/>
)}
{showBodies && (
<CodeDetail
label={i18n._(t`Workflow timed out message body`)}
value={
messages.workflow_approval.timed_out.body ||
defaults.workflow_approval.timed_out.body
}
mode="jinja2"
rows="6"
fullWidth
/>
)}
</>
);
}
export default withI18n()(NotificationTemplateDetail);

View File

@ -13,6 +13,7 @@ import { required } from '../../../util/validators';
import { FormColumnLayout } from '../../../components/FormLayout';
import TypeInputsSubForm from './TypeInputsSubForm';
import CustomMessagesSubForm from './CustomMessagesSubForm';
import hasCustomMessages from './hasCustomMessages';
import typeFieldNames, { initialConfigValues } from './typeFieldNames';
function NotificationTemplateFormFields({ i18n, defaultMessages }) {
@ -210,42 +211,6 @@ NotificationTemplateForm.defaultProps = {
export default withI18n()(NotificationTemplateForm);
function hasCustomMessages(messages, defaults) {
return (
isCustomized(messages.started, defaults.started) ||
isCustomized(messages.success, defaults.success) ||
isCustomized(messages.error, defaults.error) ||
isCustomized(
messages.workflow_approval.approved,
defaults.workflow_approval.approved
) ||
isCustomized(
messages.workflow_approval.denied,
defaults.workflow_approval.denied
) ||
isCustomized(
messages.workflow_approval.running,
defaults.workflow_approval.running
) ||
isCustomized(
messages.workflow_approval.timed_out,
defaults.workflow_approval.timed_out
)
);
}
function isCustomized(message, defaultMessage) {
if (!message) {
return false;
}
if (message.message && message.message !== defaultMessage.message) {
return true;
}
if (message.body && message.body !== defaultMessage.body) {
return true;
}
return false;
}
function normalizeFields(values, defaultMessages) {
return normalizeTypeFields(normalizeMessageFields(values, defaultMessages));
}

View File

@ -0,0 +1,40 @@
export default function hasCustomMessages(messages, defaults) {
if (!messages) {
return false;
}
return (
isCustomized(messages.started, defaults.started) ||
isCustomized(messages.success, defaults.success) ||
isCustomized(messages.error, defaults.error) ||
isCustomized(
messages.workflow_approval.approved,
defaults.workflow_approval.approved
) ||
isCustomized(
messages.workflow_approval.denied,
defaults.workflow_approval.denied
) ||
isCustomized(
messages.workflow_approval.running,
defaults.workflow_approval.running
) ||
isCustomized(
messages.workflow_approval.timed_out,
defaults.workflow_approval.timed_out
)
);
}
function isCustomized(message, defaultMessage) {
if (!message) {
return false;
}
if (message.message && message.message !== defaultMessage.message) {
return true;
}
if (message.body && message.body !== defaultMessage.body) {
return true;
}
return false;
}