Skip to content

Commit bebc40a

Browse files
committed
Reduce duplicate code in filter cell
Some cells in a table set a filter when their content is clicked. This adds a component for these types of cells. Also removes an unused component.
1 parent 69f1796 commit bebc40a

File tree

10 files changed

+155
-153
lines changed

10 files changed

+155
-153
lines changed

src/components/events/partials/EventsDateCell.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import { useTranslation } from "react-i18next";
2-
import { editFilterValue } from "../../../slices/tableFilterSlice";
3-
import React from "react";
41
import { loadEventsIntoTable } from "../../../thunks/tableThunks";
52
import { fetchEvents } from "../../../slices/eventSlice";
63
import { Event } from "../../../slices/eventSlice";

src/components/events/partials/EventsLocationCell.tsx

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
import { getFilters } from "../../../selectors/tableFilterSelectors";
2-
import { editFilterValue } from "../../../slices/tableFilterSlice";
31
import { loadEventsIntoTable } from "../../../thunks/tableThunks";
4-
import { useAppDispatch, useAppSelector } from "../../../store";
52
import { fetchEvents } from "../../../slices/eventSlice";
63
import { Event } from "../../../slices/eventSlice";
7-
import { IconButton } from "../../shared/IconButton";
4+
import FilterCell from "../../shared/FilterCell";
85

