Skip to content

Commit 4b593c7

Browse files
committed
Don't render series modal in action cells
This commit removes the series details modal component from every action cell in the table, and instead adds the component to the respective central page file (i.e. Series.tsx). The modal can then be opened through redux, similar to how it already works for events. The goal of these changes is to speed up table rendering. For a series table with 1000 rows, these changes sped up rendering by about 150ms in my local testing. This also fixes an issue where opening the events details modal would cause the entire events table to rerender. Opening the events details should be a bit smoother now.
1 parent 42668f5 commit 4b593c7

9 files changed

Lines changed: 133 additions & 64 deletions

File tree

src/components/events/Events.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ import {
3434
setShowActions,
3535
} from "../../slices/eventSlice";
3636
import EventDetailsModal from "./partials/modals/EventDetailsModal";
37-
import { showModal } from "../../selectors/eventDetailsSelectors";
3837
import { eventsLinks } from "./partials/EventsNavigation";
3938
import { Modal, ModalHandle } from "../shared/modals/Modal";
4039
import TableActionDropdown from "../shared/TableActionDropdown";
4140
import { resetTableProperties } from "../../slices/tableSlice";
41+
import SeriesDetailsModal from "./partials/modals/SeriesDetailsModal";
4242

4343
/**
4444
* This component renders the table view of events
@@ -47,8 +47,6 @@ const Events = () => {
4747
const { t } = useTranslation();
4848
const dispatch = useAppDispatch();
4949

50-
const displayEventDetailsModal = useAppSelector(state => showModal(state));
51-
5250
const [displayNavigation, setNavigation] = useState(false);
5351
const newEventModalRef = useRef<ModalHandle>(null);
5452
const startTaskModalRef = useRef<ModalHandle>(null);
@@ -230,9 +228,8 @@ const Events = () => {
230228
</div>
231229

232230
{/*Include table modal*/}
233-
{displayEventDetailsModal &&
234231
<EventDetailsModal />
235-
}
232+
<SeriesDetailsModal />
236233

237234
{/*Include table component*/}
238235
{/* <Table templateMap={eventsTemplateMap} resourceType="events" /> */}

src/components/events/Series.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ import { Modal, ModalHandle } from "../shared/modals/Modal";
2828
import { availableHotkeys } from "../../configs/hotkeysConfig";
2929
import TableActionDropdown from "../shared/TableActionDropdown";
3030
import { resetTableProperties } from "../../slices/tableSlice";
31+
import SeriesDetailsModal from "./partials/modals/SeriesDetailsModal";
3132

