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:
softwarefactory-project-zuul[bot]
2019-08-14 22:52:38 +00:00
committed by GitHub
2 changed files with 113 additions and 12 deletions

View File

@@ -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

View File

@@ -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();