From 091bc1bd9673a049989bd08d7e19d1f3d5e16560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Sun, 1 Feb 2026 04:22:39 -0300 Subject: [PATCH 1/4] feat: add sponsor pages tab, add customized and managed tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- src/actions/sponsor-pages-actions.js | 128 +++++++ src/i18n/en.json | 16 + src/pages/sponsors/edit-sponsor-page.js | 8 + src/pages/sponsors/sponsor-pages-tab/index.js | 347 ++++++++++++++++++ .../sponsor-page-pages-list-reducer.js | 149 ++++++++ src/store.js | 4 +- 6 files changed, 651 insertions(+), 1 deletion(-) create mode 100644 src/pages/sponsors/sponsor-pages-tab/index.js create mode 100644 src/reducers/sponsors/sponsor-page-pages-list-reducer.js diff --git a/src/actions/sponsor-pages-actions.js b/src/actions/sponsor-pages-actions.js index cb7355d1d..27d67e664 100644 --- a/src/actions/sponsor-pages-actions.js +++ b/src/actions/sponsor-pages-actions.js @@ -34,6 +34,14 @@ export const RECEIVE_SPONSOR_PAGES = "RECEIVE_SPONSOR_PAGES"; export const GLOBAL_PAGE_CLONED = "GLOBAL_PAGE_CLONED"; +export const REQUEST_SPONSOR_MANAGED_PAGES = "REQUEST_SPONSOR_MANAGED_PAGES"; +export const RECEIVE_SPONSOR_MANAGED_PAGES = "RECEIVE_SPONSOR_MANAGED_PAGES"; + +export const REQUEST_SPONSOR_CUSTOMIZED_PAGES = + "REQUEST_SPONSOR_CUSTOMIZED_PAGES"; +export const RECEIVE_SPONSOR_CUSTOMIZED_PAGES = + "RECEIVE_SPONSOR_CUSTOMIZED_PAGES"; + export const getSponsorPages = ( term = "", @@ -133,3 +141,123 @@ export const cloneGlobalPage = }) .finally(() => dispatch(stopLoading())); }; + +/* ************************************************************************ */ +/* MANAGED PAGES */ +/* ************************************************************************ */ + +export const getSponsorManagedPages = + ( + term = "", + page = DEFAULT_CURRENT_PAGE, + perPage = DEFAULT_PER_PAGE, + order = "id", + orderDir = DEFAULT_ORDER_DIR, + hideArchived = false + ) => + async (dispatch, getState) => { + const { currentSummitState, currentSponsorState } = getState(); + const { currentSummit } = currentSummitState; + const { + entity: { id: sponsorId } + } = currentSponsorState; + const accessToken = await getAccessTokenSafely(); + const summitTZ = currentSummit.time_zone.name; + const filter = []; + + dispatch(startLoading()); + + if (term) { + const escapedTerm = escapeFilterValue(term); + filter.push(`name=@${escapedTerm},code=@${escapedTerm}`); + } + + const params = { + page, + fields: "id,code,name,kind,modules_count,allowed_add_ons", + per_page: perPage, + access_token: accessToken + }; + + if (hideArchived) filter.push("is_archived==0"); + + if (filter.length > 0) { + params["filter[]"] = filter; + } + + // order + if (order != null && orderDir != null) { + const orderDirSign = orderDir === 1 ? "" : "-"; + params.order = `${orderDirSign}${order}`; + } + + return getRequest( + createAction(REQUEST_SPONSOR_MANAGED_PAGES), + createAction(RECEIVE_SPONSOR_MANAGED_PAGES), + `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/managed-pages`, + authErrorHandler, + { order, orderDir, page, term, summitTZ } + )(params)(dispatch).then(() => { + dispatch(stopLoading()); + }); + }; + +/* ************************************************************************ */ +/* CUSTOMIZED PAGES */ +/* ************************************************************************ */ + +export const getSponsorCustomizedPages = + ( + term = "", + page = DEFAULT_CURRENT_PAGE, + perPage = DEFAULT_PER_PAGE, + order = "id", + orderDir = DEFAULT_ORDER_DIR, + hideArchived = false + ) => + async (dispatch, getState) => { + const { currentSummitState, currentSponsorState } = getState(); + const { currentSummit } = currentSummitState; + const { + entity: { id: sponsorId } + } = currentSponsorState; + const accessToken = await getAccessTokenSafely(); + const summitTZ = currentSummit.time_zone.name; + const filter = []; + + dispatch(startLoading()); + + if (term) { + const escapedTerm = escapeFilterValue(term); + filter.push(`name=@${escapedTerm},code=@${escapedTerm}`); + } + + const params = { + page, + fields: "id,code,name,kind,modules_count,allowed_add_ons", + per_page: perPage, + access_token: accessToken + }; + + if (hideArchived) filter.push("is_archived==0"); + + if (filter.length > 0) { + params["filter[]"] = filter; + } + + // order + if (order != null && orderDir != null) { + const orderDirSign = orderDir === 1 ? "" : "-"; + params.order = `${orderDirSign}${order}`; + } + + return getRequest( + createAction(REQUEST_SPONSOR_CUSTOMIZED_PAGES), + createAction(RECEIVE_SPONSOR_CUSTOMIZED_PAGES), + `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-pages`, + authErrorHandler, + { order, orderDir, page, term, summitTZ } + )(params)(dispatch).then(() => { + dispatch(stopLoading()); + }); + }; diff --git a/src/i18n/en.json b/src/i18n/en.json index abea35a2c..43b656f62 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -2460,6 +2460,22 @@ } } }, + "pages_tab": { + "alert_info": "To add a Sponsor Specific Page for this show's sponsor, click Add Page button. Note: this Page will be visible only to this sponsor for this show. The General Pages can only be managed on the Show's Pages section.", + "hide_archived": "Hide archived Pages", + "using_template": "Using Template", + "new_page": "New Page", + "pages": "pages", + "sponsor_customized_pages": "Customized Sponsor Pages", + "code": "Code", + "name": "Name", + "add_ons": "Add-ons", + "info_mod": "Info Mod", + "upload_mod": "Upload Mod", + "download_mod": "Download Mod", + "archive": "Archive", + "unarchive": "Unarchive" + }, "cart_tab": { "new_form": "New Form", "forms": "forms", diff --git a/src/pages/sponsors/edit-sponsor-page.js b/src/pages/sponsors/edit-sponsor-page.js index d3101dc25..e50a842d2 100644 --- a/src/pages/sponsors/edit-sponsor-page.js +++ b/src/pages/sponsors/edit-sponsor-page.js @@ -43,6 +43,7 @@ import SponsorUsersListPerSponsorPage from "./sponsor-users-list-per-sponsor"; import SponsorFormsTab from "./sponsor-forms-tab"; import SponsorBadgeScans from "./sponsor-badge-scans"; import SponsorCartTab from "./sponsor-cart-tab"; +import SponsorPagesTab from "./sponsor-pages-tab"; import SponsorFormsManageItems from "./sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items"; import { SPONSOR_TABS } from "../../utils/constants"; @@ -235,6 +236,13 @@ const EditSponsorPage = (props) => { + + + {sponsorFormItemRoute ? ( diff --git a/src/pages/sponsors/sponsor-pages-tab/index.js b/src/pages/sponsors/sponsor-pages-tab/index.js new file mode 100644 index 000000000..a9436b172 --- /dev/null +++ b/src/pages/sponsors/sponsor-pages-tab/index.js @@ -0,0 +1,347 @@ +/** + * Copyright 2024 OpenStack Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ + +import React, { useEffect } from "react"; +import { connect } from "react-redux"; +import T from "i18n-react/dist/i18n-react"; +import { + Box, + Button, + Checkbox, + FormControlLabel, + FormGroup, + Grid2 +} from "@mui/material"; +import AddIcon from "@mui/icons-material/Add"; +import { + archiveSponsorCustomizedForm, + deleteSponsorCustomizedForm, + saveSponsorManagedForm, + unarchiveSponsorCustomizedForm +} from "../../../actions/sponsor-forms-actions"; +import { + getSponsorManagedPages, + getSponsorCustomizedPages +} from "../../../actions/sponsor-pages-actions"; +import CustomAlert from "../../../components/mui/custom-alert"; +import SearchInput from "../../../components/mui/search-input"; +import MuiTable from "../../../components/mui/table/mui-table"; +// import AddSponsorFormTemplatePopup from "./components/add-sponsor-form-template-popup"; +// import CustomizedFormPopup from "./components/customized-form/customized-form-popup"; +import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; + +const SponsorPagesTab = ({ + term, + hideArchived, + managedPages, + customizedPages, + getSponsorManagedPages, + getSponsorCustomizedPages +}) => { + useEffect(() => { + getSponsorManagedPages(); + getSponsorCustomizedPages(); + }, []); + + const handleManagedPageChange = (page) => { + const { perPage, order, orderDir } = managedPages; + getSponsorManagedPages(term, page, perPage, order, orderDir, hideArchived); + }; + + const handleManagedPerPageChange = (newPerPage) => { + const { currentPage, order, orderDir } = managedPages; + getSponsorManagedPages( + term, + currentPage, + newPerPage, + order, + orderDir, + hideArchived + ); + }; + + const handleManagedSort = (key, dir) => { + const { currentPage, perPage } = managedPages; + getSponsorManagedPages(term, currentPage, perPage, key, dir, hideArchived); + }; + + const handleCustomizedPageChange = (page) => { + const { perPage, order, orderDir } = customizedPages; + getSponsorCustomizedPages( + term, + page, + perPage, + order, + orderDir, + hideArchived + ); + }; + + const handleCustomizedPerPageChange = (newPerPage) => { + const { currentPage, order, orderDir } = customizedPages; + getSponsorCustomizedPages( + term, + currentPage, + newPerPage, + order, + orderDir, + hideArchived + ); + }; + + const handleCustomizedSort = (key, dir) => { + const { currentPage, perPage } = customizedPages; + + getSponsorCustomizedPages( + term, + currentPage, + perPage, + key, + dir, + hideArchived + ); + }; + + const handleSearch = (searchTerm) => { + getSponsorManagedPages(searchTerm); + getSponsorCustomizedPages(searchTerm); + }; + + const handleArchiveCustomizedPage = (item) => + console.log("ARCHIVE CUSTOMIZED ", item); + + const handleArchiveManagedPage = (item) => + console.log("ARCHIVE MANAGED ", item); + + const handleManagedEdit = (item) => { + console.log("EDIT MANAGED ", item); + }; + + const handleManagedDelete = (itemId) => { + console.log("DELETE MANAGED ", itemId); + }; + + const handleCustomizedEdit = (item) => { + console.log("EDIT CUSTOMIZED ", item); + }; + + const handleCustomizedDelete = (itemId) => { + console.log("DELETE CUSTOMIZED ", itemId); + }; + + const handleHideArchived = (ev) => { + getSponsorManagedPages( + term, + DEFAULT_CURRENT_PAGE, + managedPages.perPage, + managedPages.order, + managedPages.orderDir, + ev.target.checked + ); + getSponsorCustomizedPages( + term, + DEFAULT_CURRENT_PAGE, + customizedPages.perPage, + customizedPages.order, + customizedPages.orderDir, + ev.target.checked + ); + }; + + const baseColumns = (name) => [ + { + columnKey: "name", + header: name, + sortable: true + }, + { + columnKey: "code", + header: T.translate("edit_sponsor.pages_tab.code"), + sortable: true + }, + { + columnKey: "allowed_add_ons", + header: T.translate("edit_sponsor.pages_tab.add_ons"), + sortable: true, + render: (row) => + row.allowed_add_ons?.length > 0 + ? row.allowed_add_ons.map((a) => `${a.type} ${a.name}`).join(", ") + : "" + }, + { + columnKey: "info_mod", + header: T.translate("edit_sponsor.pages_tab.info_mod") + }, + { + columnKey: "upload_mod", + header: T.translate("edit_sponsor.pages_tab.upload_mod") + }, + { + columnKey: "download_mod", + header: T.translate("edit_sponsor.pages_tab.download_mod") + } + ]; + + const managedPagesColumns = [ + ...baseColumns(T.translate("edit_sponsor.pages_tab.managed_forms")) + ]; + + const customizedPagesColumns = [ + ...baseColumns( + T.translate("edit_sponsor.pages_tab.sponsor_customized_pages") + ) + ]; + + return ( + + + + + + {managedPages.totalCount + customizedPages.totalCount}{" "} + {T.translate("edit_sponsor.pages_tab.pages")} + + + + + + } + label={T.translate("edit_sponsor.pages_tab.hide_archived")} + /> + + + + + + + + + + + + +
+ +
+ +
+ +
+ + {/* setOpenPopup(null)} + onSubmit={saveSponsorManagedForm} + sponsor={sponsor} + summitId={summitId} + /> + + setCustomFormEdit(null)} + sponsor={sponsor} + summitId={summitId} + /> */} +
+ ); +}; + +const mapStateToProps = ({ sponsorPagePagesListState }) => ({ + ...sponsorPagePagesListState +}); + +export default connect(mapStateToProps, { + getSponsorManagedPages, + saveSponsorManagedForm, + getSponsorCustomizedPages, + archiveSponsorCustomizedForm, + unarchiveSponsorCustomizedForm, + deleteSponsorCustomizedForm +})(SponsorPagesTab); diff --git a/src/reducers/sponsors/sponsor-page-pages-list-reducer.js b/src/reducers/sponsors/sponsor-page-pages-list-reducer.js new file mode 100644 index 000000000..cea56a94e --- /dev/null +++ b/src/reducers/sponsors/sponsor-page-pages-list-reducer.js @@ -0,0 +1,149 @@ +/** + * Copyright 2019 OpenStack Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ + +import { LOGOUT_USER } from "openstack-uicore-foundation/lib/security/actions"; +import { + REQUEST_SPONSOR_MANAGED_PAGES, + RECEIVE_SPONSOR_MANAGED_PAGES, + RECEIVE_SPONSOR_CUSTOMIZED_PAGES, + REQUEST_SPONSOR_CUSTOMIZED_PAGES +} from "../../actions/sponsor-pages-actions"; +import { SET_CURRENT_SUMMIT } from "../../actions/summit-actions"; + +const DEFAULT_STATE = { + managedPages: { + pages: [], + order: "name", + orderDir: 1, + currentPage: 1, + lastPage: 1, + perPage: 10, + totalCount: 0 + }, + customizedPages: { + pages: [], + order: "name", + orderDir: 1, + currentPage: 1, + lastPage: 1, + perPage: 10, + totalCount: 0 + }, + term: "", + hideArchived: false, + summitTZ: "" +}; + +const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => { + const { type, payload } = action; + + switch (type) { + case SET_CURRENT_SUMMIT: + case LOGOUT_USER: { + return DEFAULT_STATE; + } + case REQUEST_SPONSOR_MANAGED_PAGES: { + const { order, orderDir, page, term, summitTZ, hideArchived } = payload; + + return { + ...state, + managedPages: { + ...state.managedPages, + order, + orderDir, + forms: [], + currentPage: page + }, + term, + summitTZ, + hideArchived + }; + } + case REQUEST_SPONSOR_CUSTOMIZED_PAGES: { + const { order, orderDir, page, term, summitTZ, hideArchived } = payload; + + return { + ...state, + customizedPages: { + ...state.customizedPages, + order, + orderDir, + forms: [], + currentPage: page + }, + term, + summitTZ, + hideArchived + }; + } + case RECEIVE_SPONSOR_MANAGED_PAGES: { + const { + current_page: currentPage, + total, + last_page: lastPage + } = payload.response; + + const pages = payload.response.data.map((a) => ({ + id: a.id, + code: a.code, + name: a.name, + info_mod: a.modules_count.info_modules_count, + upload_mod: a.modules_count.document_download_modules_count, + download_mod: a.modules_count.media_request_modules_count + })); + + return { + ...state, + managedPages: { + ...state.managedPages, + pages, + currentPage, + totalCount: total, + lastPage + } + }; + } + case RECEIVE_SPONSOR_CUSTOMIZED_PAGES: { + const { + current_page: currentPage, + total, + last_page: lastPage + } = payload.response; + + const pages = payload.response.data.map((a) => ({ + id: a.id, + code: a.code, + name: a.name, + allowed_add_ons: a.allowed_add_ons, + info_mod: a.modules_count.info_modules_count, + upload_mod: a.modules_count.document_download_modules_count, + download_mod: a.modules_count.media_request_modules_count + })); + + return { + ...state, + customizedPages: { + ...state.customizedPages, + pages, + currentPage, + totalCount: total, + lastPage + } + }; + } + default: + return state; + } +}; + +export default sponsorPagePagesListReducer; diff --git a/src/store.js b/src/store.js index ae9386539..978711df4 100644 --- a/src/store.js +++ b/src/store.js @@ -168,6 +168,7 @@ import sponsorCustomizedFormReducer from "./reducers/sponsors/sponsor-customized import sponsorPageCartListReducer from "./reducers/sponsors/sponsor-page-cart-list-reducer"; import sponsorCustomizedFormItemsListReducer from "./reducers/sponsors/sponsor-customized-form-items-list-reducer.js"; import sponsorPagesListReducer from "./reducers/sponsors/sponsor-pages-list-reducer.js"; +import sponsorPagePagesListReducer from "./reducers/sponsors/sponsor-page-pages-list-reducer.js"; // default: localStorage if web, AsyncStorage if react-native @@ -255,6 +256,7 @@ const reducers = persistCombineReducers(config, { sponsorUsersListState: sponsorUsersListReducer, sponsorPageFormsListState: sponsorPageFormsListReducer, sponsorPageCartListState: sponsorPageCartListReducer, + sponsorPagePagesListState: sponsorPagePagesListReducer, sponsorCustomizedFormState: sponsorCustomizedFormReducer, sponsorCustomizedFormItemsListState: sponsorCustomizedFormItemsListReducer, currentSponsorPromocodeListState: sponsorPromocodeListReducer, @@ -307,7 +309,7 @@ const reducers = persistCombineReducers(config, { sponsoredProjectState: sponsoredProjectReducer, sponsoredProjectSponsorshipTypeState: sponsoredProjectSponsorshipTypeReducer, sponsoredProjectSponsorshipTypeSupportingCompanyState: - sponsoredProjectSponsorshipTypeSupportingCompanyReducer, + sponsoredProjectSponsorshipTypeSupportingCompanyReducer, scheduleSettingsState: scheduleSettingsReducer, scheduleSettingsListState: scheduleSettingsListReducer, currentSelectionPlanExtraQuestionState: selectionPlanExtraQuestionReducer, From 8936391f31d0c16cd598adee79cd3dd94730037b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Mon, 2 Feb 2026 16:03:25 -0300 Subject: [PATCH 2/4] fix: adjust reducer and actions, fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- src/actions/sponsor-pages-actions.js | 4 +- src/i18n/en.json | 1 + src/pages/sponsors/sponsor-pages-tab/index.js | 50 +++++++++++-------- .../sponsor-page-pages-list-reducer.js | 21 +++++--- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/actions/sponsor-pages-actions.js b/src/actions/sponsor-pages-actions.js index 27d67e664..e8517585e 100644 --- a/src/actions/sponsor-pages-actions.js +++ b/src/actions/sponsor-pages-actions.js @@ -196,7 +196,7 @@ export const getSponsorManagedPages = createAction(RECEIVE_SPONSOR_MANAGED_PAGES), `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/managed-pages`, authErrorHandler, - { order, orderDir, page, term, summitTZ } + { order, orderDir, page, perPage, term, hideArchived, summitTZ } )(params)(dispatch).then(() => { dispatch(stopLoading()); }); @@ -256,7 +256,7 @@ export const getSponsorCustomizedPages = createAction(RECEIVE_SPONSOR_CUSTOMIZED_PAGES), `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsor-pages`, authErrorHandler, - { order, orderDir, page, term, summitTZ } + { order, orderDir, page, perPage, term, hideArchived, summitTZ } )(params)(dispatch).then(() => { dispatch(stopLoading()); }); diff --git a/src/i18n/en.json b/src/i18n/en.json index 43b656f62..8b9a4e6d0 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -2466,6 +2466,7 @@ "using_template": "Using Template", "new_page": "New Page", "pages": "pages", + "managed_pages": "Managed Pages", "sponsor_customized_pages": "Customized Sponsor Pages", "code": "Code", "name": "Name", diff --git a/src/pages/sponsors/sponsor-pages-tab/index.js b/src/pages/sponsors/sponsor-pages-tab/index.js index a9436b172..e1ccca6b2 100644 --- a/src/pages/sponsors/sponsor-pages-tab/index.js +++ b/src/pages/sponsors/sponsor-pages-tab/index.js @@ -113,8 +113,32 @@ const SponsorPagesTab = ({ }; const handleSearch = (searchTerm) => { - getSponsorManagedPages(searchTerm); - getSponsorCustomizedPages(searchTerm); + const { + perPage: perPageManaged, + order: orderManaged, + orderDir: orderDirManaged + } = managedPages; + const { + perPage: perPageCustomized, + order: orderCustomized, + orderDir: orderDirCustomized + } = customizedPages; + getSponsorManagedPages( + searchTerm, + DEFAULT_CURRENT_PAGE, + perPageManaged, + orderManaged, + orderDirManaged, + hideArchived + ); + getSponsorCustomizedPages( + searchTerm, + DEFAULT_CURRENT_PAGE, + perPageCustomized, + orderCustomized, + orderDirCustomized, + hideArchived + ); }; const handleArchiveCustomizedPage = (item) => @@ -193,7 +217,7 @@ const SponsorPagesTab = ({ ]; const managedPagesColumns = [ - ...baseColumns(T.translate("edit_sponsor.pages_tab.managed_forms")) + ...baseColumns(T.translate("edit_sponsor.pages_tab.managed_pages")) ]; const customizedPagesColumns = [ @@ -253,7 +277,7 @@ const SponsorPagesTab = ({ variant="contained" size="medium" fullWidth - onClick={() => setOpenPopup("template")} + onClick={() => console.log("open popup template")} startIcon={} sx={{ height: "36px" }} > @@ -265,7 +289,7 @@ const SponsorPagesTab = ({ variant="contained" size="medium" fullWidth - onClick={() => setCustomFormEdit("new")} + onClick={() => console.log("open popup new")} startIcon={} sx={{ height: "36px" }} > @@ -313,22 +337,6 @@ const SponsorPagesTab = ({ onArchive={handleArchiveManagedPage} /> - - {/* setOpenPopup(null)} - onSubmit={saveSponsorManagedForm} - sponsor={sponsor} - summitId={summitId} - /> - - setCustomFormEdit(null)} - sponsor={sponsor} - summitId={summitId} - /> */} ); }; diff --git a/src/reducers/sponsors/sponsor-page-pages-list-reducer.js b/src/reducers/sponsors/sponsor-page-pages-list-reducer.js index cea56a94e..b5e799ea0 100644 --- a/src/reducers/sponsors/sponsor-page-pages-list-reducer.js +++ b/src/reducers/sponsors/sponsor-page-pages-list-reducer.js @@ -53,7 +53,8 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => { return DEFAULT_STATE; } case REQUEST_SPONSOR_MANAGED_PAGES: { - const { order, orderDir, page, term, summitTZ, hideArchived } = payload; + const { order, orderDir, page, perPage, term, summitTZ, hideArchived } = + payload; return { ...state, @@ -61,8 +62,9 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => { ...state.managedPages, order, orderDir, - forms: [], - currentPage: page + pages: [], + currentPage: page, + perPage }, term, summitTZ, @@ -70,7 +72,8 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => { }; } case REQUEST_SPONSOR_CUSTOMIZED_PAGES: { - const { order, orderDir, page, term, summitTZ, hideArchived } = payload; + const { order, orderDir, page, perPage, term, summitTZ, hideArchived } = + payload; return { ...state, @@ -78,8 +81,9 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => { ...state.customizedPages, order, orderDir, - forms: [], - currentPage: page + pages: [], + currentPage: page, + perPage }, term, summitTZ, @@ -97,6 +101,7 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => { id: a.id, code: a.code, name: a.name, + allowed_add_ons: a.allowed_add_ons, info_mod: a.modules_count.info_modules_count, upload_mod: a.modules_count.document_download_modules_count, download_mod: a.modules_count.media_request_modules_count @@ -126,8 +131,8 @@ const sponsorPagePagesListReducer = (state = DEFAULT_STATE, action) => { name: a.name, allowed_add_ons: a.allowed_add_ons, info_mod: a.modules_count.info_modules_count, - upload_mod: a.modules_count.document_download_modules_count, - download_mod: a.modules_count.media_request_modules_count + upload_mod: a.modules_count.media_request_modules_count, + download_mod: a.modules_count.document_download_modules_count })); return { From 45f01d367ea6c724bb802b12a21730dca44488f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Mon, 2 Feb 2026 16:11:30 -0300 Subject: [PATCH 3/4] fix: replace value with checked on hide archived checkbox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- src/pages/sponsors/sponsor-pages-tab/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/sponsors/sponsor-pages-tab/index.js b/src/pages/sponsors/sponsor-pages-tab/index.js index e1ccca6b2..2bccf1a86 100644 --- a/src/pages/sponsors/sponsor-pages-tab/index.js +++ b/src/pages/sponsors/sponsor-pages-tab/index.js @@ -252,7 +252,7 @@ const SponsorPagesTab = ({ Date: Wed, 18 Feb 2026 09:53:37 -0300 Subject: [PATCH 4/4] feat: add new template popup on sponsor tab to add managed pages from templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- src/actions/sponsor-pages-actions.js | 44 +++ .../formik-inputs/mui-formik-select-group.js | 124 ++++--- src/i18n/en.json | 5 +- .../add-sponsor-page-template-popup/index.js | 311 ++++++++++++++++++ src/pages/sponsors/sponsor-pages-tab/index.js | 50 ++- 5 files changed, 468 insertions(+), 66 deletions(-) create mode 100644 src/pages/sponsors/sponsor-pages-tab/components/add-sponsor-page-template-popup/index.js diff --git a/src/actions/sponsor-pages-actions.js b/src/actions/sponsor-pages-actions.js index e8517585e..66beca17e 100644 --- a/src/actions/sponsor-pages-actions.js +++ b/src/actions/sponsor-pages-actions.js @@ -36,6 +36,7 @@ export const GLOBAL_PAGE_CLONED = "GLOBAL_PAGE_CLONED"; export const REQUEST_SPONSOR_MANAGED_PAGES = "REQUEST_SPONSOR_MANAGED_PAGES"; export const RECEIVE_SPONSOR_MANAGED_PAGES = "RECEIVE_SPONSOR_MANAGED_PAGES"; +export const SPONSOR_MANAGED_PAGE_ADDED = "SPONSOR_MANAGED_PAGE_ADDED"; export const REQUEST_SPONSOR_CUSTOMIZED_PAGES = "REQUEST_SPONSOR_CUSTOMIZED_PAGES"; @@ -202,6 +203,49 @@ export const getSponsorManagedPages = }); }; +export const saveSponsorManagedPage = + (entity) => async (dispatch, getState) => { + const { currentSummitState, currentSponsorState } = getState(); + const { currentSummit } = currentSummitState; + const { + entity: { id: sponsorId } + } = currentSponsorState; + const accessToken = await getAccessTokenSafely(); + + dispatch(startLoading()); + + const normalizedEntity = normalizeSponsorManagedPage(entity); + + const params = { + access_token: accessToken, + fields: "id,code,name,kind,modules_count,allowed_add_ons" + }; + + return postRequest( + null, + createAction(SPONSOR_MANAGED_PAGE_ADDED), + `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/managed-pages`, + normalizedEntity, + snackbarErrorHandler + )(params)(dispatch).then(() => { + dispatch(stopLoading()); + }); + }; + +const normalizeSponsorManagedPage = (entity) => { + const normalizedEntity = { + show_page_ids: entity.pages, + allowed_add_ons: entity.add_ons.map((a) => a.id), + apply_to_all_add_ons: false + }; + + if (entity.add_ons.includes("all")) { + normalizedEntity.apply_to_all_add_ons = true; + normalizedEntity.allowed_add_ons = []; + } + + return normalizedEntity; +}; /* ************************************************************************ */ /* CUSTOMIZED PAGES */ /* ************************************************************************ */ diff --git a/src/components/mui/formik-inputs/mui-formik-select-group.js b/src/components/mui/formik-inputs/mui-formik-select-group.js index 9a1261d0a..60be7c1df 100644 --- a/src/components/mui/formik-inputs/mui-formik-select-group.js +++ b/src/components/mui/formik-inputs/mui-formik-select-group.js @@ -44,6 +44,7 @@ const MuiFormikSelectGroup = ({ selectAllLabel = "Select All", getOptionLabel = (item) => item.name, getOptionValue = (item) => item.id, + noOptionsLabel = "No items", getGroupId = null, getGroupLabel = null, disabled = false @@ -213,6 +214,79 @@ const MuiFormikSelectGroup = ({ .flat() .filter(Boolean); + const renderMenuContent = () => { + if (loading) { + return ( + + + + ); + } + + if (options.length === 0) { + return ( + + + + ); + } + + return ( + <> + {showSelectAll && ( + <> + { + // custom event value to select all + handleChange({ target: { value: ["selectAll"] } }); + }} + > + 0 && !isAllSelected} + sx={{ + p: 1, + "& svg": { + fontSize: 24 + } + }} + /> + + + + + )} + {renderGroupedOptions()} + + ); + }; + const IconWithLoading = useMemo(() => getCustomIcon(loading), [loading]); return ( @@ -243,54 +317,7 @@ const MuiFormikSelectGroup = ({ error={Boolean(error)} IconComponent={IconWithLoading} > - {loading ? ( - - - - ) : ( - <> - {showSelectAll && options.length > 0 && ( - <> - { - // custom event value to select all - handleChange({ target: { value: ["selectAll"] } }); - }} - > - 0 && !isAllSelected} - sx={{ - p: 1, - "& svg": { - fontSize: 24 - } - }} - /> - - - - - )} - {renderGroupedOptions()} - - )} + {renderMenuContent()} {error && (
{ + const [searchTerm, setSearchTerm] = useState(""); + const [selectedPages, setSelectedPages] = useState([]); + + const sponsorshipIds = sponsor.sponsorships.map((e) => e.id); + + const sponsorshipTypeIds = sponsor.sponsorships.map((e) => e.type.id); + + const formik = useFormik({ + initialValues: { + add_ons: [] + }, + validationSchema: yup.object({ + add_ons: yup + .array() + .test( + "add_ons-required", + "Select at least one add-on", + (value) => value?.includes("all") || value?.length > 0 + ) + }), + onSubmit: (values) => { + const { add_ons } = values; + const entity = { + pages: selectedPages, + add_ons + }; + onSubmit(entity); + }, + enableReinitialize: true + }); + + useEffect(() => { + getSponsorPages( + term, + currentPage, + FIVE_PER_PAGE, + order, + orderDir, + false, + sponsorshipTypeIds + ); + }, []); + + const handlePageChange = (page) => { + getSponsorPages( + term, + page, + FIVE_PER_PAGE, + order, + orderDir, + false, + sponsorshipTypeIds + ); + }; + + const handleSort = (key, dir) => { + getSponsorPages( + term, + currentPage, + FIVE_PER_PAGE, + key, + dir, + false, + sponsorshipTypeIds + ); + }; + + const handleOnSearch = (ev) => { + if (ev.key === "Enter") + getSponsorPages( + searchTerm, + currentPage, + perPage, + order, + orderDir, + false, + sponsorshipTypeIds + ); + }; + + const handleSelected = (id, isSelected) => { + if (isSelected) { + setSelectedPages([...selectedPages, id]); + return; + } + const updatedSelected = selectedPages.filter((e) => e !== id); + setSelectedPages(updatedSelected); + }; + + const handleClose = () => { + onClose(); + }; + + const tableOptions = { + sortCol: order, + sortDir: orderDir + }; + + const columns = [ + { + columnKey: "select", + header: "", + width: 30, + align: "center", + render: (row) => ( + handleSelected(row.id, ev.target.checked)} + /> + } + /> + ) + }, + { + columnKey: "code", + header: T.translate("edit_sponsor.pages_tab.code"), + sortable: false + }, + { + columnKey: "name", + header: T.translate("edit_sponsor.pages_tab.name"), + sortable: false + }, + { + columnKey: "info_mod", + header: T.translate("edit_sponsor.pages_tab.info_mod") + }, + { + columnKey: "upload_mod", + header: T.translate("edit_sponsor.pages_tab.upload_mod") + }, + { + columnKey: "download_mod", + header: T.translate("edit_sponsor.pages_tab.download_mod") + } + ]; + + return ( + + + + {T.translate("edit_sponsor.pages_tab.add_page_using_template")} + + handleClose()} sx={{ mr: 1 }}> + + + + + + + + + addon.sponsorship.type.id} + getGroupLabel={(addon) => addon.sponsorship.type.type.name} + noOptionsLabel={T.translate( + "edit_sponsor.pages_tab.no_add_ons" + )} + placeholder={T.translate( + "edit_sponsor.placeholders.select_add_ons" + )} + /> + + + + {selectedPages.length} items selected + + + + handleSort("name", 1) }, + { label: "Z-A", onClick: () => handleSort("name", 0) } + ]} + > + sort by + + + + + } + }} + onChange={(event) => setSearchTerm(event.target.value)} + onKeyDown={handleOnSearch} + fullWidth + sx={{ + "& .MuiOutlinedInput-root": { + height: "36px" + } + }} + /> + + + + + {sponsorPages.length > 0 && ( + + + + )} + + + + + + + + + ); +}; + +AddSponsorPageTemplatePopup.propTypes = { + onClose: PropTypes.func.isRequired +}; + +const mapStateToProps = ({ sponsorPagesListState }) => ({ + ...sponsorPagesListState +}); + +export default connect(mapStateToProps, { + getSponsorPages +})(AddSponsorPageTemplatePopup); diff --git a/src/pages/sponsors/sponsor-pages-tab/index.js b/src/pages/sponsors/sponsor-pages-tab/index.js index 2bccf1a86..811801bc8 100644 --- a/src/pages/sponsors/sponsor-pages-tab/index.js +++ b/src/pages/sponsors/sponsor-pages-tab/index.js @@ -11,7 +11,7 @@ * limitations under the License. * */ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { connect } from "react-redux"; import T from "i18n-react/dist/i18n-react"; import { @@ -23,31 +23,30 @@ import { Grid2 } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; -import { - archiveSponsorCustomizedForm, - deleteSponsorCustomizedForm, - saveSponsorManagedForm, - unarchiveSponsorCustomizedForm -} from "../../../actions/sponsor-forms-actions"; import { getSponsorManagedPages, - getSponsorCustomizedPages + getSponsorCustomizedPages, + saveSponsorManagedPage } from "../../../actions/sponsor-pages-actions"; import CustomAlert from "../../../components/mui/custom-alert"; import SearchInput from "../../../components/mui/search-input"; import MuiTable from "../../../components/mui/table/mui-table"; -// import AddSponsorFormTemplatePopup from "./components/add-sponsor-form-template-popup"; -// import CustomizedFormPopup from "./components/customized-form/customized-form-popup"; import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; +import AddSponsorPageTemplatePopup from "./components/add-sponsor-page-template-popup"; const SponsorPagesTab = ({ + sponsor, + summitId, term, hideArchived, managedPages, customizedPages, getSponsorManagedPages, - getSponsorCustomizedPages + getSponsorCustomizedPages, + saveSponsorManagedPage }) => { + const [openPopup, setOpenPopup] = useState(null); + useEffect(() => { getSponsorManagedPages(); getSponsorCustomizedPages(); @@ -141,6 +140,10 @@ const SponsorPagesTab = ({ ); }; + const handleUsingTemplate = () => { + setOpenPopup("template"); + }; + const handleArchiveCustomizedPage = (item) => console.log("ARCHIVE CUSTOMIZED ", item); @@ -182,6 +185,13 @@ const SponsorPagesTab = ({ ); }; + const handleSaveManagedPageFromTemplate = (entity) => { + saveSponsorManagedPage(entity).then(() => { + setOpenPopup(null); + getSponsorManagedPages(); + }); + }; + const baseColumns = (name) => [ { columnKey: "name", @@ -277,7 +287,7 @@ const SponsorPagesTab = ({ variant="contained" size="medium" fullWidth - onClick={() => console.log("open popup template")} + onClick={handleUsingTemplate} startIcon={} sx={{ height: "36px" }} > @@ -337,6 +347,15 @@ const SponsorPagesTab = ({ onArchive={handleArchiveManagedPage} />
+ + {openPopup === "template" && ( + setOpenPopup(null)} + /> + )} ); }; @@ -347,9 +366,6 @@ const mapStateToProps = ({ sponsorPagePagesListState }) => ({ export default connect(mapStateToProps, { getSponsorManagedPages, - saveSponsorManagedForm, - getSponsorCustomizedPages, - archiveSponsorCustomizedForm, - unarchiveSponsorCustomizedForm, - deleteSponsorCustomizedForm + saveSponsorManagedPage, + getSponsorCustomizedPages })(SponsorPagesTab);