3233
/**
3334
* This component renders the table view of series
3435
*/
3536
const Series = () => {
3637
const { t } = useTranslation();
3738
const dispatch = useAppDispatch();
39+
3840
const [displayNavigation, setNavigation] = useState(false);
3941
const newSeriesModalRef = useRef<ModalHandle>(null);
4042
const deleteModalRef = useRef<ModalHandle>(null);
@@ -150,6 +152,10 @@ const Series = () => {
150152
{/* Include table view */}
151153
<h4>{t("TABLE_SUMMARY", { numberOfRows: series })}</h4>
152154
</div>
155+
156+
{/*Include table modal*/}
157+
<SeriesDetailsModal />
158+
153159
<Table templateMap={seriesTemplateMap} />
154160
</MainView>
155161
<Footer />

src/components/events/partials/EventActionCell.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,22 @@ import { useTranslation } from "react-i18next";
33
import EmbeddingCodeModal from "./modals/EmbeddingCodeModal";
44
import { getUserInformation } from "../../../selectors/userInfoSelectors";
55
import { hasAccess } from "../../../utils/utils";
6-
import SeriesDetailsModal from "./modals/SeriesDetailsModal";
76
import { EventDetailsPage } from "./modals/EventDetails";
87
import { useAppDispatch, useAppSelector } from "../../../store";
98
import {
109
fetchSeriesDetailsAcls,
1110
fetchSeriesDetailsMetadata,
1211
fetchSeriesDetailsTheme,
1312
fetchSeriesDetailsThemeNames,
13+
openModal as openSeriesModal,
1414
} from "../../../slices/seriesDetailsSlice";
1515
import { Event, deleteEvent } from "../../../slices/eventSlice";
1616
import { Tooltip } from "../../shared/Tooltip";
1717
import { openModal } from "../../../slices/eventDetailsSlice";
1818
import { ActionCellDelete } from "../../shared/ActionCellDelete";
1919
import { Modal, ModalHandle } from "../../shared/modals/Modal";
2020
import ButtonLikeAnchor from "../../shared/ButtonLikeAnchor";
21+
import { SeriesDetailsPage } from "./modals/SeriesDetails";
2122

2223
/**
2324
* This component renders the action cells of events in the table view
@@ -30,7 +31,6 @@ const EventActionCell = ({
3031
const { t } = useTranslation();
3132
const dispatch = useAppDispatch();
3233

33-
const seriesDetailsModalRef = useRef<ModalHandle>(null);
3434
const embeddingCodeModalRef = useRef<ModalHandle>(null);
3535

3636
const user = useAppSelector(state => getUserInformation(state));
@@ -48,7 +48,7 @@ const EventActionCell = ({
4848
};
4949

5050
const showSeriesDetailsModal = () => {
51-
seriesDetailsModalRef.current?.open();
51+
dispatch(openSeriesModal(SeriesDetailsPage.Metadata, row.series ? row.series : null));
5252
};
5353

5454
const onClickSeriesDetails = async () => {
@@ -82,14 +82,6 @@ const EventActionCell = ({
8282

8383
return (
8484
<>
85-
{!!row.series && (
86-
<SeriesDetailsModal
87-
seriesId={row.series.id}
88-
seriesTitle={row.series.title}
89-
modalRef={seriesDetailsModalRef}
90-
/>
91-
)}
92-
9385
{/* Open event details */}
9486
<ButtonLikeAnchor
9587
onClick={onClickEventDetails}

src/components/events/partials/SeriesActionsCell.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React, { useRef } from "react";
22
import ConfirmModal from "../../shared/ConfirmModal";
3-
import SeriesDetailsModal from "./modals/SeriesDetailsModal";
43
import {
54
fetchSeriesDetailsThemeNames,
65
fetchSeriesDetailsAcls,
76
fetchSeriesDetailsMetadata,
87
fetchSeriesDetailsTheme,
98
fetchSeriesDetailsTobira,
9+
openModal,
1010
} from "../../../slices/seriesDetailsSlice";
1111
import {
1212
getSeriesHasEvents,
@@ -20,6 +20,7 @@ import {
2020
} from "../../../slices/seriesSlice";
2121
import { ModalHandle } from "../../shared/modals/Modal";
2222
import ButtonLikeAnchor from "../../shared/ButtonLikeAnchor";
23+
import { SeriesDetailsPage } from "./modals/SeriesDetails";
2324

2425
/**
2526
* This component renders the action cells of series in the table view
@@ -32,7 +33,6 @@ const SeriesActionsCell = ({
3233
const dispatch = useAppDispatch();
3334

3435
const deleteConfirmationModalRef = useRef<ModalHandle>(null);
35-
const detailsModalRef = useRef<ModalHandle>(null);
3636

3737
const hasEvents = useAppSelector(state => getSeriesHasEvents(state));
3838
const deleteAllowed = useAppSelector(state => isSeriesDeleteAllowed(state));
@@ -60,7 +60,7 @@ const SeriesActionsCell = ({
6060
dispatch(fetchSeriesDetailsTobira(row.id)),
6161
]);
6262

63-
detailsModalRef.current?.open();
63+
dispatch(openModal(SeriesDetailsPage.Metadata, row));
6464
};
6565

6666
return (
@@ -73,12 +73,6 @@ const SeriesActionsCell = ({
7373
tooltipText={"EVENTS.SERIES.TABLE.TOOLTIP.DETAILS"}
7474
/>
7575

76-
<SeriesDetailsModal
77-
seriesId={row.id}
78-
seriesTitle={row.title}
79-
modalRef={detailsModalRef}
80-
/>
81-
8276
{/* delete series */}
8377
<ButtonLikeAnchor
8478
onClick={() => showDeleteConfirmation()}

src/components/events/partials/modals/EventDetailsModal.tsx

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next";
33
import EventDetails from "./EventDetails";
44
import { useAppDispatch, useAppSelector } from "../../../../store";
55
import { removeNotificationWizardForm } from "../../../../slices/notificationSlice";
6-
import { getModalEvent } from "../../../../selectors/eventDetailsSelectors";
6+
import { getModalEvent, showModal } from "../../../../selectors/eventDetailsSelectors";
77
import { setModalEvent, setShowModal } from "../../../../slices/eventDetailsSlice";
88
import { Modal } from "../../../shared/modals/Modal";
99
import { FormikProps } from "formik";
@@ -20,6 +20,7 @@ const EventDetailsModal = () => {
2020
const [policyChanged, setPolicyChanged] = useState(false);
2121
const formikRef = useRef<FormikProps<any>>(null);
2222

23+
const displayEventDetailsModal = useAppSelector(state => showModal(state));
2324
const event = useAppSelector(state => getModalEvent(state))!;
2425

2526
const hideModal = () => {
@@ -44,19 +45,23 @@ const EventDetailsModal = () => {
4445
};
4546

4647
return (
47-
<Modal
48-
open
49-
closeCallback={close}
50-
header={t("EVENTS.EVENTS.DETAILS.HEADER", { name: event.title })}
51-
classId="details-modal"
52-
>
53-
<EventDetails
54-
eventId={event.id}
55-
policyChanged={policyChanged}
56-
setPolicyChanged={(value) => setPolicyChanged(value)}
57-
formikRef={formikRef}
58-
/>
59-
</Modal>
48+
<>
49+
{displayEventDetailsModal &&
50+
<Modal
51+
open
52+
closeCallback={close}
53+
header={t("EVENTS.EVENTS.DETAILS.HEADER", { name: event.title })}
54+
classId="details-modal"
55+
>
56+
<EventDetails
57+
eventId={event.id}
58+
policyChanged={policyChanged}
59+
setPolicyChanged={(value) => setPolicyChanged(value)}
60+
formikRef={formikRef}
61+
/>
62+
</Modal>
63+
}
64+
</>
6065
);
6166
}
6267

src/components/events/partials/modals/SeriesDetails.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ import { removeNotificationWizardTobira } from "../../../../slices/notificationS
3030
import { ParseKeys } from "i18next";
3131
import { FormikProps } from "formik";
3232

33+
export enum SeriesDetailsPage {
34+
Metadata,
35+
ExtendedMetadata,
36+
AccessPolicy,
37+
Theme,
38+
Tobira,
39+
Statistics,
40+
}
41+
3342
/**
3443
* This component manages the tabs of the series details modal
3544
*/

src/components/events/partials/modals/SeriesDetailsModal.tsx

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,32 @@ import React, { useRef, useState } from "react";
22
import { useTranslation } from "react-i18next";
33
import SeriesDetails from "./SeriesDetails";
44
import { removeNotificationWizardForm } from "../../../../slices/notificationSlice";
5-
import { useAppDispatch } from "../../../../store";
6-
import { Modal, ModalHandle } from "../../../shared/modals/Modal";
5+
import { useAppDispatch, useAppSelector } from "../../../../store";
6+
import { Modal } from "../../../shared/modals/Modal";
77
import { confirmUnsaved } from "../../../../utils/utils";
88
import { FormikProps } from "formik";
9+
import { setModalSeries, setShowModal } from "../../../../slices/seriesDetailsSlice";
10+
import { getModalSeries, showModal } from "../../../../selectors/seriesDetailsSelectors";
911

1012
/**
1113
* This component renders the modal for displaying series details
1214
*/
13-
const SeriesDetailsModal = ({
14-
seriesTitle,
15-
seriesId,
16-
modalRef,
17-
}: {
18-
seriesTitle: string
19-
seriesId: string
20-
modalRef: React.RefObject<ModalHandle | null>
21-
}) => {
15+
const SeriesDetailsModal = () => {
2216
const { t } = useTranslation();
2317
const dispatch = useAppDispatch();
2418

2519
// tracks, whether the policies are different to the initial value
2620
const [policyChanged, setPolicyChanged] = useState(false);
2721
const formikRef = useRef<FormikProps<any>>(null);
2822

23+
const displaySeriesDetailsModal = useAppSelector(state => showModal(state));
24+
const series = useAppSelector(state => getModalSeries(state))!;
25+
26+
const hideModal = () => {
27+
dispatch(setModalSeries(null));
28+
dispatch(setShowModal(false));
29+
};
30+
2931
const close = () => {
3032
let isUnsavedChanges = false
3133
isUnsavedChanges = policyChanged
@@ -36,25 +38,30 @@ const SeriesDetailsModal = ({
3638
if (!isUnsavedChanges || confirmUnsaved(t)) {
3739
setPolicyChanged(false);
3840
dispatch(removeNotificationWizardForm());
41+
hideModal();
3942
return true;
4043
}
4144
return false;
4245
};
4346

4447
return (
45-
<Modal
46-
closeCallback={close}
47-
header={t("EVENTS.SERIES.DETAILS.HEADER", { name: seriesTitle })}
48-
classId="details-modal"
49-
ref={modalRef}
50-
>
51-
<SeriesDetails
52-
seriesId={seriesId}
53-
policyChanged={policyChanged}
54-
setPolicyChanged={(value) => setPolicyChanged(value)}
55-
formikRef={formikRef}
56-
/>
57-
</Modal>
48+
<>
49+
{displaySeriesDetailsModal &&
50+
<Modal
51+
open
52+
closeCallback={close}
53+
header={t("EVENTS.SERIES.DETAILS.HEADER", { name: series.title })}
54+
classId="details-modal"
55+
>
56+
<SeriesDetails
57+
seriesId={series.id}
58+
policyChanged={policyChanged}
59+
setPolicyChanged={(value) => setPolicyChanged(value)}
60+
formikRef={formikRef}
61+
/>
62+
</Modal>
63+
}
64+
</>
5865
);
5966
};
6067

src/selectors/seriesDetailsSelectors.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import { RootState } from "../store";
33
/**
44
* This file contains selectors regarding details of a certain series
55
*/
6+
/* selectors for modal */
7+
export const showModal = (state: RootState) => state.seriesDetails.modal.show;
8+
export const getModalPage = (state: RootState) => state.seriesDetails.modal.page;
9+
export const getModalSeries = (state: RootState) => state.seriesDetails.modal.series;
10+
611
export const getSeriesDetailsMetadata = (state: RootState) => state.seriesDetails.metadata;
712
export const getSeriesDetailsExtendedMetadata = (state: RootState) => state.seriesDetails.extendedMetadata;
813
export const getSeriesDetailsAcl = (state: RootState) => state.seriesDetails.acl;

0 commit comments

Comments
 (0)