96
/**
107
* This component renders the location cells of events in the table view
@@ -14,29 +11,18 @@ const EventsLocationCell = ({
1411
}: {
1512
row: Event
1613
}) => {
17-
const dispatch = useAppDispatch();
18-
19-
const filterMap = useAppSelector(state => getFilters(state, "events"));
20-
21-
// Filter with value of current cell
22-
const addFilter = (location: string) => {
23-
const filter = filterMap.find(({ name }) => name === "location");
24-
if (filter) {
25-
dispatch(editFilterValue({ filterName: filter.name, value: location, resource: "events" }));
26-
dispatch(fetchEvents());
27-
dispatch(loadEventsIntoTable());
28-
}
29-
};
30-
3114
return (
32-
// Link template for location of event
33-
<IconButton
34-
callback={() => addFilter(row.location)}
35-
iconClassname={"crosslink"}
36-
tooltipText={"EVENTS.EVENTS.TABLE.TOOLTIP.LOCATION"}
37-
>
38-
{row.location}
39-
</IconButton>
15+
<FilterCell
16+
resource={"events"}
17+
filterName={"location"}
18+
filterItems={[{
19+
filterValue: row.location,
20+
children: row.location,
21+
cellTooltipText: "EVENTS.EVENTS.TABLE.TOOLTIP.LOCATION",
22+
}]}
23+
fetchResource={fetchEvents}
24+
loadResourceIntoTable={loadEventsIntoTable}
25+
/>
4026
);
4127
};
4228

src/components/events/partials/EventsPresentersCell.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { loadEventsIntoTable } from "../../../thunks/tableThunks";
22
import { fetchEvents } from "../../../slices/eventSlice";
33
import { Event } from "../../../slices/eventSlice";
4-
import MultiValueCell from "../../shared/MultiValueCell";
4+
import FilterCell from "../../shared/FilterCell";
55

66
/**
77
* This component renders the presenters cells of events in the table view
@@ -12,13 +12,16 @@ const EventsPresentersCell = ({
1212
row: Event
1313
}) => {
1414
return (
15-
<MultiValueCell
16-
resource="events"
17-
values={row.presenters}
18-
filterName="presentersBibliographic"
15+
<FilterCell
16+
resource={"events"}
17+
filterName={"presentersBibliographic"}
18+
filterItems={row.presenters.map(presenter => ({
19+
filterValue: presenter,
20+
children: presenter,
21+
cellTooltipText: "EVENTS.EVENTS.TABLE.TOOLTIP.PRESENTER",
22+
}))}
1923
fetchResource={fetchEvents}
2024
loadResourceIntoTable={loadEventsIntoTable}
21-
tooltipText="EVENTS.EVENTS.TABLE.TOOLTIP.PRESENTER"
2225
/>
2326
);
2427
};

src/components/events/partials/EventsSeriesCell.tsx

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
import { getFilters } from "../../../selectors/tableFilterSelectors";
2-
import { editFilterValue } from "../../../slices/tableFilterSlice";
31
import { loadEventsIntoTable } from "../../../thunks/tableThunks";
4-
import { useAppDispatch, useAppSelector } from "../../../store";
52
import { fetchEvents } from "../../../slices/eventSlice";
63
import { Event } from "../../../slices/eventSlice";
7-
import { IconButton } from "../../shared/IconButton";
4+
import FilterCell from "../../shared/FilterCell";
85

96
/**
107
* This component renders the series cells of events in the table view
@@ -14,33 +11,19 @@ const EventsSeriesCell = ({
1411
}: {
1512
row: Event
1613
}) => {
17-
const dispatch = useAppDispatch();
18-
19-
const filterMap = useAppSelector(state => getFilters(state, "events"));
20-
21-
// Filter with value of current cell
22-
const addFilter = async (seriesId: string) => {
23-
const filter = filterMap.find(({ name }) => name === "series");
24-
if (filter) {
25-
dispatch(editFilterValue({ filterName: filter.name, value: seriesId, resource: "events" }));
26-
await dispatch(fetchEvents());
27-
dispatch(loadEventsIntoTable());
28-
}
29-
};
30-
3114
return (
3215
row.series ? (
33-
// Link template for series of event
34-
<IconButton
35-
callback={() => row.series
36-
? addFilter(row.series.id)
37-
: console.error("Tried to sort by a series, but the series did not exist.")
38-
}
39-
iconClassname={"crosslink"}
40-
tooltipText={"EVENTS.EVENTS.TABLE.TOOLTIP.SERIES"}
41-
>
42-
{row.series.title}
43-
</IconButton>
16+
<FilterCell
17+
resource={"events"}
18+
filterName={"series"}
19+
filterItems={[{
20+
filterValue: row.series.id,
21+
children: row.series.title,
22+
cellTooltipText: "EVENTS.EVENTS.TABLE.TOOLTIP.SERIES",
23+
}]}
24+
fetchResource={fetchEvents}
25+
loadResourceIntoTable={loadEventsIntoTable}
26+
/>
4427
)
4528
: <></>
4629
);

src/components/events/partials/EventsTechnicalDateCell.tsx

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/components/events/partials/SeriesTitleCell.tsx

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useNavigate } from "react-router";
44
import { useAppDispatch } from "../../../store";
55
import { Tooltip } from "../../shared/Tooltip";
66
import { Series } from "../../../slices/seriesSlice";
7+
import RedirectCell from "../../shared/RedirectCell";
78

89
/**
910
* This component renders the title cells of series in the table view
@@ -13,25 +14,15 @@ const SeriesTitleCell = ({
1314
}: {
1415
row: Series
1516
}) => {
16-
const { t } = useTranslation();
17-
const dispatch = useAppDispatch();
18-
const navigate = useNavigate();
19-
20-
const redirectToEvents = async (seriesId: string) => {
21-
// set the series filter value of events to series title
22-
await dispatch(setSpecificEventFilter({ filter: "series", filterValue: seriesId }));
23-
navigate("/events/events");
24-
};
25-
2617
return (
27-
<Tooltip title={t("EVENTS.SERIES.TABLE.TOOLTIP.SERIES")}>
28-
<button
29-
className="button-like-anchor crosslink"
30-
onClick={() => redirectToEvents(row.id)}
31-
>
32-
{row.title}
33-
</button>
34-
</Tooltip>
18+
<RedirectCell
19+
path={"/events/events"}
20+
filterName={"series"}
21+
filterValue={row.id}
22+
tooltipText={"EVENTS.SERIES.TABLE.TOOLTIP.SERIES"}
23+
>
24+
{row.title}
25+
</RedirectCell>
3526
);
3627
};
3728

src/components/recordings/partials/RecordingsNameCell.tsx

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import { useTranslation } from "react-i18next";
2-
import { useNavigate } from "react-router";
3-
import { setSpecificEventFilter } from "../../../slices/tableFilterSlice";
4-
import { useAppDispatch } from "../../../store";
5-
import { Tooltip } from "../../shared/Tooltip";
61
import { Recording } from "../../../slices/recordingSlice";
2+
import RedirectCell from "../../shared/RedirectCell";
73

84
/**
95
* This component renders the name cells of recordings in the table view
@@ -13,25 +9,15 @@ const RecordingsNameCell = ({
139
}: {
1410
row: Recording
1511
}) => {
16-
const { t } = useTranslation();
17-
const dispatch = useAppDispatch();
18-
const navigate = useNavigate();
19-
20-
const redirectToEvents = async (locationName: string) => {
21-
// set the location filter value of events to location name
22-
await dispatch(setSpecificEventFilter({ filter: "location", filterValue: locationName }));
23-
navigate("/events/events");
24-
};
25-
2612
return (
27-
<Tooltip title={t("RECORDINGS.RECORDINGS.TABLE.TOOLTIP.NAME")}>
28-
<button
29-
className="button-like-anchor crosslink"
30-
onClick={() => redirectToEvents(row.name)}
31-
>
32-
{row.name}
33-
</button>
34-
</Tooltip>
13+
<RedirectCell
14+
path={"/events/events"}
15+
filterName={"location"}
16+
filterValue={row.name}
17+
tooltipText={"RECORDINGS.RECORDINGS.TABLE.TOOLTIP.NAME"}
18+
>
19+
{row.name}
20+
</RedirectCell>
3521
);
3622
};
3723

src/components/shared/FilterCell.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { getFilters } from "../../selectors/tableFilterSelectors";
2+
import { editFilterValue } from "../../slices/tableFilterSlice";
3+
import { AppThunk, useAppDispatch, useAppSelector } from "../../store";
4+
import { IconButton } from "./IconButton";
5+
import { Resource } from "../../slices/tableSlice";
6+
import { AsyncThunk } from "@reduxjs/toolkit";
7+
import { ParseKeys } from "i18next";
8+
import { ReactNode } from "react";
9+
10+
/**
11+
* This component renders a table cell with one or more clickable items
12+
* where clicking the items will set a filter
13+
*/
14+
const FilterCell = ({
15+
resource,
16+
filterName,
17+
filterItems,
18+
fetchResource,
19+
loadResourceIntoTable,
20+
}: {
21+
resource: Resource
22+
filterName: string
23+
filterItems: {
24+
filterValue: string
25+
children: ReactNode
26+
cellTooltipText?: ParseKeys
27+
}[]
28+
fetchResource: AsyncThunk<unknown, void, any>
29+
loadResourceIntoTable: () => AppThunk,
30+
}) => {
31+
const dispatch = useAppDispatch();
32+
33+
const filterMap = useAppSelector(state => getFilters(state, resource));
34+
35+
// Filter with value of current cell
36+
const addFilter = async (filterValue: string) => {
37+
const filter = filterMap.find(({ name }) => name === filterName);
38+
if (filter) {
39+
dispatch(editFilterValue({ filterName: filter.name, value: filterValue, resource }));
40+
await dispatch(fetchResource());
41+
dispatch(loadResourceIntoTable());
42+
}
43+
};
44+
45+
return (
46+
// Link template for location of event
47+
filterItems.map((item, key) => (
48+
<IconButton
49+
key={key}
50+
callback={() => addFilter(item.filterValue)}
51+
iconClassname={"crosslink"}
52+
tooltipText={item.cellTooltipText}
53+
>
54+
{item.children}
55+
</IconButton>
56+
))
57+
);
58+
};
59+
60+
export default FilterCell;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { useNavigate } from "react-router";
2+
import { setSpecificEventFilter } from "../../slices/tableFilterSlice";
3+
import { useAppDispatch } from "../../store";
4+
import ButtonLikeAnchor from "./ButtonLikeAnchor";
5+
import { ParseKeys } from "i18next";
6+
import { ReactNode } from "react";
7+
8+
/**
9+
* This component renders the name cells of recordings in the table view
10+
*/
11+
const RedirectCell = ({
12+
path,
13+
filterName,
14+
filterValue,
15+
tooltipText,
16+
children,
17+
}: {
18+
path: string
19+
filterName: string
20+
filterValue: string
21+
tooltipText?: ParseKeys
22+
children: ReactNode
23+
}) => {
24+
const dispatch = useAppDispatch();
25+
const navigate = useNavigate();
26+
27+
const redirectToResource = async (filterValue: string) => {
28+
// Set filter before redirecting
29+
await dispatch(setSpecificEventFilter({ filter: filterName, filterValue }));
30+
navigate(path);
31+
};
32+
33+
return (
34+
<ButtonLikeAnchor
35+
extraClassName="crosslink"
36+
tooltipText={tooltipText}
37+
onClick={() => redirectToResource(filterValue)}
38+
>
39+
{children}
40+
</ButtonLikeAnchor>
41+
);
42+
};
43+
44+
export default RedirectCell;

0 commit comments

Comments
 (0)