@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
|
@@ -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
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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`, {
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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>
|