@openeventkit/event-site 2.0.129 → 2.0.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/gatsby-node.js CHANGED
@@ -92,12 +92,16 @@ const SSR_getEvents = async (baseUrl, summitId, accessToken) => {
92
92
 
93
93
  const endpoint = `${baseUrl}/api/v1/summits/${summitId}/events/published`;
94
94
 
95
+ const speakers_fields = ['id', 'first_name', 'last_name', 'title', 'bio','member_id','pic', 'big_pic', 'company'];
96
+ const current_attendance_fields = ['member_first_name', 'member_last_name', 'member_pic'];
97
+
95
98
  const params = {
96
99
  access_token: accessToken,
97
100
  per_page: 50,
98
101
  page: 1,
99
- expand: "slides,links,videos,media_uploads,type,track,track.subtracks,track.allowed_access_levels,location,location.venue,location.floor,speakers,moderator,sponsors,current_attendance,groups,rsvp_template,tags",
100
- relations: "speakers.badge_features,speakers.affiliations,speakers.languages,speakers.other_presentation_links,speakers.areas_of_expertise,speakers.travel_preferences,speakers.organizational_roles,speakers.all_presentations,speakers.all_moderated_presentations",
102
+ expand: 'slides,links,videos,media_uploads,type,track,track.subtracks,track.allowed_access_levels,location,location.venue,location.floor,speakers,moderator,sponsors,groups,rsvp_template,tags,current_attendance',
103
+ relations: 'speakers.badge_features,speakers.affiliations,speakers.languages,speakers.other_presentation_links,speakers.areas_of_expertise,speakers.travel_preferences,speakers.organizational_roles,speakers.all_presentations,speakers.all_moderated_presentations',
104
+ fields: `speakers.${speakers_fields.join(",speakers.")},current_attendance.${current_attendance_fields.join(',current_attendance.')}`,
101
105
  }
102
106
 
103
107
  return await axios.get(endpoint, { params }).then(async ({data}) => {
@@ -161,11 +165,27 @@ const SSR_getSponsorCollections = async (allSponsors, baseUrl, summitId, accessT
161
165
 
162
166
  const SSR_getSpeakers = async (baseUrl, summitId, accessToken, filter = null) => {
163
167
 
168
+ const speakers_relations = [
169
+ 'badge_features',
170
+ 'affiliations',
171
+ 'languages',
172
+ 'other_presentation_links',
173
+ 'areas_of_expertise',
174
+ 'travel_preferences',
175
+ 'organizational_roles',
176
+ 'all_presentations',
177
+ 'all_moderated_presentations',
178
+ ];
179
+
180
+ const speakers_fields =
181
+ ['id', 'first_name', 'last_name', 'title', 'bio','member_id','pic', 'big_pic', 'company'];
182
+
164
183
  const params = {
165
184
  access_token: accessToken,
166
185
  per_page: 30,
167
186
  page: 1,
168
- relations: 'badge_features,affiliations,languages,other_presentation_links,areas_of_expertise,travel_preferences,organizational_roles,all_presentations,all_moderated_presentations',
187
+ relations: speakers_relations.join(','),
188
+ fields: speakers_fields.join(',')
169
189
  };
170
190
 
171
191
  const endpoint = `${baseUrl}/api/v1/summits/${summitId}/speakers/on-schedule`;
@@ -273,11 +293,11 @@ exports.onPreBootstrap = async () => {
273
293
  // write colors json used to set runtime colors in gatsby-browser
274
294
  fs.writeFileSync(COLORS_FILE_PATH, JSON.stringify(colors), "utf8");
275
295
 
276
- // generate and write colors SCSS file used by built styles
296
+ // generate and write colors SCSS file used by built styles
277
297
  generateAndWriteScssFile(generateColorsScssFile, colors, COLORS_SCSS_FILE_PATH);
278
298
 
279
- if (siteSettings.siteFont) {
280
- // generate and write font SCSS file used by built styles
299
+ if (siteSettings.siteFont) {
300
+ // generate and write font SCSS file used by built styles
281
301
  generateAndWriteScssFile(generateFontScssFile, siteSettings.siteFont, FONTS_SCSS_FILE_PATH);
282
302
  }
283
303
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openeventkit/event-site",
3
3
  "description": "Event Site",
4
- "version": "2.0.129",
4
+ "version": "2.0.131",
5
5
  "author": "Tipit LLC",
6
6
  "dependencies": {
7
7
  "@fortawesome/fontawesome-svg-core": "^6.5.2",
@@ -126,7 +126,7 @@
126
126
  "slick-carousel": "^1.8.1",
127
127
  "smoothscroll-polyfill": "^0.4.4",
128
128
  "socket.io-client": "^4.5.2",
129
- "speakers-widget": "4.0.1",
129
+ "speakers-widget": "4.0.2",
130
130
  "stream-browserify": "^3.0.0",
131
131
  "stream-chat": "^2.7.2",
132
132
  "stream-chat-react": "3.1.7",
@@ -33,9 +33,20 @@ export const setEventLastUpdate = (lastUpdate) => (dispatch) => {
33
33
  */
34
34
  export const getEventById = (
35
35
  eventId
36
- ) => async (dispatch) => {
36
+ ) => async (dispatch, getState) => {
37
37
 
38
38
  dispatch(startLoading());
39
+ // if we have it on the reducer , provide that first
40
+ let {allSchedulesState: {allEvents}} = getState();
41
+ const event = allEvents.find(ev => ev.id === parseInt(eventId));
42
+
43
+ if (event) {
44
+ dispatch(stopLoading());
45
+ dispatch(createAction(GET_EVENT_DATA)({event}));
46
+ const res = { response: event, err: null };
47
+ return Promise.resolve(res);
48
+ }
49
+ // then refresh from api
39
50
 
40
51
  let accessToken;
41
52
  try {
@@ -6,6 +6,7 @@ import URI from "urijs";
6
6
  * @param accessToken
7
7
  * @returns {Promise<Response>}
8
8
  */
9
+
9
10
  export const fetchEventById = async (summitId, eventId, accessToken = null) => {
10
11
 
11
12
  let apiUrl = URI(`${process.env.GATSBY_SUMMIT_API_BASE_URL}/api/public/v1/summits/${summitId}/events/${eventId}/published`);
@@ -14,10 +15,13 @@ export const fetchEventById = async (summitId, eventId, accessToken = null) => {
14
15
  apiUrl.addQuery('access_token', accessToken);
15
16
  }
16
17
 
18
+ const speakers_fields = ['id', 'first_name', 'last_name', 'title', 'bio','member_id','pic', 'big_pic', 'company'];
19
+ const current_attendance_fields = ['member_first_name', 'member_last_name', 'member_pic'];
20
+
17
21
  apiUrl.addQuery('expand', 'slides, links, videos, media_uploads, type, track, track.allowed_access_levels, location, location.venue, location.floor, speakers, moderator, sponsors, current_attendance, groups, rsvp_template, tags');
18
22
  apiUrl.addQuery('evict_cache', 1);
19
23
  apiUrl.addQuery('relations', "speakers.badge_features,speakers.affiliations,speakers.languages,speakers.other_presentation_links,speakers.areas_of_expertise,speakers.travel_preferences,speakers.organizational_roles,speakers.all_presentations,speakers.all_moderated_presentations");
20
-
24
+ apiUrl.addQuery('fields', `speakers.${speakers_fields.join(",speakers.")},current_attendance.${current_attendance_fields.join(',current_attendance.')}`);
21
25
  return fetch(apiUrl.toString(), {
22
26
  method: 'GET'
23
27
  }).then(async (response) => {
@@ -53,7 +57,6 @@ export const fetchEventTypeById = async (summitId, eventTypeId, accessToken = nu
53
57
  });
54
58
  }
55
59
 
56
-
57
60
  /**
58
61
  *
59
62
  * @param summitId
@@ -101,8 +104,24 @@ export const fetchSpeakerById = async(summitId, speakerId, accessToken = null) =
101
104
  apiUrl.addQuery('access_token', accessToken);
102
105
  }
103
106
 
104
- apiUrl.addQuery('relations', 'badge_features,affiliations,languages,other_presentation_links,areas_of_expertise,travel_preferences,organizational_roles,all_presentations,all_moderated_presentations');
107
+ const speakers_relations = [
108
+ 'badge_features',
109
+ 'affiliations',
110
+ 'languages',
111
+ 'other_presentation_links',
112
+ 'areas_of_expertise',
113
+ 'travel_preferences',
114
+ 'organizational_roles',
115
+ 'all_presentations',
116
+ 'all_moderated_presentations',
117
+ ];
118
+
119
+ const speakers_fields =
120
+ ['id', 'first_name', 'last_name', 'title', 'bio','member_id','pic', 'big_pic', 'company'];
121
+
105
122
  apiUrl.addQuery('evict_cache', 1);
123
+ apiUrl.addQuery('relations', speakers_relations.join(','));
124
+ apiUrl.addQuery('fields', speakers_fields.join(','));
106
125
 
107
126
  return fetch(apiUrl.toString(), {
108
127
  method: 'GET'
@@ -1,5 +1,6 @@
1
1
  import React, { useState, useRef, useEffect } from "react";
2
2
  import AvatarEditor from "react-avatar-editor";
3
+ import { AjaxLoader } from "openstack-uicore-foundation/lib/components";
3
4
  import { Box, Typography, Slider, Modal } from "@mui/material";
4
5
  import { Button, IconButton } from "../ui";
5
6
  import { styled } from "@mui/system";
@@ -15,30 +16,50 @@ const CustomSlider = styled(Slider)(({ theme }) => ({
15
16
  color: "var(--color-primary)"
16
17
  }));
17
18
 
18
- const AvatarEditorModal = ({
19
- userProfile,
20
- open,
21
- changePicture,
19
+ const getUserProfilePic = async (imageUrl) => {
20
+ try {
21
+ const response = await fetch(imageUrl, {
22
+ method: "GET",
23
+ mode: "cors"
24
+ });
25
+
26
+ if (!response.ok) {
27
+ throw new Error(`Failed to fetch image: ${response.statusText}`);
28
+ }
29
+
30
+ const blob = await response.blob();
31
+ const imageObjectURL = URL.createObjectURL(blob);
32
+ return imageObjectURL;
33
+ } catch (error) {
34
+ console.error("Error fetching image:", error);
35
+ throw error;
36
+ }
37
+ };
38
+
39
+ const AvatarUploadButton = ({
40
+ onUpload,
41
+ ...rest
42
+ }) => (
43
+ <IconButton
44
+ onClick={onUpload}
45
+ {...rest}
46
+ >
47
+ <CameraAltIcon fontSize="large" />
48
+ </IconButton>
49
+ );
50
+
51
+ const AvatarEditorContent = ({
52
+ editorRef,
53
+ image,
54
+ onUpload,
55
+ handleSave,
22
56
  handleClose
23
57
  }) => {
24
- const editorRef = useRef(null);
25
- const fileInputRef = useRef(null);
26
-
27
- const [image, setImage] = useState(userProfile.picture || null);
28
58
  const [position, setPosition] = useState({ x: 0.5, y: 0.5 });
29
59
  const [scale, setScale] = useState(1);
30
60
  const [rotate, setRotate] = useState(0);
31
61
  const [newImage, setNewImage] = useState(false);
32
62
 
33
- useEffect(() => {
34
- setImage(userProfile.picture);
35
- }, [userProfile.picture]);
36
-
37
- const handleNewImage = (e) => {
38
- setImage(e.target.files[0]);
39
- setNewImage(true);
40
- };
41
-
42
63
  const handleScale = (e, newValue) => {
43
64
  setScale(newValue);
44
65
  setNewImage(true);
@@ -59,13 +80,161 @@ const AvatarEditorModal = ({
59
80
  setNewImage(true);
60
81
  };
61
82
 
83
+ return (
84
+ <>
85
+ <Box
86
+ sx={{
87
+ padding: "20px",
88
+ textAlign: "center",
89
+ position: "relative"
90
+ }}
91
+ >
92
+ <AvatarEditor
93
+ ref={editorRef}
94
+ image={image}
95
+ width={200}
96
+ height={200}
97
+ border={50}
98
+ color={[0, 0, 0, 0.8]}
99
+ position={position}
100
+ onPositionChange={handlePositionChange}
101
+ scale={scale}
102
+ rotate={rotate}
103
+ />
104
+ <AvatarUploadButton
105
+ onUpload={onUpload}
106
+ sx={{
107
+ position: "absolute",
108
+ top: "79.5%",
109
+ right: "45%",
110
+ color: "#fff"
111
+ }}
112
+ />
113
+ </Box>
114
+ <Box
115
+ sx={{
116
+ px: "20px",
117
+ display: "flex",
118
+ flexDirection: "column",
119
+ gap: "20px"
120
+ }}
121
+ >
122
+ <Box
123
+ sx={{
124
+ display: "flex",
125
+ alignItems: "center",
126
+ gap: "20px",
127
+ justifyContent: "center"
128
+ }}
129
+ >
130
+ <Typography
131
+ sx={{
132
+ fontSize: "1.5rem",
133
+ fontFamily: "var(--font_family)"
134
+ }}
135
+ >
136
+ Zoom
137
+ </Typography>
138
+ <CustomSlider
139
+ value={scale}
140
+ min={0}
141
+ max={2}
142
+ step={0.01}
143
+ onChange={handleScale}
144
+ sx={{ flex: 1, mx: 2 }}
145
+ />
146
+ </Box>
147
+ <Box
148
+ sx={{
149
+ display: "flex",
150
+ alignItems: "center"
151
+ }}
152
+ >
153
+ <Typography
154
+ sx={{
155
+ fontSize: "1.5rem",
156
+ fontFamily: "var(--font_family)"
157
+ }}
158
+ >
159
+ Rotate
160
+ </Typography>
161
+ <Box
162
+ sx={{
163
+ display: "flex",
164
+ flex: 1,
165
+ justifyContent: "center",
166
+ gap: "20px"
167
+ }}
168
+ >
169
+ <IconButton onClick={rotateLeft}>
170
+ <RotateLeftIcon fontSize="inherit" />
171
+ </IconButton>
172
+ <IconButton onClick={rotateRight}>
173
+ <RotateRightIcon fontSize="inherit" />
174
+ </IconButton>
175
+ </Box>
176
+ </Box>
177
+ </Box>
178
+ <Box
179
+ sx={{
180
+ backgroundColor: "var(--color_background_light)",
181
+ display: "flex",
182
+ justifyContent: "space-between",
183
+ padding: "20px",
184
+ gap: "20px"
185
+ }}
186
+ >
187
+ <Button onClick={handleClose}>Discard</Button>
188
+ <Button onClick={handleSave} disabled={!newImage}>
189
+ Update
190
+ </Button>
191
+ </Box>
192
+ </>
193
+ );
194
+ };
195
+
196
+ const AvatarEditorModal = ({
197
+ userProfile,
198
+ open,
199
+ changePicture,
200
+ handleClose,
201
+ }) => {
202
+ const editorRef = useRef(null);
203
+ const fileInputRef = useRef(null);
204
+
205
+ const [image, setImage] = useState(null);
206
+ const [loadingPicture, setLoadingPicture] = useState(false);
207
+ const [fetchError, setFetchError] = useState(false);
208
+
209
+ useEffect(() => {
210
+ setLoadingPicture(true);
211
+ getUserProfilePic(userProfile.picture)
212
+ .then((imageObjectURL) => {
213
+ setImage(imageObjectURL);
214
+ setFetchError(false);
215
+ })
216
+ .catch(() => {
217
+ setFetchError(true);
218
+ })
219
+ .finally(() => {
220
+ setLoadingPicture(false);
221
+ });
222
+ }, [userProfile.picture]);
223
+
224
+ const handleNewImage = (e) => {
225
+ setImage(e.target.files[0]);
226
+ setFetchError(false);
227
+ };
228
+
62
229
  const handleSave = () => {
63
- if (editorRef.current && newImage) {
230
+ if (editorRef.current) {
64
231
  const canvas = editorRef.current.getImage().toDataURL();
65
232
  fetch(canvas)
66
233
  .then((res) => res.blob())
67
234
  .then((blob) => {
68
- const file = new File([blob], `${create_UUID()}.png`, { type: blob.type });
235
+ const file = new File([blob], `${create_UUID()}.png`, {
236
+ type: blob.type
237
+ });
69
238
  changePicture(file);
70
239
  });
71
240
  }
@@ -124,36 +293,13 @@ const AvatarEditorModal = ({
124
293
  <i className="fa fa-times" />
125
294
  </IconButton>
126
295
  </Box>
127
- <Box
128
- sx={{
129
- padding: "20px",
130
- textAlign: "center",
131
- position: "relative"
132
- }}
133
- >
134
- <AvatarEditor
135
- ref={editorRef}
136
- image={image}
137
- width={200}
138
- height={200}
139
- border={50}
140
- color={[0, 0, 0, 0.8]}
141
- position={position}
142
- onPositionChange={handlePositionChange}
143
- scale={scale}
144
- rotate={rotate}
296
+ <Box>
297
+ <AjaxLoader
298
+ relative={true}
299
+ color={"var(--color_background_light)"}
300
+ show={loadingPicture}
301
+ size={120}
145
302
  />
146
- <IconButton
147
- onClick={() => fileInputRef.current.click()}
148
- sx={{
149
- position: "absolute",
150
- top: "79.5%",
151
- right: "44%",
152
- color: "#fff"
153
- }}
154
- >
155
- <CameraAltIcon fontSize="inherit" />
156
- </IconButton>
157
303
  <input
158
304
  ref={fileInputRef}
159
305
  type="file"
@@ -161,86 +307,44 @@ const AvatarEditorModal = ({
161
307
  style={{ display: "none" }}
162
308
  onChange={handleNewImage}
163
309
  />
164
- </Box>
165
- <Box
166
- sx={{
167
- px: "20px",
168
- display: "flex",
169
- flexDirection: "column",
170
- gap: "20px"
171
- }}
172
- >
173
- <Box
174
- sx={{
175
- display: "flex",
176
- alignItems: "center",
177
- gap: "20px",
178
- justifyContent: "center"
179
- }}
180
- >
181
- <Typography
182
- sx={{
183
- fontSize: "1.5rem",
184
- fontFamily: "var(--font_family)"
185
- }
186
- }>
187
- Zoom
188
- </Typography>
189
- <CustomSlider
190
- value={scale}
191
- min={0}
192
- max={2}
193
- step={0.01}
194
- onChange={handleScale}
195
- sx={{ flex: 1, mx: 2 }}
196
- />
197
- </Box>
198
- <Box
199
- sx={{
200
- display: "flex",
201
- alignItems: "center"
202
- }}
203
- >
204
- <Typography
205
- sx={{
206
- fontSize: "1.5rem",
207
- fontFamily: "var(--font_family)"
208
- }}
209
- >
210
- Rotate
211
- </Typography>
310
+ {fetchError ? (
212
311
  <Box
213
- sx={{
214
- display: "flex",
215
- flex: 1,
216
- justifyContent: "center",
217
- gap: "20px"
218
- }}
219
- >
220
- <IconButton onClick={rotateLeft}>
221
- <RotateLeftIcon fontSize="inherit" />
222
- </IconButton>
223
- <IconButton onClick={rotateRight}>
224
- <RotateRightIcon fontSize="inherit" />
225
- </IconButton>
312
+ sx={{
313
+ padding: "20px",
314
+ display: "flex",
315
+ flexDirection: "column",
316
+ alignItems: "center",
317
+ gap: "20px"
318
+ }}
319
+ >
320
+ <Typography
321
+ sx={{
322
+ fontSize: "1.5rem",
323
+ fontFamily: "var(--font_family)",
324
+ color: "var(--color_text_dark)"
325
+ }}
326
+ >
327
+ There was an error retrieving your profile picture.
328
+ Please upload a new one.
329
+ </Typography>
330
+ <AvatarUploadButton
331
+ onUpload={() => fileInputRef.current.click()}
332
+ sx={{
333
+ color: "var(--color-primary)",
334
+ border: "1px solid var(--color-primary)",
335
+ padding: "10px"
336
+ }}
337
+ />
226
338
  </Box>
227
- </Box>
228
- </Box>
229
- <Box
230
- sx={{
231
- backgroundColor: "var(--color_background_light)",
232
- display: "flex",
233
- justifyContent: "space-between",
234
- padding: "20px",
235
- gap: "20px"
236
- }}
237
- >
238
- <Button onClick={handleClose}>
239
- Discard
240
- </Button>
241
- <Button onClick={handleSave} disabled={!newImage}>
242
- Update
243
- </Button>
339
+ ) : (
340
+ <AvatarEditorContent
341
+ editorRef={editorRef}
342
+ image={image}
343
+ onUpload={() => fileInputRef.current.click()}
344
+ handleSave={handleSave}
345
+ handleClose={handleClose}
346
+ />
347
+ )}
244
348
  </Box>
245
349
  </Box>
246
350
  </Modal>
@@ -202,7 +202,7 @@ h2 {
202
202
  }
203
203
 
204
204
  .talk {
205
- color: var(--color_text_med);
205
+ color: var(--color_text_dark);
206
206
 
207
207
  &__break {
208
208
  background-color: var(--color_secondary);