Skip to content

Commit ca40b80

Browse files
committed
4905: add and implement initial fetch data hook, add helper for mapping ids
1 parent 9900e5e commit ca40b80

File tree

14 files changed

+164
-230
lines changed

14 files changed

+164
-230
lines changed

assets/admin/components/playlist-drag-and-drop/playlist-drag-and-drop.jsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,16 @@ function PlaylistDragAndDrop({
3333
keyPrefix: "playlist-drag-and-drop",
3434
});
3535
const [searchText, setSearchText] = useState();
36-
const [page, setPage] = useState(1);
3736
const [onlySharedPlaylists, setOnlySharedPlaylists] = useState(false);
3837

39-
const {
40-
data: {
41-
"hydra:member": playlists = null,
42-
"hydra:totalItems": totalItems = 0,
43-
} = {},
44-
} = useGetV2PlaylistsQuery({
45-
isCampaign: false,
46-
title: searchText,
47-
itemsPerPage: 30,
48-
order: { createdAt: "desc" },
49-
sharedWithMe: onlySharedPlaylists,
50-
});
38+
const { data: { "hydra:member": playlists = null } = {} } =
39+
useGetV2PlaylistsQuery({
40+
isCampaign: false,
41+
title: searchText,
42+
itemsPerPage: 30,
43+
order: { createdAt: "desc" },
44+
sharedWithMe: onlySharedPlaylists,
45+
});
5146

