@openeventkit/event-site 2.0.129 → 2.0.130

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/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.130",
5
5
  "author": "Tipit LLC",
6
6
  "dependencies": {
7
7
  "@fortawesome/fontawesome-svg-core": "^6.5.2",
@@ -33,9 +33,18 @@ 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
+ }
47
+ // then refresh from api
39
48
 
40
49
  let accessToken;
41
50
  try {
@@ -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);