mirror of
https://github.com/ansible/awx.git
synced 2024-10-31 15:21:13 +03:00
build basic job details
This commit is contained in:
parent
41b0367627
commit
4372e977f0
@ -5,6 +5,11 @@ class Jobs extends Base {
|
||||
super(http);
|
||||
this.baseUrl = '/api/v2/jobs/';
|
||||
}
|
||||
|
||||
readDetail (id, type) {
|
||||
// TODO: adjust url based on type
|
||||
return this.http.get(`${this.baseUrl}${id}/`);
|
||||
}
|
||||
}
|
||||
|
||||
export default Jobs;
|
||||
|
@ -26,7 +26,7 @@ const DetailValue = styled(({ fullWidth, ...props }) => (
|
||||
`;
|
||||
|
||||
const Detail = ({ label, value, fullWidth }) => {
|
||||
if (!value) return null;
|
||||
if (!value && typeof value !== 'number') { return null; }
|
||||
return (
|
||||
<Fragment>
|
||||
<DetailName component={TextListItemVariants.dt} fullWidth={fullWidth}>
|
||||
|
@ -49,7 +49,7 @@ class Job extends Component {
|
||||
|
||||
this.setState({ contentError: null, hasContentLoading: true });
|
||||
try {
|
||||
const { data } = await JobsAPI.readDetail(id);
|
||||
const { data } = await JobsAPI.readDetail(id, match.params.type);
|
||||
setBreadcrumb(data);
|
||||
this.setState({ job: data });
|
||||
} catch (err) {
|
||||
@ -106,17 +106,31 @@ class Job extends Component {
|
||||
<Card>
|
||||
{cardHeader}
|
||||
<Switch>
|
||||
<Redirect from="/jobs/:id" to="/jobs/:id/details" exact />
|
||||
<Redirect
|
||||
from="/jobs/:type/:id"
|
||||
to="/jobs/:type/:id/details"
|
||||
exact
|
||||
/>
|
||||
{job && (
|
||||
<Route
|
||||
path="/jobs/:id/details"
|
||||
render={() => <JobDetail match={match} job={job} />}
|
||||
path="/jobs/:type/:id/details"
|
||||
render={() => (
|
||||
<JobDetail
|
||||
match={match}
|
||||
job={job}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{job && (
|
||||
<Route
|
||||
path="/jobs/:id/output"
|
||||
render={() => <JobOutput match={match} job={job} />}
|
||||
path="/jobs/:type/:id/output"
|
||||
render={() => (
|
||||
<JobOutput
|
||||
match={match}
|
||||
job={job}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</Switch>
|
||||
|
@ -1,35 +1,145 @@
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, useState, useEffect } from 'react';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { CardBody, Button } from '@patternfly/react-core';
|
||||
import styled from 'styled-components';
|
||||
import { DetailList, Detail } from '@components/DetailList';
|
||||
import { ChipGroup, Chip } from '@components/Chip';
|
||||
import ContentError from '@components/ContentError';
|
||||
import ContentLoading from '@components/ContentLoading';
|
||||
import { toTitleCase } from '@util/strings';
|
||||
|
||||
const ActionButtonWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
`;
|
||||
class JobDetail extends Component {
|
||||
render() {
|
||||
const { job, i18n } = this.props;
|
||||
|
||||
return (
|
||||
<CardBody>
|
||||
<b>{job.name}</b>
|
||||
const VERBOSITY = {
|
||||
0: '0 (Normal)',
|
||||
1: '1 (Verbose)',
|
||||
2: '2 (More Verbose)',
|
||||
3: '3 (Debug)',
|
||||
4: '4 (Connection Debug)',
|
||||
};
|
||||
|
||||
<ActionButtonWrapper>
|
||||
<Button
|
||||
variant="secondary"
|
||||
aria-label="close"
|
||||
component={Link}
|
||||
to="/jobs"
|
||||
>
|
||||
{i18n._(t`Close`)}
|
||||
</Button>
|
||||
</ActionButtonWrapper>
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
function JobDetail ({ job, i18n }) {
|
||||
const [instanceGroups, setInstanceGroups] = useState(null);
|
||||
console.log(job);
|
||||
const {
|
||||
job_template: jobTemplate,
|
||||
project,
|
||||
inventory,
|
||||
instance_group: instanceGroup,
|
||||
} = job.summary_fields;
|
||||
|
||||
return (
|
||||
<CardBody>
|
||||
<DetailList>
|
||||
{/* TODO: add status icon? */}
|
||||
<Detail
|
||||
label={i18n._(t`Status`)}
|
||||
value={toTitleCase(job.status)}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Started`)}
|
||||
value={job.started}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Finished`)}
|
||||
value={job.finished}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Template`)}
|
||||
value={(
|
||||
<Link to={`/templates/job_template/${jobTemplate.id}`}>
|
||||
{jobTemplate.name}
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Job Type`)}
|
||||
value={toTitleCase(job.job_type)}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Inventory`)}
|
||||
value={(
|
||||
<Link to={`/inventory/${inventory.id}`}>
|
||||
{inventory.name}
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
{/* TODO: show project status icon */}
|
||||
<Detail
|
||||
label={i18n._(t`Project`)}
|
||||
value={(
|
||||
<Link to={`/projects/${project.id}`}>
|
||||
{project.name}
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Revision`)}
|
||||
value={job.scm_revision}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Playbook`)}
|
||||
value={null}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Limit`)}
|
||||
value={job.limit}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Verbosity`)}
|
||||
value={VERBOSITY[job.verbosity]}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Environment`)}
|
||||
value={null}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Execution Node`)}
|
||||
value={job.exucution_node}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Instance Group`)}
|
||||
value={(
|
||||
<Link to={`/instance_groups/${instanceGroup.id}`}>
|
||||
{instanceGroup.name}
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
<Detail
|
||||
label={i18n._(t`Job Slice`)}
|
||||
value={`${job.job_slice_number}/${job.job_slice_count}`}
|
||||
/>
|
||||
{(instanceGroups && instanceGroups.length > 0) && (
|
||||
<Detail
|
||||
fullWidth
|
||||
label={i18n._(t`Instance Groups`)}
|
||||
value={(
|
||||
<ChipGroup showOverflowAfter={5}>
|
||||
{instanceGroups.map(ig => (
|
||||
<Chip key={ig.id} isReadOnly>{ig.name}</Chip>
|
||||
))}
|
||||
</ChipGroup>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</DetailList>
|
||||
<ActionButtonWrapper>
|
||||
<Button
|
||||
variant="secondary"
|
||||
aria-label="close"
|
||||
component={Link}
|
||||
to="/jobs"
|
||||
>
|
||||
{i18n._(t`Close`)}
|
||||
</Button>
|
||||
</ActionButtonWrapper>
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
|
||||
export default withI18n()(withRouter(JobDetail));
|
||||
|
@ -32,7 +32,7 @@ class JobListItem extends Component {
|
||||
<DataListCell key="divider">
|
||||
<VerticalSeparator />
|
||||
<span>
|
||||
<Link to={`/jobs/${job.id}`}>
|
||||
<Link to={`/jobs/${job.type}/${job.id}`}>
|
||||
<b>{job.name}</b>
|
||||
</Link>
|
||||
</span>
|
||||
|
@ -58,7 +58,7 @@ class Jobs extends Component {
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/:id`}
|
||||
path={`${match.path}/:type/:id`}
|
||||
render={() => (
|
||||
<Job
|
||||
history={history}
|
||||
|
Loading…
Reference in New Issue
Block a user