5247
/**
5348
* Fetches data for the multi component
@@ -94,9 +89,6 @@ function PlaylistDragAndDrop({
9489
onDropped={handleChange}
9590
name={name}
9691
data={selectedPlaylists}
97-
callback={() => setPage(page + 1)}
98-
label={t("more-playlists")}
99-
totalItems={totalItems}
10092
/>
10193
)}
10294
{selectedPlaylists?.length > 0 && (

assets/admin/components/playlist/campaign-form.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useTranslation } from "react-i18next";
22
import idFromUrl from "../util/helpers/id-from-url";
3-
import { useGetV2CampaignsByIdScreenGroupsQuery } from "../../../shared/redux/enhanced-api.ts";
3+
import { enhancedApi } from "../../../shared/redux/enhanced-api.ts";
44
import ContentBody from "../util/content-body/content-body";
55
import SelectScreensTable from "../util/multi-and-table/select-screens-table";
66
import SelectGroupsTable from "../util/multi-and-table/select-groups-table";
@@ -34,7 +34,9 @@ function CampaignForm({ campaign = null, handleInput }) {
3434
mappingId="screenGroup"
3535
handleChange={handleInput}
3636
name="groups"
37-
getSelectedMethod={useGetV2CampaignsByIdScreenGroupsQuery}
37+
getSelectedMethod={
38+
enhancedApi.endpoints.getV2CampaignsByIdScreenGroups.initiate
39+
}
3840
id={idFromUrl(campaign["@id"])}
3941
/>
4042
</ContentBody>

assets/admin/components/screen/screen-form.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import MultiSelectComponent from "../util/forms/multiselect-dropdown/multi-dropd
1313
import idFromUrl from "../util/helpers/id-from-url";
1414
import {
1515
useGetV2LayoutsQuery,
16-
useGetV2ScreensByIdScreenGroupsQuery,
16+
enhancedApi,
1717
} from "../../../shared/redux/enhanced-api.ts";
1818
import FormCheckbox from "../util/forms/form-checkbox";
1919
import Preview from "../preview/preview";
@@ -196,7 +196,9 @@ function ScreenForm({
196196
handleChange={handleInput}
197197
name="inScreenGroups"
198198
id={groupId}
199-
getSelectedMethod={useGetV2ScreensByIdScreenGroupsQuery}
199+
getSelectedMethod={
200+
enhancedApi.endpoints.getV2ScreensByIdScreenGroups.initiate
201+
}
200202
/>
201203
</ContentBody>
202204
<ContentBody>

assets/admin/components/screen/util/grid-generation-and-select.jsx

Lines changed: 23 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { useState, useEffect } from "react";
22
import { Tabs, Tab, Alert } from "react-bootstrap";
33
import Grid from "./grid";
44
import { useTranslation } from "react-i18next";
5-
import { useDispatch } from "react-redux";
65
import idFromUrl from "../../util/helpers/id-from-url";
76
import PlaylistDragAndDrop from "../../playlist-drag-and-drop/playlist-drag-and-drop";
87
import { enhancedApi } from "../../../../shared/redux/enhanced-api.ts";
8+
import useFetchDataHook from "../../util/fetch-data-hook.js";
9+
import mapToIds from "../../util/helpers/map-to-ids.js";
910
import "./grid.scss";
1011

1112
/**
@@ -27,11 +28,18 @@ function GridGenerationAndSelect({
2728
regions = [],
2829
}) {
2930
const { t } = useTranslation("common");
30-
const dispatch = useDispatch();
3131
const [selectedRegion, setSelectedRegion] = useState(
3232
regions.length > 0 ? regions[0]["@id"] : "",
3333
);
3434
const [selectedPlaylists, setSelectedPlaylists] = useState([]);
35+
const { data: playlistsAndRegions } = useFetchDataHook(
36+
enhancedApi.endpoints.getV2ScreensByIdRegionsAndRegionIdPlaylists.initiate,
37+
mapToIds(regions), // returns and array with ids to fetch for all ids
38+
{
39+
id: screenId, // screen id is the id
40+
},
41+
"regionId", // The key for the list of ids
42+
);
3543

3644
/**
3745
* @param {object} props The props
@@ -85,48 +93,22 @@ function GridGenerationAndSelect({
8593
return localSelectedPlaylists;
8694
}
8795

96+
// On received data, map to fit the components
97+
// We need region id to figure out which dropdown they should be placed in
98+
// and weight (order) for sorting.
8899
useEffect(() => {
89-
if (regions.length > 0) {
90-
const promises = [];
91-
regions.forEach(({ "@id": id }) => {
92-
promises.push(
93-
dispatch(
94-
enhancedApi.endpoints.getV2ScreensByIdRegionsAndRegionIdPlaylists.initiate(
95-
{
96-
id: screenId,
97-
regionId: idFromUrl(id),
98-
page: 1,
99-
itemsPerPage: 50,
100-
},
101-
),
102-
),
103-
);
104-
});
100+
if (playlistsAndRegions && playlistsAndRegions.length > 0) {
101+
const playlists = playlistsAndRegions
102+
.map(({ originalArgs: { regionId }, playlist, weight }) => ({
103+
...playlist,
104+
weight,
105+
region: regionId,
106+
}))
107+
.sort((a, b) => a.weight - b.weight);
105108

106-
Promise.allSettled(promises).then((results) => {
107-
let playlists = [];
108-
results.forEach(
109-
({
110-
value: {
111-
originalArgs: { regionId },
112-
data: { "hydra:member": promisedPlaylists = null } = {},
113-
},
114-
}) => {
115-
playlists = [
116-
...playlists,
117-
...promisedPlaylists.map(({ playlist, weight }) => ({
118-
...playlist,
119-
weight,
120-
region: regionId,
121-
})),
122-
];
123-
},
124-
);
125-
playlists = playlists.sort((a, b) => a.weight - b.weight);
126-
setSelectedPlaylists(playlists);
127-
});
109+
setSelectedPlaylists(playlists);
128110
}
129-
}, [regions]);
111+
}, [playlistsAndRegions]);
130112

131113
useEffect(() => {
132114
handleInput({ target: { value: selectedPlaylists, id: "playlists" } });

assets/admin/components/util/drag-and-drop-table/drag-and-drop-table.jsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { Row, Table, Col } from "react-bootstrap";
1+
import { Table } from "react-bootstrap";
22
import { DragDropContext, Draggable, Droppable } from "@hello-pangea/dnd";
33
import { useTranslation } from "react-i18next";
44
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
55
import { faGripVertical } from "@fortawesome/free-solid-svg-icons";
66
import TableHeader from "../table/table-header";
7-
import PaginationButton from "../forms/multiselect-dropdown/pagination-button";
87
import "./drag-and-drop-table.scss";
98

109
/**
@@ -14,20 +13,9 @@ import "./drag-and-drop-table.scss";
1413
* @param {string} props.name The id of the form element
1514
* @param {Function} props.onDropped Callback for when an item is dropped and
1615
* the list is reordered.
17-
* @param {Function} props.callback - The callback.
18-
* @param {string} props.label - The label.
19-
* @param {number} props.totalItems - Total data items.
2016
* @returns {object} The drag and drop table.
2117
*/
22-
function DragAndDropTable({
23-
columns,
24-
data,
25-
name,
26-
onDropped,
27-
label,
28-
callback,
29-
totalItems,
30-
}) {
18+
function DragAndDropTable({ columns, data, name, onDropped }) {
3119
const { t } = useTranslation("common", {
3220
keyPrefix: "drag-and-drop-table",
3321
});
@@ -156,13 +144,6 @@ function DragAndDropTable({
156144
</Droppable>
157145
</DragDropContext>
158146
</Table>
159-
<Row>
160-
<Col>
161-
{totalItems > data.length && (
162-
<PaginationButton label={label} callback={callback} showButton />
163-
)}
164-
</Col>
165-
</Row>
166147
<small id="aria-label-for-drag-and-drop">{t("help-text")}</small>
167148
</div>
168149
);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { useState, useEffect } from "react";
2+
import { useDispatch } from "react-redux";
3+
4+
function useFetchDataHook(apiCall, ids, params = {}, key = "id") {
5+
const [data, setData] = useState([]);
6+
const [loading, setLoading] = useState(true);
7+
const [error, setError] = useState(null);
8+
const dispatch = useDispatch();
9+
10+
useEffect(() => {
11+
if (!ids || ids.length === 0) return;
12+
13+
async function fetchItems() {
14+
setLoading(true);
15+
16+
try {
17+
let allItems = [];
18+
let fetchedItems = [];
19+
20+
for (const id of ids) {
21+
let page = 1;
22+
let totalItems = 1; // Will be overridden when we know the total amount.
23+
24+
while (fetchedItems.length < totalItems) {
25+
params[key] = id;
26+
const {
27+
data: {
28+
"hydra:member": items = [],
29+
"hydra:totalItems": hydraTotalItems = 0,
30+
},
31+
originalArgs,
32+
} = await dispatch(
33+
apiCall({
34+
...params,
35+
page,
36+
itemsPerPage: 10,
37+
}),
38+
);
39+
40+
// We don't like those darn infinite loops.
41+
if (items.length === 0) {
42+
break;
43+
}
44+
45+
// Sometimes we use the arguments from the api call
46+
const itemsWithOriginalArgs = items.map((item) => ({
47+
...item,
48+
originalArgs,
49+
}));
50+
51+
totalItems = hydraTotalItems;
52+
fetchedItems = fetchedItems.concat(itemsWithOriginalArgs);
53+
page++;
54+
}
55+
allItems = allItems.concat(fetchedItems);
56+
fetchedItems = [];
57+
}
58+
setData(allItems);
59+
} catch (err) {
60+
setError(err.message);
61+
} finally {
62+
setLoading(false);
63+
}
64+
}
65+
66+
fetchItems();
67+
}, [apiCall]); // Should params beadded here to rerun on change?
68+
69+
return { data, loading, error };
70+
}
71+
72+
export default useFetchDataHook;

assets/admin/components/util/forms/multiselect-dropdown/pagination-button.jsx

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import idFromUrl from "./id-from-url";
2+
3+
function mapToIds(array) {
4+
return array.map((item) => idFromUrl(item["@id"]));
5+
}
6+
7+
export default mapToIds;

0 commit comments

Comments
 (0)