diff --git a/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx b/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx
index 3374fd90bb..c3ef0ebff5 100644
--- a/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx
+++ b/awx/ui_next/src/screens/Credential/CredentialList/CredentialList.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { useLocation } from 'react-router-dom';
+import { useLocation, useHistory } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { CredentialsAPI } from '@api';
@@ -11,7 +11,12 @@ import PaginatedDataList, {
ToolbarAddButton,
ToolbarDeleteButton,
} from '@components/PaginatedDataList';
-import { getQSConfig, parseQueryString } from '@util/qs';
+import {
+ getQSConfig,
+ parseQueryString,
+ replaceParams,
+ encodeNonDefaultQueryString,
+} from '@util/qs';
import { CredentialListItem } from '.';
const QS_CONFIG = getQSConfig('credential', {
@@ -30,6 +35,7 @@ function CredentialList({ i18n }) {
const [selected, setSelected] = useState([]);
const location = useLocation();
+ const history = useHistory();
const loadCredentials = async ({ search }) => {
const params = parseQueryString(QS_CONFIG, search);
@@ -92,20 +98,21 @@ function CredentialList({ i18n }) {
setDeletionError(error);
}
+ adjustPagination();
+ setSelected([]);
+ };
+
+ const adjustPagination = () => {
const params = parseQueryString(QS_CONFIG, location.search);
- try {
- const {
- data: { count, results },
- } = await CredentialsAPI.read(params);
-
- setCredentials(results);
- setCredentialCount(count);
- setSelected([]);
- } catch (error) {
- setContentError(error);
+ if (params.page > 1 && selected.length === credentials.length) {
+ const newParams = encodeNonDefaultQueryString(
+ QS_CONFIG,
+ replaceParams(params, { page: params.page - 1 })
+ );
+ history.push(`${location.pathname}?${newParams}`);
+ } else {
+ loadCredentials(location);
}
-
- setHasContentLoading(false);
};
const canAdd =
diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx
index 3051861a05..02b176ffda 100644
--- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx
+++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback } from 'react';
-import { useLocation, useRouteMatch } from 'react-router-dom';
+import { useLocation, useHistory, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Card, PageSection } from '@patternfly/react-core';
@@ -13,7 +13,12 @@ import PaginatedDataList, {
ToolbarAddButton,
ToolbarDeleteButton,
} from '@components/PaginatedDataList';
-import { getQSConfig, parseQueryString } from '@util/qs';
+import {
+ getQSConfig,
+ parseQueryString,
+ replaceParams,
+ encodeNonDefaultQueryString,
+} from '@util/qs';
import OrganizationListItem from './OrganizationListItem';
@@ -25,6 +30,7 @@ const QS_CONFIG = getQSConfig('organization', {
function OrganizationsList({ i18n }) {
const location = useLocation();
+ const history = useHistory();
const match = useRouteMatch();
const [selected, setSelected] = useState([]);
@@ -81,7 +87,21 @@ function OrganizationsList({ i18n }) {
const handleOrgDelete = async () => {
await deleteOrganizations();
- await fetchOrganizations();
+ await adjustPagination();
+ setSelected([]);
+ };
+
+ const adjustPagination = () => {
+ const params = parseQueryString(QS_CONFIG, location.search);
+ if (params.page > 1 && selected.length === organizations.length) {
+ const newParams = encodeNonDefaultQueryString(
+ QS_CONFIG,
+ replaceParams(params, { page: params.page - 1 })
+ );
+ history.push(`${location.pathname}?${newParams}`);
+ } else {
+ fetchOrganizations();
+ }
};
const hasContentLoading = isDeleteLoading || isOrgsLoading;
diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx
index ce24889924..8937a2e364 100644
--- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx
+++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx
@@ -29,7 +29,7 @@ const QS_CONFIG = getQSConfig('template', {
type: 'job_template,workflow_job_template',
});
-function TemplatesList({ i18n }) {
+function TemplateList({ i18n }) {
const { id: projectId } = useParams();
const { pathname, search } = useLocation();
@@ -268,5 +268,4 @@ function TemplatesList({ i18n }) {
);
}
-export { TemplatesList as _TemplatesList };
-export default withI18n()(TemplatesList);
+export default withI18n()(TemplateList);
diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplatesList.test.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.test.jsx
similarity index 94%
rename from awx/ui_next/src/screens/Template/TemplateList/TemplatesList.test.jsx
rename to awx/ui_next/src/screens/Template/TemplateList/TemplateList.test.jsx
index 58eefbbe5b..d80a244b27 100644
--- a/awx/ui_next/src/screens/Template/TemplateList/TemplatesList.test.jsx
+++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.test.jsx
@@ -9,7 +9,7 @@ import {
} from '@api';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
-import TemplatesList from './TemplateList';
+import TemplateList from './TemplateList';
jest.mock('@api');
@@ -71,7 +71,7 @@ const mockTemplates = [
},
];
-describe('', () => {
+describe('', () => {
beforeEach(() => {
UnifiedJobTemplatesAPI.read.mockResolvedValue({
data: {
@@ -94,7 +94,7 @@ describe('', () => {
test('initially renders successfully', async () => {
await act(async () => {
mountWithContexts(
-
@@ -105,7 +105,7 @@ describe('', () => {
test('Templates are retrieved from the api and the components finishes loading', async () => {
let wrapper;
await act(async () => {
- wrapper = mountWithContexts();
+ wrapper = mountWithContexts();
});
expect(UnifiedJobTemplatesAPI.read).toBeCalled();
await act(async () => {
@@ -115,7 +115,7 @@ describe('', () => {
});
test('handleSelect is called when a template list item is selected', async () => {
- const wrapper = mountWithContexts();
+ const wrapper = mountWithContexts();
await act(async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
@@ -143,7 +143,7 @@ describe('', () => {
});
test('handleSelectAll is called when a template list item is selected', async () => {
- const wrapper = mountWithContexts();
+ const wrapper = mountWithContexts();
await act(async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
@@ -158,7 +158,7 @@ describe('', () => {
});
test('delete button is disabled if user does not have delete capabilities on a selected template', async () => {
- const wrapper = mountWithContexts();
+ const wrapper = mountWithContexts();
await act(async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
@@ -217,7 +217,7 @@ describe('', () => {
});
test('api is called to delete templates for each selected template.', async () => {
- const wrapper = mountWithContexts();
+ const wrapper = mountWithContexts();
await act(async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
@@ -277,7 +277,7 @@ describe('', () => {
},
})
);
- const wrapper = mountWithContexts();
+ const wrapper = mountWithContexts();
await act(async () => {
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
});
@@ -315,7 +315,7 @@ describe('', () => {
const wrapper = mountWithContexts(
}
+ component={() => }
/>,
{
context: {
diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplatesListItem.test.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateListItem.test.jsx
similarity index 93%
rename from awx/ui_next/src/screens/Template/TemplateList/TemplatesListItem.test.jsx
rename to awx/ui_next/src/screens/Template/TemplateList/TemplateListItem.test.jsx
index 8a340f1e62..8fa48e08d6 100644
--- a/awx/ui_next/src/screens/Template/TemplateList/TemplatesListItem.test.jsx
+++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateListItem.test.jsx
@@ -2,12 +2,12 @@ import React from 'react';
import { mountWithContexts } from '@testUtils/enzymeHelpers';
-import TemplatesListItem from './TemplateListItem';
+import TemplateListItem from './TemplateListItem';
-describe('', () => {
+describe('', () => {
test('launch button shown to users with start capabilities', () => {
const wrapper = mountWithContexts(
- ', () => {
});
test('launch button hidden from users without start capabilities', () => {
const wrapper = mountWithContexts(
- ', () => {
});
test('edit button shown to users with edit capabilities', () => {
const wrapper = mountWithContexts(
- ', () => {
});
test('edit button hidden from users without edit capabilities', () => {
const wrapper = mountWithContexts(
- ', () => {
});
test('missing resource icon is shown.', () => {
const wrapper = mountWithContexts(
- ', () => {
});
test('missing resource icon is not shown when there is a project and an inventory.', () => {
const wrapper = mountWithContexts(
- ', () => {
});
test('missing resource icon is not shown when inventory is prompt_on_launch, and a project', () => {
const wrapper = mountWithContexts(
- ', () => {
});
test('missing resource icon is not shown type is workflow_job_template', () => {
const wrapper = mountWithContexts(
-