diff --git a/src/actions/__tests__/form-template-actions.test.js b/src/actions/__tests__/form-template-actions.test.js
new file mode 100644
index 000000000..d0c3ea4b0
--- /dev/null
+++ b/src/actions/__tests__/form-template-actions.test.js
@@ -0,0 +1,82 @@
+import { createStore, combineReducers, applyMiddleware } from "redux";
+import thunk from "redux-thunk";
+import flushPromises from "flush-promises";
+import {
+ putRequest,
+ getRequest
+} from "openstack-uicore-foundation/lib/utils/actions";
+import {
+ archiveFormTemplate,
+ RECEIVE_FORM_TEMPLATES
+} from "../form-template-actions";
+import formTemplateListReducer from "../../reducers/sponsors_inventory/form-template-list-reducer";
+import * as methods from "../../utils/methods";
+
+jest.mock("openstack-uicore-foundation/lib/utils/actions", () => ({
+ __esModule: true,
+ ...jest.requireActual("openstack-uicore-foundation/lib/utils/actions"),
+ putRequest: jest.fn(),
+ getRequest: jest.fn()
+}));
+
+describe("archiveFormTemplate", () => {
+ beforeEach(() => {
+ window.INVENTORY_API_BASE_URL = "http://test-api";
+ jest.spyOn(methods, "getAccessTokenSafely").mockReturnValue("TOKEN");
+
+ putRequest.mockImplementation(
+ (nullArg, receiveActionCreator) => () => (dispatch) => {
+ dispatch(
+ receiveActionCreator({ response: { id: 21, is_archived: true } })
+ );
+ return Promise.resolve({ response: { id: 21, is_archived: true } });
+ }
+ );
+
+ getRequest.mockImplementation(
+ () => () => () => Promise.resolve({ response: {} })
+ );
+ });
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it("refetches the corrected page after archiving the last item on the last page", async () => {
+ // Real store so the reducer runs and getState() reflects the corrected page
+ const store = createStore(
+ combineReducers({
+ currentFormTemplateListState: formTemplateListReducer
+ }),
+ applyMiddleware(thunk)
+ );
+
+ // Land on page 3 with 21 items (1 item on page 3, 10 per page)
+ store.dispatch({
+ type: RECEIVE_FORM_TEMPLATES,
+ payload: {
+ response: {
+ data: [{ id: 21, is_archived: false, items: [] }],
+ total: 21,
+ last_page: 3,
+ current_page: 3
+ }
+ }
+ });
+
+ await store.dispatch(archiveFormTemplate({ id: 21 }));
+ await flushPromises();
+
+ // Reducer corrects page 3 → 2 after FORM_TEMPLATE_ARCHIVED
+ expect(store.getState().currentFormTemplateListState.currentPage).toBe(2);
+
+ // getFormTemplates must refetch page 2, not the stale page 3
+ expect(getRequest).toHaveBeenCalledWith(
+ expect.any(Function),
+ expect.any(Function),
+ "http://test-api/api/v1/form-templates",
+ expect.any(Function),
+ expect.objectContaining({ page: 2 })
+ );
+ });
+});
diff --git a/src/actions/form-template-actions.js b/src/actions/form-template-actions.js
index dfa330bdd..8cc700481 100644
--- a/src/actions/form-template-actions.js
+++ b/src/actions/form-template-actions.js
@@ -325,18 +325,44 @@ export const deleteFormTemplateMaterial = (templateId, materialId) => {
/* ************************************** ARCHIVE ************************************** */
-export const archiveFormTemplate = (formTemplate) => {
- const settings = {
- url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplate.id}/archive`,
- updatedActionName: FORM_TEMPLATE_ARCHIVED
+export const archiveFormTemplate =
+ (formTemplate) => async (dispatch, getState) => {
+ const settings = {
+ url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplate.id}/archive`,
+ updatedActionName: FORM_TEMPLATE_ARCHIVED
+ };
+ await archiveItem(formTemplate, settings)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().currentFormTemplateListState;
+ dispatch(
+ getFormTemplates(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
- return archiveItem(formTemplate, settings);
-};
-export const unarchiveFormTemplate = (formTemplate) => {
- const settings = {
- url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplate.id}/archive`,
- deletedActionName: FORM_TEMPLATE_UNARCHIVED
+export const unarchiveFormTemplate =
+ (formTemplate) => async (dispatch, getState) => {
+ const settings = {
+ url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplate.id}/archive`,
+ deletedActionName: FORM_TEMPLATE_UNARCHIVED
+ };
+ await unarchiveItem(formTemplate, settings)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().currentFormTemplateListState;
+ dispatch(
+ getFormTemplates(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
- return unarchiveItem(formTemplate, settings);
-};
diff --git a/src/actions/form-template-item-actions.js b/src/actions/form-template-item-actions.js
index 53086a433..f1de074ab 100644
--- a/src/actions/form-template-item-actions.js
+++ b/src/actions/form-template-item-actions.js
@@ -393,18 +393,46 @@ export const deleteItemImage = (
/* ************************************** ARCHIVE ************************************** */
-export const archiveFormTemplateItem = (formTemplateId, formTemplateItem) => {
- const settings = {
- url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplateId}/items/${formTemplateItem.id}/archive`,
- updatedActionName: FORM_TEMPLATE_ITEM_ARCHIVED
+export const archiveFormTemplateItem =
+ (formTemplateId, formTemplateItem) => async (dispatch, getState) => {
+ const settings = {
+ url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplateId}/items/${formTemplateItem.id}/archive`,
+ updatedActionName: FORM_TEMPLATE_ITEM_ARCHIVED
+ };
+ await archiveItem(formTemplateItem, settings)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().currentFormTemplateItemListState;
+ dispatch(
+ getFormTemplateItems(
+ formTemplateId,
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
- return archiveItem(formTemplateItem, settings);
-};
-export const unarchiveFormTemplateItem = (formTemplateId, formTemplateItem) => {
- const settings = {
- url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplateId}/items/${formTemplateItem.id}/archive`,
- deletedActionName: FORM_TEMPLATE_ITEM_UNARCHIVED
+export const unarchiveFormTemplateItem =
+ (formTemplateId, formTemplateItem) => async (dispatch, getState) => {
+ const settings = {
+ url: `${window.INVENTORY_API_BASE_URL}/api/v1/form-templates/${formTemplateId}/items/${formTemplateItem.id}/archive`,
+ deletedActionName: FORM_TEMPLATE_ITEM_UNARCHIVED
+ };
+ await unarchiveItem(formTemplateItem, settings)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().currentFormTemplateItemListState;
+ dispatch(
+ getFormTemplateItems(
+ formTemplateId,
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
- return unarchiveItem(formTemplateItem, settings);
-};
diff --git a/src/actions/inventory-item-actions.js b/src/actions/inventory-item-actions.js
index 1b6277390..b60dc7de0 100644
--- a/src/actions/inventory-item-actions.js
+++ b/src/actions/inventory-item-actions.js
@@ -370,18 +370,44 @@ export const deleteInventoryItemImage = (inventoryItemId, imageId) => {
/* ************************************** ARCHIVE ************************************** */
-export const archiveInventoryItem = (inventoryItem) => {
- const settings = {
- url: `${window.INVENTORY_API_BASE_URL}/api/v1/inventory-items/${inventoryItem.id}/archive`,
- updatedActionName: INVENTORY_ITEM_ARCHIVED
+export const archiveInventoryItem =
+ (inventoryItem) => async (dispatch, getState) => {
+ const settings = {
+ url: `${window.INVENTORY_API_BASE_URL}/api/v1/inventory-items/${inventoryItem.id}/archive`,
+ updatedActionName: INVENTORY_ITEM_ARCHIVED
+ };
+ await archiveItem(inventoryItem, settings)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().currentInventoryItemListState;
+ dispatch(
+ getInventoryItems(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
- return archiveItem(inventoryItem, settings);
-};
-export const unarchiveInventoryItem = (inventoryItem) => {
- const settings = {
- url: `${window.INVENTORY_API_BASE_URL}/api/v1/inventory-items/${inventoryItem.id}/archive`,
- deletedActionName: INVENTORY_ITEM_UNARCHIVED
+export const unarchiveInventoryItem =
+ (inventoryItem) => async (dispatch, getState) => {
+ const settings = {
+ url: `${window.INVENTORY_API_BASE_URL}/api/v1/inventory-items/${inventoryItem.id}/archive`,
+ deletedActionName: INVENTORY_ITEM_UNARCHIVED
+ };
+ await unarchiveItem(inventoryItem, settings)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().currentInventoryItemListState;
+ dispatch(
+ getInventoryItems(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
- return unarchiveItem(inventoryItem, settings);
-};
diff --git a/src/actions/page-template-actions.js b/src/actions/page-template-actions.js
index ecf7ca78b..62c631d7d 100644
--- a/src/actions/page-template-actions.js
+++ b/src/actions/page-template-actions.js
@@ -211,35 +211,60 @@ export const savePageTemplate = (entity) => async (dispatch) => {
/* ************************************** ARCHIVE ************************************** */
-export const archivePageTemplate = (pageTemplateId) => async (dispatch) => {
- const accessToken = await getAccessTokenSafely();
- const params = { access_token: accessToken };
-
- return putRequest(
- null,
- createAction(PAGE_TEMPLATE_ARCHIVED),
- `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${pageTemplateId}/archive`,
- null,
- snackbarErrorHandler
- )(params)(dispatch);
-};
+export const archivePageTemplate =
+ (pageTemplateId) => async (dispatch, getState) => {
+ const accessToken = await getAccessTokenSafely();
+ const params = { access_token: accessToken };
+
+ await putRequest(
+ null,
+ createAction(PAGE_TEMPLATE_ARCHIVED),
+ `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${pageTemplateId}/archive`,
+ null,
+ snackbarErrorHandler
+ )(params)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().pageTemplateListState;
+ dispatch(
+ getPageTemplates(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
+ };
-export const unarchivePageTemplate = (pageTemplateId) => async (dispatch) => {
- const accessToken = await getAccessTokenSafely();
- const params = { access_token: accessToken };
+export const unarchivePageTemplate =
+ (pageTemplateId) => async (dispatch, getState) => {
+ const accessToken = await getAccessTokenSafely();
+ const params = { access_token: accessToken };
- dispatch(startLoading());
+ dispatch(startLoading());
- return deleteRequest(
- null,
- createAction(PAGE_TEMPLATE_UNARCHIVED)({ pageTemplateId }),
- `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${pageTemplateId}/archive`,
- null,
- snackbarErrorHandler
- )(params)(dispatch).then(() => {
+ await deleteRequest(
+ null,
+ createAction(PAGE_TEMPLATE_UNARCHIVED)({ pageTemplateId }),
+ `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${pageTemplateId}/archive`,
+ null,
+ snackbarErrorHandler
+ )(params)(dispatch);
dispatch(stopLoading());
- });
-};
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().pageTemplateListState;
+ dispatch(
+ getPageTemplates(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
+ };
export const clonePageTemplate = (templateId) => async (dispatch) => {
const accessToken = await getAccessTokenSafely();
diff --git a/src/actions/show-pages-actions.js b/src/actions/show-pages-actions.js
index 42bf426b1..56034be7c 100644
--- a/src/actions/show-pages-actions.js
+++ b/src/actions/show-pages-actions.js
@@ -236,24 +236,25 @@ export const archiveShowPage = (pageId) => async (dispatch, getState) => {
dispatch(startLoading());
- return putRequest(
+ await putRequest(
null,
createAction(SHOW_PAGE_ARCHIVED)({ pageId }),
`${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/show-pages/${pageId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch)
- .then(() => {
- dispatch(
- snackbarSuccessHandler({
- title: T.translate("general.success"),
- html: T.translate("show_pages.archived")
- })
- );
+ )(params)(dispatch);
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("show_pages.archived")
})
- .finally(() => {
- dispatch(stopLoading());
- });
+ );
+ dispatch(stopLoading());
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().showPagesListState;
+ dispatch(
+ getShowPages(term, currentPage, perPage, order, orderDir, showArchived)
+ );
};
export const unarchiveShowPage = (pageId) => async (dispatch, getState) => {
@@ -264,22 +265,23 @@ export const unarchiveShowPage = (pageId) => async (dispatch, getState) => {
dispatch(startLoading());
- return deleteRequest(
+ await deleteRequest(
null,
createAction(SHOW_PAGE_UNARCHIVED)({ pageId }),
`${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/show-pages/${pageId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch)
- .then(() => {
- dispatch(
- snackbarSuccessHandler({
- title: T.translate("general.success"),
- html: T.translate("show_pages.unarchived")
- })
- );
+ )(params)(dispatch);
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("show_pages.unarchived")
})
- .finally(() => {
- dispatch(stopLoading());
- });
+ );
+ dispatch(stopLoading());
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().showPagesListState;
+ dispatch(
+ getShowPages(term, currentPage, perPage, order, orderDir, showArchived)
+ );
};
diff --git a/src/actions/sponsor-forms-actions.js b/src/actions/sponsor-forms-actions.js
index 951db2846..e791247e9 100644
--- a/src/actions/sponsor-forms-actions.js
+++ b/src/actions/sponsor-forms-actions.js
@@ -202,13 +202,18 @@ export const archiveSponsorForm = (formId) => async (dispatch, getState) => {
const { currentSummit } = currentSummitState;
const params = { access_token: accessToken };
- return putRequest(
+ await putRequest(
null,
createAction(SPONSOR_FORM_ARCHIVED),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/show-forms/${formId}/archive`,
null,
snackbarErrorHandler
)(params)(dispatch);
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().sponsorFormsListState;
+ dispatch(
+ getSponsorForms(term, currentPage, perPage, order, orderDir, showArchived)
+ );
};
export const unarchiveSponsorForm = (formId) => async (dispatch, getState) => {
@@ -219,15 +224,19 @@ export const unarchiveSponsorForm = (formId) => async (dispatch, getState) => {
dispatch(startLoading());
- return deleteRequest(
+ await deleteRequest(
null,
createAction(SPONSOR_FORM_UNARCHIVED)({ formId }),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/show-forms/${formId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch).then(() => {
- dispatch(stopLoading());
- });
+ )(params)(dispatch);
+ dispatch(stopLoading());
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().sponsorFormsListState;
+ dispatch(
+ getSponsorForms(term, currentPage, perPage, order, orderDir, showArchived)
+ );
};
export const deleteSponsorForm = (formId) => async (dispatch, getState) => {
@@ -945,7 +954,7 @@ export const archiveSponsorCustomizedForm =
dispatch(startLoading());
- return putRequest(
+ await putRequest(
null,
createAction(SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED)({
formId,
@@ -954,18 +963,27 @@ export const archiveSponsorCustomizedForm =
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch)
- .then(() => {
- dispatch(
- snackbarSuccessHandler({
- title: T.translate("general.success"),
- html: T.translate("edit_sponsor.forms_tab.customized_form.archived")
- })
- );
+ )(params)(dispatch);
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_sponsor.forms_tab.customized_form.unarchived")
})
- .finally(() => {
- dispatch(stopLoading());
- });
+ );
+ dispatch(stopLoading());
+ const { term, showArchived, customizedForms } =
+ getState().sponsorPageFormsListState;
+ const { currentPage, perPage, order, orderDir } = customizedForms;
+ dispatch(
+ getSponsorCustomizedForms(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
export const unarchiveSponsorCustomizedForm =
@@ -980,7 +998,7 @@ export const unarchiveSponsorCustomizedForm =
dispatch(startLoading());
- return deleteRequest(
+ await deleteRequest(
null,
createAction(SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED)({
formId,
@@ -989,20 +1007,27 @@ export const unarchiveSponsorCustomizedForm =
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch)
- .then(() => {
- dispatch(
- snackbarSuccessHandler({
- title: T.translate("general.success"),
- html: T.translate(
- "edit_sponsor.forms_tab.customized_form.unarchived"
- )
- })
- );
+ )(params)(dispatch);
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_sponsor.forms_tab.customized_form.unarchived")
})
- .finally(() => {
- dispatch(stopLoading());
- });
+ );
+ dispatch(stopLoading());
+ const { term, showArchived, customizedForms } =
+ getState().sponsorPageFormsListState;
+ const { currentPage, perPage, order, orderDir } = customizedForms;
+ dispatch(
+ getSponsorCustomizedForms(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
export const deleteSponsorCustomizedForm =
@@ -1278,13 +1303,25 @@ export const archiveSponsorFormItem =
const { currentSummit } = currentSummitState;
const params = { access_token: accessToken };
- return putRequest(
+ await putRequest(
null,
createAction(SPONSOR_FORM_ITEM_ARCHIVED),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/show-forms/${formId}/items/${itemId}/archive`,
null,
snackbarErrorHandler
)(params)(dispatch);
+ const { currentPage, perPage, order, orderDir, showArchived } =
+ getState().sponsorFormItemsListState;
+ dispatch(
+ getSponsorFormItems(
+ formId,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
export const unarchiveSponsorFormItem =
@@ -1296,15 +1333,26 @@ export const unarchiveSponsorFormItem =
dispatch(startLoading());
- return deleteRequest(
+ await deleteRequest(
null,
createAction(SPONSOR_FORM_ITEM_UNARCHIVED)({ itemId }),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/show-forms/${formId}/items/${itemId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch).then(() => {
- dispatch(stopLoading());
- });
+ )(params)(dispatch);
+ dispatch(stopLoading());
+ const { currentPage, perPage, order, orderDir, showArchived } =
+ getState().sponsorFormItemsListState;
+ dispatch(
+ getSponsorFormItems(
+ formId,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
export const resetSponsorFormItem = () => (dispatch) => {
@@ -1566,15 +1614,27 @@ export const archiveSponsorCustomizedFormItem =
dispatch(startLoading());
- return putRequest(
+ await putRequest(
null,
createAction(SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/${itemId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch).then(() => {
- dispatch(stopLoading());
- });
+ )(params)(dispatch);
+ dispatch(stopLoading());
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().sponsorCustomizedFormItemsListState;
+ dispatch(
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
export const unarchiveSponsorCustomizedFormItem =
@@ -1589,13 +1649,25 @@ export const unarchiveSponsorCustomizedFormItem =
dispatch(startLoading());
- return deleteRequest(
+ await deleteRequest(
null,
createAction(SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED)({ itemId }),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-forms/${formId}/items/${itemId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch).then(() => {
- dispatch(stopLoading());
- });
+ )(params)(dispatch);
+ dispatch(stopLoading());
+ const { term, currentPage, perPage, order, orderDir, showArchived } =
+ getState().sponsorCustomizedFormItemsListState;
+ dispatch(
+ getSponsorCustomizedFormItems(
+ formId,
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
diff --git a/src/actions/sponsor-pages-actions.js b/src/actions/sponsor-pages-actions.js
index b5db07e7a..60f1ab6ee 100644
--- a/src/actions/sponsor-pages-actions.js
+++ b/src/actions/sponsor-pages-actions.js
@@ -480,24 +480,33 @@ export const archiveCustomizedPage = (pageId) => async (dispatch, getState) => {
dispatch(startLoading());
- return putRequest(
+ await putRequest(
null,
createAction(SPONSOR_CUSTOMIZED_PAGE_ARCHIVED)({ pageId }),
`${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-pages/${pageId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch)
- .then(() => {
- dispatch(
- snackbarSuccessHandler({
- title: T.translate("general.success"),
- html: T.translate("edit_sponsor.pages_tab.customized_page_archived")
- })
- );
+ )(params)(dispatch);
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_sponsor.pages_tab.customized_page_archived")
})
- .finally(() => {
- dispatch(stopLoading());
- });
+ );
+ dispatch(stopLoading());
+ const { term, showArchived, customizedPages } =
+ getState().sponsorPagePagesListState;
+ const { currentPage, perPage, order, orderDir } = customizedPages;
+ dispatch(
+ getSponsorCustomizedPages(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
export const unarchiveCustomizedPage =
@@ -512,26 +521,33 @@ export const unarchiveCustomizedPage =
dispatch(startLoading());
- return deleteRequest(
+ await deleteRequest(
null,
createAction(SPONSOR_CUSTOMIZED_PAGE_UNARCHIVED)({ pageId }),
`${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-pages/${pageId}/archive`,
null,
snackbarErrorHandler
- )(params)(dispatch)
- .then(() => {
- dispatch(
- snackbarSuccessHandler({
- title: T.translate("general.success"),
- html: T.translate(
- "edit_sponsor.pages_tab.customized_page_unarchived"
- )
- })
- );
+ )(params)(dispatch);
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("edit_sponsor.pages_tab.customized_page_unarchived")
})
- .finally(() => {
- dispatch(stopLoading());
- });
+ );
+ dispatch(stopLoading());
+ const { term, showArchived, customizedPages } =
+ getState().sponsorPagePagesListState;
+ const { currentPage, perPage, order, orderDir } = customizedPages;
+ dispatch(
+ getSponsorCustomizedPages(
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ showArchived
+ )
+ );
};
export const deleteSponsorCustomizedPage =
diff --git a/src/pages/sponsors/sponsor-form-item-list-page/components/__test__/inventory-popup.test.js b/src/pages/sponsors/sponsor-form-item-list-page/components/__test__/inventory-popup.test.js
index 427d6d0a3..f602a371c 100644
--- a/src/pages/sponsors/sponsor-form-item-list-page/components/__test__/inventory-popup.test.js
+++ b/src/pages/sponsors/sponsor-form-item-list-page/components/__test__/inventory-popup.test.js
@@ -104,7 +104,7 @@ describe("InventoryPopup", () => {
);
const user = userEvent.setup();
- const node = screen.getByTestId("CloseIcon");
+ const node = screen.getByTestId("close-dialog");
await user.click(node);
expect(onClose).toHaveBeenCalledTimes(1);
@@ -161,7 +161,7 @@ describe("InventoryPopup", () => {
const textNode = await screen.findByText("1 items selected");
expect(textNode.textContent).toBe("1 items selected");
- const node = screen.getByTestId("CloseIcon");
+ const node = screen.getByTestId("close-dialog");
await user.click(node);
const textNode2 = screen.getByText("0 items selected");
diff --git a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js
index e2b40d06e..b2e980d8a 100644
--- a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js
+++ b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js
@@ -169,7 +169,12 @@ const SponsorFormAddItemFromInventoryPopup = ({
{T.translate("sponsor_form_item_list.add_from_inventory.title")}
-
+
diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
index 2c5e82b44..958ce85fc 100644
--- a/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
+++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js
@@ -180,20 +180,9 @@ const SponsorPagesTab = ({
};
const handleArchiveCustomizedPage = (item) =>
- (item.is_archived
+ item.is_archived
? unarchiveCustomizedPage(item.id)
- : archiveCustomizedPage(item.id)
- ).then(() => {
- const { perPage, order, orderDir, currentPage } = customizedPages;
- return getSponsorCustomizedPages(
- term,
- currentPage,
- perPage,
- order,
- orderDir,
- showArchived
- );
- });
+ : archiveCustomizedPage(item.id);
const handleManagedEdit = (item) => {
getSponsorManagedPage(item.id).then(() => setOpenPopup("managedPagePopup"));
diff --git a/src/reducers/sponsors/show-pages-list-reducer.js b/src/reducers/sponsors/show-pages-list-reducer.js
index 9b69913f3..00b4186a0 100644
--- a/src/reducers/sponsors/show-pages-list-reducer.js
+++ b/src/reducers/sponsors/show-pages-list-reducer.js
@@ -27,6 +27,7 @@ import {
RECEIVE_SUMMIT_SPONSORSHIP_TYPES
} from "../../actions/summit-actions";
import { denormalizePageModules } from "../../utils/page-template";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_SHOW_PAGE = {
code: "",
@@ -109,22 +110,26 @@ const showPagesListReducer = (state = DEFAULT_STATE, action) => {
}
case SHOW_PAGE_ARCHIVED: {
const { pageId } = payload;
+ const { totalCount, perPage, currentPage } = state;
const pages = state.showPages.map((page) =>
page.id === pageId ? { ...page, is_archived: true } : page
);
return {
...state,
- showPages: [...pages]
+ showPages: [...pages],
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
};
}
case SHOW_PAGE_UNARCHIVED: {
const { pageId } = payload;
+ const { totalCount, perPage, currentPage } = state;
const pages = state.showPages.map((page) =>
page.id === pageId ? { ...page, is_archived: false } : page
);
return {
...state,
- showPages: [...pages]
+ showPages: [...pages],
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
};
}
case RECEIVE_SHOW_PAGE: {
diff --git a/src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js b/src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js
index a2de1b315..84c58770f 100644
--- a/src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js
+++ b/src/reducers/sponsors/sponsor-customized-form-items-list-reducer.js
@@ -25,6 +25,7 @@ import {
RESET_SPONSOR_FORM_MANAGED_ITEM
} from "../../actions/sponsor-forms-actions";
import { SET_CURRENT_SUMMIT } from "../../actions/summit-actions";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_ITEM_ENTITY = {
code: "",
@@ -126,21 +127,31 @@ const sponsorCustomizedFormItemsListReducer = (
}
case SPONSOR_CUSTOMIZED_FORM_ITEM_ARCHIVED: {
const { id: itemId } = payload.response;
+ const { totalCount, currentPage, perPage } = state;
const items = state.items.map((item) =>
item.id === itemId ? { ...item, is_archived: true } : item
);
- return { ...state, items };
+ return {
+ ...state,
+ items,
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
+ };
}
case SPONSOR_CUSTOMIZED_FORM_ITEM_UNARCHIVED: {
const { itemId } = payload;
+ const { totalCount, currentPage, perPage } = state;
const items = state.items.map((item) =>
item.id === itemId ? { ...item, is_archived: false } : item
);
- return { ...state, items };
+ return {
+ ...state,
+ items,
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
+ };
}
case SPONSOR_FORM_MANAGED_ITEM_UPDATED: {
const updatedItem = payload.response;
diff --git a/src/reducers/sponsors/sponsor-form-items-list-reducer.js b/src/reducers/sponsors/sponsor-form-items-list-reducer.js
index 318ea185f..21e0c7597 100644
--- a/src/reducers/sponsors/sponsor-form-items-list-reducer.js
+++ b/src/reducers/sponsors/sponsor-form-items-list-reducer.js
@@ -23,6 +23,7 @@ import {
SPONSOR_FORM_ITEM_UNARCHIVED
} from "../../actions/sponsor-forms-actions";
import { SET_CURRENT_SUMMIT } from "../../actions/summit-actions";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_STATE = {
items: [],
@@ -117,21 +118,31 @@ const sponsorFormItemsListReducer = (state = DEFAULT_STATE, action) => {
}
case SPONSOR_FORM_ITEM_ARCHIVED: {
const { id: itemId } = payload.response;
+ const { totalCount, perPage, currentPage } = state;
const items = state.items.map((item) =>
item.id === itemId ? { ...item, is_archived: true } : item
);
- return { ...state, items };
+ return {
+ ...state,
+ items,
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
+ };
}
case SPONSOR_FORM_ITEM_UNARCHIVED: {
const { itemId } = payload;
+ const { totalCount, perPage, currentPage } = state;
const items = state.items.map((item) =>
item.id === itemId ? { ...item, is_archived: false } : item
);
- return { ...state, items };
+ return {
+ ...state,
+ items,
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
+ };
}
default:
return state;
diff --git a/src/reducers/sponsors/sponsor-forms-list-reducer.js b/src/reducers/sponsors/sponsor-forms-list-reducer.js
index de8688891..ee3213724 100644
--- a/src/reducers/sponsors/sponsor-forms-list-reducer.js
+++ b/src/reducers/sponsors/sponsor-forms-list-reducer.js
@@ -28,6 +28,7 @@ import {
SET_CURRENT_SUMMIT,
RECEIVE_SUMMIT_SPONSORSHIP_TYPES
} from "../../actions/summit-actions";
+import { getSafePageAfterRemove } from "../../utils/methods";
export const DEFAULT_STATE = {
sponsorForms: [],
@@ -152,21 +153,31 @@ const sponsorFormsListReducer = (state = DEFAULT_STATE, action) => {
}
case SPONSOR_FORM_ARCHIVED: {
const { id: formId } = payload.response;
+ const { totalCount, perPage, currentPage } = state;
const sponsorForms = state.sponsorForms.map((item) =>
item.id === formId ? { ...item, is_archived: true } : item
);
- return { ...state, sponsorForms };
+ return {
+ ...state,
+ sponsorForms,
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
+ };
}
case SPONSOR_FORM_UNARCHIVED: {
const { formId } = payload;
+ const { totalCount, perPage, currentPage } = state;
const sponsorForms = state.sponsorForms.map((item) =>
item.id === formId ? { ...item, is_archived: false } : item
);
- return { ...state, sponsorForms };
+ return {
+ ...state,
+ sponsorForms,
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
+ };
}
case SPONSOR_FORM_DELETED: {
const { formId } = payload;
diff --git a/src/reducers/sponsors/sponsor-page-forms-list-reducer.js b/src/reducers/sponsors/sponsor-page-forms-list-reducer.js
index 4a01a7eea..da056b21a 100644
--- a/src/reducers/sponsors/sponsor-page-forms-list-reducer.js
+++ b/src/reducers/sponsors/sponsor-page-forms-list-reducer.js
@@ -24,6 +24,7 @@ import {
SPONSOR_CUSTOMIZED_FORM_UPDATED
} from "../../actions/sponsor-forms-actions";
import { SET_CURRENT_SUMMIT } from "../../actions/summit-actions";
+import { getSafePageAfterRemove } from "../../utils/methods";
export const DEFAULT_STATE = {
managedForms: {
@@ -238,6 +239,10 @@ const sponsorPageFormsListReducer = (state = DEFAULT_STATE, action) => {
}
case SPONSOR_CUSTOMIZED_FORM_ARCHIVED_CHANGED: {
const { formId, isArchived } = payload;
+ const {
+ customizedForms: { totalCount, currentPage, perPage }
+ } = state;
+
const forms = state.customizedForms.forms.map((form) => {
if (form.id === formId) {
return {
@@ -252,7 +257,8 @@ const sponsorPageFormsListReducer = (state = DEFAULT_STATE, action) => {
...state,
customizedForms: {
...state.customizedForms,
- forms
+ forms,
+ currentPage: getSafePageAfterRemove(totalCount, perPage, currentPage)
}
};
}
diff --git a/src/reducers/sponsors/sponsor-page-pages-list-reducer.js b/src/reducers/sponsors/sponsor-page-pages-list-reducer.js
index e30e9d436..2a13020e3 100644
--- a/src/reducers/sponsors/sponsor-page-pages-list-reducer.js
+++ b/src/reducers/sponsors/sponsor-page-pages-list-reducer.js
@@ -29,6 +29,7 @@ import {
} from "../../actions/summit-actions";
import { PAGES_MODULE_KINDS } from "../../utils/constants";
import { denormalizePageModules } from "../../utils/page-template";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_PAGE = {
code: "",
@@ -198,6 +199,9 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => {
}
case SPONSOR_CUSTOMIZED_PAGE_ARCHIVED: {
const { pageId } = payload;
+ const {
+ customizedPages: { totalItems, currentPage, perPage }
+ } = state;
const pages = state.customizedPages.pages.map((page) =>
page.id === pageId ? { ...page, is_archived: true } : page
);
@@ -205,12 +209,16 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => {
...state,
customizedPages: {
...state.customizedPages,
- pages: [...pages]
+ pages: [...pages],
+ currentPage: getSafePageAfterRemove(totalItems, perPage, currentPage)
}
};
}
case SPONSOR_CUSTOMIZED_PAGE_UNARCHIVED: {
const { pageId } = payload;
+ const {
+ customizedPages: { totalItems, currentPage, perPage }
+ } = state;
const pages = state.customizedPages.pages.map((page) =>
page.id === pageId ? { ...page, is_archived: false } : page
);
@@ -218,7 +226,8 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => {
...state,
customizedPages: {
...state.customizedPages,
- pages: [...pages]
+ pages: [...pages],
+ currentPage: getSafePageAfterRemove(totalItems, perPage, currentPage)
}
};
}
diff --git a/src/reducers/sponsors_inventory/__tests__/form-template-list-reducer.test.js b/src/reducers/sponsors_inventory/__tests__/form-template-list-reducer.test.js
new file mode 100644
index 000000000..afb0b7159
--- /dev/null
+++ b/src/reducers/sponsors_inventory/__tests__/form-template-list-reducer.test.js
@@ -0,0 +1,30 @@
+import formTemplateListReducer from "../form-template-list-reducer";
+import {
+ RECEIVE_FORM_TEMPLATES,
+ FORM_TEMPLATE_ARCHIVED
+} from "../../../actions/form-template-actions";
+
+// This test currently FAILS, proving the stale-closure bug.
+// The fix: move page correction into the action thunk via getState() instead of the reducer.
+it("stays on the corrected page after the .then() refetch that follows an archive", () => {
+ // 21 items across 3 pages; page 3 has exactly 1 item
+ const onPage3 = formTemplateListReducer(undefined, {
+ type: RECEIVE_FORM_TEMPLATES,
+ payload: {
+ response: {
+ data: [{ id: 21, is_archived: false, items: [] }],
+ total: 21,
+ last_page: 3,
+ current_page: 3
+ }
+ }
+ });
+ expect(onPage3.currentPage).toBe(3);
+
+ // Archive that item — reducer correctly decrements to page 2
+ const afterArchive = formTemplateListReducer(onPage3, {
+ type: FORM_TEMPLATE_ARCHIVED,
+ payload: { response: { id: 21, is_archived: true } }
+ });
+ expect(afterArchive.currentPage).toBe(2); // reducer correction works
+});
diff --git a/src/reducers/sponsors_inventory/form-template-item-list-reducer.js b/src/reducers/sponsors_inventory/form-template-item-list-reducer.js
index aa9cb2570..d040b7a6b 100644
--- a/src/reducers/sponsors_inventory/form-template-item-list-reducer.js
+++ b/src/reducers/sponsors_inventory/form-template-item-list-reducer.js
@@ -20,6 +20,7 @@ import {
FORM_TEMPLATE_ITEM_ARCHIVED,
FORM_TEMPLATE_ITEM_UNARCHIVED
} from "../../actions/form-template-item-actions";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_STATE = {
formTemplateItems: [],
@@ -89,10 +90,16 @@ const formTemplateItemListReducer = (state = DEFAULT_STATE, action = {}) => {
}
case FORM_TEMPLATE_ITEM_DELETED: {
const { formTemplateItemId } = payload;
+ const { totalFormTemplateItems, perPage, currentPage } = state;
return {
...state,
formTemplateItems: state.formTemplateItems.filter(
(a) => a.id !== formTemplateItemId
+ ),
+ currentPage: getSafePageAfterRemove(
+ totalFormTemplateItems,
+ perPage,
+ currentPage
)
};
}
@@ -102,23 +109,39 @@ const formTemplateItemListReducer = (state = DEFAULT_STATE, action = {}) => {
}
case FORM_TEMPLATE_ITEM_ARCHIVED: {
const updatedFormTemplateItem = payload.response;
-
+ const { totalFormTemplateItems, perPage, currentPage } = state;
const updatedFormTemplatesItems = state.formTemplateItems.map((item) =>
item.id === updatedFormTemplateItem.id
? { ...item, is_archived: true }
: item
);
- return { ...state, formTemplateItems: updatedFormTemplatesItems };
+ return {
+ ...state,
+ formTemplateItems: updatedFormTemplatesItems,
+ currentPage: getSafePageAfterRemove(
+ totalFormTemplateItems,
+ perPage,
+ currentPage
+ )
+ };
}
case FORM_TEMPLATE_ITEM_UNARCHIVED: {
const updatedFormTemplateItemId = payload;
-
+ const { totalFormTemplateItems, perPage, currentPage } = state;
const updatedFormTemplatesItems = state.formTemplateItems.map((item) =>
item.id === updatedFormTemplateItemId
? { ...item, is_archived: false }
: item
);
- return { ...state, formTemplateItems: updatedFormTemplatesItems };
+ return {
+ ...state,
+ formTemplateItems: updatedFormTemplatesItems,
+ currentPage: getSafePageAfterRemove(
+ totalFormTemplateItems,
+ perPage,
+ currentPage
+ )
+ };
}
default:
return state;
diff --git a/src/reducers/sponsors_inventory/form-template-list-reducer.js b/src/reducers/sponsors_inventory/form-template-list-reducer.js
index 8406d3b3c..ea2cf493e 100644
--- a/src/reducers/sponsors_inventory/form-template-list-reducer.js
+++ b/src/reducers/sponsors_inventory/form-template-list-reducer.js
@@ -20,6 +20,7 @@ import {
FORM_TEMPLATE_ARCHIVED,
FORM_TEMPLATE_UNARCHIVED
} from "../../actions/form-template-actions";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_STATE = {
formTemplates: [],
@@ -99,23 +100,41 @@ const formTemplateListReducer = (state = DEFAULT_STATE, action = {}) => {
}
case FORM_TEMPLATE_ARCHIVED: {
const updatedFormTemplate = payload.response;
+ const { totalFormTemplates, currentPage, perPage } = state;
const updatedFormTemplates = state.formTemplates.map((item) =>
item.id === updatedFormTemplate.id
? { ...item, is_archived: true }
: item
);
- return { ...state, formTemplates: updatedFormTemplates };
+ return {
+ ...state,
+ formTemplates: updatedFormTemplates,
+ currentPage: getSafePageAfterRemove(
+ totalFormTemplates,
+ perPage,
+ currentPage
+ )
+ };
}
case FORM_TEMPLATE_UNARCHIVED: {
const updatedFormTemplateId = payload;
+ const { totalFormTemplates, currentPage, perPage } = state;
const updatedFormTemplates = state.formTemplates.map((item) =>
item.id === updatedFormTemplateId
? { ...item, is_archived: false }
: item
);
- return { ...state, formTemplates: updatedFormTemplates };
+ return {
+ ...state,
+ formTemplates: updatedFormTemplates,
+ currentPage: getSafePageAfterRemove(
+ totalFormTemplates,
+ perPage,
+ currentPage
+ )
+ };
}
case CHANGE_FORM_TEMPLATE_SEARCH_TERM: {
const { term } = payload;
diff --git a/src/reducers/sponsors_inventory/inventory-item-list-reducer.js b/src/reducers/sponsors_inventory/inventory-item-list-reducer.js
index 6da37a276..955ea04bb 100644
--- a/src/reducers/sponsors_inventory/inventory-item-list-reducer.js
+++ b/src/reducers/sponsors_inventory/inventory-item-list-reducer.js
@@ -25,6 +25,7 @@ import {
INVENTORY_ITEM_UNARCHIVED,
INVENTORY_ITEM_IMAGE_SAVED
} from "../../actions/inventory-item-actions";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_STATE = {
inventoryItems: [],
@@ -102,10 +103,16 @@ const inventoryItemListReducer = (state = DEFAULT_STATE, action = {}) => {
}
case INVENTORY_ITEM_DELETED: {
const { inventoryItemId } = payload;
+ const { totalInventoryItems, perPage, currentPage } = state;
return {
...state,
inventoryItems: state.inventoryItems.filter(
(a) => a.id !== inventoryItemId
+ ),
+ currentPage: getSafePageAfterRemove(
+ totalInventoryItems,
+ perPage,
+ currentPage
)
};
}
@@ -199,19 +206,35 @@ const inventoryItemListReducer = (state = DEFAULT_STATE, action = {}) => {
}
case INVENTORY_ITEM_ARCHIVED: {
const updatedItem = payload.response;
-
+ const { totalInventoryItems, perPage, currentPage } = state;
const updatedInventoryItems = state.inventoryItems.map((item) =>
item.id === updatedItem.id ? { ...item, is_archived: true } : item
);
- return { ...state, inventoryItems: updatedInventoryItems };
+ return {
+ ...state,
+ inventoryItems: updatedInventoryItems,
+ currentPage: getSafePageAfterRemove(
+ totalInventoryItems,
+ perPage,
+ currentPage
+ )
+ };
}
case INVENTORY_ITEM_UNARCHIVED: {
const updatedItemId = payload;
-
+ const { totalInventoryItems, perPage, currentPage } = state;
const updatedInventoryItems = state.inventoryItems.map((item) =>
item.id === updatedItemId ? { ...item, is_archived: false } : item
);
- return { ...state, inventoryItems: updatedInventoryItems };
+ return {
+ ...state,
+ inventoryItems: updatedInventoryItems,
+ currentPage: getSafePageAfterRemove(
+ totalInventoryItems,
+ perPage,
+ currentPage
+ )
+ };
}
case INVENTORY_ITEM_IMAGE_SAVED: {
const newImage = payload.response;
diff --git a/src/reducers/sponsors_inventory/page-template-list-reducer.js b/src/reducers/sponsors_inventory/page-template-list-reducer.js
index c7d955d45..ebefd76a7 100644
--- a/src/reducers/sponsors_inventory/page-template-list-reducer.js
+++ b/src/reducers/sponsors_inventory/page-template-list-reducer.js
@@ -20,6 +20,7 @@ import {
PAGE_TEMPLATE_UNARCHIVED
} from "../../actions/page-template-actions";
import { PAGES_MODULE_KINDS } from "../../utils/constants";
+import { getSafePageAfterRemove } from "../../utils/methods";
const DEFAULT_STATE = {
pageTemplates: [],
@@ -97,30 +98,52 @@ const pageTemplateListReducer = (state = DEFAULT_STATE, action = {}) => {
}
case PAGE_TEMPLATE_DELETED: {
const { pageTemplateId } = payload;
+ const { totalPageTemplates, perPage, currentPage } = state;
return {
...state,
pageTemplates: state.pageTemplates.filter(
(a) => a.id !== pageTemplateId
+ ),
+ currentPage: getSafePageAfterRemove(
+ totalPageTemplates,
+ perPage,
+ currentPage
)
};
}
case PAGE_TEMPLATE_ARCHIVED: {
const updatedFormTemplate = payload.response;
-
+ const { totalPageTemplates, perPage, currentPage } = state;
const updatedPageTemplates = state.pageTemplates.map((item) =>
item.id === updatedFormTemplate.id
? { ...item, is_archived: true }
: item
);
- return { ...state, pageTemplates: updatedPageTemplates };
+ return {
+ ...state,
+ pageTemplates: updatedPageTemplates,
+ currentPage: getSafePageAfterRemove(
+ totalPageTemplates,
+ perPage,
+ currentPage
+ )
+ };
}
case PAGE_TEMPLATE_UNARCHIVED: {
const { pageTemplateId } = payload;
-
+ const { totalPageTemplates, perPage, currentPage } = state;
const updatedPageTemplates = state.pageTemplates.map((item) =>
item.id === pageTemplateId ? { ...item, is_archived: false } : item
);
- return { ...state, pageTemplates: updatedPageTemplates };
+ return {
+ ...state,
+ pageTemplates: updatedPageTemplates,
+ currentPage: getSafePageAfterRemove(
+ totalPageTemplates,
+ perPage,
+ currentPage
+ )
+ };
}
default:
return state;
diff --git a/src/utils/__tests__/methods.test.js b/src/utils/__tests__/methods.test.js
index 0200a1756..4258a688a 100644
--- a/src/utils/__tests__/methods.test.js
+++ b/src/utils/__tests__/methods.test.js
@@ -1,7 +1,8 @@
import {
getMediaInputValue,
isImageUrl,
- normalizeSelectAllField
+ normalizeSelectAllField,
+ getSafePageAfterRemove
} from "../methods";
const FIXED_NOW = 1_772_551_911_231;
@@ -59,69 +60,69 @@ describe("getMediaInputValue", () => {
expect(result.filename).toBe("README");
});
});
+});
- describe("normalizeSelectAllField", () => {
- it("should return default object when items is empty array", () => {
- expect(normalizeSelectAllField([], "apply_to_all", "items")).toEqual({
- apply_to_all: false,
- items: []
- });
+describe("normalizeSelectAllField", () => {
+ it("should return default object when items is empty array", () => {
+ expect(normalizeSelectAllField([], "apply_to_all", "items")).toEqual({
+ apply_to_all: false,
+ items: []
});
+ });
- it("should return all selected when array contains 'all'", () => {
- expect(
- normalizeSelectAllField(
- ["all", { id: 1 }, { id: 2 }],
- "apply_to_all",
- "items"
- )
- ).toEqual({
- apply_to_all: true,
- items: []
- });
+ it("should return all selected when array contains 'all'", () => {
+ expect(
+ normalizeSelectAllField(
+ ["all", { id: 1 }, { id: 2 }],
+ "apply_to_all",
+ "items"
+ )
+ ).toEqual({
+ apply_to_all: true,
+ items: []
});
+ });
- it("should return all selected when allSelected flag is true", () => {
- expect(
- normalizeSelectAllField([{ id: 1 }], "apply_to_all", "items", true)
- ).toEqual({
- apply_to_all: true,
- items: []
- });
+ it("should return all selected when allSelected flag is true", () => {
+ expect(
+ normalizeSelectAllField([{ id: 1 }], "apply_to_all", "items", true)
+ ).toEqual({
+ apply_to_all: true,
+ items: []
});
+ });
- it.each([[], null, undefined])(
- "should return apply_to_all true when allSelected is true and items is %s",
- (items) => {
- expect(
- normalizeSelectAllField(items, "apply_to_all", "items", true)
- ).toEqual({ apply_to_all: true, items: [] });
- }
- );
-
- it.each([[], null, undefined])(
- "should return apply_to_all false when allSelected is false and items is %s",
- (items) => {
- expect(
- normalizeSelectAllField(items, "apply_to_all", "items", false)
- ).toEqual({ apply_to_all: false, items: [] });
- }
- );
-
- it("should return array of ids when items are objects with id", () => {
+ it.each([[], null, undefined])(
+ "should return apply_to_all true when allSelected is true and items is %s",
+ (items) => {
expect(
- normalizeSelectAllField([{ id: 1 }, { id: 2 }], "apply_to_all", "items")
- ).toEqual({
- apply_to_all: false,
- items: [1, 2]
- });
+ normalizeSelectAllField(items, "apply_to_all", "items", true)
+ ).toEqual({ apply_to_all: true, items: [] });
+ }
+ );
+
+ it.each([[], null, undefined])(
+ "should return apply_to_all false when allSelected is false and items is %s",
+ (items) => {
+ expect(
+ normalizeSelectAllField(items, "apply_to_all", "items", false)
+ ).toEqual({ apply_to_all: false, items: [] });
+ }
+ );
+
+ it("should return array of ids when items are objects with id", () => {
+ expect(
+ normalizeSelectAllField([{ id: 1 }, { id: 2 }], "apply_to_all", "items")
+ ).toEqual({
+ apply_to_all: false,
+ items: [1, 2]
});
+ });
- it("should return an array of values directly when items are primitives", () => {
- expect(normalizeSelectAllField([1, 2], "apply_to_all", "items")).toEqual({
- apply_to_all: false,
- items: [1, 2]
- });
+ it("should return an array of values directly when items are primitives", () => {
+ expect(normalizeSelectAllField([1, 2], "apply_to_all", "items")).toEqual({
+ apply_to_all: false,
+ items: [1, 2]
});
});
@@ -154,3 +155,29 @@ describe("getMediaInputValue", () => {
});
});
});
+
+describe("getSafePageAfterRemove", () => {
+ it("should stay on page 1 when there is only one page", () => {
+ expect(getSafePageAfterRemove(10, 10, 1)).toBe(1);
+ });
+
+ it("should go back to page 1 when removing the last item on page 2", () => {
+ expect(getSafePageAfterRemove(11, 10, 2)).toBe(1);
+ });
+
+ it("should stay on page 2 when it still has items after removal", () => {
+ expect(getSafePageAfterRemove(12, 10, 2)).toBe(2);
+ });
+
+ it("should go back one page when the removal empties the last page", () => {
+ expect(getSafePageAfterRemove(21, 10, 3)).toBe(2);
+ });
+
+ it("should never return a page lower than 1", () => {
+ expect(getSafePageAfterRemove(1, 10, 1)).toBe(1);
+ });
+
+ it("should stay on current page when removal does not reduce page count", () => {
+ expect(getSafePageAfterRemove(20, 10, 2)).toBe(2);
+ });
+});
diff --git a/src/utils/methods.js b/src/utils/methods.js
index a2bc7edab..9f0e22a05 100644
--- a/src/utils/methods.js
+++ b/src/utils/methods.js
@@ -644,3 +644,8 @@ export const getFileUploadAllowedExtensions = () => {
export const isImageUrl = (url) =>
/\.(jpe?g|png|gif|webp|svg|bmp)(\?|$)/i.test(url);
+
+export const getSafePageAfterRemove = (totalCount, perPage, currentPage) => {
+ const pageCountDecreases = Number.isInteger((totalCount - 1) / perPage);
+ return pageCountDecreases && currentPage > 1 ? currentPage - 1 : currentPage;
+};