diff --git a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx index f273971034..48bc97bf73 100644 --- a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx @@ -38,6 +38,14 @@ class PaginatedDataList extends React.Component { this.handleSort = this.handleSort.bind(this); } + componentDidUpdate(prevProps) { + const { itemCount: prevItemCount } = prevProps; + const { itemCount } = this.props; + if (prevItemCount !== itemCount) { + this.getCurrPage(itemCount); + } + } + getSortOrder() { const { qsConfig, location } = this.props; const queryParams = parseNamespacedQueryString(qsConfig, location.search); @@ -47,6 +55,21 @@ class PaginatedDataList extends React.Component { return [queryParams.order_by, 'ascending']; } + getCurrPage(itemCount) { + if (itemCount < 0) { + return; + } + const { qsConfig, location } = this.props; + const { page_size, page: currPage } = parseNamespacedQueryString( + qsConfig, + location.search + ); + const lastPage = Math.ceil(itemCount / page_size); + if (currPage > lastPage) { + this.pushHistoryState({ page: lastPage || 1 }); + } + } + handleSetPage(event, pageNumber) { this.pushHistoryState({ page: pageNumber }); } diff --git a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.test.jsx b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.test.jsx index e8182d7616..1c9a22c374 100644 --- a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.test.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.test.jsx @@ -10,6 +10,8 @@ const mockData = [ { id: 3, name: 'three', url: '/org/team/3' }, { id: 4, name: 'four', url: '/org/team/4' }, { id: 5, name: 'five', url: '/org/team/5' }, + { id: 6, name: 'six', url: '/org/team/6' }, + { id: 7, name: 'seven', url: '/org/team/7' }, ]; const qsConfig = { @@ -123,4 +125,37 @@ describe('', () => { pagination.prop('onPerPageSelect')(null, 25); expect(history.location.search).toEqual('?item.page_size=25'); }); + test('should navigate to correct current page when list items change', () => { + const customQSConfig = { + namespace: 'foo', + defaultParams: { page: 7, page_size: 1 }, // show only 1 item per page + integerFields: [], + }; + const testParams = [5, 25, 0, -1]; // number of items + const expected = [5, 5, 1, 1]; // expected current page + const history = createMemoryHistory({ + initialEntries: ['/organizations/1/teams'], + }); + const wrapper = mountWithContexts( + , + { context: { router: { history } } } + ); + testParams.forEach((param, i) => { + wrapper.setProps({ itemCount: param }); + expect(history.location.search).toEqual( + `?${customQSConfig.namespace}.page=${expected[i]}` + ); + wrapper.update(); + }); + wrapper.unmount(); + }); }); diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx index fb07b0e7f1..037241a156 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx @@ -76,11 +76,12 @@ class OrganizationsList extends Component { } async handleOrgDelete() { - const { selected } = this.state; + const { selected, itemCount } = this.state; this.setState({ hasContentLoading: true }); try { await Promise.all(selected.map(org => OrganizationsAPI.destroy(org.id))); + this.setState({ itemCount: itemCount - selected.length }); } catch (err) { this.setState({ deletionError: err }); } finally { diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index 4ac2956c5e..93c3352790 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -78,7 +78,7 @@ class TemplatesList extends Component { } async handleTemplateDelete() { - const { selected } = this.state; + const { selected, itemCount } = this.state; this.setState({ hasContentLoading: true }); try { @@ -93,6 +93,7 @@ class TemplatesList extends Component { return deletePromise; }) ); + this.setState({ itemCount: itemCount - selected.length }); } catch (err) { this.setState({ deletionError: err }); } finally {