@@ -2,10 +2,11 @@ import { useState, useEffect } from "react";
2
2
import { Tabs , Tab , Alert } from "react-bootstrap" ;
3
3
import Grid from "./grid" ;
4
4
import { useTranslation } from "react-i18next" ;
5
- import { useDispatch } from "react-redux" ;
6
5
import idFromUrl from "../../util/helpers/id-from-url" ;
7
6
import PlaylistDragAndDrop from "../../playlist-drag-and-drop/playlist-drag-and-drop" ;
8
7
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" ;
9
10
import "./grid.scss" ;
10
11
11
12
/**
@@ -27,11 +28,18 @@ function GridGenerationAndSelect({
27
28
regions = [ ] ,
28
29
} ) {
29
30
const { t } = useTranslation ( "common" ) ;
30
- const dispatch = useDispatch ( ) ;
31
31
const [ selectedRegion , setSelectedRegion ] = useState (
32
32
regions . length > 0 ? regions [ 0 ] [ "@id" ] : "" ,
33
33
) ;
34
34
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
+ ) ;
35
43
36
44
/**
37
45
* @param {object } props The props
@@ -40,93 +48,72 @@ function GridGenerationAndSelect({
40
48
* @returns {Array } Mapped data
41
49
*/
42
50
function mapData ( { value : inputPlaylists , id } ) {
43
- // Map to add region id to incoming data.
44
- const localTarget = inputPlaylists . map ( ( playlist ) => {
45
- return {
46
- region : idFromUrl ( id ) ,
47
- ...playlist ,
48
- } ;
49
- } ) ;
50
- // A copy, to be able to remove items.
51
- let selectedPlaylistsCopy = [ ...selectedPlaylists ] ;
52
-
53
- // The following is used to determine if something has been removed from a list.
54
- const regionPlaylists = selectedPlaylists
55
- . filter ( ( { region } ) => region === id )
56
- . map ( ( { region } ) => region ) ;
57
-
58
- const selectedWithoutRegion = [ ] ;
59
-
60
- // Checks if an element has been removed from the list
61
- if ( inputPlaylists . length < regionPlaylists . length ) {
62
- selectedPlaylists . forEach ( ( playlist ) => {
63
- if ( ! regionPlaylists . includes ( playlist . region ) ) {
64
- selectedWithoutRegion . push ( playlist ) ;
65
- }
66
- } ) ;
67
- // If a playlist is removed from a list, all the playlists in that region will be removed.
68
- selectedPlaylistsCopy = selectedWithoutRegion ;
51
+ // Region id form id url
52
+ const region = idFromUrl ( id ) ;
53
+
54
+ // Add the region id to each inputted playlist
55
+ const playlistsWithRegion = inputPlaylists . map ( ( playlist ) => ( {
56
+ region,
57
+ ...playlist ,
58
+ } ) ) ;
59
+
60
+ // Get the playlists that belong the same region from the selected playlists
61
+ const existingRegionPlaylists = selectedPlaylists . filter (
62
+ ( playlist ) => playlist . region === region ,
63
+ ) ;
64
+
65
+ // Check if any playlists from the existing region playlists are missing from
66
+ // The inputted playlists if so, they are removed from the list
67
+ const removedPlaylists = existingRegionPlaylists . some (
68
+ ( { "@id" : existingId } ) =>
69
+ ! inputPlaylists . find (
70
+ ( { "@id" : incomingId } ) => incomingId === existingId ,
71
+ ) ,
72
+ ) ;
73
+
74
+ // Start with the existing selected playlists
75
+ let updatedRegionPlaylists = [ ...selectedPlaylists ] ;
76
+
77
+ // If any playlists were removed, filter out all playlists for this region
78
+ if ( removedPlaylists ) {
79
+ updatedRegionPlaylists = selectedPlaylists . filter (
80
+ ( playlist ) => playlist . region !== region ,
81
+ ) ;
69
82
}
70
83
71
- // Removes duplicates.
72
- const localSelectedPlaylists = [
73
- ...localTarget ,
74
- ...selectedPlaylistsCopy ,
84
+ // Merge the updated region playlists with the input playlists,
85
+ // and remove any duplicate region and id combinations
86
+ const mappedData = [
87
+ ...playlistsWithRegion ,
88
+ ...updatedRegionPlaylists ,
75
89
] . filter (
76
90
( playlist , index , self ) =>
77
91
index ===
78
92
self . findIndex (
79
- ( secondPlaylist ) =>
80
- secondPlaylist [ "@id" ] === playlist [ "@id" ] &&
81
- secondPlaylist . region === playlist . region ,
93
+ ( { region, "@id" : playlistId } ) =>
94
+ playlistId === playlist [ "@id" ] && region === playlist . region ,
82
95
) ,
83
96
) ;
84
97
85
- return localSelectedPlaylists ;
98
+ return mappedData ;
86
99
}
87
100
101
+ // On received data, map to fit the components
102
+ // We need region id to figure out which dropdown they should be placed in
103
+ // and weight (order) for sorting.
88
104
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
- } ) ;
105
-
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
- } ) ;
105
+ if ( playlistsAndRegions && playlistsAndRegions . length > 0 ) {
106
+ const playlists = playlistsAndRegions
107
+ . map ( ( { originalArgs : { regionId } , playlist, weight } ) => ( {
108
+ ...playlist ,
109
+ weight,
110
+ region : regionId ,
111
+ } ) )
112
+ . sort ( ( a , b ) => a . weight - b . weight ) ;
113
+
114
+ setSelectedPlaylists ( playlists ) ;
128
115
}
129
- } , [ regions ] ) ;
116
+ } , [ playlistsAndRegions ] ) ;
130
117
131
118
useEffect ( ( ) => {
132
119
handleInput ( { target : { value : selectedPlaylists , id : "playlists" } } ) ;
@@ -156,6 +143,7 @@ function GridGenerationAndSelect({
156
143
) ;
157
144
} ;
158
145
146
+ // If there are no regions, the components should not spend time rendering.
159
147
if ( regions ?. length === 0 ) return null ;
160
148
161
149
return (
@@ -171,37 +159,35 @@ function GridGenerationAndSelect({
171
159
</ div >
172
160
</ div >
173
161
< div className = "col-md-12" >
174
- < >
175
- < h3 className = "h5" > { t ( "screen-form.screen-region-playlists" ) } </ h3 >
176
- < Tabs
177
- defaultActiveKey = { regions [ 0 ] [ "@id" ] }
178
- id = "tabs"
179
- onSelect = { setSelectedRegion }
180
- className = "mb-3"
181
- >
182
- { regions . map ( ( { title, "@id" : id , type } ) => (
183
- < Tab eventKey = { id } key = { id } title = { title } >
184
- < PlaylistDragAndDrop
185
- id = "playlist_drag_and_drop"
186
- handleChange = { handleChange }
187
- removeFromList = { removeFromList }
188
- name = { id }
189
- regionIdForInitializeCallback = { id }
190
- screenId = { screenId }
191
- regionId = { idFromUrl ( id ) }
192
- selectedPlaylists = { selectedPlaylists . filter (
193
- ( { region } ) => region === idFromUrl ( id ) ,
194
- ) }
195
- />
196
- { type === "touch-buttons" && (
197
- < Alert key = "screen-form-touch-buttons" variant = "info" >
198
- { t ( "screen-form.touch-region-helptext" ) }
199
- </ Alert >
162
+ < h3 className = "h5" > { t ( "screen-form.screen-region-playlists" ) } </ h3 >
163
+ < Tabs
164
+ defaultActiveKey = { regions [ 0 ] [ "@id" ] }
165
+ id = "tabs"
166
+ onSelect = { setSelectedRegion }
167
+ className = "mb-3"
168
+ >
169
+ { regions . map ( ( { title, "@id" : id , type } ) => (
170
+ < Tab eventKey = { id } key = { id } title = { title } >
171
+ < PlaylistDragAndDrop
172
+ id = "playlist_drag_and_drop"
173
+ handleChange = { handleChange }
174
+ removeFromList = { removeFromList }
175
+ name = { id }
176
+ regionIdForInitializeCallback = { id }
177
+ screenId = { screenId }
178
+ regionId = { idFromUrl ( id ) }
179
+ selectedPlaylists = { selectedPlaylists . filter (
180
+ ( { region } ) => region === idFromUrl ( id ) ,
200
181
) }
201
- </ Tab >
202
- ) ) }
203
- </ Tabs >
204
- </ >
182
+ />
183
+ { type === "touch-buttons" && (
184
+ < Alert key = "screen-form-touch-buttons" variant = "info" >
185
+ { t ( "screen-form.touch-region-helptext" ) }
186
+ </ Alert >
187
+ ) }
188
+ </ Tab >
189
+ ) ) }
190
+ </ Tabs >
205
191
</ div >
206
192
</ >
207
193
) ;
0 commit comments