mirror of
https://github.com/ansible/awx.git
synced 2026-02-17 19:20:05 -03:30
Merge pull request #4305 from catjones9/jobTemplateAddButton
Adds Job Template Add Button to TemplatesList with link to add form Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
This commit is contained in:
@@ -1,18 +1,23 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter, Link } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
|
||||||
import { Card, PageSection, PageSectionVariants } from '@patternfly/react-core';
|
|
||||||
|
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
JobTemplatesAPI,
|
Card,
|
||||||
UnifiedJobTemplatesAPI,
|
PageSection,
|
||||||
WorkflowJobTemplatesAPI,
|
PageSectionVariants,
|
||||||
} from '@api';
|
Dropdown,
|
||||||
|
DropdownItem,
|
||||||
|
DropdownPosition,
|
||||||
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
|
import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '@api';
|
||||||
import AlertModal from '@components/AlertModal';
|
import AlertModal from '@components/AlertModal';
|
||||||
import DatalistToolbar from '@components/DataListToolbar';
|
import DatalistToolbar from '@components/DataListToolbar';
|
||||||
import PaginatedDataList, {
|
import PaginatedDataList, {
|
||||||
ToolbarDeleteButton,
|
ToolbarDeleteButton,
|
||||||
|
ToolbarAddButton,
|
||||||
} from '@components/PaginatedDataList';
|
} from '@components/PaginatedDataList';
|
||||||
import { getQSConfig, parseQueryString } from '@util/qs';
|
import { getQSConfig, parseQueryString } from '@util/qs';
|
||||||
|
|
||||||
@@ -38,12 +43,15 @@ class TemplatesList extends Component {
|
|||||||
selected: [],
|
selected: [],
|
||||||
templates: [],
|
templates: [],
|
||||||
itemCount: 0,
|
itemCount: 0,
|
||||||
|
isAddOpen: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loadTemplates = this.loadTemplates.bind(this);
|
this.loadTemplates = this.loadTemplates.bind(this);
|
||||||
this.handleSelectAll = this.handleSelectAll.bind(this);
|
this.handleSelectAll = this.handleSelectAll.bind(this);
|
||||||
this.handleSelect = this.handleSelect.bind(this);
|
this.handleSelect = this.handleSelect.bind(this);
|
||||||
this.handleTemplateDelete = this.handleTemplateDelete.bind(this);
|
this.handleTemplateDelete = this.handleTemplateDelete.bind(this);
|
||||||
this.handleDeleteErrorClose = this.handleDeleteErrorClose.bind(this);
|
this.handleDeleteErrorClose = this.handleDeleteErrorClose.bind(this);
|
||||||
|
this.handleAddToggle = this.handleAddToggle.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -76,8 +84,13 @@ class TemplatesList extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleAddToggle() {
|
||||||
|
const { isAddOpen } = this.state;
|
||||||
|
this.setState({ isAddOpen: !isAddOpen });
|
||||||
|
}
|
||||||
|
|
||||||
async handleTemplateDelete() {
|
async handleTemplateDelete() {
|
||||||
const { selected } = this.state;
|
const { selected, itemCount } = this.state;
|
||||||
|
|
||||||
this.setState({ hasContentLoading: true, hasDeletionError: false });
|
this.setState({ hasContentLoading: true, hasDeletionError: false });
|
||||||
try {
|
try {
|
||||||
@@ -92,6 +105,7 @@ class TemplatesList extends Component {
|
|||||||
return deletePromise;
|
return deletePromise;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
this.setState({ itemCount: itemCount - selected.length });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.setState({ hasDeletionError: true });
|
this.setState({ hasDeletionError: true });
|
||||||
} finally {
|
} finally {
|
||||||
@@ -101,14 +115,35 @@ class TemplatesList extends Component {
|
|||||||
|
|
||||||
async loadTemplates() {
|
async loadTemplates() {
|
||||||
const { location } = this.props;
|
const { location } = this.props;
|
||||||
|
const { actions: cachedActions } = this.state;
|
||||||
const params = parseQueryString(QS_CONFIG, location.search);
|
const params = parseQueryString(QS_CONFIG, location.search);
|
||||||
|
|
||||||
|
let optionsPromise;
|
||||||
|
if (cachedActions) {
|
||||||
|
optionsPromise = Promise.resolve({ data: { actions: cachedActions } });
|
||||||
|
} else {
|
||||||
|
optionsPromise = JobTemplatesAPI.readOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
const promises = Promise.all([
|
||||||
|
JobTemplatesAPI.read(params),
|
||||||
|
optionsPromise,
|
||||||
|
]);
|
||||||
|
|
||||||
this.setState({ contentError: null, hasContentLoading: true });
|
this.setState({ contentError: null, hasContentLoading: true });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const {
|
const [
|
||||||
data: { count, results },
|
{
|
||||||
} = await UnifiedJobTemplatesAPI.read(params);
|
data: { count, results },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: { actions },
|
||||||
|
},
|
||||||
|
] = await promises;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
actions,
|
||||||
itemCount: count,
|
itemCount: count,
|
||||||
templates: results,
|
templates: results,
|
||||||
selected: [],
|
selected: [],
|
||||||
@@ -128,8 +163,12 @@ class TemplatesList extends Component {
|
|||||||
templates,
|
templates,
|
||||||
itemCount,
|
itemCount,
|
||||||
selected,
|
selected,
|
||||||
|
isAddOpen,
|
||||||
|
actions,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { match, i18n } = this.props;
|
const { match, i18n } = this.props;
|
||||||
|
const canAdd =
|
||||||
|
actions && Object.prototype.hasOwnProperty.call(actions, 'POST');
|
||||||
const isAllSelected = selected.length === templates.length;
|
const isAllSelected = selected.length === templates.length;
|
||||||
const { medium } = PageSectionVariants;
|
const { medium } = PageSectionVariants;
|
||||||
return (
|
return (
|
||||||
@@ -176,6 +215,34 @@ class TemplatesList extends Component {
|
|||||||
itemsToDelete={selected}
|
itemsToDelete={selected}
|
||||||
itemName={i18n._(t`Template`)}
|
itemName={i18n._(t`Template`)}
|
||||||
/>,
|
/>,
|
||||||
|
canAdd && (
|
||||||
|
<Dropdown
|
||||||
|
key="add"
|
||||||
|
isPlain
|
||||||
|
isOpen={isAddOpen}
|
||||||
|
position={DropdownPosition.right}
|
||||||
|
onSelect={this.handleAddSelect}
|
||||||
|
toggle={
|
||||||
|
<ToolbarAddButton onClick={this.handleAddToggle} />
|
||||||
|
}
|
||||||
|
dropdownItems={[
|
||||||
|
<DropdownItem
|
||||||
|
key="job"
|
||||||
|
component={Link}
|
||||||
|
to={`${match.url}/job_template/add`}
|
||||||
|
>
|
||||||
|
{i18n._(t`Job Template`)}
|
||||||
|
</DropdownItem>,
|
||||||
|
<DropdownItem
|
||||||
|
key="workflow"
|
||||||
|
component={Link}
|
||||||
|
to={`${match.url}/add`}
|
||||||
|
>
|
||||||
|
{i18n._(t`Workflow Template`)}
|
||||||
|
</DropdownItem>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -189,6 +256,34 @@ class TemplatesList extends Component {
|
|||||||
isSelected={selected.some(row => row.id === template.id)}
|
isSelected={selected.some(row => row.id === template.id)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
emptyStateControls={
|
||||||
|
canAdd && (
|
||||||
|
<Dropdown
|
||||||
|
key="add"
|
||||||
|
isPlain
|
||||||
|
isOpen={isAddOpen}
|
||||||
|
position={DropdownPosition.right}
|
||||||
|
onSelect={this.handleAddSelect}
|
||||||
|
toggle={<ToolbarAddButton onClick={this.handleAddToggle} />}
|
||||||
|
dropdownItems={[
|
||||||
|
<DropdownItem
|
||||||
|
key="job"
|
||||||
|
component={Link}
|
||||||
|
to={`${match.url}/job_template/add/`}
|
||||||
|
>
|
||||||
|
{i18n._(t`Job Template`)}
|
||||||
|
</DropdownItem>,
|
||||||
|
<DropdownItem
|
||||||
|
key="workflow"
|
||||||
|
component={Link}
|
||||||
|
to={`${match.url}_workflow/add/`}
|
||||||
|
>
|
||||||
|
{i18n._(t`Workflow Template`)}
|
||||||
|
</DropdownItem>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
<AlertModal
|
<AlertModal
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ describe('<TemplatesList />', () => {
|
|||||||
results: mockTemplates,
|
results: mockTemplates,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
UnifiedJobTemplatesAPI.readOptions.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
actions: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -116,7 +122,7 @@ describe('<TemplatesList />', () => {
|
|||||||
'TemplatesList',
|
'TemplatesList',
|
||||||
el => el.state('hasContentLoading') === false
|
el => el.state('hasContentLoading') === false
|
||||||
);
|
);
|
||||||
wrapper
|
await wrapper
|
||||||
.find('DataListCheck#select-jobTemplate-1')
|
.find('DataListCheck#select-jobTemplate-1')
|
||||||
.props()
|
.props()
|
||||||
.onChange();
|
.onChange();
|
||||||
|
|||||||
Reference in New Issue
Block a user