diff --git a/package.json b/package.json index 1058855e5..0e869b5fc 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "moment": "^2.29.1", "moment-duration-format": "^2.3.2", "moment-timezone": "^0.5.33", - "openstack-uicore-foundation": "5.0.34", + "openstack-uicore-foundation": "5.0.36-beta.1", "p-limit": "^6.1.0", "path-browserify": "^1.0.1", "postcss-loader": "^6.2.1", @@ -114,7 +114,7 @@ "react-dropzone": "^4.2.13", "react-final-form": "^6.5.9", "react-google-maps": "^9.4.5", - "react-redux": "^5.0.7", + "react-redux": "^7.1.0", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", "react-rte": "^0.16.3", @@ -124,7 +124,7 @@ "react-switch": "^6.0.0", "react-tooltip": "^5.28.0", "react-window": "^1.8.10", - "redux": "^3.7.2", + "redux": "^4.2.1", "redux-persist": "^5.10.0", "redux-thunk": "^2.3.0", "segmented-control": "0.1.12", diff --git a/src/actions/__tests__/event-actions.test.js b/src/actions/__tests__/event-actions.test.js index 0dce052d8..ba2e72dec 100644 --- a/src/actions/__tests__/event-actions.test.js +++ b/src/actions/__tests__/event-actions.test.js @@ -52,7 +52,7 @@ describe("Event Actions", () => { capturedParams = null; }); - test("builds speakers_count between filter using [] syntax", async () => { + test("passes pre-built [] range filter strings through to the request", async () => { const store = mockStore({ currentSummitState: { currentSummit: { @@ -63,7 +63,7 @@ describe("Event Actions", () => { }); store.dispatch( - getEvents(null, 1, 10, "id", 1, { speakers_count_filter: [1, 3] }, []) + getEvents(null, 1, 10, "id", 1, ["speakers_count[]1&&3"], []) ); await flushPromises(); @@ -71,7 +71,6 @@ describe("Event Actions", () => { expect(getRequest).toHaveBeenCalledTimes(1); expect(capturedParams).toBeTruthy(); expect(capturedParams["filter[]"]).toContain("speakers_count[]1&&3"); - expect(capturedParams["filter[]"]).not.toContain("speakers_count[]]1&&3"); }); test("requests type.use_speakers in fields for event list", async () => { @@ -93,7 +92,7 @@ describe("Event Actions", () => { expect(capturedParams.fields).toContain("type.use_speakers"); }); - test("builds speakers_count operator filter when value is not an array", async () => { + test("passes pre-built operator filter strings through to the request", async () => { const store = mockStore({ currentSummitState: { currentSummit: { @@ -103,9 +102,7 @@ describe("Event Actions", () => { } }); - store.dispatch( - getEvents(null, 1, 10, "id", 1, { speakers_count_filter: ">=2" }, []) - ); + store.dispatch(getEvents(null, 1, 10, "id", 1, ["speakers_count>=2"], [])); await flushPromises(); diff --git a/src/actions/event-actions.js b/src/actions/event-actions.js index 795915f49..60a669f89 100644 --- a/src/actions/event-actions.js +++ b/src/actions/event-actions.js @@ -36,11 +36,9 @@ import { epochToMomentTimeZone } from "openstack-uicore-foundation/lib/utils/met import URI from "urijs"; import history from "../history"; import { - checkOrFilter, getAccessTokenSafely, isNumericString, - joinCVSChunksAndNormalizeHeaders, - parseDateRangeFilter + joinCVSChunksAndNormalizeHeaders } from "../utils/methods"; import { getQAUsersBySummitEvent } from "./user-chat-roles-actions"; import { getAuditLog } from "./audit-log-actions"; @@ -51,9 +49,7 @@ import { DEFAULT_PER_PAGE, EXPORT_PAGE_SIZE_200, FIVE_PER_PAGE, - HOUR_AND_HALF, - SECONDS_TO_MINUTES, - TWO + HOUR_AND_HALF } from "../utils/constants"; import { getIdValue } from "../utils/summitUtils"; @@ -99,323 +95,6 @@ const fieldsBoundToQuestions = [ SOCIAL_DESCRIPTION ]; -const parseFilters = (filters, term = null) => { - const filter = []; - - if ( - filters.hasOwnProperty("event_type_capacity_filter") && - Array.isArray(filters.event_type_capacity_filter) && - filters.event_type_capacity_filter.length > 0 - ) { - if ( - filters.event_type_capacity_filter.includes("allows_attendee_vote_filter") - ) { - filter.push("type_allows_attendee_vote==1"); - } - if (filters.event_type_capacity_filter.includes("allows_location_filter")) { - filter.push("type_allows_location==1"); - } - if ( - filters.event_type_capacity_filter.includes( - "allows_publishing_dates_filter" - ) - ) { - filter.push("type_allows_publishing_dates==1"); - } - } - - if ( - filters.hasOwnProperty("selection_plan_id_filter") && - Array.isArray(filters.selection_plan_id_filter) && - filters.selection_plan_id_filter.length > 0 - ) { - filter.push( - `selection_plan_id==${filters.selection_plan_id_filter.join("||")}` - ); - } - - if ( - filters.hasOwnProperty("location_id_filter") && - Array.isArray(filters.location_id_filter) && - filters.location_id_filter.length > 0 - ) { - filter.push(`location_id==${filters.location_id_filter.join("||")}`); - } - - if ( - filters.hasOwnProperty("selection_status_filter") && - Array.isArray(filters.selection_status_filter) && - filters.selection_status_filter.length > 0 - ) { - filter.push( - `selection_status==${filters.selection_status_filter.join("||")}` - ); - } - - if ( - filters.hasOwnProperty("review_status_filter") && - Array.isArray(filters.review_status_filter) && - filters.review_status_filter.length > 0 - ) { - filter.push(`review_status==${filters.review_status_filter.join("||")}`); - } - - if (filters?.progress_flag?.length > 0) { - filter.push( - filters.progress_flag - .map((pf) => `actions==type_id==${pf}&&is_completed==1`) - .join(",") - ); - } - - if ( - filters.hasOwnProperty("track_id_filter") && - Array.isArray(filters.track_id_filter) && - filters.track_id_filter.length > 0 - ) { - filter.push(`track_id==${filters.track_id_filter.join("||")}`); - } - - if ( - filters.hasOwnProperty("event_type_id_filter") && - Array.isArray(filters.event_type_id_filter) && - filters.event_type_id_filter.length > 0 - ) { - filter.push(`event_type_id==${filters.event_type_id_filter.join("||")}`); - } - - if ( - filters.hasOwnProperty("speaker_id_filter") && - Array.isArray(filters.speaker_id_filter) && - filters.speaker_id_filter.length > 0 - ) { - filter.push( - `speaker_id==${filters.speaker_id_filter - .map((speaker) => speaker.id) - .join("||")}` - ); - } - - if ( - filters.hasOwnProperty("level_filter") && - Array.isArray(filters.level_filter) && - filters.level_filter.length > 0 - ) { - filter.push(`level==${filters.level_filter.join("||")}`); - } - - if ( - filters.hasOwnProperty("tags_filter") && - Array.isArray(filters.tags_filter) && - filters.tags_filter.length > 0 - ) { - filter.push(`tags==${filters.tags_filter.map((t) => t.tag).join("||")}`); - } - - if (filters.published_filter) { - filter.push( - `published==${filters.published_filter === "published" ? "1" : "0"}` - ); - } - - if (filters.has_rsvp_filter) { - filter.push( - `rsvp_type${filters.has_rsvp_filter === "yes" ? "<>" : "=="}None` - ); - } - - if (filters.start_date_filter) { - parseDateRangeFilter(filter, filters.start_date_filter, "start_date"); - } - - if (filters.end_date_filter) { - parseDateRangeFilter(filter, filters.end_date_filter, "end_date"); - } - - if (filters.created_filter) { - parseDateRangeFilter(filter, filters.created_filter, "created"); - } - - if (filters.modified_filter) { - parseDateRangeFilter(filter, filters.modified_filter, "last_edited"); - } - - if (filters.duration_filter) { - // multiply values to send the minutes in seconds - if (Array.isArray(filters.duration_filter)) { - // between - filter.push( - `duration[]${filters.duration_filter[0] * SECONDS_TO_MINUTES}&&${ - filters.duration_filter[1] * SECONDS_TO_MINUTES - }` - ); - } else { - filter.push( - `duration${filters.duration_filter.replace(/\d/g, "")}${ - filters.duration_filter.replace(/\D/g, "") * SECONDS_TO_MINUTES - }` - ); - } - } - - if (filters.speakers_count_filter) { - if ( - Array.isArray(filters.speakers_count_filter) && - filters.speakers_count_filter.length === TWO - ) { - // between - filter.push( - `speakers_count[]${filters.speakers_count_filter[0]}&&${filters.speakers_count_filter[1]}` - ); - } else { - filter.push(`speakers_count${filters.speakers_count_filter}`); - } - } - - if ( - filters.hasOwnProperty("submitters") && - Array.isArray(filters.submitters) && - filters.submitters.length > 0 - ) { - // created by fullname | created_by_email - filter.push( - filters.submitters.map((tt) => { - const escapedFullName = escapeFilterValue( - `${tt.first_name} ${tt.last_name}` - ); - const escapedEmail = escapeFilterValue(tt.email); - const fullNameFilter = `created_by_fullname==${escapedFullName}`; - const emailFilter = `created_by_email==${escapedEmail}`; - return [fullNameFilter, emailFilter]; - }, "") - ); - } - - if (filters.hasOwnProperty("streaming_url") && filters.streaming_url) { - const searchString = escapeFilterValue(filters.streaming_url); - filter.push(`streaming_url@@${searchString}`); - } - if (filters.hasOwnProperty("meeting_url") && filters.meeting_url) { - const searchString = escapeFilterValue(filters.meeting_url); - filter.push(`meeting_url@@${searchString}`); - } - if (filters.hasOwnProperty("etherpad_link") && filters.etherpad_link) { - const searchString = escapeFilterValue(filters.etherpad_link); - filter.push(`etherpad_link@@${searchString}`); - } - - if (filters.hasOwnProperty("streaming_type") && filters.streaming_type) { - filter.push(`streaming_type==${filters.streaming_type}`); - } - - if ( - filters.hasOwnProperty("submission_source_filter") && - filters.submission_source_filter - ) { - filter.push(`submission_source==${filters.submission_source_filter}`); - } - - if ( - filters.hasOwnProperty("speaker_company") && - Array.isArray(filters.speaker_company) && - filters.speaker_company.length > 0 - ) { - filter.push( - `speaker_company==${filters.speaker_company - .map((c) => escapeFilterValue(c.name)) - .join("||")}` - ); - } - - if ( - filters.hasOwnProperty("submitter_company") && - Array.isArray(filters.submitter_company) && - filters.submitter_company.length > 0 - ) { - filter.push( - `created_by_company==${filters.submitter_company - .map((c) => escapeFilterValue(c.name)) - .join("||")}` - ); - } - - if ( - filters.hasOwnProperty("sponsor") && - Array.isArray(filters.sponsor) && - filters.sponsor.length > 0 - ) { - filter.push( - `sponsor==${filters.sponsor.map((sponsor) => sponsor.name).join("||")}` - ); - } - - if ( - filters.hasOwnProperty("all_companies") && - Array.isArray(filters.all_companies) && - filters.all_companies.length > 0 - ) { - const companies = filters.all_companies - .map((c) => escapeFilterValue(c.name)) - .join("||"); - filter.push( - `speaker_company==${companies},created_by_company==${companies},sponsor==${companies}` - ); - } - - if (filters.is_public) { - filter.push("is_public==1"); - } - - if (filters.is_activity) { - filter.push("is_activity==1"); - } - - if ( - filters.hasOwnProperty("submission_status_filter") && - Array.isArray(filters.submission_status_filter) && - filters.submission_status_filter.length > 0 - ) { - filter.push( - `submission_status==${filters.submission_status_filter.join("||")}` - ); - } - - if ( - filters.hasOwnProperty("media_upload_with_type") && - filters.media_upload_with_type.operator !== null && - Array.isArray(filters.media_upload_with_type.value) && - filters.media_upload_with_type.value.length > 0 - ) { - const concatOperator = - filters.media_upload_with_type.operator === "has_media_upload_with_type==" - ? "||" - : "&&"; - filter.push( - `${ - filters.media_upload_with_type.operator - }${filters.media_upload_with_type.value - .map((v) => v.id) - .join(concatOperator)}` - ); - } - - if (term) { - const escapedTerm = escapeFilterValue(term); - let searchString = - `title=@${escapedTerm},` + - `abstract=@${escapedTerm},` + - `speaker_title=@${escapedTerm}`; - - if (isNumericString(term)) { - searchString += `,id==${term}`; - } - - filter.push(searchString); - } - - return checkOrFilter(filters, filter); -}; - export const normalizeEvent = (entity, eventTypeConfig, summit) => { const normalizedEntity = { ...entity }; if (!normalizedEntity.start_date) delete normalizedEntity.start_date; @@ -545,12 +224,12 @@ export const normalizeBulkEvents = (entity) => { export const getEvents = ( - term = null, + term = "", page = DEFAULT_CURRENT_PAGE, perPage = DEFAULT_PER_PAGE, order = "id", orderDir = DEFAULT_ORDER_DIR, - filters = {}, + filters = [], extraColumns = [] ) => async (dispatch, getState) => { @@ -558,10 +237,23 @@ export const getEvents = const accessToken = await getAccessTokenSafely(); const { currentSummit } = currentSummitState; const summitTZ = currentSummit.time_zone.name; + const filter = [...filters]; dispatch(startLoading()); - const filter = parseFilters(filters, term); + if (term) { + const escapedTerm = escapeFilterValue(term); + let searchString = + `title=@${escapedTerm},` + + `abstract=@${escapedTerm},` + + `speaker_title=@${escapedTerm}`; + + if (isNumericString(term)) { + searchString += `,id==${term}`; + } + + filter.push(searchString); + } const params = { expand: @@ -1236,26 +928,35 @@ export const deleteEvent = (eventId) => async (dispatch, getState) => { }; export const exportEvents = - ( - term = null, - order = "id", - orderDir = DEFAULT_ORDER_DIR, - extraFilters = {} - ) => + (term = null, order = "id", orderDir = DEFAULT_ORDER_DIR, filters = []) => async (dispatch, getState) => { dispatch(startLoading()); const { currentSummitState, currentEventListState } = getState(); const accessToken = await getAccessTokenSafely(); const { currentSummit } = currentSummitState; const { totalEvents } = currentEventListState; - const csvMIME = "text/csv;charset=utf-8"; const filename = `${currentSummit.name}-Activities.csv`; const totalPages = Math.ceil(totalEvents / EXPORT_PAGE_SIZE_200); - const endpoint = `${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/events/csv`; - const filter = parseFilters(extraFilters, term); + const filter = [...filters]; + + dispatch(startLoading()); + + if (term) { + const escapedTerm = escapeFilterValue(term); + let searchString = + `title=@${escapedTerm},` + + `abstract=@${escapedTerm},` + + `speaker_title=@${escapedTerm}`; + + if (isNumericString(term)) { + searchString += `,id==${term}`; + } + + filter.push(searchString); + } const params = Array.from({ length: totalPages }, (_, i) => { const res = { @@ -1489,10 +1190,17 @@ export const getEventComments = const { currentSummitState } = getState(); const { currentSummit } = currentSummitState; const summitTZ = currentSummit.time_zone_id; + const filter = []; dispatch(startLoading()); - const filter = parseFilters(filters); + if (filters.is_public) { + filter.push("is_public==1"); + } + + if (filters.is_activity) { + filter.push("is_activity==1"); + } if (term) { const escapedTerm = escapeFilterValue(term); @@ -1500,9 +1208,6 @@ export const getEventComments = filter.push(searchString); } - // `is_public==${escapedTerm},`; - // `is_activity==${escapedTerm},`; - const params = { page, per_page: perPage, diff --git a/src/components/filters/select-filter-criteria/index.js b/src/components/filters/select-filter-criteria/index.js index 06c7c4a04..f4d8c9420 100644 --- a/src/components/filters/select-filter-criteria/index.js +++ b/src/components/filters/select-filter-criteria/index.js @@ -1,4 +1,4 @@ -/** +/* * * 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. @@ -9,15 +9,13 @@ * 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, useState } from "react"; import PropTypes from "prop-types"; import T from "i18n-react/dist/i18n-react"; import Swal from "sweetalert2"; import AsyncSelect from "react-select/lib/Async"; - -import styles from "./index.module.less"; import { queryFilterCriterias } from "../../../actions/filter-criteria-actions"; const SelectFilterCriteria = ({ @@ -30,7 +28,6 @@ const SelectFilterCriteria = ({ }) => { const [selectedFilter, setSelectedFilter] = useState(null); const [defaultOptions, setDefaultOptions] = useState([]); - const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (!selectedFilterCriteria) setSelectedFilter(null); @@ -44,9 +41,9 @@ const SelectFilterCriteria = ({ const handleFilterDelete = () => { Swal.fire({ title: T.translate("general.are_you_sure"), - text: - T.translate("select_filter_criteria.remove_filter_criteria_warning") + - `"${selectedFilter.label}"`, + text: `${T.translate( + "select_filter_criteria.remove_filter_criteria_warning" + )}"${selectedFilter.label}"`, type: "warning", showCancelButton: true, confirmButtonColor: "#DD6B55", @@ -59,7 +56,6 @@ const SelectFilterCriteria = ({ }; const getCriterias = (input, callback) => { - setIsLoading(true); // we need to map into value/label because of a bug in react-select 2 // https://github.com/JedWatson/react-select/issues/2998 @@ -69,7 +65,6 @@ const SelectFilterCriteria = ({ label: c.name, ...c })); - setIsLoading(false); callback(newOptions); }; @@ -88,18 +83,18 @@ const SelectFilterCriteria = ({ }; return ( -
+
diff --git a/src/components/filters/select-filter-criteria/index.module.less b/src/components/filters/select-filter-criteria/index.module.less deleted file mode 100644 index c9a629fe6..000000000 --- a/src/components/filters/select-filter-criteria/index.module.less +++ /dev/null @@ -1,3 +0,0 @@ -.selectFilterWrapper { - margin-bottom: 20px; -} diff --git a/src/i18n/en.json b/src/i18n/en.json index eda7913d2..1092c1a45 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -1155,19 +1155,18 @@ "add_event": "Add Activity", "title": "Title", "type": "Activity Type", - "event_type_capacity": "Activity Type Capacity", - "selection_plan": "Selection Plan", - "location": "Location", - "level": "Level", + "event_type_capacity": "Select..", + "selection_plan": "Select Selection Plan", + "location": "Select Location", + "level": "Select Level", "tags": "Tags", "progress_flags": "Progress Flags", "streaming_url": "Streaming URL", "meeting_url": "Meeting URL", "etherpad_link": "Etherpad URL", "streaming_type": "Streaming Type", - "status": "Status", - "selection_status": "Selection Status", - "submission_status": "Submission Status", + "selection_status": "Select Status", + "submission_status": "Select Status", "published": "Published", "speakers": "Speakers", "duration": "Duration", @@ -1176,7 +1175,7 @@ "submitter_company": "Submitter Company", "sponsor": "Sponsors", "all_companies": "All Companies", - "track": "Activity Category", + "track": "Select Activity Category", "start_date": "Start Date", "end_date": "End Date", "media_uploads_display": "Display on Site", @@ -1194,7 +1193,6 @@ "mux_token_secret_info": "MUX Token Secret", "mux_email_to": "Email to", "mux_email_to_info": "Recipient to send process excerpt.", - "export": "Export", "created_by": "Submitter", "mux_import_done": "MUX MP4 Import Process Requested Successfuly.", "allows_attendee_vote_filter": "Allows attendee vote", @@ -1215,50 +1213,12 @@ "submission_status_accepted": "Accepted", "submission_status_received": "Received", "submission_status_not_submitted": "Not Submitted", - "media_upload_type": "Media Upload Type", "media_uploads": "Media Uploads", - "media_upload_with_type": "Media Upload Types", "edit_selected": "Edit Selected", - "delete_selected": "Delete Selected", "placeholders": { "search_events": "Search by Id, Title, Abstract, Speaker Title", - "event_type_capacity": "Filter by Activity Type Capacity", - "selection_plan": "Filter by Selection Plan", - "location": "Filter by Location", - "selection_status": "Filter by Selection Status", - "progress_flag": "Filter by Progress Flag", - "track": "Filter by Activity Category", "event_type": "Filter by Activity Type", - "speaker": "Filter by Speaker", - "speaker_company": "Filter by Speaker Company", - "level": "Filter by Level", - "tags": "Filter by Tags", - "start_date": "Filter from Date", - "end_date": "Filter to Date", - "start_date_from": "Filter Start Date from", - "start_date_to": "Filter Start Date to", - "end_date_from": "Filter End Date from", - "end_date_to": "Filter End Date to", - "created_from": "Filter Created Date from", - "created_to": "Filter Created Date to", - "modified_from": "Filter Modified Date from", - "modified_to": "Filter Modified Date to", - "select_fields": "Select data to display", - "has_rsvp": "Has RSVP?", - "submitters": "Filter by Submitter", - "submitter_company": "Filter by Submitter Company", - "streaming_url": "Filter by Stream URL", - "meeting_url": "Filter by Meeting URL", - "etherpad_link": "Filter by Etherpad URL", - "streaming_type": "Filter by Streaming Type", - "sponsor": "Filter by Sponsor", - "all_companies": "Filter by All Companies", - "submission_status": "Filter by Submission Status", - "review_status": "Filter by Review Status", - "media_upload_type": "Filter by Media Upload Type", - "submission_source": "Filter by Submission Source", - "media_upload_type_id_to_include": "Select the Media Upload Types to include", - "media_upload_type_id_to_exclude": "Select the Media Upload Types to exclude" + "select_fields": "Select data to display" } }, "event_type_list": { diff --git a/src/pages/events/__tests__/summit-event-list-page.test.js b/src/pages/events/__tests__/summit-event-list-page.test.js index 00ab2f5c5..e932bbb16 100644 --- a/src/pages/events/__tests__/summit-event-list-page.test.js +++ b/src/pages/events/__tests__/summit-event-list-page.test.js @@ -4,19 +4,6 @@ import { renderWithRedux } from "../../../utils/test-utils"; const mockEditableTableSpy = jest.fn(() => null); -jest.mock("openstack-uicore-foundation/lib/components", () => ({ - CompanyInput: () => null, - DateTimePicker: () => null, - Dropdown: () => null, - FreeTextSearch: () => null, - Input: () => null, - MemberInput: () => null, - OperatorInput: () => null, - SpeakerInput: () => null, - TagInput: () => null, - UploadInput: () => null -})); - jest.mock( "../../../components/tables/editable-table/EditableTable", () => @@ -51,8 +38,6 @@ jest.mock("react-bootstrap", () => { }; }); -jest.mock("../../../components/filters/media-type-filter", () => () => null); -jest.mock("../../../components/filters/or-and-filter", () => () => null); jest.mock("../../../components/filters/save-filter-criteria", () => () => null); jest.mock( "../../../components/filters/select-filter-criteria", @@ -86,6 +71,9 @@ describe("SummitEventListPage", () => { presentation_action_types: [] } }, + mediaUploadListState: { + media_uploads: [] + }, currentEventListState: { events: [ { @@ -104,8 +92,7 @@ describe("SummitEventListPage", () => { term: "", filters: {}, extraColumns: ["media_uploads"], - perPage: 10, - enabledFilters: [] + perPage: 10 } } }); @@ -134,6 +121,9 @@ describe("SummitEventListPage", () => { presentation_action_types: [] } }, + mediaUploadListState: { + media_uploads: [] + }, currentEventListState: { events: [ { @@ -161,8 +151,7 @@ describe("SummitEventListPage", () => { term: "", filters: {}, extraColumns: ["media_uploads"], - perPage: 10, - enabledFilters: [] + perPage: 10 } } }); @@ -215,6 +204,9 @@ describe("SummitEventListPage", () => { presentation_action_types: [] } }, + mediaUploadListState: { + media_uploads: [] + }, currentEventListState: { events: [ { @@ -239,8 +231,7 @@ describe("SummitEventListPage", () => { term: "", filters: {}, extraColumns: ["media_uploads"], - perPage: 10, - enabledFilters: [] + perPage: 10 } } }); @@ -290,6 +281,9 @@ describe("SummitEventListPage", () => { presentation_action_types: [] } }, + mediaUploadListState: { + media_uploads: [] + }, currentEventListState: { events: [ { @@ -315,8 +309,7 @@ describe("SummitEventListPage", () => { term: "", filters: {}, extraColumns: ["media_uploads"], - perPage: 10, - enabledFilters: [] + perPage: 10 } } }); diff --git a/src/pages/events/summit-event-list-page.js b/src/pages/events/summit-event-list-page.js deleted file mode 100644 index 058754b88..000000000 --- a/src/pages/events/summit-event-list-page.js +++ /dev/null @@ -1,2150 +0,0 @@ -/** - * Copyright 2026 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 { connect } from "react-redux"; -import T from "i18n-react/dist/i18n-react"; -import Swal from "sweetalert2"; -import { Modal, Pagination } from "react-bootstrap"; -import CompanyInput from "openstack-uicore-foundation/lib/components/inputs/company-input" -import DateTimePicker from "openstack-uicore-foundation/lib/components/inputs/datetimepicker" -import Dropdown from "openstack-uicore-foundation/lib/components/inputs/dropdown" -import FreeTextSearch from "openstack-uicore-foundation/lib/components/free-text-search" -import Input from "openstack-uicore-foundation/lib/components/inputs/text-input" -import MemberInput from "openstack-uicore-foundation/lib/components/inputs/member-input" -import OperatorInput from "openstack-uicore-foundation/lib/components/inputs/operator-input" -import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input" -import TagInput from "openstack-uicore-foundation/lib/components/inputs/tag-input" -import UploadInput from "openstack-uicore-foundation/lib/components/inputs/upload-input"; -import { SegmentedControl } from "segmented-control"; -import { epochToMomentTimeZone } from "openstack-uicore-foundation/lib/utils/methods"; -import { - bulkUpdateEvents, - changeEventListSearchTerm, - deleteEvent, - exportEvents, - getEvents, - importEventsCSV, - importMP4AssetsFromMUX, - queryAllCompanies, - querySpeakerCompany, - querySubmitterCompany -} from "../../actions/event-actions"; -import { handleDDLSortByLabel, hasErrors } from "../../utils/methods"; -import "../../styles/summit-event-list-page.less"; -import OrAndFilter from "../../components/filters/or-and-filter"; -import MediaTypeFilter from "../../components/filters/media-type-filter"; -import { - ALL_FILTER, - DATE_FILTER_ARRAY_SIZE, - DEFAULT_CURRENT_PAGE, - DEFAULT_PER_PAGE, - DEFAULT_Z_INDEX, - HIGH_Z_INDEX -} from "../../utils/constants"; -import { - defaultColumns, - editableColumns, - formatEventData -} from "../../utils/summitUtils"; -import SaveFilterCriteria from "../../components/filters/save-filter-criteria"; -import SelectFilterCriteria from "../../components/filters/select-filter-criteria"; -import { - deleteFilterCriteria, - saveFilterCriteria -} from "../../actions/filter-criteria-actions"; -import { CONTEXT_ACTIVITIES } from "../../utils/filter-criteria-constants"; -import EditableTable from "../../components/tables/editable-table/EditableTable"; -import { buildNameIdDDL } from "../../utils/events/summit-event-list-page.utils"; - -const fieldNames = ( - allSelectionPlans, - allTracks, - event_types, - currentSummitId -) => [ - { - columnKey: "speakers", - value: "speakers", - customStyle: { minWidth: "350px" }, - editableField: (extraProps) => { - const useSpeakers = extraProps.row.type?.use_speakers; - return useSpeakers ? ( - ({ ...base, zIndex: 9999 }), - control: (base, state) => ({ - ...base, - zIndex: state.menuIsOpen ? HIGH_Z_INDEX : DEFAULT_Z_INDEX - }) - }} - getOptionLabel={(speaker) => - `${speaker.first_name} ${speaker.last_name} (${speaker.email})` - } - // eslint-disable-next-line react/jsx-props-no-spreading - {...extraProps} - /> - ) : ( - false - ); - } - }, - { columnKey: "created_by_fullname", value: "created_by", sortable: true }, - { columnKey: "published_date", value: "published", sortable: true }, - { columnKey: "duration", value: "duration", sortable: true }, - { columnKey: "speakers_count", value: "speakers_count", sortable: true }, - { columnKey: "speaker_company", value: "speaker_company", sortable: true }, - { - columnKey: "track", - value: "track", - sortable: true, - editableField: (extraProps) => { - const track_ddl = buildNameIdDDL(allTracks); - - return ( - ({ ...base, zIndex: 9999 }), - control: (base, state) => ({ - ...base, - zIndex: state.menuIsOpen ? HIGH_Z_INDEX : DEFAULT_Z_INDEX - }) - }} - // eslint-disable-next-line react/jsx-props-no-spreading - {...extraProps} - /> - ); - } - }, - { columnKey: "start_date", value: "start_date", sortable: true }, - { columnKey: "end_date", value: "end_date", sortable: true }, - { columnKey: "submitters", value: "submitters" }, - { - columnKey: "submitter_company", - value: "submitter_company", - sortable: true - }, - { columnKey: "sponsor", value: "sponsor", sortable: true }, - { columnKey: "event_type_capacity", value: "event_type_capacity" }, - { - columnKey: "selection_plan", - value: "selection_plan", - sortable: true, - editableField: (extraProps) => { - if (!extraProps.row?.type?.id) return false; - const event_type = Array.isArray(event_types) - ? event_types.find( - (t) => t?.id !== undefined && t.id === extraProps.row.type?.id - ) - : null; - if (!event_type) return false; - - const allowSelectionPlanEdit = - ["PresentationType"].includes(event_type.class_name) || - ["PresentationType"].includes(event_type.name); - if (!allowSelectionPlanEdit) return false; - - const trackId = extraProps.row?.track?.id; - const track = - trackId !== undefined && trackId !== null - ? allTracks.find((t) => t?.id !== undefined && t.id === trackId) - : null; - - const selection_plans_per_track = buildNameIdDDL( - (Array.isArray(allSelectionPlans) ? allSelectionPlans : []).filter( - (sp) => - !track || - (Array.isArray(sp.track_groups) && - Array.isArray(track.track_groups) && - sp.track_groups.some((gr) => track.track_groups.includes(gr))) - ) - ); - - return ( - ({ ...base, zIndex: 9999 }), - control: (base, state) => ({ - ...base, - width: 220, - zIndex: state.menuIsOpen ? HIGH_Z_INDEX : DEFAULT_Z_INDEX - }) - }} - // eslint-disable-next-line react/jsx-props-no-spreading - {...extraProps} - /> - ); - }, - render: (e) => (e?.name ? e.name : "N/A") - }, - { columnKey: "location", value: "location", sortable: true }, - { columnKey: "level", value: "level", sortable: true }, - { columnKey: "tags", value: "tags", sortable: true }, - { - columnKey: "streaming_url", - value: "streaming_url", - sortable: true, - title: true, - editableField: true - }, - { - columnKey: "meeting_url", - value: "meeting_url", - sortable: true, - title: true, - editableField: true - }, - { - columnKey: "etherpad_link", - value: "etherpad_link", - sortable: true, - title: true, - editableField: true - }, - { columnKey: "streaming_type", value: "streaming_type", sortable: true }, - { - columnKey: "review_status", - value: "review_status", - sortable: true, - title: true - }, - { - columnKey: "status", - value: "submission_status", - sortable: true, - title: true - }, - { - columnKey: "progress_flags", - value: "progress_flags", - sortable: true, - title: true - }, - { columnKey: "created", value: "created", sortable: true }, - { columnKey: "modified", value: "modified", sortable: true }, - { - columnKey: "submission_source", - value: "submission_source", - sortable: true - }, - { - columnKey: "media_uploads", - value: "media_uploads", - sortable: false, - render: (e, row) => { - if (!e?.length) return "N/A"; - return ( - <> - {e.map((m) => ( - - -
-
- ))} - - ); - } - }, - { - columnKey: "media_uploads_display", - value: "media_uploads_display", - sortable: false, - render: (e, row) => { - const media_uploads = row?.media_uploads || []; - if (!media_uploads.length) return "N/A"; - return ( - <> - {media_uploads.map((m) => ( - - {`"${m.media_upload_type.name}" : `} - {`${m.display_on_site ? "Yes" : "No"}`} -
-
- ))} - - ); - } - }, - { - columnKey: "allow_feedback", - value: "allow_feedback", - sortable: false, - render: (field) => - field === undefined ? "N/A" : field === true ? "Yes" : "No", - editableField: (extraProps) => ( - ({ ...base, zIndex: 9999 }), - control: (base, state) => ({ - ...base, - zIndex: state.menuIsOpen ? HIGH_Z_INDEX : DEFAULT_Z_INDEX - }) - }} - // eslint-disable-next-line react/jsx-props-no-spreading - {...extraProps} - /> - ) - }, - { - columnKey: "to_record", - value: "to_record", - sortable: false, - render: (field) => - field === undefined ? "N/A" : field === true ? "Yes" : "No", - editableField: (extraProps) => ( - ({ ...base, zIndex: 9999 }), - control: (base, state) => ({ - ...base, - zIndex: state.menuIsOpen ? HIGH_Z_INDEX : DEFAULT_Z_INDEX - }) - }} - // eslint-disable-next-line react/jsx-props-no-spreading - {...extraProps} - /> - ) - } -]; - -const defaultFilters = { - event_type_capacity_filter: [], - selection_plan_id_filter: [], - location_id_filter: [], - selection_status_filter: [], - track_id_filter: [], - event_type_id_filter: [], - speaker_id_filter: [], - speaker_company: [], - level_filter: [], - tags_filter: [], - published_filter: null, - has_rsvp_filter: null, - progress_flag: [], - created_filter: Array(DATE_FILTER_ARRAY_SIZE).fill(null), - modified_filter: Array(DATE_FILTER_ARRAY_SIZE).fill(null), - start_date_filter: Array(DATE_FILTER_ARRAY_SIZE).fill(null), - end_date_filter: Array(DATE_FILTER_ARRAY_SIZE).fill(null), - duration_filter: "", - speakers_count_filter: "", - submitters: [], - submitter_company: [], - streaming_url: "", - meeting_url: "", - etherpad_link: "", - streaming_type: "", - sponsor: [], - all_companies: [], - submission_status_filter: [], - media_upload_with_type: { operator: null, value: [] }, - review_status_filter: [], - submission_source_filter: "" -}; - -class SummitEventListPage extends React.Component { - constructor(props) { - super(props); - - this.handleEdit = this.handleEdit.bind(this); - this.handlePageChange = this.handlePageChange.bind(this); - this.handleSort = this.handleSort.bind(this); - this.handleSearch = this.handleSearch.bind(this); - this.handleNewEvent = this.handleNewEvent.bind(this); - this.handleDeleteEvent = this.handleDeleteEvent.bind(this); - this.handleExport = this.handleExport.bind(this); - this.handleChangeSendSpeakerEmail = - this.handleChangeSendSpeakerEmail.bind(this); - this.handleImportEvents = this.handleImportEvents.bind(this); - this.handleMUXImport = this.handleMUXImport.bind(this); - this.handleChangeMUXModal = this.handleChangeMUXModal.bind(this); - this.handleImportAssetsFromMUX = this.handleImportAssetsFromMUX.bind(this); - this.handleExtraFilterChange = this.handleExtraFilterChange.bind(this); - this.handleTagOrSpeakerFilterChange = - this.handleTagOrSpeakerFilterChange.bind(this); - this.handleSetPublishedFilter = this.handleSetPublishedFilter.bind(this); - this.handleSetRSVPFilter = this.handleSetRSVPFilter.bind(this); - this.handleChangeDateFilter = this.handleChangeDateFilter.bind(this); - this.handleApplyEventFilters = this.handleApplyEventFilters.bind(this); - this.handleFiltersChange = this.handleFiltersChange.bind(this); - this.handleColumnsChange = this.handleColumnsChange.bind(this); - this.handleTermChange = this.handleTermChange.bind(this); - this.handleOrAndFilter = this.handleOrAndFilter.bind(this); - this.handleFilterCriteriaSave = this.handleFilterCriteriaSave.bind(this); - this.handleFilterCriteriaChange = - this.handleFilterCriteriaChange.bind(this); - this.handleFilterCriteriaDelete = - this.handleFilterCriteriaDelete.bind(this); - - this.state = { - showImportModal: false, - send_speaker_email: false, - showImportFromMUXModal: false, - importFile: null, - muxModalState: { - mux_token_id: "", - mux_token_secret: "", - mux_email_to: "" - }, - enabledFilters: [], - errors: {}, - eventFilters: { - ...defaultFilters, - orAndFilter: ALL_FILTER - }, - selectedColumns: [], - selectedFilterCriteria: null - }; - - this.extraFilters = { - allows_attendee_vote_filter: false, - allows_location_filter: false, - allows_publishing_dates_filter: false - }; - } - - componentDidMount() { - const { - getEvents, - currentSummit, - filters, - extraColumns, - term, - currentPage, - perPage, - order, - orderDir - } = this.props; - const { eventFilters } = this.state; - const enabledFilters = Object.keys(filters).filter((e) => - Array.isArray(filters[e]) - ? filters[e]?.some((e) => e !== null) - : filters[e]?.length > 0 - ); - - this.setState((prevState) => ({ - ...prevState, - selectedColumns: extraColumns, - enabledFilters, - eventFilters: { ...eventFilters, ...filters } - })); - - if (currentSummit) { - getEvents( - term, - currentPage, - perPage, - order, - orderDir, - filters, - extraColumns - ); - } - } - - handleChangeSendSpeakerEmail(ev) { - this.setState((prevState) => ({ - ...prevState, - send_speaker_email: ev.target.checked - })); - } - - handleChangeMUXModal(ev) { - const { errors, muxModalState } = this.state; - const newErrors = { ...errors }; - const newMuxModalState = { ...muxModalState }; - const { value, id } = ev.target; - newErrors[id] = ""; - newMuxModalState[id] = value; - this.setState((prevState) => ({ - ...prevState, - muxModalState, - errors: newErrors - })); - } - - handleMUXImport(ev) { - ev.preventDefault(); - this.setState((prevState) => ({ - ...prevState, - showImportFromMUXModal: true - })); - } - - handleImportAssetsFromMUX(ev) { - const { importMP4AssetsFromMUX } = this.props; - const { - muxModalState: { mux_token_id, mux_token_secret, mux_email_to } - } = this.state; - ev.preventDefault(); - importMP4AssetsFromMUX(mux_token_id, mux_token_secret, mux_email_to).then( - () => - this.setState((prevState) => ({ - ...prevState, - muxModalState: { - mux_token_id: "", - mux_token_secret: "", - mux_email_to: "" - } - })) - ); - } - - handleImportEvents() { - const { importEventsCSV } = this.props; - const { importFile, send_speaker_email } = this.state; - if (importFile) { - importEventsCSV(importFile, send_speaker_email); - } - this.setState((prevState) => ({ - ...prevState, - showImportModal: false, - send_speaker_email: false, - importFile: null - })); - } - - handleEdit(event_id) { - const { currentSummit, history } = this.props; - history.push(`/app/summits/${currentSummit.id}/events/${event_id}`); - } - - handleExport(ev) { - const { order, orderDir, term, exportEvents } = this.props; - const { eventFilters, selectedColumns } = this.state; - ev.preventDefault(); - exportEvents(term, order, orderDir, eventFilters, selectedColumns); - } - - handlePageChange(page) { - const { order, orderDir, perPage, term, getEvents } = this.props; - const { eventFilters, selectedColumns } = this.state; - getEvents( - term, - page, - perPage, - order, - orderDir, - eventFilters, - selectedColumns - ); - } - - handleSort(index, key, dir) { - const { term, getEvents } = this.props; - const { eventFilters, selectedColumns } = this.state; - - switch (key) { - case "name": - key = "last_name"; - break; - case "submitter_company": - key = "created_by_company"; - break; - case "progress_flags": - key = "actions"; - break; - default: - break; - } - - getEvents( - term, - DEFAULT_CURRENT_PAGE, - DEFAULT_PER_PAGE, - key, - dir, - eventFilters, - selectedColumns - ); - } - - handleSearch(term) { - const { order, orderDir, getEvents } = this.props; - const { eventFilters, selectedColumns } = this.state; - getEvents( - term, - DEFAULT_CURRENT_PAGE, - DEFAULT_PER_PAGE, - order, - orderDir, - eventFilters, - selectedColumns - ); - } - - handleNewEvent() { - const { currentSummit, history } = this.props; - history.push(`/app/summits/${currentSummit.id}/events/new`); - } - - handleDeleteEvent(eventId) { - const { deleteEvent, events } = this.props; - const event = events.find((e) => e.id === eventId); - - Swal.fire({ - title: T.translate("general.are_you_sure"), - text: `${T.translate("event_list.delete_event_warning")} ${event.title}`, - type: "warning", - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: T.translate("general.yes_delete") - }).then((result) => { - if (result.value) { - deleteEvent(eventId); - } - }); - } - - handleTermChange(term) { - const { changeEventListSearchTerm } = this.props; - changeEventListSearchTerm(term); - } - - handleApplyEventFilters() { - const { order, orderDir, term, getEvents } = this.props; - const { eventFilters, selectedColumns } = this.state; - getEvents( - term, - DEFAULT_CURRENT_PAGE, - DEFAULT_PER_PAGE, - order, - orderDir, - eventFilters, - selectedColumns - ); - this.setState((prevState) => ({ - ...prevState, - selectedFilterCriteria: null - })); - } - - handleExtraFilterChange(ev) { - const { eventFilters } = this.state; - const { type, id } = ev.target; - let { value } = ev.target; - if (type === "operatorinput") { - value = Array.isArray(value) - ? value - : `${ev.target.operator}${ev.target.value}`; - if (id === "duration_filter") { - value = Array.isArray(value) - ? value - : `${ev.target.operator}${ev.target.value}`; - } - } - if (type === "mediatypeinput") { - value = { - operator: ev.target.operator, - value: ev.target.value - }; - } - this.setState((prevState) => ({ - ...prevState, - eventFilters: { ...eventFilters, [id]: value }, - selectedFilterCriteria: null - })); - } - - handleOrAndFilter(ev) { - const { eventFilters } = this.state; - this.setState((prevState) => ({ - ...prevState, - eventFilters: { ...eventFilters, orAndFilter: ev } - })); - } - - handleTagOrSpeakerFilterChange(ev) { - const { value, id } = ev.target; - const { eventFilters } = this.state; - this.setState((prevState) => ({ - ...prevState, - eventFilters: { ...eventFilters, [id]: value } - })); - } - - handleSetPublishedFilter(ev) { - const { eventFilters } = this.state; - this.extraFilters.published_filter = ev; - this.setState((prevState) => ({ - ...prevState, - eventFilters: { ...eventFilters, published_filter: ev } - })); - } - - handleSetRSVPFilter(ev) { - const { eventFilters } = this.state; - this.extraFilters.has_rsvp_filter = ev; - this.setState((prevState) => ({ - ...prevState, - eventFilters: { ...eventFilters, has_rsvp_filter: ev } - })); - } - - handleFiltersChange(ev) { - const { value } = ev.target; - const { enabledFilters, eventFilters } = this.state; - if (value.length < enabledFilters.length) { - if (value.length === 0) { - this.setState((prevState) => ({ - ...prevState, - enabledFilters: value, - eventFilters: defaultFilters, - selectedFilterCriteria: null - })); - } else { - const removedFilter = enabledFilters.filter( - (e) => !value.includes(e) - )[0]; - let defaultValue; - if ( - removedFilter === "published_filter" || - removedFilter === "has_rsvp_filter" - ) { - defaultValue = null; - } else if (Array.isArray(eventFilters[removedFilter])) { - defaultValue = []; - } else { - defaultValue = ""; - } - const newEventFilters = { - ...eventFilters, - [removedFilter]: defaultValue - }; - this.setState((prevState) => ({ - ...prevState, - enabledFilters: value, - eventFilters: newEventFilters, - selectedFilterCriteria: null - })); - } - } else { - this.setState((prevState) => ({ - ...prevState, - enabledFilters: value, - selectedFilterCriteria: null - })); - } - } - - handleChangeDateFilter(ev, lastDate) { - const { value, id } = ev.target; - const { eventFilters } = this.state; - const newDateFilter = eventFilters[id]; - - this.setState((prevState) => ({ - ...prevState, - eventFilters: { - ...eventFilters, - [id]: lastDate - ? [newDateFilter[0], value.unix()] - : [value.unix(), newDateFilter[1]] - } - })); - } - - handleFilterCriteriaSave(filterData) { - const { enabledFilters, eventFilters } = this.state; - const { currentSummit, saveFilterCriteria } = this.props; - const filterToSave = { - id: filterData.id, - show_id: currentSummit.id, - name: filterData.name, - enabled_filters: enabledFilters, - // only save criteria for enabled filters - criteria: Object.fromEntries( - Object.entries(eventFilters).filter(([key]) => - enabledFilters.includes(key) - ) - ), - context: CONTEXT_ACTIVITIES, - visibility: filterData.visibility - }; - saveFilterCriteria(filterToSave); - } - - handleColumnsChange(ev) { - const { value } = ev.target; - const { selectedColumns } = this.state; - let newColumns = value; - const all_companies = ["submitter_company", "speaker_company", "sponsor"]; - - const mediaUploadsSelected = newColumns.includes("media_uploads"); - - // Ensure 'media_uploads_display' is included if 'media_uploads' is selected - if (mediaUploadsSelected && !newColumns.includes("media_uploads_display")) { - newColumns = [...newColumns, "media_uploads_display"]; - } - - // Remove 'media_uploads_display' if 'media_uploads' is deselected - if (!mediaUploadsSelected && newColumns.includes("media_uploads_display")) { - newColumns = newColumns.filter((col) => col !== "media_uploads_display"); - } - - if ( - selectedColumns.includes("all_companies") && - !newColumns.includes("all_companies") - ) { - newColumns = [...newColumns.filter((e) => !all_companies.includes(e))]; - } - const selectedCompanies = selectedColumns.filter((c) => - all_companies.includes(c) - ).length; - const newCompanies = newColumns.filter((c) => - all_companies.includes(c) - ).length; - if (newColumns.includes("all_companies")) { - if (newColumns.filter((c) => all_companies.includes(c)).length === 0) { - newColumns = [...selectedColumns, ...all_companies, "all_companies"]; - } else if (selectedCompanies === newCompanies) { - newColumns = [ - ...new Set([...newColumns, ...all_companies, "all_companies"]) - ]; - } else if (newCompanies < selectedCompanies) { - newColumns = [...newColumns.filter((c) => c !== "all_companies")]; - } - } - this.setState((prevState) => ({ - ...prevState, - selectedColumns: newColumns - })); - } - - handleFilterCriteriaChange(filterCriteria) { - const { extraColumns, term, order, orderDir, getEvents } = this.props; - const { eventFilters } = this.state; - let newEventFilters = {}; - if (filterCriteria) { - Object.entries(filterCriteria.criteria).forEach(([key, values]) => { - newEventFilters = { ...newEventFilters, [key]: values }; - }); - } - - this.setState( - (prevState) => ({ - ...prevState, - eventFilters: { ...defaultFilters, ...newEventFilters }, - enabledFilters: filterCriteria ? filterCriteria.enabled_filters : [], - selectedFilterCriteria: filterCriteria || null - }), - () => - getEvents( - term, - DEFAULT_CURRENT_PAGE, - DEFAULT_PER_PAGE, - order, - orderDir, - eventFilters, - extraColumns - ) - ); - } - - handleFilterCriteriaDelete(filterCriteriaId) { - const { - extraColumns, - term, - order, - orderDir, - getEvents, - deleteFilterCriteria - } = this.props; - const { eventFilters } = this.state; - deleteFilterCriteria(filterCriteriaId).then(() => - this.setState( - (prevState) => ({ - ...prevState, - eventFilters: { ...defaultFilters, orAndFilter: ALL_FILTER }, - enabledFilters: [], - selectedFilterCriteria: null - }), - () => - getEvents( - term, - DEFAULT_CURRENT_PAGE, - DEFAULT_PER_PAGE, - order, - orderDir, - eventFilters, - extraColumns - ) - ) - ); - } - - translateSortKey = (key) => { - switch (key) { - case "last_name": - return "name"; - case "created_by_company": - return "submitter_company"; - case "actions": - return "progress_flags"; - default: - break; - } - - return key; - }; - - render() { - const { - currentSummit, - events, - lastPage, - currentPage, - order, - orderDir, - totalEvents, - term, - bulkUpdateEvents - } = this.props; - const { - enabledFilters, - eventFilters, - selectedFilterCriteria, - selectedColumns, - showImportModal, - send_speaker_email, - importFile, - showImportFromMUXModal, - errors, - muxModalState: { mux_token_id, mux_token_secret, mux_email_to } - } = this.state; - - let columns = [ - { columnKey: "id", value: T.translate("general.id"), sortable: true }, - { - columnKey: "type", - value: T.translate("event_list.type"), - sortable: true, - // eslint-disable-next-line react/no-unstable-nested-components - editableField: (extraProps) => ( - ({ ...base, zIndex: 9999 }), - control: (base, state) => ({ - ...base, - zIndex: state.menuIsOpen ? HIGH_Z_INDEX : DEFAULT_Z_INDEX - }) - }} - // eslint-disable-next-line react/jsx-props-no-spreading - {...extraProps} - /> - ), - render: (e) => e.name - }, - { - columnKey: "title", - value: T.translate("event_list.title"), - sortable: true, - editableField: true - }, - { - columnKey: "selection_status", - value: T.translate("event_list.selection_status"), - sortable: true - } - ]; - - const table_options = { - sortCol: this.translateSortKey(order), - sortDir: orderDir, - className: "summit-event-list-table", - actions: { - edit: { onClick: this.handleEdit }, - delete: { onClick: this.handleDeleteEvent } - } - }; - - const selection_plans_ddl = buildNameIdDDL(currentSummit.selection_plans); - - const location_ddl = buildNameIdDDL(currentSummit.locations); - - const selection_status_ddl = [ - { label: "Pending", value: "pending" }, - { label: "Accepted", value: "accepted" }, - { label: "Rejected", value: "rejected" }, - { label: "Alternate", value: "alternate" } - ]; - - const track_ddl = buildNameIdDDL(currentSummit.tracks); - - const event_type_ddl = buildNameIdDDL(currentSummit.event_types); - - const level_ddl = [ - { label: "Beginner", value: "beginner" }, - { label: "Intermediate", value: "intermediate" }, - { label: "Advanced", value: "advanced" }, - { label: "N/A", value: "na" } - ]; - - const streaming_type_ddl = [ - { label: "LIVE", value: "LIVE" }, - { label: "VOD", value: "VOD" } - ]; - - const submission_source_ddl = [ - { label: "Admin", value: "Admin" }, - { label: "Submission", value: "Submission" } - ]; - - const filters_ddl = [ - { label: "Activity Type Capacity", value: "event_type_capacity_filter" }, - { label: "Selection Plan", value: "selection_plan_id_filter" }, - { label: "Activity Type", value: "event_type_id_filter" }, - { label: "Activity Category", value: "track_id_filter" }, - { label: "Level", value: "level_filter" }, - { label: "Etherpad URL", value: "etherpad_link" }, - { label: "Location", value: "location_id_filter" }, - { label: "Meeting URL", value: "meeting_url" }, - { label: "Progress Flag", value: "progress_flag" }, - { label: "Published Status", value: "published_filter" }, - { label: "Speakers", value: "speaker_id_filter" }, - { label: "Speakers Companies", value: "speaker_company" }, - { label: "Tags", value: "tags_filter" }, - { label: "Start Date", value: "start_date_filter" }, - { label: "End Date", value: "end_date_filter" }, - { label: "Duration", value: "duration_filter" }, - { label: "Speakers Count", value: "speakers_count_filter" }, - { label: "Submitter", value: "submitters" }, - { label: "Submitter Company", value: "submitter_company" }, - { label: "Selection Status", value: "selection_status_filter" }, - { label: "Stream URL", value: "streaming_url" }, - { label: "Streaming Type", value: "streaming_type" }, - { label: "Sponsors", value: "sponsor" }, - { label: "All Companies", value: "all_companies" }, - { - label: T.translate("event_list.submission_status"), - value: "submission_status_filter" - }, - { - label: T.translate("event_list.media_upload_with_type"), - value: "media_upload_with_type" - }, - { label: "Review Status", value: "review_status_filter" }, - { label: "Created", value: "created_filter" }, - { label: "Modified", value: "modified_filter" }, - { label: "Submission Source", value: "submission_source_filter" }, - { label: "Has RSVP?", value: "has_rsvp_filter" } - ]; - - const ddl_columns = [ - { - value: "event_type_capacity", - label: T.translate("event_list.event_type_capacity") - }, - { value: "speakers", label: T.translate("event_list.speakers") }, - { - value: "all_companies", - label: T.translate("event_list.all_companies") - }, - { - value: "created_by_fullname", - label: T.translate("event_list.created_by") - }, - { value: "duration", label: T.translate("event_list.duration") }, - { value: "end_date", label: T.translate("event_list.end_date") }, - { value: "published_date", label: T.translate("event_list.published") }, - { - value: "speaker_company", - label: T.translate("event_list.speaker_company") - }, - { - value: "speakers_count", - label: T.translate("event_list.speakers_count") - }, - { value: "sponsor", label: T.translate("event_list.sponsor") }, - { - value: "selection_plan", - label: T.translate("event_list.selection_plan") - }, - { value: "location", label: T.translate("event_list.location") }, - { value: "level", label: T.translate("event_list.level") }, - { value: "tags", label: T.translate("event_list.tags") }, - { - value: "streaming_url", - label: T.translate("event_list.streaming_url") - }, - { value: "meeting_url", label: T.translate("event_list.meeting_url") }, - { - value: "etherpad_link", - label: T.translate("event_list.etherpad_link") - }, - { - value: "streaming_type", - label: T.translate("event_list.streaming_type") - }, - { value: "start_date", label: T.translate("event_list.start_date") }, - { - value: "submitter_company", - label: T.translate("event_list.submitter_company") - }, - { value: "track", label: T.translate("event_list.track") }, - { value: "status", label: T.translate("event_list.submission_status") }, - { - value: "submission_source", - label: T.translate("event_list.submission_source") - }, - { - value: "progress_flags", - label: T.translate("event_list.progress_flags") - }, - { - value: "media_uploads", - label: T.translate("event_list.media_uploads") - }, - { - value: "review_status", - label: T.translate("event_list.review_status") - }, - { value: "created", label: T.translate("event_list.created") }, - { value: "modified", label: T.translate("event_list.modified") }, - { - value: "allow_feedback", - label: T.translate("event_list.allow_feedback") - }, - { - value: "to_record", - label: T.translate("event_list.to_record") - } - ]; - - const ddl_filterByEventTypeCapacity = [ - { - value: "allows_attendee_vote_filter", - label: T.translate("event_list.allows_attendee_vote_filter") - }, - { - value: "allows_location_filter", - label: T.translate("event_list.allows_location_filter") - }, - { - value: "allows_publishing_dates_filter", - label: T.translate("event_list.allows_publishing_dates_filter") - } - ]; - - const submission_status_ddl = [ - { - label: T.translate("event_list.submission_status_accepted"), - value: "Accepted" - }, - { - label: T.translate("event_list.submission_status_received"), - value: "Received" - }, - { - label: T.translate("event_list.submission_status_not_submitted"), - value: "NonReceived" - } - ]; - - const review_status_ddl = [ - { - label: T.translate("event_list.review_status_accepted"), - value: "Accepted" - }, - { - label: T.translate("event_list.review_status_in_review"), - value: "InReview" - }, - { - label: T.translate("event_list.review_status_no_submitted"), - value: "NotSubmitted" - }, - { - label: T.translate("event_list.review_status_published"), - value: "Published" - }, - { - label: T.translate("event_list.review_status_received"), - value: "Received" - }, - { - label: T.translate("event_list.review_status_rejected"), - value: "Rejected" - } - ]; - - const progress_flag_ddl = currentSummit.presentation_action_types.map( - (pf) => ({ value: pf.id, label: pf.label }) - ); - - const showColumns = fieldNames( - currentSummit.selection_plans, - currentSummit.tracks, - currentSummit.event_types, - currentSummit.id - ) - .filter( - (f) => - selectedColumns.includes(f.columnKey) && - !defaultColumns.includes(f.columnKey) - ) - .map((f2) => { - let c = { - columnKey: f2.columnKey, - value: T.translate(`event_list.${f2.value}`), - sortable: f2.sortable, - editable: !!editableColumns.includes(f2.editable), - customStyle: f2.customStyle - }; - // optional fields - if (f2.hasOwnProperty("title")) c = { ...c, title: f2.title }; - - if (f2.hasOwnProperty("render")) c = { ...c, render: f2.render }; - - if (f2.hasOwnProperty("editableField")) - c = { ...c, editableField: f2.editableField }; - - return c; - }); - - columns = [...columns, ...showColumns]; - - if (!currentSummit.id) return
; - - return ( -
-

- {" "} - {T.translate("event_list.event_list")} ({totalEvents}) -

-
-
- -
-
- - - - -
-
-
-
-
- this.handleOrAndFilter(filter)} - /> -
-
- -
-
-
-
- -
-
- -
-
- -
- {enabledFilters.includes("event_type_capacity_filter") && ( -
- -
- )} - {enabledFilters.includes("selection_plan_id_filter") && ( -
- -
- )} - {enabledFilters.includes("location_id_filter") && ( -
- -
- )} - {enabledFilters.includes("selection_status_filter") && ( -
- -
- )} - {enabledFilters.includes("published_filter") && ( -
- this.handleSetPublishedFilter(newValue)} - style={{ - width: "100%", - height: 40, - color: "#337ab7", - fontSize: "10px" - }} - /> -
- )} - {enabledFilters.includes("progress_flag") && ( -
- -
- )} - {enabledFilters.includes("track_id_filter") && ( -
- -
- )} - {enabledFilters.includes("event_type_id_filter") && ( -
- -
- )} - {enabledFilters.includes("speaker_id_filter") && ( -
- -
- )} - {enabledFilters.includes("speaker_company") && ( -
- -
- )} - {enabledFilters.includes("level_filter") && ( -
- -
- )} - {enabledFilters.includes("tags_filter") && ( -
- -
- )} - {enabledFilters.includes("sponsor") && ( -
-
- )} - {enabledFilters.includes("all_companies") && ( -
- ({ ...base, zIndex: 9999 }), - control: (base, state) => ({ - ...base, - zIndex: state.menuIsOpen ? HIGH_Z_INDEX : DEFAULT_Z_INDEX - }) - }} - /> -
- )} - {enabledFilters.includes("start_date_filter") && ( - <> -
- this.handleChangeDateFilter(ev, false)} - value={epochToMomentTimeZone( - eventFilters.start_date_filter[0], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
-
- this.handleChangeDateFilter(ev, true)} - value={epochToMomentTimeZone( - eventFilters.start_date_filter[1], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
- - )} - {enabledFilters.includes("end_date_filter") && ( - <> -
- this.handleChangeDateFilter(ev, false)} - value={epochToMomentTimeZone( - eventFilters.end_date_filter[0], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
-
- this.handleChangeDateFilter(ev, true)} - value={epochToMomentTimeZone( - eventFilters.end_date_filter[1], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
- - )} - {enabledFilters.includes("created_filter") && ( - <> -
- this.handleChangeDateFilter(ev, false)} - value={epochToMomentTimeZone( - eventFilters.created_filter[0], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
-
- this.handleChangeDateFilter(ev, true)} - value={epochToMomentTimeZone( - eventFilters.created_filter[1], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
- - )} - {enabledFilters.includes("modified_filter") && ( - <> -
- this.handleChangeDateFilter(ev, false)} - value={epochToMomentTimeZone( - eventFilters.modified_filter[0], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
-
- this.handleChangeDateFilter(ev, true)} - value={epochToMomentTimeZone( - eventFilters.modified_filter[1], - currentSummit.time_zone_id - )} - className="event-list-date-picker" - /> -
- - )} - {enabledFilters.includes("submitters") && ( -
- - member.hasOwnProperty("email") - ? `${member.first_name} ${member.last_name} (${member.email})` - : `${member.first_name} ${member.last_name} (${member.id})` - } - /> -
- )} - {enabledFilters.includes("submitter_company") && ( -
- -
- )} - {enabledFilters.includes("streaming_url") && ( -
- -
- )} - {enabledFilters.includes("meeting_url") && ( -
- -
- )} - {enabledFilters.includes("etherpad_link") && ( -
- -
- )} - {enabledFilters.includes("streaming_type") && ( -
- -
- )} - {enabledFilters.includes("submission_source_filter") && ( -
- -
- )} - {enabledFilters.includes("has_rsvp_filter") && ( -
- this.handleSetRSVPFilter(newValue)} - style={{ - width: "100%", - height: 40, - color: "#337ab7", - fontSize: "10px" - }} - /> -
- )} - {enabledFilters.includes("duration_filter") && ( -
- -
- )} - {enabledFilters.includes("speakers_count_filter") && ( -
- -
- )} - {enabledFilters.includes("submission_status_filter") && ( -
- -
- )} - {enabledFilters.includes("review_status_filter") && ( -
- -
- )} - {enabledFilters.includes("media_upload_with_type") && ( -
- -
- )} -
- -
- -
-
- - -
-
- - {events.length === 0 && ( -
{T.translate("event_list.no_events")}
- )} - - {events.length > 0 && ( -
-
- -
- -
- )} - - this.setState({ showImportModal: false })} - > - - {T.translate("event_list.import_events")} - - -
-
- Format must be the following: -
- (Minimal data required) -
- * title ( text )
- * description (text )
- * type_id (int) or type (string type name) -
- * track_id (int) or track ( string track name) -
- * speaker_emails ( list of email | delimited) [optional] -
- * speaker_fullnames ( list of full names | delimited) [optional] -
- * speaker_companies ( list of companies | delimited) [optional] -
- * speaker_titles ( list of titles | delimited) [optional] -
-
-
-
- this.setState({ importFile: file })} - handleRemove={() => this.setState({ importFile: null })} - className="dropzone col-md-6" - multiple={false} - accept=".csv" - /> -
-
-
- - -
-
-
-
- - - -
- - this.setState({ showImportFromMUXModal: false })} - > - - {T.translate("event_list.mux_import")} - - -
-
- -   -