Add mgmt job launch

This commit is contained in:
Jake McDermott
2020-09-10 12:34:11 -04:00
parent eaf55728d8
commit daaabd935c
5 changed files with 81 additions and 24 deletions

View File

@@ -9,8 +9,8 @@ const getBaseURL = type => {
case 'project': case 'project':
case 'project_update': case 'project_update':
return '/project_updates/'; return '/project_updates/';
case 'system': case 'management':
case 'system_job': case 'management_job':
return '/system_jobs/'; return '/system_jobs/';
case 'inventory': case 'inventory':
case 'inventory_update': case 'inventory_update':

View File

@@ -15,6 +15,10 @@ class SystemJobTemplates extends Mixins {
return this.http.get(path).then(({ data }) => data); return this.http.get(path).then(({ data }) => data);
} }
launch(id, data) {
return this.http.post(`${this.baseUrl}${id}/launch/`, data);
}
} }
export default SystemJobTemplates; export default SystemJobTemplates;

View File

@@ -2,7 +2,7 @@
export const JOB_TYPE_URL_SEGMENTS = { export const JOB_TYPE_URL_SEGMENTS = {
job: 'playbook', job: 'playbook',
project_update: 'project', project_update: 'project',
system_job: 'system', system_job: 'management',
inventory_update: 'inventory', inventory_update: 'inventory',
ad_hoc_command: 'command', ad_hoc_command: 'command',
workflow_job: 'workflow', workflow_job: 'workflow',

View File

@@ -1,19 +1,21 @@
import React, { useEffect, useCallback } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { Card, PageSection } from '@patternfly/react-core'; import { Card, PageSection } from '@patternfly/react-core';
import { SystemJobTemplatesAPI } from '../../../api'; import { SystemJobTemplatesAPI } from '../../../api';
import { useConfig } from '../../../contexts/Config'; import AlertModal from '../../../components/AlertModal';
import { getQSConfig, parseQueryString } from '../../../util/qs';
import useRequest from '../../../util/useRequest';
import DatalistToolbar from '../../../components/DataListToolbar'; import DatalistToolbar from '../../../components/DataListToolbar';
import ErrorDetail from '../../../components/ErrorDetail';
import PaginatedDataList from '../../../components/PaginatedDataList'; import PaginatedDataList from '../../../components/PaginatedDataList';
import { useConfig } from '../../../contexts/Config';
import { parseQueryString, getQSConfig } from '../../../util/qs';
import useRequest from '../../../util/useRequest';
import ManagementJobListItem from './ManagementJobListItem'; import ManagementJobListItem from './ManagementJobListItem';
const QS_CONFIG = getQSConfig('management_jobs', { const QS_CONFIG = getQSConfig('system_job_templates', {
page: 1, page: 1,
page_size: 20, page_size: 20,
}); });
@@ -46,6 +48,7 @@ const loadManagementJobs = async search => {
function ManagementJobList({ i18n }) { function ManagementJobList({ i18n }) {
const { search } = useLocation(); const { search } = useLocation();
const { me } = useConfig(); const { me } = useConfig();
const [launchError, setLaunchError] = useState(null);
const { const {
request, request,
@@ -85,15 +88,26 @@ function ManagementJobList({ i18n }) {
)} )}
renderItem={({ id, name, description }) => ( renderItem={({ id, name, description }) => (
<ManagementJobListItem <ManagementJobListItem
isSuperUser={me?.is_superuser} key={id}
id={id} id={id}
name={name} name={name}
description={description} description={description}
isSuperUser={me?.is_superuser}
onLaunchError={setLaunchError}
/> />
)} )}
/> />
</Card> </Card>
</PageSection> </PageSection>
<AlertModal
isOpen={Boolean(launchError)}
variant="error"
title={i18n._(t`Error!`)}
onClose={() => setLaunchError(null)}
>
{i18n._(t`Failed to launch job.`)}
<ErrorDetail error={launchError} />
</AlertModal>
</> </>
); );
} }

View File

@@ -1,32 +1,55 @@
import React from 'react'; import React, { useState } from 'react';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Link } from 'react-router-dom'; import { Link, useHistory } from 'react-router-dom';
import { import {
Button, Button,
DataListAction as _DataListAction, DataListAction as _DataListAction,
DataListCell,
DataListItem, DataListItem,
DataListItemRow, DataListItemRow,
DataListItemCells, DataListItemCells,
Tooltip, Tooltip,
} from '@patternfly/react-core'; } from '@patternfly/react-core';
import { PencilAltIcon } from '@patternfly/react-icons'; import { PencilAltIcon, RocketIcon } from '@patternfly/react-icons';
import styled from 'styled-components'; import styled from 'styled-components';
import DataListCell from '../../../components/DataListCell'; import { SystemJobTemplatesAPI } from '../../../api';
const DataListAction = styled(_DataListAction)` const DataListAction = styled(_DataListAction)`
align-items: center; align-items: center;
display: grid; display: grid;
grid-gap: 16px; grid-gap: 16px;
grid-template-columns: 40px; grid-template-columns: repeat(2, 40px);
`; `;
function ManagementJobListItem({ i18n, isSuperUser, id, name, description }) { function ManagementJobListItem({
i18n,
onLaunchError,
isSuperUser,
id,
name,
description,
}) {
const detailsUrl = `/management_jobs/${id}/details`; const detailsUrl = `/management_jobs/${id}/details`;
const editUrl = `/management_jobs/${id}/edit`; const editUrl = `/management_jobs/${id}/edit`;
const labelId = `mgmt-job-action-${id}`; const labelId = `mgmt-job-action-${id}`;
const history = useHistory();
const [isLaunchLoading, setIsLaunchLoading] = useState(false);
const handleLaunch = async () => {
setIsLaunchLoading(true);
try {
const { data } = await SystemJobTemplatesAPI.launch(id);
history.push(`/jobs/management/${data.id}/output`);
} catch (error) {
onLaunchError(error);
} finally {
setIsLaunchLoading(false);
}
};
return ( return (
<DataListItem key={id} id={id} aria-labelledby={labelId}> <DataListItem key={id} id={id} aria-labelledby={labelId}>
<DataListItemRow> <DataListItemRow>
@@ -54,16 +77,32 @@ function ManagementJobListItem({ i18n, isSuperUser, id, name, description }) {
id={labelId} id={labelId}
> >
{isSuperUser ? ( {isSuperUser ? (
<Tooltip content={i18n._(t`Edit management job`)} position="top"> <>
<Button <Tooltip
aria-label={i18n._(t`Edit management job`)} content={i18n._(t`Launch management job`)}
variant="plain" position="top"
component={Link}
to={editUrl}
> >
<PencilAltIcon /> <Button
</Button> aria-label={i18n._(t`Launch management job`)}
</Tooltip> variant="plain"
onClick={handleLaunch}
isDisabled={isLaunchLoading}
>
<RocketIcon />
</Button>
</Tooltip>
<Tooltip content={i18n._(t`Edit management job`)} position="top">
<Button
aria-label={i18n._(t`Edit management job`)}
variant="plain"
component={Link}
to={editUrl}
isDisabled={isLaunchLoading}
>
<PencilAltIcon />
</Button>
</Tooltip>
</>
) : null} ) : null}
</DataListAction> </DataListAction>
</DataListItemRow> </DataListItemRow>