From e3b2cbbdb257f0fc0e3aaad5d536a20ef85f4021 Mon Sep 17 00:00:00 2001 From: Santiago Palenque Date: Thu, 11 Dec 2025 14:47:55 -0300 Subject: [PATCH 1/4] feat: page templates grid and menu --- .env.example | 2 + src/actions/page-template-actions.js | 254 +++++++++++++++++ src/app.js | 1 + src/components/menu/index.js | 4 + src/i18n/en.json | 23 +- src/layouts/page-template-layout.js | 55 ++++ src/layouts/primary-layout.js | 2 + .../edit-page-template-page.js | 85 ++++++ .../page-template-list-page.js | 257 ++++++++++++++++++ .../page-template-list-reducer.js | 124 +++++++++ src/store.js | 4 +- 11 files changed, 809 insertions(+), 2 deletions(-) create mode 100644 src/actions/page-template-actions.js create mode 100644 src/layouts/page-template-layout.js create mode 100644 src/pages/sponsors_inventory/edit-page-template-page.js create mode 100644 src/pages/sponsors_inventory/page-template-list-page.js create mode 100644 src/reducers/sponsors_inventory/page-template-list-reducer.js diff --git a/.env.example b/.env.example index b71ae142b..1a059072b 100644 --- a/.env.example +++ b/.env.example @@ -17,6 +17,8 @@ SPONSOR_USERS_API_SCOPES="show-medata/read show-medata/write access-requests/rea EMAIL_SCOPES="clients/read templates/read templates/write emails/read" FILE_UPLOAD_SCOPES="files/upload" SCOPES="profile openid offline_access ${SPONSOR_USERS_API_SCOPES} ${PURCHASES_API_SCOPES} ${EMAIL_SCOPES} ${FILE_UPLOAD_SCOPES} ${SCOPES_BASE_REALM}/summits/delete-event ${SCOPES_BASE_REALM}/summits/write ${SCOPES_BASE_REALM}/summits/write-event ${SCOPES_BASE_REALM}/summits/read/all ${SCOPES_BASE_REALM}/summits/read ${SCOPES_BASE_REALM}/summits/publish-event ${SCOPES_BASE_REALM}/members/read ${SCOPES_BASE_REALM}/members/read/me ${SCOPES_BASE_REALM}/speakers/write ${SCOPES_BASE_REALM}/attendees/write ${SCOPES_BASE_REALM}/members/write ${SCOPES_BASE_REALM}/organizations/write ${SCOPES_BASE_REALM}/organizations/read ${SCOPES_BASE_REALM}/summits/write-presentation-materials ${SCOPES_BASE_REALM}/summits/registration-orders/update ${SCOPES_BASE_REALM}/summits/registration-orders/delete ${SCOPES_BASE_REALM}/summits/registration-orders/create/offline ${SCOPES_BASE_REALM}/summits/badge-scans/read entity-updates/publish ${SCOPES_BASE_REALM}/audit-logs/read" +SPONSOR_PAGES_API_URL=https://sponsor-pages-api.dev.fnopen.com +SPONSOR_PAGES_SCOPES=page-template/read page-template/write GOOGLE_API_KEY= ALLOWED_USER_GROUPS="super-admins administrators summit-front-end-administrators summit-room-administrators track-chairs-admins sponsors" APP_CLIENT_NAME = "openstack" diff --git a/src/actions/page-template-actions.js b/src/actions/page-template-actions.js new file mode 100644 index 000000000..44c341bd2 --- /dev/null +++ b/src/actions/page-template-actions.js @@ -0,0 +1,254 @@ +/** + * 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 T from "i18n-react/dist/i18n-react"; +import { + getRequest, + putRequest, + postRequest, + deleteRequest, + createAction, + stopLoading, + startLoading, + showMessage, + showSuccessMessage, + authErrorHandler, + escapeFilterValue +} from "openstack-uicore-foundation/lib/utils/actions"; +import history from "../history"; +import { getAccessTokenSafely } from "../utils/methods"; +import { + DEFAULT_CURRENT_PAGE, + DEFAULT_ORDER_DIR, + DEFAULT_PER_PAGE +} from "../utils/constants"; +import { snackbarErrorHandler } from "./base-actions"; + + + +export const ADD_PAGE_TEMPLATE = "ADD_PAGE_TEMPLATE"; +export const PAGE_TEMPLATE_ADDED = "PAGE_TEMPLATE_ADDED"; +export const PAGE_TEMPLATE_DELETED = "PAGE_TEMPLATE_DELETED"; +export const PAGE_TEMPLATE_UPDATED = "PAGE_TEMPLATE_UPDATED"; +export const RECEIVE_PAGE_TEMPLATE = "RECEIVE_PAGE_TEMPLATE"; +export const RECEIVE_PAGE_TEMPLATES = "RECEIVE_PAGE_TEMPLATES"; +export const REQUEST_PAGE_TEMPLATES = "REQUEST_PAGE_TEMPLATES"; +export const RESET_PAGE_TEMPLATE_FORM = "RESET_PAGE_TEMPLATE_FORM"; +export const UPDATE_PAGE_TEMPLATE = "UPDATE_PAGE_TEMPLATE"; +export const PAGE_TEMPLATE_ARCHIVED = "PAGE_TEMPLATE_ARCHIVED"; +export const PAGE_TEMPLATE_UNARCHIVED = "PAGE_TEMPLATE_UNARCHIVED"; + +export const getPageTemplates = + ( + term = null, + page = DEFAULT_CURRENT_PAGE, + perPage = DEFAULT_PER_PAGE, + order = "id", + orderDir = DEFAULT_ORDER_DIR, + hideArchived = false + ) => + async (dispatch) => { + const accessToken = await getAccessTokenSafely(); + const filter = []; + + dispatch(startLoading()); + + if (term) { + const escapedTerm = escapeFilterValue(term); + filter.push(`name=@${escapedTerm},code=@${escapedTerm}`); + } + + const params = { + page, + /* + expand: "modules", + fields: "id,code,name,modules,is_archived,modules.kind,modules.id,modules.content", + relations: "modules,modules.none", + */ + 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_PAGE_TEMPLATES), + createAction(RECEIVE_PAGE_TEMPLATES), + `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates`, + authErrorHandler, + { order, orderDir, page, perPage, term, hideArchived } + )(params)(dispatch).then(() => { + dispatch(stopLoading()); + }); + }; + +export const getPageTemplate = (formTemplateId) => async (dispatch) => { + const accessToken = await getAccessTokenSafely(); + + dispatch(startLoading()); + + const params = { + access_token: accessToken, + expand: "materials,meta_fields,meta_fields.values" + }; + + return getRequest( + null, + createAction(RECEIVE_PAGE_TEMPLATE), + `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${formTemplateId}`, + authErrorHandler + )(params)(dispatch).then(() => { + dispatch(stopLoading()); + }); +}; + +export const deletePageTemplate = (formTemplateId) => async (dispatch) => { + const accessToken = await getAccessTokenSafely(); + + dispatch(startLoading()); + + const params = { + access_token: accessToken + }; + + return deleteRequest( + null, + createAction(PAGE_TEMPLATE_DELETED)({ formTemplateId }), + `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${formTemplateId}`, + null, + authErrorHandler + )(params)(dispatch).then(() => { + dispatch(stopLoading()); + }); +}; + +export const resetPageTemplateForm = () => (dispatch) => { + dispatch(createAction(RESET_PAGE_TEMPLATE_FORM)({})); +}; + +const normalizeEntity = (entity) => { + const normalizedEntity = { ...entity }; + normalizedEntity.meta_fields = normalizedEntity.meta_fields?.filter( + (mf) => mf.name + ); + normalizedEntity.materials = normalizedEntity.materials?.filter( + (mat) => mat.file_path + ); + return normalizedEntity; +}; + +export const savePageTemplate = (entity) => async (dispatch) => { + const accessToken = await getAccessTokenSafely(); + const params = { + access_token: accessToken, + expand: "materials,meta_fields,meta_fields.values" + }; + + dispatch(startLoading()); + + const normalizedEntity = normalizeEntity(entity); + + if (entity.id) { + return putRequest( + createAction(UPDATE_PAGE_TEMPLATE), + createAction(PAGE_TEMPLATE_UPDATED), + `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${entity.id}`, + normalizedEntity, + authErrorHandler, + entity + )(params)(dispatch) + .then(() => { + dispatch( + showSuccessMessage( + T.translate("edit_form_template.form_template_saved") + ) + ); + }) + .catch((err) => { + console.error(err); + }) + .finally(() => { + dispatch(stopLoading()); + }); + } + + const success_message = { + title: T.translate("general.done"), + html: T.translate("edit_form_template.form_template_created"), + type: "success" + }; + + return postRequest( + createAction(ADD_PAGE_TEMPLATE), + createAction(PAGE_TEMPLATE_ADDED), + `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates`, + normalizedEntity, + authErrorHandler, + entity + )(params)(dispatch) + .then(() => { + dispatch( + showMessage(success_message, () => { + history.push("/app/page-templates"); + }) + ); + }) + .catch((err) => { + console.error(err); + }) + .finally(() => { + dispatch(stopLoading()); + }); +}; + +/* ************************************** 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 unarchivePageTemplate = (pageTemplateId) => async (dispatch) => { + const accessToken = await getAccessTokenSafely(); + const params = { access_token: accessToken }; + + 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(() => { + dispatch(stopLoading()); + }); +}; diff --git a/src/app.js b/src/app.js index edf4be49d..eb5b5e2b2 100644 --- a/src/app.js +++ b/src/app.js @@ -81,6 +81,7 @@ window.MARKETING_API_BASE_URL = process.env.MARKETING_API_BASE_URL; window.EMAIL_API_BASE_URL = process.env.EMAIL_API_BASE_URL; window.PURCHASES_API_URL = process.env.PURCHASES_API_URL; window.SPONSOR_USERS_API_URL = process.env.SPONSOR_USERS_API_URL; +window.SPONSOR_PAGES_API_URL = process.env.SPONSOR_PAGES_API_URL; window.FILE_UPLOAD_API_BASE_URL = process.env.FILE_UPLOAD_API_BASE_URL; window.SIGNAGE_BASE_URL = process.env.SIGNAGE_BASE_URL; window.INVENTORY_API_BASE_URL = process.env.INVENTORY_API_BASE_URL; diff --git a/src/components/menu/index.js b/src/components/menu/index.js index 61177a4a4..83e492498 100644 --- a/src/components/menu/index.js +++ b/src/components/menu/index.js @@ -61,6 +61,10 @@ const getGlobalItems = () => [ { name: "form_templates", linkUrl: "form-templates" + }, + { + name: "page_templates", + linkUrl: "page-templates" } ] }, diff --git a/src/i18n/en.json b/src/i18n/en.json index 8a04b78c8..c38c72f8a 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -187,7 +187,8 @@ "submission_invitations": "Submission Invitations", "sponsors_inventory": "Sponsors", "form_templates": "Form Templates", - "inventory": "Inventory" + "inventory": "Inventory", + "page_templates": "Pages" }, "schedule": { "schedule": "Schedule", @@ -3828,5 +3829,25 @@ "seat_type": "Select a Seat Type", "status": "Select a Status" } + }, + "page_template_list": { + "page_templates": "Page Templates", + "alert_info": "You can create or archive Pages from the list. To edit a Page click on the item's Edit botton.", + "code": "Code", + "name": "Name", + "info_mod": "Info Mod", + "upload_mod": "Upload Mod", + "download_mod": "Download Mod", + "hide_archived": "Hide archived pages", + "no_pages": "No pages found.", + "add_new": "New Page", + "add_template": "Using Template", + "delete_form_template_warning": "Are you sure you want to delete form template ", + "using_duplicate": "Using Duplicate", + "add_form_template": "New Form", + "add_using_global_template": "Using Global Template", + "placeholders": { + "search": "Search" + } } } diff --git a/src/layouts/page-template-layout.js b/src/layouts/page-template-layout.js new file mode 100644 index 000000000..ab4fc6e13 --- /dev/null +++ b/src/layouts/page-template-layout.js @@ -0,0 +1,55 @@ +/** + * 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 from "react"; +import { Switch, Route, withRouter } from "react-router-dom"; +import T from "i18n-react/dist/i18n-react"; +import { Breadcrumb } from "react-breadcrumbs"; +import Restrict from "../routes/restrict"; +import NoMatchPage from "../pages/no-match-page"; +import EditPageTemplatePage from "../pages/sponsors_inventory/edit-page-template-page"; +import PageTemplateListPage from "../pages/sponsors_inventory/page-template-list-page"; + +const PageTemplateLayout = ({ match }) => ( +
+ + + + + + + +
+); + +export default Restrict(withRouter(PageTemplateLayout), "page-template"); diff --git a/src/layouts/primary-layout.js b/src/layouts/primary-layout.js index 29f46f0b4..086398890 100644 --- a/src/layouts/primary-layout.js +++ b/src/layouts/primary-layout.js @@ -29,6 +29,7 @@ import MediaFileTypeLayout from "./media-file-type-layout"; import SponsoredProjectLayout from "./sponsored-project-layout"; import TagLayout from "./tag-layout"; import SponsorshipLayout from "./sponsorship-layout"; +import PageTemplateLayout from "./page-template-layout"; const PrimaryLayout = ({ match, currentSummit, location, member }) => { let extraClass = "container"; @@ -65,6 +66,7 @@ const PrimaryLayout = ({ match, currentSummit, location, member }) => { + { + const { + match, + entity, + errors, + getFormTemplate, + resetFormTemplateForm, + saveFormTemplate, + deleteFormTemplateMetaFieldType, + deleteFormTemplateMetaFieldTypeValue, + deleteFormTemplateMaterial + } = props; + const formTemplateId = match.params.form_template_id; + + useEffect(() => { + if (!formTemplateId) { + resetFormTemplateForm(); + } else { + getFormTemplate(formTemplateId); + } + }, [formTemplateId, getFormTemplate, resetFormTemplateForm]); + + const title = entity.id + ? T.translate("general.edit") + : T.translate("general.add"); + const breadcrumb = entity.id ? entity.name : T.translate("general.new"); + + return ( +
+ +

+ {title} {T.translate("edit_form_template.form_template")} +

+
+ +
+ ); +}; + +const mapStateToProps = ({ currentFormTemplateState }) => ({ + ...currentFormTemplateState +}); + +export default connect(mapStateToProps, { + getFormTemplate, + resetFormTemplateForm, + saveFormTemplate, + deleteFormTemplateMetaFieldType, + deleteFormTemplateMetaFieldTypeValue, + deleteFormTemplateMaterial +})(EditPageTemplatePage); diff --git a/src/pages/sponsors_inventory/page-template-list-page.js b/src/pages/sponsors_inventory/page-template-list-page.js new file mode 100644 index 000000000..893c03e05 --- /dev/null +++ b/src/pages/sponsors_inventory/page-template-list-page.js @@ -0,0 +1,257 @@ +/** + * 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 { + Alert, + Button, + Checkbox, + FormControlLabel, + FormGroup, + Grid2 +} from "@mui/material"; +import Box from "@mui/material/Box"; +import AddIcon from "@mui/icons-material/Add"; +import { connect } from "react-redux"; +import T from "i18n-react/dist/i18n-react"; +import { + archivePageTemplate, + getPageTemplates, + unarchivePageTemplate +} from "../../actions/page-template-actions"; +import MuiTable from "../../components/mui/table/mui-table"; +import SearchInput from "../../components/mui/search-input"; +import { DEFAULT_CURRENT_PAGE } from "../../utils/constants"; + +const PageTemplateListPage = ({ + pageTemplates, + currentPage, + perPage, + term, + order, + orderDir, + hideArchived, + totalPageTemplates, + getPageTemplates, + archivePageTemplate, + unarchivePageTemplate +}) => { + useEffect(() => { + getPageTemplates(); + }, []); + + const handlePageChange = (page) => { + getPageTemplates(term, page, perPage, order, orderDir, hideArchived); + }; + + const handlePerPageChange = (newPerPage) => { + getPageTemplates( + term, + DEFAULT_CURRENT_PAGE, + newPerPage, + order, + orderDir, + hideArchived + ); + }; + + const handleSort = (key, dir) => { + getPageTemplates(term, currentPage, perPage, key, dir, hideArchived); + }; + + const handleSearch = (searchTerm) => { + getPageTemplates( + searchTerm, + currentPage, + perPage, + order, + orderDir, + hideArchived + ); + }; + + const handleHideArchived = (ev) => { + getPageTemplates( + term, + currentPage, + perPage, + order, + orderDir, + ev.target.checked + ); + }; + + const handleNewPageTemplate = () => { + console.log("NEW PAGE"); + }; + + const handleClonePageTemplate = () => { + console.log("CLONE PAGE"); + }; + + const handleArchive = (item) => + item.is_archived + ? unarchivePageTemplate(item.id) + : archivePageTemplate(item.id); + + const handleEdit = (row) => { + console.log("EDIT", row); + }; + + const handleDelete = (row) => { + console.log("DELETE", row); + }; + + const columns = [ + { + columnKey: "code", + header: T.translate("page_template_list.code"), + sortable: true + }, + { + columnKey: "name", + header: T.translate("page_template_list.name"), + sortable: true + }, + { + columnKey: "info_mod", + header: T.translate("page_template_list.info_mod"), + sortable: false + }, + { + columnKey: "upload_mod", + header: T.translate("page_template_list.upload_mod"), + sortable: false + }, + { + columnKey: "download_mod", + header: T.translate("page_template_list.download_mod"), + sortable: false + } + ]; + + const tableOptions = { + sortCol: order, + sortDir: orderDir + }; + + return ( +
+

+ {T.translate("page_template_list.page_templates")} ({totalPageTemplates} + ) +

+ + {T.translate("page_template_list.alert_info")} + + + + + {totalPageTemplates} pages + + + + } + label={T.translate("page_template_list.hide_archived")} + /> + + + + + + + + + + + {pageTemplates.length === 0 && ( + + {T.translate("page_template_list.no_pages")} + + )} + + {pageTemplates.length > 0 && ( +
+ +
+ )} +
+
+ ); +}; + +const mapStateToProps = ({ pageTemplateListState }) => ({ + ...pageTemplateListState +}); + +export default connect(mapStateToProps, { + getPageTemplates, + archivePageTemplate, + unarchivePageTemplate +})(PageTemplateListPage); diff --git a/src/reducers/sponsors_inventory/page-template-list-reducer.js b/src/reducers/sponsors_inventory/page-template-list-reducer.js new file mode 100644 index 000000000..e2ff363d0 --- /dev/null +++ b/src/reducers/sponsors_inventory/page-template-list-reducer.js @@ -0,0 +1,124 @@ +/** + * 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 { LOGOUT_USER } from "openstack-uicore-foundation/lib/security/actions"; +import { + REQUEST_PAGE_TEMPLATES, + RECEIVE_PAGE_TEMPLATES, + PAGE_TEMPLATE_DELETED, + PAGE_TEMPLATE_ARCHIVED, + PAGE_TEMPLATE_UNARCHIVED +} from "../../actions/page-template-actions"; + +const DEFAULT_STATE = { + pageTemplates: [], + term: null, + order: "name", + orderDir: 1, + currentPage: 1, + lastPage: 1, + perPage: 10, + totalPageTemplates: 0, + hideArchived: false +}; + +const pageTemplateListReducer = (state = DEFAULT_STATE, action = {}) => { + const { type, payload } = action; + switch (type) { + case LOGOUT_USER: { + return DEFAULT_STATE; + } + case REQUEST_PAGE_TEMPLATES: { + const { order, orderDir, page, perPage, ...rest } = payload; + + if ( + order !== state.order || + orderDir !== state.orderDir || + page !== state.currentPage + ) { + // if the change was in page or order, keep selection + return { + ...state, + order, + orderDir, + currentPage: page, + ...rest + }; + } + + return { + ...state, + order, + orderDir, + pageTemplates: [], + currentPage: page, + perPage, + ...rest + }; + } + case RECEIVE_PAGE_TEMPLATES: { + const { current_page, total, last_page } = payload.response; + + const pageTemplates = payload.response.data.map((a) => ({ + id: a.id, + code: a.code, + name: a.name, + info_mod: a.modules.filter((m) => m.kind === "Info").length, + upload_mod: a.modules.filter((m) => m.kind === "Upload").length, + download_mod: a.modules.filter((m) => m.kind === "Download").length, + is_archived: a.is_archived + })); + + return { + ...state, + pageTemplates, + currentPage: current_page, + totalPageTemplates: total, + lastPage: last_page + }; + } + case PAGE_TEMPLATE_DELETED: { + const { pageTemplateId } = payload; + return { + ...state, + pageTemplates: state.pageTemplates.filter( + (a) => a.id !== pageTemplateId + ) + }; + } + case PAGE_TEMPLATE_ARCHIVED: { + const updatedFormTemplate = payload.response; + + const updatedPageTemplates = state.pageTemplates.map((item) => + item.id === updatedFormTemplate.id + ? { ...item, is_archived: true } + : item + ); + return { ...state, pageTemplates: updatedPageTemplates }; + } + case PAGE_TEMPLATE_UNARCHIVED: { + const updatedFormTemplateId = payload; + + const updatedPageTemplates = state.pageTemplates.map((item) => + item.id === updatedFormTemplateId + ? { ...item, is_archived: false } + : item + ); + return { ...state, pageTemplates: updatedPageTemplates }; + } + default: + return state; + } +}; + +export default pageTemplateListReducer; diff --git a/src/store.js b/src/store.js index 64762f8ac..e61a3c172 100644 --- a/src/store.js +++ b/src/store.js @@ -158,6 +158,7 @@ import formTemplateReducer from "./reducers/sponsors_inventory/form-template-red import formTemplateListReducer from "./reducers/sponsors_inventory/form-template-list-reducer.js"; import formTemplateItemReducer from "./reducers/sponsors_inventory/form-template-item-reducer.js"; import formTemplateItemListReducer from "./reducers/sponsors_inventory/form-template-item-list-reducer.js"; +import pageTemplateListReducer from "./reducers/sponsors_inventory/page-template-list-reducer.js"; import sponsorSettingsReducer from "./reducers/sponsor_settings/sponsor-settings-reducer"; import eventRSVPListReducer from "./reducers/rsvps/event-rsvp-list-reducer.js"; import eventRSVPInvitationListReducer from "./reducers/rsvps/event-rsvp-invitation-list-reducer.js"; @@ -322,7 +323,8 @@ const reducers = persistCombineReducers(config, { currentFormTemplateListState: formTemplateListReducer, currentFormTemplateItemState: formTemplateItemReducer, currentFormTemplateItemListState: formTemplateItemListReducer, - sponsorSettingsState: sponsorSettingsReducer + sponsorSettingsState: sponsorSettingsReducer, + pageTemplateListState: pageTemplateListReducer }); const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; From 5dc9876093df0f3e57bc09c04e7f73ed04758677 Mon Sep 17 00:00:00 2001 From: Santiago Palenque Date: Thu, 11 Dec 2025 15:42:12 -0300 Subject: [PATCH 2/4] feat: pages grid - fix api fields --- src/actions/page-template-actions.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/actions/page-template-actions.js b/src/actions/page-template-actions.js index 44c341bd2..998932b7b 100644 --- a/src/actions/page-template-actions.js +++ b/src/actions/page-template-actions.js @@ -34,8 +34,6 @@ import { } from "../utils/constants"; import { snackbarErrorHandler } from "./base-actions"; - - export const ADD_PAGE_TEMPLATE = "ADD_PAGE_TEMPLATE"; export const PAGE_TEMPLATE_ADDED = "PAGE_TEMPLATE_ADDED"; export const PAGE_TEMPLATE_DELETED = "PAGE_TEMPLATE_DELETED"; @@ -70,11 +68,10 @@ export const getPageTemplates = const params = { page, - /* expand: "modules", - fields: "id,code,name,modules,is_archived,modules.kind,modules.id,modules.content", + fields: + "id,code,name,modules,is_archived,modules.kind,modules.id,modules.content", relations: "modules,modules.none", - */ per_page: perPage, access_token: accessToken }; From 5ce667d0325d3327c9aeeb22c7c9983afac9d592 Mon Sep 17 00:00:00 2001 From: Santiago Palenque Date: Fri, 12 Dec 2025 15:18:09 -0300 Subject: [PATCH 3/4] feat: sponsor pages - build crud popup --- src/actions/page-template-actions.js | 43 ++--- src/i18n/en.json | 8 + src/layouts/form-template-item-layout.js | 4 +- src/layouts/form-template-layout.js | 4 +- src/layouts/inventory-item-layout.js | 4 +- src/layouts/page-template-layout.js | 4 +- .../add-form-template-item-popup.js | 0 .../edit-form-template-item-page.js | 4 +- .../edit-form-template-page.js | 4 +- .../form-template-from-duplicate-popup.js | 0 .../form-template-item-list-page.js | 14 +- .../form-template-list-page.js | 12 +- .../form-templates}/form-template-popup.js | 2 +- .../sponsor-inventory-popup.js | 2 +- .../inventory}/edit-inventory-item-page.js | 4 +- .../inventory}/inventory-list-page.js | 8 +- .../edit-page-template-page.js | 4 +- .../page-template-list-page.js | 27 ++- .../page-templates/page-template-popup.js | 154 ++++++++++++++++++ .../shared}/meta-field-values.js | 0 .../sponsors/components/additional-input.js | 2 +- 21 files changed, 234 insertions(+), 70 deletions(-) rename src/pages/{sponsors_inventory/popup => sponsors-global/form-templates}/add-form-template-item-popup.js (100%) rename src/pages/{sponsors_inventory => sponsors-global/form-templates}/edit-form-template-item-page.js (96%) rename src/pages/{sponsors_inventory => sponsors-global/form-templates}/edit-form-template-page.js (95%) rename src/pages/{sponsors_inventory/popup => sponsors-global/form-templates}/form-template-from-duplicate-popup.js (100%) rename src/pages/{sponsors_inventory => sponsors-global/form-templates}/form-template-item-list-page.js (95%) rename src/pages/{sponsors_inventory => sponsors-global/form-templates}/form-template-list-page.js (96%) rename src/pages/{sponsors_inventory/popup => sponsors-global/form-templates}/form-template-popup.js (99%) rename src/pages/{sponsors_inventory/popup => sponsors-global/form-templates}/sponsor-inventory-popup.js (99%) rename src/pages/{sponsors_inventory => sponsors-global/inventory}/edit-inventory-item-page.js (95%) rename src/pages/{sponsors_inventory => sponsors-global/inventory}/inventory-list-page.js (96%) rename src/pages/{sponsors_inventory => sponsors-global/page-templates}/edit-page-template-page.js (95%) rename src/pages/{sponsors_inventory => sponsors-global/page-templates}/page-template-list-page.js (89%) create mode 100644 src/pages/sponsors-global/page-templates/page-template-popup.js rename src/pages/{sponsors_inventory/popup => sponsors-global/shared}/meta-field-values.js (100%) diff --git a/src/actions/page-template-actions.js b/src/actions/page-template-actions.js index 998932b7b..363230881 100644 --- a/src/actions/page-template-actions.js +++ b/src/actions/page-template-actions.js @@ -20,19 +20,16 @@ import { createAction, stopLoading, startLoading, - showMessage, - showSuccessMessage, authErrorHandler, escapeFilterValue } from "openstack-uicore-foundation/lib/utils/actions"; -import history from "../history"; import { getAccessTokenSafely } from "../utils/methods"; import { DEFAULT_CURRENT_PAGE, DEFAULT_ORDER_DIR, DEFAULT_PER_PAGE } from "../utils/constants"; -import { snackbarErrorHandler } from "./base-actions"; +import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions"; export const ADD_PAGE_TEMPLATE = "ADD_PAGE_TEMPLATE"; export const PAGE_TEMPLATE_ADDED = "PAGE_TEMPLATE_ADDED"; @@ -145,20 +142,16 @@ export const resetPageTemplateForm = () => (dispatch) => { const normalizeEntity = (entity) => { const normalizedEntity = { ...entity }; - normalizedEntity.meta_fields = normalizedEntity.meta_fields?.filter( - (mf) => mf.name - ); - normalizedEntity.materials = normalizedEntity.materials?.filter( - (mat) => mat.file_path - ); + + normalizedEntity.modules = []; + return normalizedEntity; }; -export const savePageTemplate = (entity) => async (dispatch) => { +export const savePageTemplate = (entity) => async (dispatch, getState) => { const accessToken = await getAccessTokenSafely(); const params = { - access_token: accessToken, - expand: "materials,meta_fields,meta_fields.values" + access_token: accessToken }; dispatch(startLoading()); @@ -171,15 +164,17 @@ export const savePageTemplate = (entity) => async (dispatch) => { createAction(PAGE_TEMPLATE_UPDATED), `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates/${entity.id}`, normalizedEntity, - authErrorHandler, + snackbarErrorHandler, entity )(params)(dispatch) .then(() => { dispatch( - showSuccessMessage( - T.translate("edit_form_template.form_template_saved") - ) + snackbarSuccessHandler({ + title: T.translate("general.success"), + html: T.translate("page_template_list.page_crud.page_saved") + }) ); + getPageTemplates()(dispatch, getState); }) .catch((err) => { console.error(err); @@ -189,26 +184,22 @@ export const savePageTemplate = (entity) => async (dispatch) => { }); } - const success_message = { - title: T.translate("general.done"), - html: T.translate("edit_form_template.form_template_created"), - type: "success" - }; - return postRequest( createAction(ADD_PAGE_TEMPLATE), createAction(PAGE_TEMPLATE_ADDED), `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates`, normalizedEntity, - authErrorHandler, + snackbarErrorHandler, entity )(params)(dispatch) .then(() => { dispatch( - showMessage(success_message, () => { - history.push("/app/page-templates"); + snackbarSuccessHandler({ + title: T.translate("general.success"), + html: T.translate("page_template_list.page_crud.page_created") }) ); + getPageTemplates()(dispatch, getState); }) .catch((err) => { console.error(err); diff --git a/src/i18n/en.json b/src/i18n/en.json index c38c72f8a..a4e1a6627 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -3848,6 +3848,14 @@ "add_using_global_template": "Using Global Template", "placeholders": { "search": "Search" + }, + "page_crud": { + "title": "Create New Page", + "add_info": "Add Info", + "add_doc": "Add Document Download", + "add_media": "Add Media Request", + "no_modules": "No modules added yet.", + "save": "Save Page" } } } diff --git a/src/layouts/form-template-item-layout.js b/src/layouts/form-template-item-layout.js index 2ee8c4a40..f3526ebde 100644 --- a/src/layouts/form-template-item-layout.js +++ b/src/layouts/form-template-item-layout.js @@ -16,8 +16,8 @@ import { Switch, Route, withRouter } from "react-router-dom"; import T from "i18n-react/dist/i18n-react"; import { Breadcrumb } from "react-breadcrumbs"; import Restrict from "../routes/restrict"; -import EditFormTemplateItemPage from "../pages/sponsors_inventory/edit-form-template-item-page"; -import FormTemplateItemListPage from "../pages/sponsors_inventory/form-template-item-list-page"; +import EditFormTemplateItemPage from "../pages/sponsors-global/form-templates/edit-form-template-item-page"; +import FormTemplateItemListPage from "../pages/sponsors-global/form-templates/form-template-item-list-page"; import NoMatchPage from "../pages/no-match-page"; const FormTemplateItemLayout = ({ match }) => ( diff --git a/src/layouts/form-template-layout.js b/src/layouts/form-template-layout.js index ead05f5d2..7a9f037ad 100644 --- a/src/layouts/form-template-layout.js +++ b/src/layouts/form-template-layout.js @@ -16,8 +16,8 @@ import { Switch, Route, withRouter } from "react-router-dom"; import T from "i18n-react/dist/i18n-react"; import { Breadcrumb } from "react-breadcrumbs"; import Restrict from "../routes/restrict"; -import FormTemplateListPage from "../pages/sponsors_inventory/form-template-list-page"; -import EditFormTemplatePage from "../pages/sponsors_inventory/edit-form-template-page"; +import FormTemplateListPage from "../pages/sponsors-global/form-templates/form-template-list-page"; +import EditFormTemplatePage from "../pages/sponsors-global/form-templates/edit-form-template-page"; import FormTemplateItemLayout from "./form-template-item-layout"; import NoMatchPage from "../pages/no-match-page"; diff --git a/src/layouts/inventory-item-layout.js b/src/layouts/inventory-item-layout.js index 025166cd3..b012fbe99 100644 --- a/src/layouts/inventory-item-layout.js +++ b/src/layouts/inventory-item-layout.js @@ -16,8 +16,8 @@ import { Switch, Route, withRouter } from "react-router-dom"; import T from "i18n-react/dist/i18n-react"; import { Breadcrumb } from "react-breadcrumbs"; import Restrict from "../routes/restrict"; -import InventoryListPage from "../pages/sponsors_inventory/inventory-list-page"; -import EditInventoryItemPage from "../pages/sponsors_inventory/edit-inventory-item-page"; +import InventoryListPage from "../pages/sponsors-global/inventory/inventory-list-page"; +import EditInventoryItemPage from "../pages/sponsors-global/inventory/edit-inventory-item-page"; import NoMatchPage from "../pages/no-match-page"; const InventoryItemLayout = ({ match }) => ( diff --git a/src/layouts/page-template-layout.js b/src/layouts/page-template-layout.js index ab4fc6e13..445381daa 100644 --- a/src/layouts/page-template-layout.js +++ b/src/layouts/page-template-layout.js @@ -17,8 +17,8 @@ import T from "i18n-react/dist/i18n-react"; import { Breadcrumb } from "react-breadcrumbs"; import Restrict from "../routes/restrict"; import NoMatchPage from "../pages/no-match-page"; -import EditPageTemplatePage from "../pages/sponsors_inventory/edit-page-template-page"; -import PageTemplateListPage from "../pages/sponsors_inventory/page-template-list-page"; +import EditPageTemplatePage from "../pages/sponsors-global/page-templates/edit-page-template-page"; +import PageTemplateListPage from "../pages/sponsors-global/page-templates/page-template-list-page"; const PageTemplateLayout = ({ match }) => (
diff --git a/src/pages/sponsors_inventory/popup/add-form-template-item-popup.js b/src/pages/sponsors-global/form-templates/add-form-template-item-popup.js similarity index 100% rename from src/pages/sponsors_inventory/popup/add-form-template-item-popup.js rename to src/pages/sponsors-global/form-templates/add-form-template-item-popup.js diff --git a/src/pages/sponsors_inventory/edit-form-template-item-page.js b/src/pages/sponsors-global/form-templates/edit-form-template-item-page.js similarity index 96% rename from src/pages/sponsors_inventory/edit-form-template-item-page.js rename to src/pages/sponsors-global/form-templates/edit-form-template-item-page.js index 8ea06f672..bc7389ce2 100644 --- a/src/pages/sponsors_inventory/edit-form-template-item-page.js +++ b/src/pages/sponsors-global/form-templates/edit-form-template-item-page.js @@ -15,7 +15,7 @@ import React, { useEffect } from "react"; import { connect } from "react-redux"; import { Breadcrumb } from "react-breadcrumbs"; import T from "i18n-react/dist/i18n-react"; -import InventoryItemForm from "../../components/forms/inventory-item-form"; +import InventoryItemForm from "../../../components/forms/inventory-item-form"; import { getFormTemplateItem, resetFormTemplateItemForm, @@ -23,7 +23,7 @@ import { deleteItemMetaFieldType, deleteItemMetaFieldTypeValue, deleteItemImage -} from "../../actions/form-template-item-actions"; +} from "../../../actions/form-template-item-actions"; const EditFormTemplateItemPage = (props) => { const { diff --git a/src/pages/sponsors_inventory/edit-form-template-page.js b/src/pages/sponsors-global/form-templates/edit-form-template-page.js similarity index 95% rename from src/pages/sponsors_inventory/edit-form-template-page.js rename to src/pages/sponsors-global/form-templates/edit-form-template-page.js index 495987f62..f026badd7 100644 --- a/src/pages/sponsors_inventory/edit-form-template-page.js +++ b/src/pages/sponsors-global/form-templates/edit-form-template-page.js @@ -15,7 +15,7 @@ import React, { useEffect } from "react"; import { connect } from "react-redux"; import { Breadcrumb } from "react-breadcrumbs"; import T from "i18n-react/dist/i18n-react"; -import FormTemplateForm from "../../components/forms/form-template-form"; +import FormTemplateForm from "../../../components/forms/form-template-form"; import { getFormTemplate, resetFormTemplateForm, @@ -23,7 +23,7 @@ import { deleteFormTemplateMetaFieldType, deleteFormTemplateMetaFieldTypeValue, deleteFormTemplateMaterial -} from "../../actions/form-template-actions"; +} from "../../../actions/form-template-actions"; const EditFormTemplatePage = (props) => { const { diff --git a/src/pages/sponsors_inventory/popup/form-template-from-duplicate-popup.js b/src/pages/sponsors-global/form-templates/form-template-from-duplicate-popup.js similarity index 100% rename from src/pages/sponsors_inventory/popup/form-template-from-duplicate-popup.js rename to src/pages/sponsors-global/form-templates/form-template-from-duplicate-popup.js diff --git a/src/pages/sponsors_inventory/form-template-item-list-page.js b/src/pages/sponsors-global/form-templates/form-template-item-list-page.js similarity index 95% rename from src/pages/sponsors_inventory/form-template-item-list-page.js rename to src/pages/sponsors-global/form-templates/form-template-item-list-page.js index 9eebcc662..16b6acf04 100644 --- a/src/pages/sponsors_inventory/form-template-item-list-page.js +++ b/src/pages/sponsors-global/form-templates/form-template-item-list-page.js @@ -27,7 +27,7 @@ import AddIcon from "@mui/icons-material/Add"; import IconButton from "@mui/material/IconButton"; import Tooltip from "@mui/material/Tooltip"; import ImageIcon from "@mui/icons-material/Image"; -import MuiTable from "../../components/mui/table/mui-table"; +import MuiTable from "../../../components/mui/table/mui-table"; import { cloneFromInventoryItem, deleteFormTemplateItem, @@ -39,12 +39,12 @@ import { deleteItemImage, unarchiveFormTemplateItem, archiveFormTemplateItem -} from "../../actions/form-template-item-actions"; -import { getFormTemplate } from "../../actions/form-template-actions"; -import AddFormTemplateItemDialog from "./popup/add-form-template-item-popup"; -import SponsorItemDialog from "./popup/sponsor-inventory-popup"; -import { getInventoryItems } from "../../actions/inventory-item-actions"; -import { DEFAULT_CURRENT_PAGE } from "../../utils/constants"; +} from "../../../actions/form-template-item-actions"; +import { getFormTemplate } from "../../../actions/form-template-actions"; +import AddFormTemplateItemDialog from "./add-form-template-item-popup"; +import SponsorItemDialog from "./sponsor-inventory-popup"; +import { getInventoryItems } from "../../../actions/inventory-item-actions"; +import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; const FormTemplateItemListPage = ({ formTemplateId, diff --git a/src/pages/sponsors_inventory/form-template-list-page.js b/src/pages/sponsors-global/form-templates/form-template-list-page.js similarity index 96% rename from src/pages/sponsors_inventory/form-template-list-page.js rename to src/pages/sponsors-global/form-templates/form-template-list-page.js index e8882fe04..a149553b0 100644 --- a/src/pages/sponsors_inventory/form-template-list-page.js +++ b/src/pages/sponsors-global/form-templates/form-template-list-page.js @@ -37,12 +37,12 @@ import { resetFormTemplateForm, saveFormTemplate, unarchiveFormTemplate -} from "../../actions/form-template-actions"; -import MuiTable from "../../components/mui/table/mui-table"; -import FormTemplateDialog from "./popup/form-template-popup"; -import history from "../../history"; -import FormTemplateFromDuplicateDialog from "./popup/form-template-from-duplicate-popup"; -import { DEFAULT_CURRENT_PAGE } from "../../utils/constants"; +} from "../../../actions/form-template-actions"; +import MuiTable from "../../../components/mui/table/mui-table"; +import FormTemplateDialog from "./form-template-popup"; +import history from "../../../history"; +import FormTemplateFromDuplicateDialog from "./form-template-from-duplicate-popup"; +import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; const FormTemplateListPage = ({ formTemplates, diff --git a/src/pages/sponsors_inventory/popup/form-template-popup.js b/src/pages/sponsors-global/form-templates/form-template-popup.js similarity index 99% rename from src/pages/sponsors_inventory/popup/form-template-popup.js rename to src/pages/sponsors-global/form-templates/form-template-popup.js index 88b97044d..d47e94488 100644 --- a/src/pages/sponsors_inventory/popup/form-template-popup.js +++ b/src/pages/sponsors-global/form-templates/form-template-popup.js @@ -20,7 +20,7 @@ import CloseIcon from "@mui/icons-material/Close"; import { useFormik, FormikProvider, FieldArray } from "formik"; import * as yup from "yup"; import showConfirmDialog from "../../../components/mui/showConfirmDialog"; -import MetaFieldValues from "./meta-field-values"; +import MetaFieldValues from "../shared/meta-field-values"; import MuiFormikTextField from "../../../components/mui/formik-inputs/mui-formik-textfield"; import FormikTextEditor from "../../../components/inputs/formik-text-editor"; import MuiFormikSelect from "../../../components/mui/formik-inputs/mui-formik-select"; diff --git a/src/pages/sponsors_inventory/popup/sponsor-inventory-popup.js b/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js similarity index 99% rename from src/pages/sponsors_inventory/popup/sponsor-inventory-popup.js rename to src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js index e59f3a254..4718d499d 100644 --- a/src/pages/sponsors_inventory/popup/sponsor-inventory-popup.js +++ b/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js @@ -28,7 +28,7 @@ import { METAFIELD_TYPES } from "../../../utils/constants"; import showConfirmDialog from "../../../components/mui/showConfirmDialog"; -import MetaFieldValues from "./meta-field-values"; +import MetaFieldValues from "../shared/meta-field-values"; import MuiFormikTextField from "../../../components/mui/formik-inputs/mui-formik-textfield"; import useScrollToError from "../../../hooks/useScrollToError"; import MuiFormikSelect from "../../../components/mui/formik-inputs/mui-formik-select"; diff --git a/src/pages/sponsors_inventory/edit-inventory-item-page.js b/src/pages/sponsors-global/inventory/edit-inventory-item-page.js similarity index 95% rename from src/pages/sponsors_inventory/edit-inventory-item-page.js rename to src/pages/sponsors-global/inventory/edit-inventory-item-page.js index cecac7cc0..f51c73a81 100644 --- a/src/pages/sponsors_inventory/edit-inventory-item-page.js +++ b/src/pages/sponsors-global/inventory/edit-inventory-item-page.js @@ -15,7 +15,7 @@ import React, { useEffect } from "react"; import { connect } from "react-redux"; import { Breadcrumb } from "react-breadcrumbs"; import T from "i18n-react/dist/i18n-react"; -import InventoryItemForm from "../../components/forms/inventory-item-form"; +import InventoryItemForm from "../../../components/forms/inventory-item-form"; import { getInventoryItem, resetInventoryItemForm, @@ -23,7 +23,7 @@ import { deleteInventoryItemMetaFieldType, deleteInventoryItemMetaFieldTypeValue, deleteInventoryItemImage -} from "../../actions/inventory-item-actions"; +} from "../../../actions/inventory-item-actions"; const EditInventoryItemPage = (props) => { const { diff --git a/src/pages/sponsors_inventory/inventory-list-page.js b/src/pages/sponsors-global/inventory/inventory-list-page.js similarity index 96% rename from src/pages/sponsors_inventory/inventory-list-page.js rename to src/pages/sponsors-global/inventory/inventory-list-page.js index 344bae974..6475634a2 100644 --- a/src/pages/sponsors_inventory/inventory-list-page.js +++ b/src/pages/sponsors-global/inventory/inventory-list-page.js @@ -39,10 +39,10 @@ import { resetInventoryItemForm, saveInventoryItem, unarchiveInventoryItem -} from "../../actions/inventory-item-actions"; -import MuiTable from "../../components/mui/table/mui-table"; -import SponsorInventoryDialog from "./popup/sponsor-inventory-popup"; -import { DEFAULT_CURRENT_PAGE } from "../../utils/constants"; +} from "../../../actions/inventory-item-actions"; +import MuiTable from "../../../components/mui/table/mui-table"; +import SponsorInventoryDialog from "../form-templates/sponsor-inventory-popup"; +import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; const InventoryListPage = ({ inventoryItems, diff --git a/src/pages/sponsors_inventory/edit-page-template-page.js b/src/pages/sponsors-global/page-templates/edit-page-template-page.js similarity index 95% rename from src/pages/sponsors_inventory/edit-page-template-page.js rename to src/pages/sponsors-global/page-templates/edit-page-template-page.js index 99b041c69..ac2ff1c3e 100644 --- a/src/pages/sponsors_inventory/edit-page-template-page.js +++ b/src/pages/sponsors-global/page-templates/edit-page-template-page.js @@ -15,7 +15,7 @@ import React, { useEffect } from "react"; import { connect } from "react-redux"; import { Breadcrumb } from "react-breadcrumbs"; import T from "i18n-react/dist/i18n-react"; -import FormTemplateForm from "../../components/forms/form-template-form"; +import FormTemplateForm from "../../../components/forms/form-template-form"; import { getFormTemplate, resetFormTemplateForm, @@ -23,7 +23,7 @@ import { deleteFormTemplateMetaFieldType, deleteFormTemplateMetaFieldTypeValue, deleteFormTemplateMaterial -} from "../../actions/form-template-actions"; +} from "../../../actions/form-template-actions"; const EditPageTemplatePage = (props) => { const { diff --git a/src/pages/sponsors_inventory/page-template-list-page.js b/src/pages/sponsors-global/page-templates/page-template-list-page.js similarity index 89% rename from src/pages/sponsors_inventory/page-template-list-page.js rename to src/pages/sponsors-global/page-templates/page-template-list-page.js index 893c03e05..19821bdfc 100644 --- a/src/pages/sponsors_inventory/page-template-list-page.js +++ b/src/pages/sponsors-global/page-templates/page-template-list-page.js @@ -11,7 +11,7 @@ * limitations under the License. * */ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { Alert, Button, @@ -27,11 +27,13 @@ import T from "i18n-react/dist/i18n-react"; import { archivePageTemplate, getPageTemplates, + savePageTemplate, unarchivePageTemplate -} from "../../actions/page-template-actions"; -import MuiTable from "../../components/mui/table/mui-table"; -import SearchInput from "../../components/mui/search-input"; -import { DEFAULT_CURRENT_PAGE } from "../../utils/constants"; +} from "../../../actions/page-template-actions"; +import MuiTable from "../../../components/mui/table/mui-table"; +import SearchInput from "../../../components/mui/search-input"; +import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; +import PageTemplatePopup from "./page-template-popup"; const PageTemplateListPage = ({ pageTemplates, @@ -44,8 +46,11 @@ const PageTemplateListPage = ({ totalPageTemplates, getPageTemplates, archivePageTemplate, - unarchivePageTemplate + unarchivePageTemplate, + savePageTemplate }) => { + const [pageTemplateId, setPageTemplateId] = useState(null); + useEffect(() => { getPageTemplates(); }, []); @@ -92,7 +97,7 @@ const PageTemplateListPage = ({ }; const handleNewPageTemplate = () => { - console.log("NEW PAGE"); + setPageTemplateId("new"); }; const handleClonePageTemplate = () => { @@ -242,6 +247,11 @@ const PageTemplateListPage = ({
)} + setPageTemplateId(null)} + onSave={savePageTemplate} + /> ); }; @@ -253,5 +263,6 @@ const mapStateToProps = ({ pageTemplateListState }) => ({ export default connect(mapStateToProps, { getPageTemplates, archivePageTemplate, - unarchivePageTemplate + unarchivePageTemplate, + savePageTemplate })(PageTemplateListPage); diff --git a/src/pages/sponsors-global/page-templates/page-template-popup.js b/src/pages/sponsors-global/page-templates/page-template-popup.js new file mode 100644 index 000000000..6fc8f89c6 --- /dev/null +++ b/src/pages/sponsors-global/page-templates/page-template-popup.js @@ -0,0 +1,154 @@ +import React from "react"; +import T from "i18n-react/dist/i18n-react"; +import { connect } from "react-redux"; +import PropTypes from "prop-types"; +import { + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Divider, + Grid2, + IconButton, + Typography +} from "@mui/material"; +import AddIcon from "@mui/icons-material/Add"; +import CloseIcon from "@mui/icons-material/Close"; +import { FormikProvider, useFormik } from "formik"; +import * as yup from "yup"; +import MuiFormikTextField from "../../../components/mui/formik-inputs/mui-formik-textfield"; + +const PageTemplatePopup = ({ pageTemplate, open, onClose, onSave }) => { + const handleClose = () => { + onClose(); + }; + + const handleAddInfo = () => { + console.log("ADD INFO"); + }; + + const handleAddDocument = () => { + console.log("ADD DOCUMENT"); + }; + + const handleAddMedia = () => { + console.log("ADD MEDIA"); + }; + + const formik = useFormik({ + initialValues: { + ...pageTemplate + }, + validationSchema: yup.object().shape({ + code: yup.string().required(T.translate("validation.required")), + name: yup.string().required(T.translate("validation.required")) + }), + enableReinitialize: true, + onSubmit: (values) => { + onSave(values); + } + }); + + return ( + + + + {T.translate("page_template_list.page_crud.title")} + + handleClose()} sx={{ mr: 1 }}> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {T.translate("page_template_list.page_crud.no_modules")} + + + + + + + + + + ); +}; + +PageTemplatePopup.propTypes = { + open: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired, + onSave: PropTypes.func.isRequired +}; + +const mapStateToProps = ({ currentPageTemplateState }) => ({ + ...currentPageTemplateState +}); + +export default connect(mapStateToProps, {})(PageTemplatePopup); diff --git a/src/pages/sponsors_inventory/popup/meta-field-values.js b/src/pages/sponsors-global/shared/meta-field-values.js similarity index 100% rename from src/pages/sponsors_inventory/popup/meta-field-values.js rename to src/pages/sponsors-global/shared/meta-field-values.js diff --git a/src/pages/sponsors/components/additional-input.js b/src/pages/sponsors/components/additional-input.js index 6386f6795..96b9ed74e 100644 --- a/src/pages/sponsors/components/additional-input.js +++ b/src/pages/sponsors/components/additional-input.js @@ -14,7 +14,7 @@ import { import T from "i18n-react"; import DeleteIcon from "@mui/icons-material/Delete"; import AddIcon from "@mui/icons-material/Add"; -import MetaFieldValues from "../../sponsors_inventory/popup/meta-field-values"; +import MetaFieldValues from "../../sponsors-global/shared/meta-field-values"; import { METAFIELD_TYPES, METAFIELD_TYPES_WITH_OPTIONS From de9802b33878dc07c4dddec078ef092ed340d03d Mon Sep 17 00:00:00 2001 From: Santiago Palenque Date: Fri, 12 Dec 2025 16:01:06 -0300 Subject: [PATCH 4/4] feat: sponsor pages - missing translation --- src/i18n/en.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/en.json b/src/i18n/en.json index a4e1a6627..8993da7e9 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -3855,7 +3855,9 @@ "add_doc": "Add Document Download", "add_media": "Add Media Request", "no_modules": "No modules added yet.", - "save": "Save Page" + "save": "Save Page", + "page_saved": "Page saved successfully.", + "page_created": "Page created successfully." } } }