@@ -6,6 +6,7 @@ import { useSearchParams } from 'react-router-dom';
6
6
import {
7
7
filterMeetingData ,
8
8
getQueryString ,
9
+ isGoogleSheetData ,
9
10
loadMeetingData ,
10
11
mergeSettings ,
11
12
SettingsContext ,
@@ -24,7 +25,7 @@ import {
24
25
Title ,
25
26
} from './' ;
26
27
27
- import type { State } from '../types' ;
28
+ import type { JSONData , State } from '../types' ;
28
29
29
30
export default function TsmlUI ( {
30
31
google,
@@ -104,6 +105,20 @@ export default function TsmlUI({
104
105
105
106
const input = getQueryString ( settings ) ;
106
107
108
+ if ( timezone ) {
109
+ // check if timezone is valid
110
+ try {
111
+ Intl . DateTimeFormat ( undefined , { timeZone : timezone } ) ;
112
+ } catch ( e ) {
113
+ return setState ( state => ( {
114
+ ...state ,
115
+ error : `Timezone ${ timezone } is not valid. Please use one like Europe/Rome.` ,
116
+ filtering : false ,
117
+ loading : false ,
118
+ } ) ) ;
119
+ }
120
+ }
121
+
107
122
if ( ! src ) {
108
123
setState ( state => ( {
109
124
...state ,
@@ -112,60 +127,59 @@ export default function TsmlUI({
112
127
loading : false ,
113
128
} ) ) ;
114
129
} else {
115
- const sheetId = src . startsWith (
116
- 'https://docs.google.com/spreadsheets/d/'
117
- )
118
- ? src . split ( '/' ) [ 5 ]
119
- : undefined ;
120
-
121
- // google sheet
122
- if ( sheetId ) {
123
- if ( ! google ) {
124
- setState ( state => ( {
125
- ...state ,
126
- error : 'Configuration error: a Google API key is required.' ,
127
- filtering : false ,
128
- loading : false ,
129
- } ) ) ;
130
- }
131
- src = `https://sheets.googleapis.com/v4/spreadsheets/${ sheetId } /values/A1:ZZ?key=${ google } ` ;
132
- }
133
-
134
- // cache busting
135
- if ( src . endsWith ( '.json' ) && input . meeting ) {
136
- src = `${ src } ?${ new Date ( ) . getTime ( ) } ` ;
137
- }
130
+ const sheets : ( string | undefined ) [ ] = [ ] ;
131
+ Promise . all (
132
+ src . split ( ',' ) . map ( src => {
133
+ const sheetId = src . startsWith (
134
+ 'https://docs.google.com/spreadsheets/d/'
135
+ )
136
+ ? src . split ( '/' ) [ 5 ]
137
+ : undefined ;
138
+ sheets . push ( sheetId ) ;
138
139
139
- // fetch json data file and build indexes
140
- fetch ( src )
141
- . then ( res => ( res . ok ? res . json ( ) : Promise . reject ( res . status ) ) )
142
- . then ( data => {
140
+ // google sheet
143
141
if ( sheetId ) {
144
- data = translateGoogleSheet ( data , sheetId , settings ) ;
145
- }
146
-
147
- if ( ! Array . isArray ( data ) || ! data . length ) {
148
- return setState ( state => ( {
149
- ...state ,
150
- error :
151
- 'Configuration error: data is not in the correct format.' ,
152
- filtering : false ,
153
- loading : false ,
154
- } ) ) ;
155
- }
156
-
157
- if ( timezone ) {
158
- try {
159
- // check if timezone is valid
160
- Intl . DateTimeFormat ( undefined , { timeZone : timezone } ) ;
161
- } catch ( e ) {
162
- return setState ( state => ( {
142
+ if ( ! google ) {
143
+ setState ( state => ( {
163
144
...state ,
164
- error : `Timezone ${ timezone } is not valid. Please use one like Europe/Rome.` ,
145
+ error : 'Configuration error: a Google API key is required.' ,
165
146
filtering : false ,
166
147
loading : false ,
167
148
} ) ) ;
168
149
}
150
+ src = `https://sheets.googleapis.com/v4/spreadsheets/${ sheetId } /values/A1:ZZ?key=${ google } ` ;
151
+ }
152
+
153
+ // cache busting
154
+ if ( src . endsWith ( '.json' ) && input . meeting ) {
155
+ src = `${ src } ?${ new Date ( ) . getTime ( ) } ` ;
156
+ }
157
+
158
+ // fetch json data file and build indexes
159
+ return fetch ( src ) ;
160
+ } )
161
+ )
162
+ . then ( responses =>
163
+ Promise . all (
164
+ responses . map ( res =>
165
+ res . ok ? res . json ( ) : Promise . reject ( res . status )
166
+ )
167
+ )
168
+ )
169
+ . then ( ( responses : JSONData [ ] [ ] ) => {
170
+ const data = responses
171
+ . map ( ( data , index ) => {
172
+ const sheetId = sheets [ index ] ;
173
+ return isGoogleSheetData ( data ) && sheetId
174
+ ? translateGoogleSheet ( data , sheetId , settings )
175
+ : data ;
176
+ } )
177
+ . flat ( ) ;
178
+
179
+ if ( ! Array . isArray ( data ) || ! data . length ) {
180
+ throw new Error (
181
+ 'Configuration error: data is not in the correct format.'
182
+ ) ;
169
183
}
170
184
171
185
const [ meetings , indexes , capabilities ] = loadMeetingData (
@@ -177,12 +191,7 @@ export default function TsmlUI({
177
191
) ;
178
192
179
193
if ( ! timezone && ! Object . keys ( meetings ) . length ) {
180
- return setState ( state => ( {
181
- ...state ,
182
- error : 'Configuration error: time zone is not set.' ,
183
- filtering : false ,
184
- loading : false ,
185
- } ) ) ;
194
+ throw new Error ( 'Configuration error: time zone is not set.' ) ;
186
195
}
187
196
188
197
const waitingForGeo =
@@ -200,27 +209,10 @@ export default function TsmlUI({
200
209
meetings,
201
210
} ) ) ;
202
211
} )
203
- . catch ( error => {
204
- const errors = {
205
- 400 : 'bad request' ,
206
- 401 : 'unauthorized' ,
207
- 403 : 'forbidden' ,
208
- 404 : 'not found' ,
209
- 429 : 'too many requests' ,
210
- 500 : 'internal server' ,
211
- 502 : 'bad gateway' ,
212
- 503 : 'service unavailable' ,
213
- 504 : 'gateway timeout' ,
214
- } ;
212
+ . catch ( ( error : string | TypeError ) => {
215
213
setState ( state => ( {
216
214
...state ,
217
- error : errors [ error as keyof typeof errors ]
218
- ? `Error: ${
219
- errors [ error as keyof typeof errors ]
220
- } (${ error } ) when ${
221
- sheetId ? 'contacting Google' : 'loading data'
222
- } .`
223
- : error . toString ( ) ,
215
+ error : String ( error ) ,
224
216
filtering : false ,
225
217
loading : false ,
226
218
} ) ) ;
0 commit comments