mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 03:10:42 -03:30
Adds ability to send slack notification to a thread, updates tooltip in ui, and adds test button to notification details view
This commit is contained in:
parent
0ae67edaba
commit
f92a49fda9
@ -36,10 +36,17 @@ class SlackBackend(AWXBaseEmailBackend, CustomNotificationBase):
|
||||
for r in m.recipients():
|
||||
if r.startswith('#'):
|
||||
r = r[1:]
|
||||
thread = None
|
||||
channel = r
|
||||
thread = None
|
||||
if ',' in r:
|
||||
channel, thread = r.split(',')
|
||||
if self.color:
|
||||
response = client.chat_postMessage(channel=r, as_user=True, attachments=[{"color": self.color, "text": m.subject}])
|
||||
response = client.chat_postMessage(
|
||||
channel=channel, thread_ts=thread, as_user=True, attachments=[{"color": self.color, "text": m.subject}]
|
||||
)
|
||||
else:
|
||||
response = client.chat_postMessage(channel=r, as_user=True, text=m.subject)
|
||||
response = client.chat_postMessage(channel=channel, thread_ts=thread, as_user=True, text=m.subject)
|
||||
logger.debug(response)
|
||||
if response['ok']:
|
||||
sent_messages += 1
|
||||
|
||||
@ -24,7 +24,7 @@ def test_send_messages():
|
||||
message,
|
||||
]
|
||||
)
|
||||
WebClient_mock.chat_postMessage.assert_called_once_with(channel='random', as_user=True, text='test subject')
|
||||
WebClient_mock.chat_postMessage.assert_called_once_with(channel='random', thread_ts=None, as_user=True, text='test subject')
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
@ -47,7 +47,9 @@ def test_send_messages_with_color():
|
||||
]
|
||||
)
|
||||
|
||||
WebClient_mock.chat_postMessage.assert_called_once_with(channel='random', as_user=True, attachments=[{'color': '#006699', 'text': 'test subject'}])
|
||||
WebClient_mock.chat_postMessage.assert_called_once_with(
|
||||
channel='random', as_user=True, thread_ts=None, attachments=[{'color': '#006699', 'text': 'test subject'}]
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import {
|
||||
Button,
|
||||
@ -20,13 +20,20 @@ import {
|
||||
import CodeDetail from 'components/DetailList/CodeDetail';
|
||||
import DeleteButton from 'components/DeleteButton';
|
||||
import ErrorDetail from 'components/ErrorDetail';
|
||||
import { NotificationTemplatesAPI } from 'api';
|
||||
import { NotificationTemplatesAPI, NotificationsAPI } from 'api';
|
||||
import useRequest, { useDismissableError } from 'hooks/useRequest';
|
||||
import StatusLabel from 'components/StatusLabel';
|
||||
import hasCustomMessages from '../shared/hasCustomMessages';
|
||||
import { NOTIFICATION_TYPES } from '../constants';
|
||||
|
||||
const NUM_RETRIES = 25;
|
||||
const RETRY_TIMEOUT = 5000;
|
||||
|
||||
function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
const history = useHistory();
|
||||
const [testStatus, setTestStatus] = useState(
|
||||
template.summary_fields?.recent_notifications[0]?.status ?? undefined
|
||||
);
|
||||
|
||||
const {
|
||||
created,
|
||||
@ -64,9 +71,35 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
}, [template.id, history])
|
||||
);
|
||||
|
||||
const { error, dismissError } = useDismissableError(deleteError);
|
||||
const typeMessageDefaults = defaultMessages[template.notification_type];
|
||||
const { request: sendTestNotification, error: testError } = useRequest(
|
||||
useCallback(async () => {
|
||||
setTestStatus('running');
|
||||
|
||||
let retries = NUM_RETRIES;
|
||||
const {
|
||||
data: { notification: notificationId },
|
||||
} = await NotificationTemplatesAPI.test(template.id);
|
||||
|
||||
async function pollForStatusChange() {
|
||||
const { data: notification } = await NotificationsAPI.readDetail(
|
||||
notificationId
|
||||
);
|
||||
if (notification.status !== 'pending') {
|
||||
setTestStatus(notification.status);
|
||||
return;
|
||||
}
|
||||
retries--;
|
||||
if (retries > 0) {
|
||||
setTimeout(pollForStatusChange, RETRY_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(pollForStatusChange, RETRY_TIMEOUT);
|
||||
}, [template.id])
|
||||
);
|
||||
|
||||
const { error, dismissError } = useDismissableError(deleteError || testError);
|
||||
const typeMessageDefaults = defaultMessages[template.notification_type];
|
||||
return (
|
||||
<CardBody>
|
||||
<DetailList gutter="sm">
|
||||
@ -76,6 +109,12 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
value={template.description}
|
||||
dataCy="nt-detail-description"
|
||||
/>
|
||||
{summary_fields.recent_notifications.length && (
|
||||
<Detail
|
||||
label={t`Status`}
|
||||
value={<StatusLabel status={testStatus} />}
|
||||
/>
|
||||
)}
|
||||
{summary_fields.organization ? (
|
||||
<Detail
|
||||
label={t`Organization`}
|
||||
@ -354,8 +393,8 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
)}
|
||||
</DetailList>
|
||||
<CardActionsRow>
|
||||
{summary_fields.user_capabilities &&
|
||||
summary_fields.user_capabilities.edit && (
|
||||
{summary_fields.user_capabilities?.edit && (
|
||||
<>
|
||||
<Button
|
||||
ouiaId="notification-template-detail-edit-button"
|
||||
component={Link}
|
||||
@ -364,18 +403,23 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
>
|
||||
{t`Edit`}
|
||||
</Button>
|
||||
)}
|
||||
{summary_fields.user_capabilities &&
|
||||
summary_fields.user_capabilities.delete && (
|
||||
<DeleteButton
|
||||
name={template.name}
|
||||
modalTitle={t`Delete Notification`}
|
||||
onConfirm={deleteTemplate}
|
||||
isDisabled={isLoading}
|
||||
>
|
||||
{t`Delete`}
|
||||
</DeleteButton>
|
||||
)}
|
||||
<Button
|
||||
onClick={sendTestNotification}
|
||||
variant="secondary"
|
||||
isDisabled={testStatus === ('running' || 'pending')}
|
||||
>{t`Test`}</Button>
|
||||
</>
|
||||
)}
|
||||
{summary_fields.user_capabilities?.delete && (
|
||||
<DeleteButton
|
||||
name={template.name}
|
||||
modalTitle={t`Delete Notification`}
|
||||
onConfirm={deleteTemplate}
|
||||
isDisabled={isLoading}
|
||||
>
|
||||
{t`Delete`}
|
||||
</DeleteButton>
|
||||
)}
|
||||
</CardActionsRow>
|
||||
{error && (
|
||||
<AlertModal
|
||||
@ -384,7 +428,9 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
title={t`Error!`}
|
||||
onClose={dismissError}
|
||||
>
|
||||
{t`Failed to delete notification.`}
|
||||
{deleteError
|
||||
? t`Failed to delete notification.`
|
||||
: t`Notification test failed.`}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
)}
|
||||
|
||||
@ -45,7 +45,7 @@ const mockTemplate = {
|
||||
delete: true,
|
||||
copy: true,
|
||||
},
|
||||
recent_notifications: [],
|
||||
recent_notifications: [{ status: 'success' }],
|
||||
},
|
||||
created: '2021-06-16T18:52:23.811374Z',
|
||||
modified: '2021-06-16T18:53:37.631371Z',
|
||||
|
||||
@ -362,8 +362,14 @@ function SlackFields() {
|
||||
type="textarea"
|
||||
validate={required(null)}
|
||||
isRequired
|
||||
tooltip={t`Enter one Slack channel per line. The pound symbol (#)
|
||||
is required for channels.`}
|
||||
tooltip={
|
||||
<>
|
||||
{t`Enter one Slack channel per line. The pound symbol (#)
|
||||
is required for channels. To respond to or start a thread to a specific message add the parent message Id to the channel where the parent message Id is 16 digits. A dot (.) must be manually inserted after the 10th digit. ie:#destination-channel, 1231257890.006423. See Slack`}{' '}
|
||||
<a href="https://api.slack.com/messaging/retrieving#individual_messages">{t`documentation`}</a>{' '}
|
||||
<span>{t`for more information.`}</span>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<PasswordField
|
||||
id="slack-token"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user