diff --git a/src/actions/page-template-actions.js b/src/actions/page-template-actions.js index 9283195ef..ee0d6d505 100644 --- a/src/actions/page-template-actions.js +++ b/src/actions/page-template-actions.js @@ -54,7 +54,10 @@ export const getPageTemplates = orderDir = DEFAULT_ORDER_DIR, hideArchived = false ) => - async (dispatch) => { + async (dispatch, getState) => { + const { currentSummitState } = getState(); + const { currentSummit } = currentSummitState; + const summitTZ = currentSummit.time_zone.name; const accessToken = await getAccessTokenSafely(); const filter = []; @@ -92,7 +95,7 @@ export const getPageTemplates = createAction(RECEIVE_PAGE_TEMPLATES), `${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates`, authErrorHandler, - { order, orderDir, page, perPage, term, hideArchived } + { order, orderDir, page, perPage, term, hideArchived, summitTZ } )(params)(dispatch).then(() => { dispatch(stopLoading()); }); diff --git a/src/actions/sponsor-pages-actions.js b/src/actions/sponsor-pages-actions.js index cb7355d1d..6124fc2ea 100644 --- a/src/actions/sponsor-pages-actions.js +++ b/src/actions/sponsor-pages-actions.js @@ -16,22 +16,31 @@ import { createAction, getRequest, postRequest, + putRequest, startLoading, stopLoading } from "openstack-uicore-foundation/lib/utils/actions"; import T from "i18n-react/dist/i18n-react"; +import moment from "moment-timezone"; import { escapeFilterValue, getAccessTokenSafely } from "../utils/methods"; import { getSponsorForms } from "./sponsor-forms-actions"; import { DEFAULT_CURRENT_PAGE, DEFAULT_ORDER_DIR, - DEFAULT_PER_PAGE + DEFAULT_PER_PAGE, + PAGES_MODULE_KINDS } from "../utils/constants"; import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions"; export const REQUEST_SPONSOR_PAGES = "REQUEST_SPONSOR_PAGES"; export const RECEIVE_SPONSOR_PAGES = "RECEIVE_SPONSOR_PAGES"; +export const RECEIVE_SPONSOR_PAGE = "RECEIVE_SPONSOR_PAGE"; + +export const SPONSOR_PAGE_UPDATED = "SPONSOR_PAGE_UPDATED"; +export const SPONSOR_PAGE_ADDED = "SPONSOR_PAGE_ADDED"; +export const RESET_SPONSOR_PAGE_FORM = "RESET_SPONSOR_PAGE_FORM"; + export const GLOBAL_PAGE_CLONED = "GLOBAL_PAGE_CLONED"; export const getSponsorPages = @@ -93,6 +102,123 @@ export const getSponsorPages = }); }; +export const getSponsorPage = (pageId) => async (dispatch, getState) => { + const { currentSummitState } = getState(); + const { currentSummit } = currentSummitState; + const accessToken = await getAccessTokenSafely(); + + dispatch(startLoading()); + + const params = { + access_token: accessToken, + expand: "modules.file_type" + }; + + return getRequest( + null, + createAction(RECEIVE_SPONSOR_PAGE), + `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/show-pages/${pageId}`, + authErrorHandler + )(params)(dispatch).then(() => { + dispatch(stopLoading()); + }); +}; + +const normalizeSponsorPage = (entity) => { + const normalizedEntity = { ...entity }; + + normalizedEntity.modules = entity.modules.map((module) => { + const normalizedModule = { ...module }; + + if (module.kind === PAGES_MODULE_KINDS.MEDIA && module.upload_deadline) { + normalizedModule.upload_deadline = moment + .utc(module.upload_deadline) + .unix(); + } + + if (module.kind === PAGES_MODULE_KINDS.MEDIA && module.file_type_id) { + normalizedModule.file_type_id = + module.file_type_id?.value || module.file_type_id; + } + + if (module.kind === PAGES_MODULE_KINDS.DOCUMENT && module.file) { + normalizedModule.file = module.file[0] || null; + } + + delete normalizedModule._tempId; + + return normalizedModule; + }); + + return normalizedEntity; +}; + +export const saveSponsorPage = (entity) => async (dispatch, getState) => { + const { currentSummitState } = getState(); + const { currentSummit } = currentSummitState; + const accessToken = await getAccessTokenSafely(); + + dispatch(startLoading()); + + const params = { + access_token: accessToken + }; + + const normalizedSponsorPage = normalizeSponsorPage(entity); + + if (entity.id) { + return putRequest( + null, + createAction(SPONSOR_PAGE_UPDATED), + `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/show-pages/${entity.id}`, + normalizedSponsorPage, + snackbarErrorHandler, + entity + )(params)(dispatch) + .then(() => { + dispatch( + snackbarSuccessHandler({ + title: T.translate("general.success"), + html: T.translate("sponsor_pages.page_saved") + }) + ); + }) + .catch((err) => { + console.error(err); + }) + .finally(() => { + dispatch(stopLoading()); + }); + } + + return postRequest( + null, + createAction(SPONSOR_PAGE_ADDED), + `${window.SPONSOR_PAGES_API_URL}/api/v1/summits/${currentSummit.id}/show-pages`, + normalizedSponsorPage, + snackbarErrorHandler, + entity + )(params)(dispatch) + .then(() => { + dispatch( + snackbarSuccessHandler({ + title: T.translate("general.success"), + html: T.translate("sponsor_pages.page_created") + }) + ); + }) + .catch((err) => { + console.error(err); + }) + .finally(() => { + dispatch(stopLoading()); + }); +}; + +export const resetSponsorPageForm = () => (dispatch) => { + dispatch(createAction(RESET_SPONSOR_PAGE_FORM)({})); +}; + export const cloneGlobalPage = (pagesIds, sponsorIds, allSponsors) => async (dispatch, getState) => { const { currentSummitState } = getState(); diff --git a/src/i18n/en.json b/src/i18n/en.json index abea35a2c..c05e245c3 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -2641,6 +2641,8 @@ "filter": "Filter", "sort_by": "Sort By", "no_sponsors_pages": "No pages found for this search criteria.", + "page_saved": "Page updated successfully.", + "page_created": "Page created successfully.", "placeholders": { "search": "Search..." }, diff --git a/src/pages/sponsors-global/page-templates/page-template-list-page.js b/src/pages/sponsors-global/page-templates/page-template-list-page.js index 34b09dd59..bedc55deb 100644 --- a/src/pages/sponsors-global/page-templates/page-template-list-page.js +++ b/src/pages/sponsors-global/page-templates/page-template-list-page.js @@ -49,7 +49,8 @@ const PageTemplateListPage = ({ archivePageTemplate, unarchivePageTemplate, savePageTemplate, - deletePageTemplate + deletePageTemplate, + summitTZ }) => { const [pageTemplateId, setPageTemplateId] = useState(null); @@ -266,6 +267,7 @@ const PageTemplateListPage = ({ open={!!pageTemplateId} onClose={() => setPageTemplateId(null)} onSave={handleSavePageTemplate} + summitTZ={summitTZ} /> ); diff --git a/src/pages/sponsors-global/page-templates/page-template-popup.js b/src/pages/sponsors-global/page-templates/page-template-popup.js index 586d76919..38440b692 100644 --- a/src/pages/sponsors-global/page-templates/page-template-popup.js +++ b/src/pages/sponsors-global/page-templates/page-template-popup.js @@ -18,6 +18,7 @@ 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 { epochToMomentTimeZone } from "openstack-uicore-foundation/lib/utils/methods"; import MuiFormikTextField from "../../../components/mui/formik-inputs/mui-formik-textfield"; import PageModules from "./page-template-modules-form"; import { @@ -25,7 +26,13 @@ import { PAGE_MODULES_MEDIA_TYPES } from "../../../utils/constants"; -const PageTemplatePopup = ({ pageTemplate, open, onClose, onSave }) => { +const PageTemplatePopup = ({ + pageTemplate, + open, + onClose, + onSave, + summitTZ +}) => { const handleClose = () => { onClose(); }; @@ -108,10 +115,31 @@ const PageTemplatePopup = ({ pageTemplate, open, onClose, onSave }) => { } }); + const normalizeModules = (modules = [], summitTZ = "UTC") => + modules.map((m) => { + if (m.kind === PAGES_MODULE_KINDS.MEDIA) { + const normalizeModule = { ...m }; + if (m.upload_deadline) { + normalizeModule.upload_deadline = epochToMomentTimeZone( + m.upload_deadline, + summitTZ + ); + } + if (m.file_type) { + normalizeModule.file_type_id = { + value: m.file_type.id, + label: `${m.file_type.name} (${m.file_type.allowed_extensions})` + }; + } + return normalizeModule; + } + return m; + }); + const formik = useFormik({ initialValues: { ...pageTemplate, - modules: pageTemplate?.modules || [] + modules: normalizeModules(pageTemplate?.modules, summitTZ) || [] }, validationSchema: yup.object().shape({ code: yup.string().required(T.translate("validation.required")), diff --git a/src/pages/sponsors/sponsor-pages-list-page/index.js b/src/pages/sponsors/sponsor-pages-list-page/index.js index b453cb6ad..142161c33 100644 --- a/src/pages/sponsors/sponsor-pages-list-page/index.js +++ b/src/pages/sponsors/sponsor-pages-list-page/index.js @@ -23,11 +23,16 @@ import { Grid2 } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; -import { getSponsorPages } from "../../../actions/sponsor-pages-actions"; -import { getSponsorForm } from "../../../actions/sponsor-forms-actions"; +import { + getSponsorPages, + getSponsorPage, + saveSponsorPage, + resetSponsorPageForm +} from "../../../actions/sponsor-pages-actions"; import CustomAlert from "../../../components/mui/custom-alert"; import MuiTable from "../../../components/mui/table/mui-table"; import GlobalPagePopup from "./components/global-page/global-page-popup"; +import PageTemplatePopup from "../../sponsors-global/page-templates/page-template-popup"; const SponsorPagesListPage = ({ sponsorPages, @@ -38,8 +43,11 @@ const SponsorPagesListPage = ({ orderDir, hideArchived, totalCount, + currentSponsorPage, getSponsorPages, - getSponsorForm + getSponsorPage, + saveSponsorPage, + resetSponsorPageForm }) => { const [openPopup, setOpenPopup] = useState(null); @@ -67,7 +75,7 @@ const SponsorPagesListPage = ({ }; const handleRowEdit = (row) => { - getSponsorForm(row.id).then(() => { + getSponsorPage(row.id).then(() => { setOpenPopup("new"); }); }; @@ -93,6 +101,18 @@ const SponsorPagesListPage = ({ ); }; + const handleSaveSponsorPage = (entity) => { + saveSponsorPage(entity).then(() => { + setOpenPopup(null); + getSponsorPages(); + }); + }; + + const handleTemplatePopupClose = () => { + resetSponsorPageForm(); + setOpenPopup(null); + }; + const columns = [ { columnKey: "code", @@ -216,10 +236,12 @@ const SponsorPagesListPage = ({ open={openPopup === "clone"} onClose={() => setOpenPopup(null)} /> - {/* setOpenPopup(null)} - /> */} + pageTemplate={currentSponsorPage} + onClose={handleTemplatePopupClose} + onSave={handleSaveSponsorPage} + /> ); }; @@ -230,5 +252,7 @@ const mapStateToProps = ({ sponsorPagesListState }) => ({ export default connect(mapStateToProps, { getSponsorPages, - getSponsorForm + getSponsorPage, + saveSponsorPage, + resetSponsorPageForm })(SponsorPagesListPage); diff --git a/src/reducers/sponsors/sponsor-pages-list-reducer.js b/src/reducers/sponsors/sponsor-pages-list-reducer.js index 41c4f2a43..41dc775e4 100644 --- a/src/reducers/sponsors/sponsor-pages-list-reducer.js +++ b/src/reducers/sponsors/sponsor-pages-list-reducer.js @@ -13,12 +13,20 @@ import { LOGOUT_USER } from "openstack-uicore-foundation/lib/security/actions"; import { + RECEIVE_SPONSOR_PAGE, RECEIVE_SPONSOR_PAGES, - REQUEST_SPONSOR_PAGES + REQUEST_SPONSOR_PAGES, + RESET_SPONSOR_PAGE_FORM } from "../../actions/sponsor-pages-actions"; import { SET_CURRENT_SUMMIT } from "../../actions/summit-actions"; import { PAGES_MODULE_KINDS } from "../../utils/constants"; +const DEFAULT_SPONSOR_PAGE = { + code: "", + name: "", + modules: [] +}; + const DEFAULT_STATE = { sponsorPages: [], term: "", @@ -28,7 +36,9 @@ const DEFAULT_STATE = { lastPage: 1, perPage: 10, totalCount: 0, - hideArchived: false + hideArchived: false, + currentSponsorPage: DEFAULT_SPONSOR_PAGE, + summitTZ: null }; const sponsorPagesListReducer = (state = DEFAULT_STATE, action) => { @@ -40,7 +50,7 @@ const sponsorPagesListReducer = (state = DEFAULT_STATE, action) => { return DEFAULT_STATE; } case REQUEST_SPONSOR_PAGES: { - const { order, orderDir, page, term, hideArchived } = payload; + const { order, orderDir, page, term, hideArchived, summitTZ } = payload; return { ...state, @@ -49,7 +59,8 @@ const sponsorPagesListReducer = (state = DEFAULT_STATE, action) => { sponsorPages: [], currentPage: page, term, - hideArchived + hideArchived, + summitTZ }; } case RECEIVE_SPONSOR_PAGES: { @@ -82,6 +93,14 @@ const sponsorPagesListReducer = (state = DEFAULT_STATE, action) => { lastPage }; } + case RECEIVE_SPONSOR_PAGE: { + const sponsorPage = payload.response; + + return { ...state, currentSponsorPage: sponsorPage }; + } + case RESET_SPONSOR_PAGE_FORM: { + return { ...state, currentSponsorPage: DEFAULT_SPONSOR_PAGE }; + } default: return state; }