build basic job details

This commit is contained in:
Keith Grant
2019-06-25 15:31:14 -07:00
parent 41b0367627
commit 4372e977f0
6 changed files with 158 additions and 29 deletions

View File

@@ -5,6 +5,11 @@ class Jobs extends Base {
super(http); super(http);
this.baseUrl = '/api/v2/jobs/'; this.baseUrl = '/api/v2/jobs/';
} }
readDetail (id, type) {
// TODO: adjust url based on type
return this.http.get(`${this.baseUrl}${id}/`);
}
} }
export default Jobs; export default Jobs;

View File

@@ -26,7 +26,7 @@ const DetailValue = styled(({ fullWidth, ...props }) => (
`; `;
const Detail = ({ label, value, fullWidth }) => { const Detail = ({ label, value, fullWidth }) => {
if (!value) return null; if (!value && typeof value !== 'number') { return null; }
return ( return (
<Fragment> <Fragment>
<DetailName component={TextListItemVariants.dt} fullWidth={fullWidth}> <DetailName component={TextListItemVariants.dt} fullWidth={fullWidth}>

View File

@@ -49,7 +49,7 @@ class Job extends Component {
this.setState({ contentError: null, hasContentLoading: true }); this.setState({ contentError: null, hasContentLoading: true });
try { try {
const { data } = await JobsAPI.readDetail(id); const { data } = await JobsAPI.readDetail(id, match.params.type);
setBreadcrumb(data); setBreadcrumb(data);
this.setState({ job: data }); this.setState({ job: data });
} catch (err) { } catch (err) {
@@ -106,17 +106,31 @@ class Job extends Component {
<Card> <Card>
{cardHeader} {cardHeader}
<Switch> <Switch>
<Redirect from="/jobs/:id" to="/jobs/:id/details" exact /> <Redirect
from="/jobs/:type/:id"
to="/jobs/:type/:id/details"
exact
/>
{job && ( {job && (
<Route <Route
path="/jobs/:id/details" path="/jobs/:type/:id/details"
render={() => <JobDetail match={match} job={job} />} render={() => (
<JobDetail
match={match}
job={job}
/>
)}
/> />
)} )}
{job && ( {job && (
<Route <Route
path="/jobs/:id/output" path="/jobs/:type/:id/output"
render={() => <JobOutput match={match} job={job} />} render={() => (
<JobOutput
match={match}
job={job}
/>
)}
/> />
)} )}
</Switch> </Switch>

View File

@@ -1,35 +1,145 @@
import React, { Component } from 'react'; import React, { Component, useState, useEffect } from 'react';
import { Link, withRouter } from 'react-router-dom'; import { Link, withRouter } from 'react-router-dom';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { CardBody, Button } from '@patternfly/react-core'; import { CardBody, Button } from '@patternfly/react-core';
import styled from 'styled-components'; 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` const ActionButtonWrapper = styled.div`
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
`; `;
class JobDetail extends Component {
render() {
const { job, i18n } = this.props;
return ( const VERBOSITY = {
<CardBody> 0: '0 (Normal)',
<b>{job.name}</b> 1: '1 (Verbose)',
2: '2 (More Verbose)',
3: '3 (Debug)',
4: '4 (Connection Debug)',
};
<ActionButtonWrapper> function JobDetail ({ job, i18n }) {
<Button const [instanceGroups, setInstanceGroups] = useState(null);
variant="secondary" console.log(job);
aria-label="close" const {
component={Link} job_template: jobTemplate,
to="/jobs" project,
> inventory,
{i18n._(t`Close`)} instance_group: instanceGroup,
</Button> } = job.summary_fields;
</ActionButtonWrapper>
</CardBody> 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)); export default withI18n()(withRouter(JobDetail));

View File

@@ -32,7 +32,7 @@ class JobListItem extends Component {
<DataListCell key="divider"> <DataListCell key="divider">
<VerticalSeparator /> <VerticalSeparator />
<span> <span>
<Link to={`/jobs/${job.id}`}> <Link to={`/jobs/${job.type}/${job.id}`}>
<b>{job.name}</b> <b>{job.name}</b>
</Link> </Link>
</span> </span>

View File

@@ -58,7 +58,7 @@ class Jobs extends Component {
)} )}
/> />
<Route <Route
path={`${match.path}/:id`} path={`${match.path}/:type/:id`}
render={() => ( render={() => (
<Job <Job
history={history} history={history}