mirror of
https://github.com/ansible/awx.git
synced 2026-05-10 02:47:36 -02:30
Support job cancellation through details panel
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import 'styled-components/macro';
|
import 'styled-components/macro';
|
||||||
import React, { useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
@@ -25,7 +25,9 @@ import {
|
|||||||
} from '../../../components/LaunchButton';
|
} from '../../../components/LaunchButton';
|
||||||
import StatusIcon from '../../../components/StatusIcon';
|
import StatusIcon from '../../../components/StatusIcon';
|
||||||
import ExecutionEnvironmentDetail from '../../../components/ExecutionEnvironmentDetail';
|
import ExecutionEnvironmentDetail from '../../../components/ExecutionEnvironmentDetail';
|
||||||
|
import isJobRunning from '../../../util/jobs';
|
||||||
import { toTitleCase } from '../../../util/strings';
|
import { toTitleCase } from '../../../util/strings';
|
||||||
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
import { formatDateString } from '../../../util/dates';
|
import { formatDateString } from '../../../util/dates';
|
||||||
import { Job } from '../../../types';
|
import { Job } from '../../../types';
|
||||||
import {
|
import {
|
||||||
@@ -58,6 +60,16 @@ const VERBOSITY = {
|
|||||||
4: '4 (Connection Debug)',
|
4: '4 (Connection Debug)',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getJobModel = type => {
|
||||||
|
if (type === 'ad_hoc_command') return AdHocCommandsAPI;
|
||||||
|
if (type === 'inventory_update') return InventoriesAPI;
|
||||||
|
if (type === 'project_update') return ProjectUpdatesAPI;
|
||||||
|
if (type === 'system_job') return SystemJobsAPI;
|
||||||
|
if (type === 'workflow_job') return WorkflowJobsAPI;
|
||||||
|
|
||||||
|
return JobsAPI;
|
||||||
|
};
|
||||||
|
|
||||||
function JobDetail({ job, i18n }) {
|
function JobDetail({ job, i18n }) {
|
||||||
const {
|
const {
|
||||||
created_by,
|
created_by,
|
||||||
@@ -77,6 +89,24 @@ function JobDetail({ job, i18n }) {
|
|||||||
const [errorMsg, setErrorMsg] = useState();
|
const [errorMsg, setErrorMsg] = useState();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
|
const [showCancelModal, setShowCancelModal] = useState(false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
error: cancelError,
|
||||||
|
isLoading: isCancelling,
|
||||||
|
request: cancelJob,
|
||||||
|
} = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
|
await getJobModel(job.type).cancel(job.id, job.type);
|
||||||
|
}, [job.id, job.type]),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
error: dismissableCancelError,
|
||||||
|
dismissError: dismissCancelError,
|
||||||
|
} = useDismissableError(cancelError);
|
||||||
|
|
||||||
const jobTypes = {
|
const jobTypes = {
|
||||||
project_update: i18n._(t`Source Control Update`),
|
project_update: i18n._(t`Source Control Update`),
|
||||||
inventory_update: i18n._(t`Inventory Sync`),
|
inventory_update: i18n._(t`Inventory Sync`),
|
||||||
@@ -91,25 +121,7 @@ function JobDetail({ job, i18n }) {
|
|||||||
|
|
||||||
const deleteJob = async () => {
|
const deleteJob = async () => {
|
||||||
try {
|
try {
|
||||||
switch (job.type) {
|
await getJobModel(job.type).destroy(job.id);
|
||||||
case 'project_update':
|
|
||||||
await ProjectUpdatesAPI.destroy(job.id);
|
|
||||||
break;
|
|
||||||
case 'system_job':
|
|
||||||
await SystemJobsAPI.destroy(job.id);
|
|
||||||
break;
|
|
||||||
case 'workflow_job':
|
|
||||||
await WorkflowJobsAPI.destroy(job.id);
|
|
||||||
break;
|
|
||||||
case 'ad_hoc_command':
|
|
||||||
await AdHocCommandsAPI.destroy(job.id);
|
|
||||||
break;
|
|
||||||
case 'inventory_update':
|
|
||||||
await InventoriesAPI.destroy(job.id);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
await JobsAPI.destroy(job.id);
|
|
||||||
}
|
|
||||||
history.push('/jobs');
|
history.push('/jobs');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrorMsg(err);
|
setErrorMsg(err);
|
||||||
@@ -410,16 +422,75 @@ function JobDetail({ job, i18n }) {
|
|||||||
)}
|
)}
|
||||||
</LaunchButton>
|
</LaunchButton>
|
||||||
))}
|
))}
|
||||||
{job.summary_fields.user_capabilities.delete && (
|
{isJobRunning(job.status) &&
|
||||||
<DeleteButton
|
job?.summary_fields?.user_capabilities?.start && (
|
||||||
name={job.name}
|
<Button
|
||||||
modalTitle={i18n._(t`Delete Job`)}
|
variant="secondary"
|
||||||
onConfirm={deleteJob}
|
aria-label={i18n._(t`Cancel`)}
|
||||||
>
|
isDisabled={isCancelling}
|
||||||
{i18n._(t`Delete`)}
|
onClick={() => setShowCancelModal(true)}
|
||||||
</DeleteButton>
|
ouiaId="job-detail-cancel-button"
|
||||||
)}
|
>
|
||||||
|
{i18n._(t`Cancel`)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{!isJobRunning(job.status) &&
|
||||||
|
job?.summary_fields?.user_capabilities?.delete && (
|
||||||
|
<DeleteButton
|
||||||
|
name={job.name}
|
||||||
|
modalTitle={i18n._(t`Delete Job`)}
|
||||||
|
onConfirm={deleteJob}
|
||||||
|
ouiaId="job-detail-delete-button"
|
||||||
|
>
|
||||||
|
{i18n._(t`Delete`)}
|
||||||
|
</DeleteButton>
|
||||||
|
)}
|
||||||
</CardActionsRow>
|
</CardActionsRow>
|
||||||
|
{showCancelModal && isJobRunning(job.status) && (
|
||||||
|
<AlertModal
|
||||||
|
isOpen={showCancelModal}
|
||||||
|
variant="danger"
|
||||||
|
onClose={() => setShowCancelModal(false)}
|
||||||
|
title={i18n._(t`Cancel Job`)}
|
||||||
|
label={i18n._(t`Cancel Job`)}
|
||||||
|
actions={[
|
||||||
|
<Button
|
||||||
|
id="cancel-job-confirm-button"
|
||||||
|
key="delete"
|
||||||
|
variant="danger"
|
||||||
|
isDisabled={isCancelling}
|
||||||
|
aria-label={i18n._(t`Cancel job`)}
|
||||||
|
onClick={cancelJob}
|
||||||
|
>
|
||||||
|
{i18n._(t`Cancel job`)}
|
||||||
|
</Button>,
|
||||||
|
<Button
|
||||||
|
id="cancel-job-return-button"
|
||||||
|
key="cancel"
|
||||||
|
variant="secondary"
|
||||||
|
aria-label={i18n._(t`Return`)}
|
||||||
|
onClick={() => setShowCancelModal(false)}
|
||||||
|
>
|
||||||
|
{i18n._(t`Return`)}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{i18n._(
|
||||||
|
t`Are you sure you want to submit the request to cancel this job?`
|
||||||
|
)}
|
||||||
|
</AlertModal>
|
||||||
|
)}
|
||||||
|
{dismissableCancelError && (
|
||||||
|
<AlertModal
|
||||||
|
isOpen={dismissableCancelError}
|
||||||
|
variant="danger"
|
||||||
|
onClose={dismissCancelError}
|
||||||
|
title={i18n._(t`Job Cancel Error`)}
|
||||||
|
label={i18n._(t`Job Cancel Error`)}
|
||||||
|
>
|
||||||
|
<ErrorDetail error={dismissableCancelError} />
|
||||||
|
</AlertModal>
|
||||||
|
)}
|
||||||
{errorMsg && (
|
{errorMsg && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={errorMsg}
|
isOpen={errorMsg}
|
||||||
|
|||||||
Reference in New Issue
Block a user