mirror of
https://github.com/ansible/awx.git
synced 2026-05-18 06:47:41 -02:30
Merge pull request #4251 from AlexSCorey/JTLaunchButton
Add Launch Button to Job Template Details Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
This commit is contained in:
@@ -1,9 +1,6 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { number } from 'prop-types';
|
import { number } from 'prop-types';
|
||||||
import { Button, Tooltip } from '@patternfly/react-core';
|
|
||||||
import { RocketIcon } from '@patternfly/react-icons';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
@@ -11,15 +8,6 @@ import AlertModal from '@components/AlertModal';
|
|||||||
import ErrorDetail from '@components/ErrorDetail';
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
import { JobTemplatesAPI } from '@api';
|
import { JobTemplatesAPI } from '@api';
|
||||||
|
|
||||||
const StyledLaunchButton = styled(Button)`
|
|
||||||
padding: 5px 8px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #0066cc;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
class LaunchButton extends React.Component {
|
class LaunchButton extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
templateId: number.isRequired,
|
templateId: number.isRequired,
|
||||||
@@ -65,20 +53,10 @@ class LaunchButton extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { launchError, promptError } = this.state;
|
const { launchError, promptError } = this.state;
|
||||||
const { i18n } = this.props;
|
const { i18n, children } = this.props;
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Tooltip content={i18n._(t`Launch Job`)} position="top">
|
{children(this.handleLaunch)}
|
||||||
<div>
|
|
||||||
<StyledLaunchButton
|
|
||||||
variant="plain"
|
|
||||||
aria-label={i18n._(t`Launch`)}
|
|
||||||
onClick={this.handleLaunch}
|
|
||||||
>
|
|
||||||
<RocketIcon />
|
|
||||||
</StyledLaunchButton>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={launchError}
|
isOpen={launchError}
|
||||||
variant="danger"
|
variant="danger"
|
||||||
|
|||||||
@@ -13,9 +13,14 @@ describe('LaunchButton', () => {
|
|||||||
can_start_without_user_input: true,
|
can_start_without_user_input: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const children = handleLaunch => (
|
||||||
|
<button type="submit" onClick={handleLaunch} />
|
||||||
|
);
|
||||||
|
|
||||||
test('renders the expected content', () => {
|
test('renders the expected content', () => {
|
||||||
const wrapper = mountWithContexts(<LaunchButton templateId={1} />);
|
const wrapper = mountWithContexts(
|
||||||
|
<LaunchButton templateId={1}>{children}</LaunchButton>
|
||||||
|
);
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(wrapper).toHaveLength(1);
|
||||||
});
|
});
|
||||||
test('redirects to details after successful launch', async done => {
|
test('redirects to details after successful launch', async done => {
|
||||||
@@ -27,15 +32,18 @@ describe('LaunchButton', () => {
|
|||||||
id: 9000,
|
id: 9000,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const wrapper = mountWithContexts(<LaunchButton templateId={1} />, {
|
const wrapper = mountWithContexts(
|
||||||
context: {
|
<LaunchButton templateId={1}>{children}</LaunchButton>,
|
||||||
router: { history },
|
{
|
||||||
},
|
context: {
|
||||||
});
|
router: { history },
|
||||||
const launchButton = wrapper.find('LaunchButton__StyledLaunchButton');
|
},
|
||||||
launchButton.simulate('click');
|
}
|
||||||
await sleep(0);
|
);
|
||||||
|
const button = wrapper.find('button');
|
||||||
|
button.prop('onClick')();
|
||||||
expect(JobTemplatesAPI.readLaunch).toHaveBeenCalledWith(1);
|
expect(JobTemplatesAPI.readLaunch).toHaveBeenCalledWith(1);
|
||||||
|
await sleep(0);
|
||||||
expect(JobTemplatesAPI.launch).toHaveBeenCalledWith(1);
|
expect(JobTemplatesAPI.launch).toHaveBeenCalledWith(1);
|
||||||
expect(history.push).toHaveBeenCalledWith('/jobs/9000/details');
|
expect(history.push).toHaveBeenCalledWith('/jobs/9000/details');
|
||||||
done();
|
done();
|
||||||
@@ -53,9 +61,11 @@ describe('LaunchButton', () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const wrapper = mountWithContexts(<LaunchButton templateId={1} />);
|
const wrapper = mountWithContexts(
|
||||||
const launchButton = wrapper.find('LaunchButton__StyledLaunchButton');
|
<LaunchButton templateId={1}>{children}</LaunchButton>
|
||||||
launchButton.simulate('click');
|
);
|
||||||
|
const button = wrapper.find('button');
|
||||||
|
button.prop('onClick')();
|
||||||
await waitForElement(
|
await waitForElement(
|
||||||
wrapper,
|
wrapper,
|
||||||
'Modal.at-c-alertModal--danger',
|
'Modal.at-c-alertModal--danger',
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import styled from 'styled-components';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
import ContentError from '@components/ContentError';
|
import ContentError from '@components/ContentError';
|
||||||
|
import LaunchButton from '@components/LaunchButton';
|
||||||
import ContentLoading from '@components/ContentLoading';
|
import ContentLoading from '@components/ContentLoading';
|
||||||
import { ChipGroup, Chip } from '@components/Chip';
|
import { ChipGroup, Chip } from '@components/Chip';
|
||||||
import { DetailList, Detail } from '@components/DetailList';
|
import { DetailList, Detail } from '@components/DetailList';
|
||||||
@@ -83,9 +84,11 @@ class JobTemplateDetail extends Component {
|
|||||||
verbosity,
|
verbosity,
|
||||||
},
|
},
|
||||||
hasTemplateLoading,
|
hasTemplateLoading,
|
||||||
|
template,
|
||||||
i18n,
|
i18n,
|
||||||
match,
|
match,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const canLaunch = summary_fields.user_capabilities.start;
|
||||||
const { instanceGroups, hasContentLoading, contentError } = this.state;
|
const { instanceGroups, hasContentLoading, contentError } = this.state;
|
||||||
const verbosityOptions = [
|
const verbosityOptions = [
|
||||||
{ verbosity: 0, details: i18n._(t`0 (Normal)`) },
|
{ verbosity: 0, details: i18n._(t`0 (Normal)`) },
|
||||||
@@ -286,14 +289,25 @@ class JobTemplateDetail extends Component {
|
|||||||
{i18n._(t`Edit`)}
|
{i18n._(t`Edit`)}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button
|
{canLaunch && (
|
||||||
variant="secondary"
|
<LaunchButton
|
||||||
component={Link}
|
variant="secondary"
|
||||||
to="/templates"
|
component={Link}
|
||||||
aria-label={i18n._(t`Launch`)}
|
to="/templates"
|
||||||
>
|
templateId={template.id}
|
||||||
{i18n._(t`Launch`)}
|
aria-label={i18n._(t`Launch`)}
|
||||||
</Button>
|
>
|
||||||
|
{handleLaunch => (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
type="submit"
|
||||||
|
onClick={handleLaunch}
|
||||||
|
>
|
||||||
|
{i18n._(t`Launch`)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</LaunchButton>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
component={Link}
|
component={Link}
|
||||||
|
|||||||
@@ -5,16 +5,30 @@ import {
|
|||||||
DataListItemRow,
|
DataListItemRow,
|
||||||
DataListItemCells,
|
DataListItemCells,
|
||||||
DataListCheck,
|
DataListCheck,
|
||||||
|
Tooltip,
|
||||||
|
Button as PFButton,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { withI18n } from '@lingui/react';
|
||||||
|
import { RocketIcon } from '@patternfly/react-icons';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import DataListCell from '@components/DataListCell';
|
import DataListCell from '@components/DataListCell';
|
||||||
import LaunchButton from '@components/LaunchButton';
|
import LaunchButton from '@components/LaunchButton';
|
||||||
import VerticalSeparator from '@components/VerticalSeparator';
|
import VerticalSeparator from '@components/VerticalSeparator';
|
||||||
import { toTitleCase } from '@util/strings';
|
import { toTitleCase } from '@util/strings';
|
||||||
|
|
||||||
|
const StyledButton = styled(PFButton)`
|
||||||
|
padding: 5px 8px;
|
||||||
|
border: none;
|
||||||
|
&:hover {
|
||||||
|
background-color: #0066cc;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
`;
|
||||||
class TemplateListItem extends Component {
|
class TemplateListItem extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { template, isSelected, onSelect } = this.props;
|
const { i18n, template, isSelected, onSelect } = this.props;
|
||||||
const canLaunch = template.summary_fields.user_capabilities.start;
|
const canLaunch = template.summary_fields.user_capabilities.start;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -44,7 +58,19 @@ class TemplateListItem extends Component {
|
|||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell lastcolumn="true" key="launch">
|
<DataListCell lastcolumn="true" key="launch">
|
||||||
{canLaunch && template.type === 'job_template' && (
|
{canLaunch && template.type === 'job_template' && (
|
||||||
<LaunchButton templateId={template.id} />
|
<Tooltip content={i18n._(t`Launch`)} position="top">
|
||||||
|
<LaunchButton
|
||||||
|
component={Link}
|
||||||
|
to="/templates"
|
||||||
|
templateId={template.id}
|
||||||
|
>
|
||||||
|
{handleLaunch => (
|
||||||
|
<StyledButton variant="plain" onClick={handleLaunch}>
|
||||||
|
<RocketIcon />
|
||||||
|
</StyledButton>
|
||||||
|
)}
|
||||||
|
</LaunchButton>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
]}
|
]}
|
||||||
@@ -55,4 +81,4 @@ class TemplateListItem extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export { TemplateListItem as _TemplateListItem };
|
export { TemplateListItem as _TemplateListItem };
|
||||||
export default TemplateListItem;
|
export default withI18n()(TemplateListItem);
|
||||||
|
|||||||
Reference in New Issue
Block a user