Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
221a9a7
fix: not render saved options if they're not available (#718)
tomrndom Dec 11, 2025
6576096
fix: prevent sponsor edit page to fail if no company is assigned (#722)
tomrndom Dec 15, 2025
d594af3
fix: adjust inventory items metafield validation to enable add button…
tomrndom Dec 15, 2025
99e0e11
chore: update uicore to 4.2.17
smarcet Dec 15, 2025
51628c1
fix: adjust text on delete popup at sponsor forms list page (#713)
tomrndom Dec 15, 2025
ae913c2
fix: adjust text on sponsor extra questions delete popup (#714)
tomrndom Dec 15, 2025
5741a6a
fix: adjust popup title on edit/new extra questions (#715)
tomrndom Dec 15, 2025
8309405
fix: use field array to manage extra questions values, disable button…
tomrndom Dec 15, 2025
e0b7575
fix: adjust default page on hide archive items (#716)
tomrndom Dec 15, 2025
8823dd3
chore: update uicore
smarcet Dec 15, 2025
33b85f0
chore: update uicore to 4.2.19
smarcet Dec 15, 2025
3c316c3
fix: change action to download room occupancy csv file (#677)
tomrndom Dec 16, 2025
253dff9
fix: adjust item form validation, add edit cell validations (#712)
tomrndom Dec 18, 2025
ec29d80
fix: rename sponsor list column for tiers (#726)
tomrndom Dec 18, 2025
9319963
fix: reload sponsorship table after delete (#727)
tomrndom Dec 18, 2025
5bcbe12
fix: adjust validation on submit for manage addons popup (#730)
tomrndom Dec 18, 2025
a013398
fix: add sponsor forms list pagination (#723)
tomrndom Dec 18, 2025
080e2a0
feat: page templates grid and menu
santipalenque Dec 11, 2025
4f8ae97
feat: pages grid - fix api fields
santipalenque Dec 11, 2025
64ce7b8
feat: sponsor pages - build crud popup
santipalenque Dec 12, 2025
28ed06e
feat: sponsor pages - missing translation
santipalenque Dec 12, 2025
fbbd53a
feat: add new menu and page for summit sponsor pages, page template p…
tomrndom Dec 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@
"file-loader": "^6.2.0",
"file-saver": "^2.0.2",
"final-form": "^4.20.7",
"formik": "^2.4.6",
"font-awesome": "^4.7.0",
"formik": "^2.4.6",
"fs": "^0.0.2",
"graphql-query-builder": "^1.0.7",
"history": "^4.7.2",
Expand All @@ -89,7 +89,7 @@
"moment-duration-format": "^2.3.2",
"moment-timezone": "^0.5.33",
"node-sass": "^7.0.1",
"openstack-uicore-foundation": "4.2.14",
"openstack-uicore-foundation": "4.2.19",
"p-limit": "^6.1.0",
"path-browserify": "^1.0.1",
"postcss-loader": "^6.2.1",
Expand Down Expand Up @@ -125,6 +125,7 @@
"redux-thunk": "^2.3.0",
"sass-loader": "^12.6.0",
"segmented-control": "^0.1.12",
"spark-md5": "^3.0.2",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.1",
"superagent": "^6.1.0",
Expand Down
242 changes: 242 additions & 0 deletions src/actions/page-template-actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
/**
* 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,
authErrorHandler,
escapeFilterValue
} from "openstack-uicore-foundation/lib/utils/actions";
import { getAccessTokenSafely } from "../utils/methods";
import {
DEFAULT_CURRENT_PAGE,
DEFAULT_ORDER_DIR,
DEFAULT_PER_PAGE
} from "../utils/constants";
import { snackbarErrorHandler, snackbarSuccessHandler } 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.modules = [];

return normalizedEntity;
};

export const savePageTemplate = (entity) => async (dispatch, getState) => {
const accessToken = await getAccessTokenSafely();
const params = {
access_token: accessToken
};

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,
snackbarErrorHandler,
entity
)(params)(dispatch)
.then(() => {
dispatch(
snackbarSuccessHandler({
title: T.translate("general.success"),
html: T.translate("page_template_list.page_crud.page_saved")
})
);
getPageTemplates()(dispatch, getState);
})
.catch((err) => {
console.error(err);
})
.finally(() => {
dispatch(stopLoading());
});
}

return postRequest(
createAction(ADD_PAGE_TEMPLATE),
createAction(PAGE_TEMPLATE_ADDED),
`${window.SPONSOR_PAGES_API_URL}/api/v1/page-templates`,
normalizedEntity,
snackbarErrorHandler,
entity
)(params)(dispatch)
.then(() => {
dispatch(
snackbarSuccessHandler({
title: T.translate("general.success"),
html: T.translate("page_template_list.page_crud.page_created")
})
);
getPageTemplates()(dispatch, getState);
})
.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());
});
};
43 changes: 30 additions & 13 deletions src/actions/room-occupancy-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import {
createAction,
deleteRequest,
escapeFilterValue,
getCSV,
getRequest,
putRequest,
startLoading,
stopLoading
stopLoading,
getRawCSV,
downloadFileByContent
} from "openstack-uicore-foundation/lib/utils/actions";
import moment from "moment-timezone";
import { getAccessTokenSafely } from "../utils/methods";
import { getAccessTokenSafely, joinCVSChunks } from "../utils/methods";
import {
DEFAULT_CURRENT_PAGE,
DEFAULT_ORDER_DIR,
Expand Down Expand Up @@ -143,11 +144,17 @@ export const getEventsForOccupancyCSV =
orderDir = DEFAULT_ORDER_DIR
) =>
async (dispatch, getState) => {
const { currentSummitState } = getState();
const accessToken = await getAccessTokenSafely();
const { currentSummitState, currentRoomOccupancyState } = getState();
const { totalEvents } = currentRoomOccupancyState;
const csvMIME = "text/csv;charset=utf-8";
const pageSize = 500;
const totalPages = Math.ceil(totalEvents / pageSize);
const { currentSummit } = currentSummitState;
const filter = [];
const summitTZ = currentSummit.time_zone.name;
const cvsFiles = [];
const endpoint = `${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/events/csv`;
const accessToken = await getAccessTokenSafely();

dispatch(startLoading());

Expand All @@ -174,7 +181,8 @@ export const getEventsForOccupancyCSV =
}

const params = {
access_token: accessToken
access_token: accessToken,
per_page: pageSize
};

if (filter.length > 0) {
Expand All @@ -192,13 +200,22 @@ export const getEventsForOccupancyCSV =

const filename = `summit-${currentSummit.slug}-rooms-occupancy.csv`;

dispatch(
getCSV(
`${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/events/csv`,
params,
filename
)
);
for (let i = 1; i <= totalPages; i++) {
cvsFiles.push(getRawCSV(endpoint, { ...params, page: i }));
}

Promise.all(cvsFiles)
.then((files) => {
if (files.length > 0) {
const cvs = joinCVSChunks(files);
// then simulate the file download
downloadFileByContent(filename, cvs, csvMIME);
}
dispatch(stopLoading());
})
.catch(() => {
dispatch(stopLoading());
});
};

export const getCurrentEventForOccupancy =
Expand Down
2 changes: 1 addition & 1 deletion src/actions/sponsor-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ export const removeTierFromSponsor =

dispatch(startLoading());

deleteRequest(
return deleteRequest(
null,
createAction(SPONSOR_TIER_DELETED)({ sponsorshipId }),
`${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/sponsors/${sponsorId}/sponsorships/${sponsorshipId}`,
Expand Down
2 changes: 1 addition & 1 deletion src/actions/sponsor-forms-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export const getSponsorForms =
createAction(RECEIVE_SPONSOR_FORMS),
`${window.PURCHASES_API_URL}/api/v1/summits/${currentSummit.id}/show-forms`,
authErrorHandler,
{ order, orderDir, page, term, hideArchived }
{ order, orderDir, page, perPage, term, hideArchived }
)(params)(dispatch).then(() => {
dispatch(stopLoading());
});
Expand Down
Loading