1
- import { useState , useEffect , useRef , ChangeEvent , useCallback } from 'react' ;
2
- import { UNSAFE_Combobox , Button , ReadMore , TextField , Alert , ProgressBar } from '@navikt/ds-react' ;
3
- import AlertWithCloseButton from './chartbuilder/AlertWithCloseButton' ;
1
+ import { useState , useEffect , useRef , useCallback } from 'react' ;
2
+ import { UNSAFE_Combobox , Alert , ProgressBar } from '@navikt/ds-react' ;
4
3
5
4
interface Website {
6
5
id : string ;
@@ -13,6 +12,8 @@ interface WebsitePickerProps {
13
12
selectedWebsite : Website | null ;
14
13
onWebsiteChange : ( website : Website | null ) => void ;
15
14
onEventsLoad ?: ( events : string [ ] , autoParameters ?: { key : string ; type : 'string' } [ ] , maxDays ?: number ) => void ;
15
+ dateRangeInDays ?: number ; // Add this prop to accept date range from parent
16
+ shouldReload ?: boolean ; // Add flag to force reload
16
17
}
17
18
18
19
interface EventProperty {
@@ -44,17 +45,23 @@ const timeoutPromise = (ms: number) => {
44
45
} ) ;
45
46
} ;
46
47
47
- const WebsitePicker = ( { selectedWebsite, onWebsiteChange, onEventsLoad } : WebsitePickerProps ) => {
48
+ const WebsitePicker = ( {
49
+ selectedWebsite,
50
+ onWebsiteChange,
51
+ onEventsLoad,
52
+ dateRangeInDays : externalDateRange , // Accept date range from props
53
+ shouldReload = false // Flag to force reload
54
+ } : WebsitePickerProps ) => {
48
55
const [ websites , setWebsites ] = useState < Website [ ] > ( [ ] ) ;
49
56
const [ loadedWebsiteId , setLoadedWebsiteId ] = useState < string | null > ( null ) ;
50
- const [ maxDaysAvailable , setMaxDaysAvailable ] = useState < number > ( 30 ) ;
51
- const [ dateRangeInDays , setDateRangeInDays ] = useState < number > ( 3 ) ; // Changed from 7 to 3
52
- const [ tempDateRangeInDays , setTempDateRangeInDays ] = useState < number > ( 3 ) ; // Changed from 7 to 3
57
+ const [ setMaxDaysAvailable ] = useState < number > ( 30 ) ;
58
+ const [ dateRangeInDays , setDateRangeInDays ] = useState < number > ( externalDateRange || 3 ) ;
53
59
const apiCache = useRef < ApiCache > ( { } ) ;
54
60
const fetchInProgress = useRef < { [ key : string ] : boolean } > ( { } ) ;
55
- const websitesLoaded = useRef < boolean > ( false ) ; // New flag to prevent repeated fetching
56
- const [ dateChanged , setDateChanged ] = useState ( false ) ;
57
- const [ isLoading , setIsLoading ] = useState < boolean > ( false ) ;
61
+ const websitesLoaded = useRef < boolean > ( false ) ;
62
+ const prevExternalDateRange = useRef < number > ( externalDateRange || 3 ) ;
63
+ const prevShouldReload = useRef < boolean > ( shouldReload ) ;
64
+
58
65
// @ts -ignore
59
66
const [ isInitialLoading , setIsInitialLoading ] = useState < boolean > ( true ) ;
60
67
const [ error , setError ] = useState < string | null > ( null ) ;
@@ -63,13 +70,11 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
63
70
64
71
const handleLoadingState = useCallback ( ( loading : boolean ) => {
65
72
if ( loading ) {
66
- setIsLoading ( true ) ;
67
73
loadingTimerRef . current = window . setTimeout ( ( ) => {
68
74
setShowLoading ( true ) ;
69
75
} , 600 ) ;
70
76
} else {
71
77
// Clear both loading states
72
- setIsLoading ( false ) ;
73
78
setShowLoading ( false ) ;
74
79
75
80
// Clear any pending timers
@@ -90,7 +95,7 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
90
95
} , [ ] ) ;
91
96
92
97
// @ts -ignore
93
- const fetchEventNames = useCallback ( async ( websiteId : string , forceFresh = false ) => {
98
+ const fetchEventNames = useCallback ( async ( websiteId : string , forceFresh = false , daysToFetch = dateRangeInDays ) => {
94
99
if ( fetchInProgress . current [ websiteId ] ) return ;
95
100
96
101
fetchInProgress . current [ websiteId ] = true ;
@@ -116,16 +121,17 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
116
121
const endDate = new Date ( dateRange . maxdate ) ;
117
122
const startDate = new Date ( dateRange . mindate ) ;
118
123
const totalDays = Math . floor ( ( endDate . getTime ( ) - startDate . getTime ( ) ) / ( 1000 * 60 * 60 * 24 ) ) ;
119
- setMaxDaysAvailable ( totalDays ) ;
120
124
121
- // Always get fresh properties when date range changes
125
+ // Use the daysToFetch parameter instead of the state variable
122
126
const calculatedEndDate = new Date ( dateRange . maxdate ) ;
123
127
const calculatedStartDate = new Date ( calculatedEndDate ) ;
124
- calculatedStartDate . setDate ( calculatedStartDate . getDate ( ) - dateRangeInDays ) ;
128
+ calculatedStartDate . setDate ( calculatedStartDate . getDate ( ) - daysToFetch ) ;
125
129
126
130
const startAt = calculatedStartDate . getTime ( ) ;
127
131
const endAt = calculatedEndDate . getTime ( ) ;
128
132
133
+ console . log ( `Fetching data for ${ daysToFetch } days from ${ new Date ( startAt ) . toLocaleDateString ( ) } to ${ new Date ( endAt ) . toLocaleDateString ( ) } ` ) ;
134
+
129
135
// Add timeout to properties fetch
130
136
const propertiesResponse = await Promise . race ( [
131
137
fetch (
@@ -136,6 +142,8 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
136
142
] ) ; // @ts -ignore
137
143
const properties : EventProperty [ ] = await propertiesResponse . json ( ) ;
138
144
145
+ console . log ( `Fetched ${ properties . length } properties from the API` ) ;
146
+
139
147
// Process events and parameters
140
148
const eventMap = new Map < string , string [ ] > ( ) ;
141
149
properties . forEach ( prop => {
@@ -158,6 +166,8 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
158
166
} ) ;
159
167
} ) ;
160
168
169
+ console . log ( `Found ${ uniqueEventNames . length } unique events and ${ paramsByEvent . length } parameters` ) ;
170
+
161
171
if ( onEventsLoad ) {
162
172
onEventsLoad ( uniqueEventNames , paramsByEvent , totalDays ) ;
163
173
}
@@ -176,9 +186,8 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
176
186
handleLoadingState ( false ) ;
177
187
} finally {
178
188
fetchInProgress . current [ websiteId ] = false ;
179
- // Removed handleLoadingState(false) from here
180
189
}
181
- } , [ dateRangeInDays , onEventsLoad , setMaxDaysAvailable , handleLoadingState ] ) ;
190
+ } , [ onEventsLoad , setMaxDaysAvailable , handleLoadingState ] ) ;
182
191
183
192
useEffect ( ( ) => {
184
193
if ( websitesLoaded . current ) {
@@ -224,33 +233,40 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
224
233
if ( selectedWebsite && selectedWebsite . id !== loadedWebsiteId && onEventsLoad ) {
225
234
// Clear cache when website changes
226
235
apiCache . current = { } ;
227
- fetchEventNames ( selectedWebsite . id , true )
236
+ fetchEventNames ( selectedWebsite . id , true , dateRangeInDays )
228
237
. finally ( ( ) => {
229
238
setLoadedWebsiteId ( selectedWebsite . id ) ;
230
239
} ) ;
231
240
}
232
- } , [ selectedWebsite ?. id , loadedWebsiteId , onEventsLoad , fetchEventNames ] ) ;
241
+ } , [ selectedWebsite ?. id , loadedWebsiteId , onEventsLoad , fetchEventNames , dateRangeInDays ] ) ;
233
242
234
- // Wrap handleDateRangeChange in useCallback
235
- const handleDateRangeChange = useCallback ( ( ) => {
236
- if ( tempDateRangeInDays < 1 ) {
237
- setTempDateRangeInDays ( 1 ) ;
238
- setDateRangeInDays ( 1 ) ;
239
- } else if ( tempDateRangeInDays > maxDaysAvailable && maxDaysAvailable > 0 ) {
240
- setTempDateRangeInDays ( maxDaysAvailable ) ;
241
- setDateRangeInDays ( maxDaysAvailable ) ;
242
- } else {
243
- setDateRangeInDays ( tempDateRangeInDays ) ;
244
- }
245
-
246
- // If we have a selected website, refresh the data with the new date range
247
- if ( selectedWebsite ) {
248
- // Clear cache and fetch fresh data when changing days
243
+ // Combine the reload effects to avoid loops
244
+ useEffect ( ( ) => {
245
+ // Only proceed if we have a selected website
246
+ if ( ! selectedWebsite ) return ;
247
+
248
+ const dateRangeChanged = externalDateRange !== prevExternalDateRange . current ;
249
+ const reloadFlagChanged = shouldReload !== prevShouldReload . current ;
250
+
251
+ // Update the refs to track current values
252
+ prevExternalDateRange . current = externalDateRange || 3 ;
253
+ prevShouldReload . current = shouldReload ;
254
+
255
+ // Only reload if something actually changed
256
+ if ( dateRangeChanged || reloadFlagChanged ) {
257
+ console . log ( `Reload triggered - dateRange: ${ dateRangeChanged } , reloadFlag: ${ reloadFlagChanged } ` ) ;
258
+
259
+ if ( dateRangeChanged ) {
260
+ // Update the internal state
261
+ setDateRangeInDays ( externalDateRange || 3 ) ;
262
+ }
263
+
264
+ // Clear cache and force a fresh fetch
249
265
apiCache . current [ selectedWebsite . id ] = { } ;
250
- fetchEventNames ( selectedWebsite . id , true ) ;
251
- setDateChanged ( true ) ; // Set dateChanged to true after updating
266
+ fetchEventNames ( selectedWebsite . id , true , externalDateRange || dateRangeInDays ) ;
252
267
}
253
- } , [ tempDateRangeInDays , maxDaysAvailable , selectedWebsite , fetchEventNames , setDateRangeInDays , setTempDateRangeInDays ] ) ;
268
+ } , [ externalDateRange , shouldReload , selectedWebsite , fetchEventNames , dateRangeInDays ] ) ;
269
+
254
270
255
271
return (
256
272
< div className = "space-y-4" >
@@ -279,52 +295,7 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
279
295
clearButton
280
296
/>
281
297
282
- { selectedWebsite && (
283
- < div className = "mt-4" >
284
- < ReadMore size = "small" header = "Innstillinger for hendelsesinnlasting" >
285
-
286
- < div className = "space-y-4 mt-2" >
287
- < div className = "text-sm" >
288
- Endre tidsperioden for å hente hendelser og detaljer fra en tidligere dato.
289
- { maxDaysAvailable > 0 &&
290
- ` Du har tilgang til data fra de siste ${ maxDaysAvailable } dagene.`
291
- }
292
- </ div >
293
-
294
- < div className = "flex items-end gap-2" >
295
- < TextField
296
- label = "Antall dager"
297
- type = "number"
298
- size = "small"
299
- value = { tempDateRangeInDays }
300
- onChange = { ( e : ChangeEvent < HTMLInputElement > ) => {
301
- const val = parseInt ( e . target . value , 10 ) ;
302
- setTempDateRangeInDays ( isNaN ( val ) ? 1 : val ) ;
303
- } }
304
- min = { 1 }
305
- max = { maxDaysAvailable }
306
- className = "w-24"
307
- />
308
- < Button
309
- variant = "secondary"
310
- size = "small"
311
- onClick = { handleDateRangeChange }
312
- className = "h-[33px]"
313
- >
314
- Oppdater
315
- </ Button >
316
- </ div >
317
-
318
- { dateChanged && ! isLoading && (
319
- < AlertWithCloseButton variant = "success" >
320
- Tilgjengelige hendelser og parametere ble lastet inn
321
- </ AlertWithCloseButton >
322
- ) }
323
-
324
- </ div >
325
- </ ReadMore >
326
- </ div >
327
- ) }
298
+ { /* The ReadMore component has been moved to EventParameterSelector */ }
328
299
</ div >
329
300
{ showLoading && (
330
301
< div className = "space-y-2" >
@@ -337,7 +308,6 @@ const WebsitePicker = ({ selectedWebsite, onWebsiteChange, onEventsLoad }: Websi
337
308
seconds : 30 ,
338
309
onTimeout : ( ) => {
339
310
setError ( 'Forespørselen tok for lang tid. Prøv igjen senere.' ) ;
340
- setIsLoading ( false ) ;
341
311
}
342
312
} }
343
313
aria-label = "Laster inn data"
0 commit comments