diff --git a/src/actions/speaker-actions.js b/src/actions/speaker-actions.js index fa8a8b9f9..b6a46c071 100644 --- a/src/actions/speaker-actions.js +++ b/src/actions/speaker-actions.js @@ -90,6 +90,10 @@ export const UNSELECT_ALL_SUMMIT_SPEAKERS = "UNSELECT_ALL_SUMMIT_SPEAKERS"; export const SEND_SPEAKERS_EMAILS = "SEND_SPEAKERS_EMAILS"; export const SET_SPEAKERS_CURRENT_FLOW_EVENT = "SET_SPEAKERS_CURRENT_FLOW_EVENT"; +export const REQUEST_SPEAKERS_ACTIVITIES_COUNT = + "REQUEST_SPEAKERS_ACTIVITIES_COUNT"; +export const RECEIVE_SPEAKERS_ACTIVITIES_COUNT = + "RECEIVE_SPEAKERS_ACTIVITIES_COUNT"; const normalizeEntity = (entity) => { const normalizedEntity = { ...entity }; @@ -882,6 +886,18 @@ const parseFilters = (filters) => { return filter; }; +const getSpeakersActivitiesCount = + (summitId, filter, accessToken) => (dispatch) => { + const params = { access_token: accessToken }; + if (filter.length > 0) params["filter[]"] = filter; + return getRequest( + createAction(REQUEST_SPEAKERS_ACTIVITIES_COUNT), + createAction(RECEIVE_SPEAKERS_ACTIVITIES_COUNT), + `${window.API_BASE_URL}/api/v1/summits/${summitId}/speakers/all/events/count`, + authErrorHandler + )(params)(dispatch); + }; + export const getSpeakersBySummit = ( term = null, @@ -928,6 +944,8 @@ export const getSpeakersBySummit = params.order = `${orderDirSign}${order}`; } + dispatch(getSpeakersActivitiesCount(currentSummit.id, filter, accessToken)); + return getRequest( createAction(REQUEST_SPEAKERS_BY_SUMMIT), createAction(RECEIVE_SPEAKERS_BY_SUMMIT), diff --git a/src/actions/submitter-actions.js b/src/actions/submitter-actions.js index 57da93e08..906be372d 100644 --- a/src/actions/submitter-actions.js +++ b/src/actions/submitter-actions.js @@ -42,11 +42,27 @@ export const UNSELECT_ALL_SUMMIT_SUBMITTERS = "UNSELECT_ALL_SUMMIT_SUBMITTERS"; export const SEND_SUBMITTERS_EMAILS = "SEND_SUBMITTERS_EMAILS"; export const SET_SUBMITTERS_CURRENT_FLOW_EVENT = "SET_SUBMITTERS_CURRENT_FLOW_EVENT"; +export const REQUEST_SUBMITTERS_ACTIVITIES_COUNT = + "REQUEST_SUBMITTERS_ACTIVITIES_COUNT"; +export const RECEIVE_SUBMITTERS_ACTIVITIES_COUNT = + "RECEIVE_SUBMITTERS_ACTIVITIES_COUNT"; export const initSubmittersList = () => async (dispatch) => { dispatch(createAction(INIT_SUBMITTERS_LIST_PARAMS)()); }; +const getSubmittersActivitiesCount = + (summitId, filter, accessToken) => (dispatch) => { + const params = { access_token: accessToken }; + if (filter.length > 0) params["filter[]"] = filter; + return getRequest( + createAction(REQUEST_SUBMITTERS_ACTIVITIES_COUNT), + createAction(RECEIVE_SUBMITTERS_ACTIVITIES_COUNT), + `${window.API_BASE_URL}/api/v1/summits/${summitId}/submitters/all/events/count`, + authErrorHandler + )(params)(dispatch); + }; + export const getSubmittersBySummit = ( term = null, @@ -97,6 +113,10 @@ export const getSubmittersBySummit = params.order = `${orderDirSign}${order}`; } + dispatch( + getSubmittersActivitiesCount(currentSummit.id, filter, accessToken) + ); + return getRequest( createAction(REQUEST_SUBMITTERS_BY_SUMMIT), createAction(RECEIVE_SUBMITTERS_BY_SUMMIT), diff --git a/src/i18n/en.json b/src/i18n/en.json index 9c4f9fd05..f9aa8bb98 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -35,6 +35,7 @@ "member": "Member", "members": "Members", "event": "Activity", + "activities": "Activities", "group": "Group", "yes": "Yes", "no": "No", @@ -1045,7 +1046,7 @@ "send_emails_title": "You are about to send an EMAIL BLAST to selected speakers !", "should_send_copy_2_submitter": "Also send to submitter?", "allows_to_reassign": "Allow to reassign?", - "items_qty": "Selected {qty} Speakers", + "items_qty": "Selected {qty} Speakers | {activitiesQty} Activities", "placeholders": { "search_speakers": "Search by Full Name, Email, Speaker Id, Member Id, Title Or Abstract", "test_recipient": "Optional Test Recipient" @@ -1059,7 +1060,8 @@ "send_emails_title": "You are about to send an EMAIL BLAST to selected submitters !", "resend_done": "Emails sent successfully.", "submitters": "Submitters", - "submitters_no_speakers": "Submitters (no speakers)" + "submitters_no_speakers": "Submitters (no speakers)", + "items_qty": "Selected {qty} Submitters | {activitiesQty} Activities" }, "speaker_attendance_list": { "speaker_attendance_list": "Speaker Attendance List", diff --git a/src/pages/summit_speakers/summit-speakers-list-page.js b/src/pages/summit_speakers/summit-speakers-list-page.js index 24e47df74..9cf5e6bf8 100644 --- a/src/pages/summit_speakers/summit-speakers-list-page.js +++ b/src/pages/summit_speakers/summit-speakers-list-page.js @@ -16,9 +16,9 @@ import { connect } from "react-redux"; import T from "i18n-react/dist/i18n-react"; import Swal from "sweetalert2"; import { Modal, Pagination } from "react-bootstrap"; -import FreeTextSearch from "openstack-uicore-foundation/lib/components/free-text-search" -import SelectableTable from "openstack-uicore-foundation/lib/components/table-selectable" -import Dropdown from "openstack-uicore-foundation/lib/components/inputs/dropdown" +import FreeTextSearch from "openstack-uicore-foundation/lib/components/free-text-search"; +import SelectableTable from "openstack-uicore-foundation/lib/components/table-selectable"; +import Dropdown from "openstack-uicore-foundation/lib/components/inputs/dropdown"; import Input from "openstack-uicore-foundation/lib/components/inputs/text-input"; import SpeakerPromoCodeSpecForm from "../../components/forms/speakers-promo-code-spec-form"; import { @@ -702,8 +702,11 @@ class SummitSpeakersListPage extends React.Component { order, orderDir, totalItems, + totalActivities, selectedCount, selectedAll, + selectedItems, + excludedItems, selectionPlanFilter, trackFilter, trackGroupFilter, @@ -713,6 +716,20 @@ class SummitSpeakersListPage extends React.Component { currentFlowEvent } = this.getSubjectProps(); + const selectedActivities = (() => { + if (selectedAll && excludedItems.length === 0) return totalActivities; + const relevant = selectedAll + ? items.filter((item) => !excludedItems.includes(item.id)) + : items.filter((item) => selectedItems.includes(item.id)); + const ids = new Set(); + relevant.forEach((item) => { + (item.accepted_presentations || []).forEach((p) => ids.add(p.id)); + (item.alternate_presentations || []).forEach((p) => ids.add(p.id)); + (item.rejected_presentations || []).forEach((p) => ids.add(p.id)); + }); + return ids.size; + })(); + const columns = [ { columnKey: "full_name", @@ -901,7 +918,11 @@ class SummitSpeakersListPage extends React.Component { {this.state.source === sources.speakers ? T.translate("summit_speakers_list.summit_speakers_list") : T.translate("summit_submitters_list.summit_submitters_list")}{" "} - ({totalItems}) + ({totalItems}{" "} + {this.state.source === sources.speakers + ? T.translate("summit_speakers_list.speakers") + : T.translate("summit_submitters_list.submitters")}{" "} + | {totalActivities} {T.translate("general.activities")})
@@ -1044,9 +1065,12 @@ class SummitSpeakersListPage extends React.Component {
- {T.translate("summit_speakers_list.items_qty", { - qty: selectedCount - })} + {T.translate( + this.state.source === sources.speakers + ? "summit_speakers_list.items_qty" + : "summit_submitters_list.items_qty", + { qty: selectedCount, activitiesQty: selectedActivities } + )} { case SET_SPEAKERS_CURRENT_FLOW_EVENT: { return { ...state, currentFlowEvent: payload }; } + case RECEIVE_SPEAKERS_ACTIVITIES_COUNT: { + return { ...state, totalActivities: payload.response.count }; + } default: return state; } diff --git a/src/reducers/summit_submitters/summit-submitters-list-reducer.js b/src/reducers/summit_submitters/summit-submitters-list-reducer.js index 330c46f73..daf1253e8 100644 --- a/src/reducers/summit_submitters/summit-submitters-list-reducer.js +++ b/src/reducers/summit_submitters/summit-submitters-list-reducer.js @@ -20,7 +20,8 @@ import { SELECT_ALL_SUMMIT_SUBMITTERS, UNSELECT_ALL_SUMMIT_SUBMITTERS, SEND_SUBMITTERS_EMAILS, - SET_SUBMITTERS_CURRENT_FLOW_EVENT + SET_SUBMITTERS_CURRENT_FLOW_EVENT, + RECEIVE_SUBMITTERS_ACTIVITIES_COUNT } from "../../actions/submitter-actions"; import { @@ -38,6 +39,7 @@ const DEFAULT_STATE = { lastPage: 1, perPage: 10, totalItems: 0, + totalActivities: 0, selectedCount: 0, selectedItems: [], excludedItems: [], @@ -193,6 +195,9 @@ const summitSubmittersListReducer = (state = DEFAULT_STATE, action) => { case SET_SUBMITTERS_CURRENT_FLOW_EVENT: { return { ...state, currentFlowEvent: payload }; } + case RECEIVE_SUBMITTERS_ACTIVITIES_COUNT: { + return { ...state, totalActivities: payload.response.count }; + } default: return state; } diff --git a/src/reducers/summits/current-summit-reducer.js b/src/reducers/summits/current-summit-reducer.js index 3e229b606..dc729f12c 100644 --- a/src/reducers/summits/current-summit-reducer.js +++ b/src/reducers/summits/current-summit-reducer.js @@ -673,6 +673,7 @@ const currentSummitReducer = (state = DEFAULT_STATE, action) => { }; } case RECEIVE_REG_LITE_SETTINGS: { + if (!payload.response) return state; const { data } = payload.response; const reg_lite_marketing_settings = {}; @@ -695,6 +696,7 @@ const currentSummitReducer = (state = DEFAULT_STATE, action) => { return { ...state, reg_lite_marketing_settings: newMarketingSettings }; } case RECEIVE_PRINT_APP_SETTINGS: { + if (!payload.response) return state; const { data } = payload.response; const print_app_marketing_settings = {}; diff --git a/webpack.dev.js b/webpack.dev.js index be1e51682..6380181bb 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -8,7 +8,7 @@ module.exports = merge(common, { devtool: "inline-source-map", devServer: { historyApiFallback: true, - server: { type: "https" } + server: { type: "http" } }, output: { filename: "[name].js",