mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 18:09:57 -03:30
more template details; add template delete button
This commit is contained in:
parent
ab4628b199
commit
a9451c9864
@ -2,14 +2,27 @@ import React, { useEffect, useCallback } from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { Link, useParams } from 'react-router-dom';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import {
|
||||
Link,
|
||||
Switch,
|
||||
Route,
|
||||
Redirect,
|
||||
useParams,
|
||||
useRouteMatch,
|
||||
useLocation,
|
||||
} from 'react-router-dom';
|
||||
import useRequest from '../../util/useRequest';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import { NotificationTemplatesAPI } from '../../api';
|
||||
import NotificationTemplateDetail from './NotificationTemplateDetail';
|
||||
import NotificationTemplateEdit from './NotificationTemplateEdit';
|
||||
|
||||
function NotificationTemplate({ i18n, setBreadcrumb }) {
|
||||
function NotificationTemplate({ setBreadcrumb, i18n }) {
|
||||
const { id: templateId } = useParams();
|
||||
const match = useRouteMatch();
|
||||
const location = useLocation();
|
||||
const {
|
||||
result: template,
|
||||
isLoading,
|
||||
@ -47,15 +60,51 @@ function NotificationTemplate({ i18n, setBreadcrumb }) {
|
||||
);
|
||||
}
|
||||
|
||||
const showCardHeader = !isLoading && !location.pathname.endsWith('edit');
|
||||
const tabs = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Notifications`)}
|
||||
</>
|
||||
),
|
||||
link: `/notification_templates`,
|
||||
id: 99,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Details`),
|
||||
link: `${match.url}/details`,
|
||||
id: 0,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{template && (
|
||||
<NotificationTemplateDetail
|
||||
template={template}
|
||||
isLoading={isLoading}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabs} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/notification_templates/:id"
|
||||
to="/notification_templates/:id/details"
|
||||
exact
|
||||
/>
|
||||
)}
|
||||
{template && (
|
||||
<>
|
||||
<Route path="/notification_templates/:id/edit">
|
||||
<NotificationTemplateEdit
|
||||
template={template}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/notification_templates/:id/details">
|
||||
<NotificationTemplateDetail
|
||||
template={template}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Route>
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React, { Fragment, useState, useEffect, useCallback } from 'react';
|
||||
import { Link, useHistory, useParams } from 'react-router-dom';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import {
|
||||
Button,
|
||||
@ -28,26 +28,27 @@ import DeleteButton from '../../../components/DeleteButton';
|
||||
import ErrorDetail from '../../../components/ErrorDetail';
|
||||
import LaunchButton from '../../../components/LaunchButton';
|
||||
import { VariablesDetail } from '../../../components/CodeMirrorInput';
|
||||
import { JobTemplatesAPI } from '../../../api';
|
||||
import { NotificationTemplatesAPI } from '../../../api';
|
||||
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||
|
||||
const TYPES = {
|
||||
email: 'Email',
|
||||
grafana: 'Grafana',
|
||||
irc: 'IRC',
|
||||
mattermost: 'Mattermost',
|
||||
pagerduty: 'Pagerduty',
|
||||
rocketchat: 'Rocket.Chat',
|
||||
slack: 'Slack',
|
||||
twilio: 'Twilio',
|
||||
webhook: 'Webhook',
|
||||
};
|
||||
import { NOTIFICATION_TYPES } from '../constants';
|
||||
|
||||
function NotificationTemplateDetail({ i18n, template }) {
|
||||
const history = useHistory();
|
||||
|
||||
const {
|
||||
notification_configuration: configuration,
|
||||
summary_fields,
|
||||
} = template;
|
||||
|
||||
const { request: deleteTemplate, isLoading, error: deleteError } = useRequest(
|
||||
useCallback(async () => {
|
||||
await NotificationTemplatesAPI.destroy(template.id);
|
||||
history.push(`/notification_templates`);
|
||||
}, [template.id, history])
|
||||
);
|
||||
|
||||
const { error, dismissError } = useDismissableError(deleteError);
|
||||
|
||||
return (
|
||||
<CardBody>
|
||||
<DetailList gutter="sm">
|
||||
@ -78,7 +79,8 @@ function NotificationTemplateDetail({ i18n, template }) {
|
||||
<Detail
|
||||
label={i18n._(t`Notification Type`)}
|
||||
value={
|
||||
TYPES[template.notification_type] || template.notification_type
|
||||
NOTIFICATION_TYPES[template.notification_type] ||
|
||||
template.notification_type
|
||||
}
|
||||
dataCy="nt-detail-type"
|
||||
/>
|
||||
@ -265,7 +267,107 @@ function NotificationTemplateDetail({ i18n, template }) {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{template.notification_type === 'slack' && (
|
||||
<>
|
||||
<Detail
|
||||
label={i18n._(t`Destination Channels`)}
|
||||
value={configuration.channels} // array
|
||||
dataCy="nt-detail-slack-channels"
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Notification Color`)}
|
||||
value={configuration.hex_color}
|
||||
dataCy="nt-detail-slack-color"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{template.notification_type === 'twilio' && (
|
||||
<>
|
||||
<Detail
|
||||
label={i18n._(t`Source Phone Number`)}
|
||||
value={configuration.from_number}
|
||||
dataCy="nt-detail-twilio-source-phone"
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Destination SMS Number`)}
|
||||
value={configuration.to_numbers} // array
|
||||
dataCy="nt-detail-twilio-destination-numbers"
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Account SID`)}
|
||||
value={configuration.account_sid}
|
||||
dataCy="nt-detail-twilio-account-sid"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{template.notification_type === 'webhook' && (
|
||||
<>
|
||||
<Detail
|
||||
label={i18n._(t`Username`)}
|
||||
value={configuration.username}
|
||||
dataCy="nt-detail-webhook-password"
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Target URL`)}
|
||||
value={configuration.url}
|
||||
dataCy="nt-detail-webhook-url"
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Disable SSL Verification`)}
|
||||
value={
|
||||
configuration.disable_ssl_verification
|
||||
? i18n._(t`True`)
|
||||
: i18n._(t`False`)
|
||||
}
|
||||
dataCy="nt-detail-disable-ssl"
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`HTTP Method`)}
|
||||
value={configuration.http_method}
|
||||
dataCy="nt-detail-webhook-http-method"
|
||||
/>
|
||||
{/* <Detail
|
||||
label={i18n._(t`HTTP Headers`)}
|
||||
value={configuration.headers}
|
||||
dataCy="nt-detail-webhook-headers"
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
</DetailList>
|
||||
<CardActionsRow>
|
||||
{summary_fields.user_capabilities &&
|
||||
summary_fields.user_capabilities.edit && (
|
||||
<Button
|
||||
component={Link}
|
||||
to={`/notification_templates/${template.id}/edit`}
|
||||
aria-label={i18n._(t`Edit`)}
|
||||
>
|
||||
{i18n._(t`Edit`)}
|
||||
</Button>
|
||||
)}
|
||||
{summary_fields.user_capabilities &&
|
||||
summary_fields.user_capabilities.delete && (
|
||||
<DeleteButton
|
||||
name={template.name}
|
||||
modalTitle={i18n._(t`Delete Notification`)}
|
||||
onConfirm={deleteTemplate}
|
||||
isDisabled={isLoading}
|
||||
>
|
||||
{i18n._(t`Delete`)}
|
||||
</DeleteButton>
|
||||
)}
|
||||
</CardActionsRow>
|
||||
{error && (
|
||||
<AlertModal
|
||||
isOpen={error}
|
||||
variant="error"
|
||||
title={i18n._(t`Error!`)}
|
||||
onClose={dismissError}
|
||||
>
|
||||
{i18n._(t`Failed to delete notification.`)}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
)}
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { CardBody } from '../../../components/Card';
|
||||
import { OrganizationsAPI } from '../../../api';
|
||||
import { Config } from '../../../contexts/Config';
|
||||
|
||||
import NotificationTemplateForm from '../shared/NotificationTemplateForm';
|
||||
|
||||
function NotificationTemplateEdit({ template }) {
|
||||
const detailsUrl = `/notification_templates/${template.id}/details`;
|
||||
const history = useHistory();
|
||||
const [formError, setFormError] = useState(null);
|
||||
|
||||
const handleSubmit = async (
|
||||
values,
|
||||
groupsToAssociate,
|
||||
groupsToDisassociate
|
||||
) => {
|
||||
try {
|
||||
await OrganizationsAPI.update(template.id, values);
|
||||
await Promise.all(
|
||||
groupsToAssociate.map(id =>
|
||||
OrganizationsAPI.associateInstanceGroup(template.id, id)
|
||||
)
|
||||
);
|
||||
await Promise.all(
|
||||
groupsToDisassociate.map(id =>
|
||||
OrganizationsAPI.disassociateInstanceGroup(template.id, id)
|
||||
)
|
||||
);
|
||||
history.push(detailsUrl);
|
||||
} catch (error) {
|
||||
setFormError(error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
history.push(detailsUrl);
|
||||
};
|
||||
|
||||
return (
|
||||
<CardBody>
|
||||
<Config>
|
||||
{({ me }) => (
|
||||
<NotificationTemplateForm
|
||||
template={template}
|
||||
onSubmit={handleSubmit}
|
||||
onCancel={handleCancel}
|
||||
me={me || {}}
|
||||
submitError={formError}
|
||||
/>
|
||||
)}
|
||||
</Config>
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
|
||||
NotificationTemplateEdit.propTypes = {
|
||||
template: PropTypes.shape().isRequired,
|
||||
};
|
||||
|
||||
NotificationTemplateEdit.contextTypes = {
|
||||
custom_virtualenvs: PropTypes.arrayOf(PropTypes.string),
|
||||
};
|
||||
|
||||
export { NotificationTemplateEdit as _NotificationTemplateEdit };
|
||||
export default NotificationTemplateEdit;
|
||||
@ -0,0 +1,3 @@
|
||||
import NotificationTemplateEdit from './NotificationTemplateEdit';
|
||||
|
||||
export default NotificationTemplateEdit;
|
||||
@ -14,6 +14,7 @@ import {
|
||||
} from '@patternfly/react-core';
|
||||
import { PencilAltIcon, BellIcon } from '@patternfly/react-icons';
|
||||
import DataListCell from '../../../components/DataListCell';
|
||||
import { NOTIFICATION_TYPES } from '../constants';
|
||||
|
||||
const DataListAction = styled(_DataListAction)`
|
||||
align-items: center;
|
||||
@ -49,7 +50,8 @@ function NotificationTemplateListItem({
|
||||
</Link>
|
||||
</DataListCell>,
|
||||
<DataListCell key="type">
|
||||
{template.notification_type}
|
||||
{NOTIFICATION_TYPES[template.notification_type] ||
|
||||
template.notification_type}
|
||||
</DataListCell>,
|
||||
]}
|
||||
/>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import NotificationTemplatesList from './NotificationTemplateList';
|
||||
import NotificationTemplateList from './NotificationTemplateList';
|
||||
|
||||
export default NotificationTemplatesList;
|
||||
export { default as NotificationTemplatesListItem } from './NotificationTemplateListItem';
|
||||
export default NotificationTemplateList;
|
||||
export { default as NotificationTemplateListItem } from './NotificationTemplateListItem';
|
||||
|
||||
12
awx/ui_next/src/screens/NotificationTemplate/constants.js
Normal file
12
awx/ui_next/src/screens/NotificationTemplate/constants.js
Normal file
@ -0,0 +1,12 @@
|
||||
/* eslint-disable-next-line import/prefer-default-export */
|
||||
export const NOTIFICATION_TYPES = {
|
||||
email: 'Email',
|
||||
grafana: 'Grafana',
|
||||
irc: 'IRC',
|
||||
mattermost: 'Mattermost',
|
||||
pagerduty: 'Pagerduty',
|
||||
rocketchat: 'Rocket.Chat',
|
||||
slack: 'Slack',
|
||||
twilio: 'Twilio',
|
||||
webhook: 'Webhook',
|
||||
};
|
||||
@ -0,0 +1,3 @@
|
||||
export default function NotificationTemplateForm() {
|
||||
//
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user