mirror of
https://github.com/ansible/awx.git
synced 2026-02-15 02:00:01 -03:30
add custom messages to Notification Detail
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
import 'styled-components/macro';
|
import 'styled-components/macro';
|
||||||
import React from 'react';
|
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 { TextListItemVariants } from '@patternfly/react-core';
|
||||||
import { DetailName, DetailValue } from './Detail';
|
import { DetailName, DetailValue } from './Detail';
|
||||||
import CodeMirrorInput from '../CodeMirrorInput';
|
import CodeMirrorInput from '../CodeMirrorInput';
|
||||||
|
|
||||||
function ObjectDetail({ value, label, rows, fullHeight }) {
|
function CodeDetail({ value, label, mode, rows, fullHeight }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DetailName
|
<DetailName
|
||||||
@@ -28,8 +28,8 @@ function ObjectDetail({ value, label, rows, fullHeight }) {
|
|||||||
css="grid-column: 1 / -1; margin-top: -20px"
|
css="grid-column: 1 / -1; margin-top: -20px"
|
||||||
>
|
>
|
||||||
<CodeMirrorInput
|
<CodeMirrorInput
|
||||||
mode="json"
|
mode={mode}
|
||||||
value={JSON.stringify(value)}
|
value={value}
|
||||||
readOnly
|
readOnly
|
||||||
rows={rows}
|
rows={rows}
|
||||||
fullHeight={fullHeight}
|
fullHeight={fullHeight}
|
||||||
@@ -39,13 +39,14 @@ function ObjectDetail({ value, label, rows, fullHeight }) {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ObjectDetail.propTypes = {
|
CodeDetail.propTypes = {
|
||||||
value: shape.isRequired,
|
value: shape.isRequired,
|
||||||
label: node.isRequired,
|
label: node.isRequired,
|
||||||
rows: number,
|
rows: number,
|
||||||
|
mode: oneOf(['json', 'yaml', 'jinja2']).isRequired,
|
||||||
};
|
};
|
||||||
ObjectDetail.defaultProps = {
|
CodeDetail.defaultProps = {
|
||||||
rows: null,
|
rows: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ObjectDetail;
|
export default CodeDetail;
|
||||||
@@ -5,7 +5,7 @@ export { default as UserDateDetail } from './UserDateDetail';
|
|||||||
export { default as DetailBadge } from './DetailBadge';
|
export { default as DetailBadge } from './DetailBadge';
|
||||||
export { default as ArrayDetail } from './ArrayDetail';
|
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
|
dependencies in testing environment. Import it directly from
|
||||||
DetailList/ObjectDetail
|
DetailList/ObjectDetail
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ function NotificationTemplate({ setBreadcrumb, i18n }) {
|
|||||||
<Route path="/notification_templates/:id/details">
|
<Route path="/notification_templates/:id/details">
|
||||||
<NotificationTemplateDetail
|
<NotificationTemplateDetail
|
||||||
template={template}
|
template={template}
|
||||||
|
defaultMessages={defaultMessages}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@@ -11,19 +11,21 @@ import {
|
|||||||
DetailList,
|
DetailList,
|
||||||
DeletedDetail,
|
DeletedDetail,
|
||||||
} from '../../../components/DetailList';
|
} from '../../../components/DetailList';
|
||||||
import ObjectDetail from '../../../components/DetailList/ObjectDetail';
|
import CodeDetail from '../../../components/DetailList/CodeDetail';
|
||||||
import DeleteButton from '../../../components/DeleteButton';
|
import DeleteButton from '../../../components/DeleteButton';
|
||||||
import ErrorDetail from '../../../components/ErrorDetail';
|
import ErrorDetail from '../../../components/ErrorDetail';
|
||||||
import { NotificationTemplatesAPI } from '../../../api';
|
import { NotificationTemplatesAPI } from '../../../api';
|
||||||
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
import hasCustomMessages from '../shared/hasCustomMessages';
|
||||||
import { NOTIFICATION_TYPES } from '../constants';
|
import { NOTIFICATION_TYPES } from '../constants';
|
||||||
|
|
||||||
function NotificationTemplateDetail({ i18n, template }) {
|
function NotificationTemplateDetail({ i18n, template, defaultMessages }) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
notification_configuration: configuration,
|
notification_configuration: configuration,
|
||||||
summary_fields,
|
summary_fields,
|
||||||
|
messages,
|
||||||
} = template;
|
} = template;
|
||||||
|
|
||||||
const { request: deleteTemplate, isLoading, error: deleteError } = useRequest(
|
const { request: deleteTemplate, isLoading, error: deleteError } = useRequest(
|
||||||
@@ -34,6 +36,7 @@ function NotificationTemplateDetail({ i18n, template }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { error, dismissError } = useDismissableError(deleteError);
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
|
const typeMessageDefaults = defaultMessages[template.notification_type];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardBody>
|
<CardBody>
|
||||||
@@ -275,7 +278,7 @@ function NotificationTemplateDetail({ i18n, template }) {
|
|||||||
dataCy="nt-detail-twilio-source-phone"
|
dataCy="nt-detail-twilio-source-phone"
|
||||||
/>
|
/>
|
||||||
<ArrayDetail
|
<ArrayDetail
|
||||||
label={i18n._(t`Destination SMS Number`)}
|
label={i18n._(t`Destination SMS Number(s)`)}
|
||||||
value={configuration.to_numbers}
|
value={configuration.to_numbers}
|
||||||
dataCy="nt-detail-twilio-destination-numbers"
|
dataCy="nt-detail-twilio-destination-numbers"
|
||||||
/>
|
/>
|
||||||
@@ -312,14 +315,23 @@ function NotificationTemplateDetail({ i18n, template }) {
|
|||||||
value={configuration.http_method}
|
value={configuration.http_method}
|
||||||
dataCy="nt-detail-webhook-http-method"
|
dataCy="nt-detail-webhook-http-method"
|
||||||
/>
|
/>
|
||||||
<ObjectDetail
|
<CodeDetail
|
||||||
label={i18n._(t`HTTP Headers`)}
|
label={i18n._(t`HTTP Headers`)}
|
||||||
value={configuration.headers}
|
value={JSON.stringify(configuration.headers)}
|
||||||
|
mode="json"
|
||||||
rows="6"
|
rows="6"
|
||||||
dataCy="nt-detail-webhook-headers"
|
dataCy="nt-detail-webhook-headers"
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{hasCustomMessages(messages, typeMessageDefaults) && (
|
||||||
|
<CustomMessageDetails
|
||||||
|
messages={messages}
|
||||||
|
defaults={typeMessageDefaults}
|
||||||
|
type={template.notification_type}
|
||||||
|
i18n={i18n}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</DetailList>
|
</DetailList>
|
||||||
<CardActionsRow>
|
<CardActionsRow>
|
||||||
{summary_fields.user_capabilities &&
|
{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);
|
export default withI18n()(NotificationTemplateDetail);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { required } from '../../../util/validators';
|
|||||||
import { FormColumnLayout } from '../../../components/FormLayout';
|
import { FormColumnLayout } from '../../../components/FormLayout';
|
||||||
import TypeInputsSubForm from './TypeInputsSubForm';
|
import TypeInputsSubForm from './TypeInputsSubForm';
|
||||||
import CustomMessagesSubForm from './CustomMessagesSubForm';
|
import CustomMessagesSubForm from './CustomMessagesSubForm';
|
||||||
|
import hasCustomMessages from './hasCustomMessages';
|
||||||
import typeFieldNames, { initialConfigValues } from './typeFieldNames';
|
import typeFieldNames, { initialConfigValues } from './typeFieldNames';
|
||||||
|
|
||||||
function NotificationTemplateFormFields({ i18n, defaultMessages }) {
|
function NotificationTemplateFormFields({ i18n, defaultMessages }) {
|
||||||
@@ -210,42 +211,6 @@ NotificationTemplateForm.defaultProps = {
|
|||||||
|
|
||||||
export default withI18n()(NotificationTemplateForm);
|
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) {
|
function normalizeFields(values, defaultMessages) {
|
||||||
return normalizeTypeFields(normalizeMessageFields(values, defaultMessages));
|
return normalizeTypeFields(normalizeMessageFields(values, defaultMessages));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user