@openeventkit/event-site 2.0.130 → 2.0.132
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 +26 -6
- package/package.json +2 -2
- package/src/actions/event-actions.js +2 -0
- package/src/actions/fetch-entities-actions.js +22 -3
- package/src/components/summit-my-orders-tickets/components/DelegatePopup/DelegatePopup.js +51 -0
- package/src/components/summit-my-orders-tickets/components/DelegatePopup/delegate-popup.scss +57 -0
- package/src/components/summit-my-orders-tickets/components/OrderList/OrderListItem.js +1 -1
- package/src/components/summit-my-orders-tickets/components/TicketPopup/TicketPopupEditDetailsForm/TicketPopupEditDetailsForm.js +102 -42
- package/src/components/summit-my-orders-tickets/store/actions/ticket-actions.js +76 -13
- package/src/components/summit-my-orders-tickets/util/ticket/useTicketDetails.js +4 -1
- package/src/styles/profile.module.scss +6 -0
- package/src/styles/style.scss +10 -0
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:
|
|
100
|
-
relations:
|
|
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: '
|
|
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.
|
|
4
|
+
"version": "2.0.132",
|
|
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.
|
|
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",
|
|
@@ -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
|
-
|
|
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'
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2022
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
+
* See the License for the specific language governing permissions and
|
|
11
|
+
* limitations under the License.
|
|
12
|
+
**/
|
|
13
|
+
import React, { useState } from 'react'
|
|
14
|
+
import { useTranslation } from "react-i18next";
|
|
15
|
+
import { Input } from 'openstack-uicore-foundation/lib/components';
|
|
16
|
+
import usePortal from 'react-useportal';
|
|
17
|
+
|
|
18
|
+
import './delegate-popup.scss';
|
|
19
|
+
|
|
20
|
+
export const DelegatePopup = ({ isOpen, onAccept, onReject }) => {
|
|
21
|
+
var { Portal } = usePortal();
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
|
|
24
|
+
const handleAcceptClick = () => {
|
|
25
|
+
if (onAccept) onAccept();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const handleRejectClick = () => {
|
|
29
|
+
if (onReject) onReject();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<>
|
|
34
|
+
{isOpen && (
|
|
35
|
+
<Portal>
|
|
36
|
+
<div className="confirm-popup-bg">
|
|
37
|
+
<div className="confirm-popup">
|
|
38
|
+
<h4>Delegate Ticket</h4>
|
|
39
|
+
<p>Delegation will create a new attendee and require to you to fill the first Name, last Name and to answer the extra questions again</p>
|
|
40
|
+
|
|
41
|
+
<div className="buttons">
|
|
42
|
+
<span onClick={handleRejectClick}>{t("confirm_popup.cancel")}</span>
|
|
43
|
+
<span onClick={handleAcceptClick}>{t("confirm_popup.accept")}</span>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</Portal>
|
|
48
|
+
)}
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
@import "../../styles/variables";
|
|
2
|
+
|
|
3
|
+
.confirm-popup-bg {
|
|
4
|
+
z-index: 1000;
|
|
5
|
+
position: fixed;
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: 100%;
|
|
8
|
+
top: 0;
|
|
9
|
+
left: 0;
|
|
10
|
+
right: 0;
|
|
11
|
+
bottom: 0;
|
|
12
|
+
margin: auto;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.confirm-popup {
|
|
16
|
+
position: absolute;
|
|
17
|
+
right: 1%;
|
|
18
|
+
top: 5%;
|
|
19
|
+
padding: 40px 20px 20px;
|
|
20
|
+
background: $color-white;
|
|
21
|
+
z-index: 35;
|
|
22
|
+
text-align: center;
|
|
23
|
+
box-shadow: 1px 1px 5px grey;
|
|
24
|
+
min-width: 300px;
|
|
25
|
+
|
|
26
|
+
h4 {
|
|
27
|
+
font-weight: bold;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
p {
|
|
31
|
+
margin: 0 40px 20px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.buttons {
|
|
35
|
+
margin-top: 35px;
|
|
36
|
+
display: flex;
|
|
37
|
+
justify-content: space-evenly;
|
|
38
|
+
align-items: baseline;
|
|
39
|
+
|
|
40
|
+
span {
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
span:last-child {
|
|
45
|
+
background: $color-secondary-contrast;
|
|
46
|
+
border-radius: 4px;
|
|
47
|
+
color: $color-white;
|
|
48
|
+
padding: 5px 30px;
|
|
49
|
+
text-align: center;
|
|
50
|
+
|
|
51
|
+
&:hover {
|
|
52
|
+
background-color: #286090;
|
|
53
|
+
border-color: #204d74;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -35,7 +35,7 @@ export const OrderListItem = ({ order, className, changeTicketsPage }) => {
|
|
|
35
35
|
<OrderSummary type="mobile" order={order} summit={summit} tickets={tickets}/>
|
|
36
36
|
|
|
37
37
|
{summit.ticket_types.map((ticketType, index) => {
|
|
38
|
-
const orderTickets = tickets.filter(t => t.
|
|
38
|
+
const orderTickets = tickets.filter(t => t.ticket_type.id == ticketType.id);
|
|
39
39
|
|
|
40
40
|
if (orderTickets.length < 1) return null;
|
|
41
41
|
|
|
@@ -12,15 +12,18 @@ import { getMainOrderExtraQuestions } from '../../../store/actions/summit-action
|
|
|
12
12
|
import {
|
|
13
13
|
editOwnedTicket,
|
|
14
14
|
removeAttendee,
|
|
15
|
+
delegateTicket,
|
|
15
16
|
TICKET_ATTENDEE_KEYS as TicketKeys
|
|
16
17
|
} from '../../../store/actions/ticket-actions';
|
|
17
18
|
import { useTicketDetails } from '../../../util';
|
|
19
|
+
import useMarketingSettings, { MARKETING_SETTINGS_KEYS } from "@utils/useMarketingSettings";
|
|
18
20
|
import { ConfirmPopup, CONFIRM_POPUP_CASE } from '../../ConfirmPopup/ConfirmPopup';
|
|
19
21
|
|
|
20
22
|
import { DefaultScrollBehaviour as ScrollBehaviour } from '@utils/scroll';
|
|
21
23
|
|
|
22
24
|
import './ticket-popup-edit-details-form.scss';
|
|
23
25
|
import { useTicketAssignedContext } from '../../../context/TicketAssignedContext';
|
|
26
|
+
import { DelegatePopup } from '../../DelegatePopup/DelegatePopup';
|
|
24
27
|
|
|
25
28
|
const noop = () => {};
|
|
26
29
|
|
|
@@ -41,15 +44,24 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
41
44
|
const [triedSubmitting, setTriedSubmitting] = useState(false);
|
|
42
45
|
const [showSaveMessage, setShowSaveMessage] = useState(false);
|
|
43
46
|
const [showConfirm, setShowConfirm] = useState(false);
|
|
47
|
+
const [showDelegate, setShowDelegate] = useState(false);
|
|
48
|
+
const [isDelegating, setIsDelegating] = useState(false);
|
|
44
49
|
const [showUnassignMessage, setShowUnassignMessage] = useState(false);
|
|
45
50
|
const {
|
|
46
51
|
isReassignable,
|
|
47
52
|
formattedReassignDate,
|
|
48
|
-
daysUntilReassignDeadline
|
|
49
|
-
|
|
53
|
+
daysUntilReassignDeadline,
|
|
54
|
+
isUnassigned,
|
|
55
|
+
allowsDelegate
|
|
56
|
+
} = useTicketDetails({ ticket, summit });
|
|
50
57
|
|
|
51
58
|
const { onTicketAssignChange } = useTicketAssignedContext();
|
|
52
59
|
|
|
60
|
+
const { getSettingByKey } = useMarketingSettings();
|
|
61
|
+
|
|
62
|
+
const showCompanyInputDefaultOptions = !!Number(getSettingByKey(MARKETING_SETTINGS_KEYS.regLiteShowCompanyInputDefaultOptions));
|
|
63
|
+
const showCompanyInput = !!Number(getSettingByKey(MARKETING_SETTINGS_KEYS.regLiteShowCompanyInput));
|
|
64
|
+
|
|
53
65
|
const initialValues = useMemo(() => {
|
|
54
66
|
const {
|
|
55
67
|
email,
|
|
@@ -78,7 +90,7 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
78
90
|
const validationSchema = useMemo(() => Yup.object().shape({
|
|
79
91
|
[TicketKeys.firstName]: Yup.string().required(),
|
|
80
92
|
[TicketKeys.lastName]: Yup.string().required(),
|
|
81
|
-
[TicketKeys.company]: Yup.object().shape({
|
|
93
|
+
[TicketKeys.company]: showCompanyInput && Yup.object().shape({
|
|
82
94
|
id: Yup.number().nullable(),
|
|
83
95
|
name: Yup.string().required(),
|
|
84
96
|
}),
|
|
@@ -115,14 +127,26 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
115
127
|
data: values,
|
|
116
128
|
};
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
if(isDelegating) {
|
|
131
|
+
dispatch(delegateTicket(params))
|
|
132
|
+
.then(() => toggleSaveMessage())
|
|
133
|
+
.catch((error) => console.error(error))
|
|
134
|
+
.then(() => {
|
|
135
|
+
formikHelpers.resetForm({ values });
|
|
136
|
+
formikHelpers.setSubmitting(false);
|
|
137
|
+
setIsDelegating(false);
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
dispatch(editOwnedTicket(params))
|
|
141
|
+
.then(() => toggleSaveMessage())
|
|
142
|
+
.catch((error) => console.error(error))
|
|
143
|
+
.then(() => {
|
|
144
|
+
// Note: Need to do this to persist the extra question values
|
|
145
|
+
formikHelpers.resetForm({ values });
|
|
146
|
+
formikHelpers.setSubmitting(false);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
126
150
|
};
|
|
127
151
|
|
|
128
152
|
const handleConfirmAccept = async () => {
|
|
@@ -137,6 +161,24 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
137
161
|
setShowConfirm(false);
|
|
138
162
|
};
|
|
139
163
|
|
|
164
|
+
const handleDelegateAccept = () => {
|
|
165
|
+
setShowDelegate(false);
|
|
166
|
+
setIsDelegating(true);
|
|
167
|
+
formik.resetForm({
|
|
168
|
+
values: {
|
|
169
|
+
...formik.values,
|
|
170
|
+
[TicketKeys.firstName]: "",
|
|
171
|
+
[TicketKeys.lastName]: "",
|
|
172
|
+
[TicketKeys.disclaimerAccepted]: false,
|
|
173
|
+
[TicketKeys.extraQuestions]: []
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const handleDelegateReject = () => {
|
|
179
|
+
setShowDelegate(false);
|
|
180
|
+
};
|
|
181
|
+
|
|
140
182
|
const handleSubmit = (values, formikHelpers) => updateTicket(values, formikHelpers);
|
|
141
183
|
|
|
142
184
|
const formik = useFormik({
|
|
@@ -209,7 +251,7 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
209
251
|
const canSubmitChanges = () => {
|
|
210
252
|
const qs = new QuestionsSet(extraQuestions, initialValues[TicketKeys.extraQuestions]);
|
|
211
253
|
const unansweredExtraQuestions = !qs.completed();
|
|
212
|
-
return canEditTicketData || isReassignable || unansweredExtraQuestions;
|
|
254
|
+
return canEditTicketData || isReassignable || unansweredExtraQuestions || isDelegating;
|
|
213
255
|
}
|
|
214
256
|
|
|
215
257
|
return (
|
|
@@ -277,8 +319,8 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
277
319
|
placeholder={t("ticket_popup.edit_first_name_placeholder")}
|
|
278
320
|
value={formik.values[TicketKeys.firstName]}
|
|
279
321
|
onBlur={formik.handleBlur}
|
|
280
|
-
onChange={!!initialValues[TicketKeys.firstName] ? noop : formik.handleChange}
|
|
281
|
-
disabled={!!initialValues[TicketKeys.firstName]}
|
|
322
|
+
onChange={!!initialValues[TicketKeys.firstName] && !isDelegating ? noop : formik.handleChange}
|
|
323
|
+
disabled={!!initialValues[TicketKeys.firstName] && !isDelegating}
|
|
282
324
|
/>
|
|
283
325
|
{(formik.touched[TicketKeys.firstName] || triedSubmitting) && formik.errors[TicketKeys.firstName] &&
|
|
284
326
|
<p className="error-label">{t("ticket_popup.edit_required")}</p>
|
|
@@ -297,39 +339,50 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
297
339
|
placeholder={t("ticket_popup.edit_last_name_placeholder")}
|
|
298
340
|
value={formik.values[TicketKeys.lastName]}
|
|
299
341
|
onBlur={formik.handleBlur}
|
|
300
|
-
onChange={!!initialValues[TicketKeys.lastName] ? noop : formik.handleChange}
|
|
301
|
-
disabled={!!initialValues[TicketKeys.lastName]}
|
|
342
|
+
onChange={!!initialValues[TicketKeys.lastName] && !isDelegating ? noop : formik.handleChange}
|
|
343
|
+
disabled={!!initialValues[TicketKeys.lastName] && !isDelegating}
|
|
302
344
|
/>
|
|
303
345
|
{(formik.touched[TicketKeys.lastName] || triedSubmitting) && formik.errors[TicketKeys.lastName] &&
|
|
304
346
|
<p className="error-label">{t("ticket_popup.edit_required")}</p>
|
|
305
347
|
}
|
|
306
348
|
</div>
|
|
307
349
|
|
|
308
|
-
|
|
309
|
-
<
|
|
310
|
-
{
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
350
|
+
{allowsDelegate &&
|
|
351
|
+
<div className="attendee-info column is-full">
|
|
352
|
+
<button className="button-text" type='button' onClick={() => setShowDelegate(true)}>Delegate</button>
|
|
353
|
+
</div>
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
{showCompanyInput &&
|
|
357
|
+
<div className="attendee-info column is-full">
|
|
358
|
+
<label htmlFor={TicketKeys.company}>
|
|
359
|
+
{t("ticket_popup.edit_company")}
|
|
360
|
+
{!initialValues[TicketKeys.company].name && <b> *</b>}
|
|
361
|
+
</label>
|
|
362
|
+
<RegistrationCompanyInput
|
|
363
|
+
id={TicketKeys.company}
|
|
364
|
+
name={TicketKeys.company}
|
|
365
|
+
summitId={summit.id}
|
|
366
|
+
placeholder={t("ticket_popup.edit_company_placeholder")}
|
|
367
|
+
value={formik.values[TicketKeys.company]}
|
|
368
|
+
onBlur={formik.handleBlur}
|
|
369
|
+
onChange={!!initialValues[TicketKeys.company].name ? noop : formik.handleChange}
|
|
370
|
+
disabled={!!initialValues[TicketKeys.company].name}
|
|
371
|
+
defaultOptions={showCompanyInputDefaultOptions}
|
|
372
|
+
openMenuOnFocus={showCompanyInputDefaultOptions}
|
|
373
|
+
openMenuOnClick={showCompanyInputDefaultOptions}
|
|
374
|
+
menuPortalTarget={document.body}
|
|
375
|
+
menuPosition="fixed"
|
|
376
|
+
styles={{
|
|
377
|
+
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
|
|
378
|
+
}}
|
|
379
|
+
tabSelectsValue={false}
|
|
380
|
+
/>
|
|
381
|
+
{(formik.touched[TicketKeys.company] || triedSubmitting) && formik.errors[TicketKeys.company] &&
|
|
382
|
+
<p className="error-label">{t("ticket_popup.edit_required")}</p>
|
|
383
|
+
}
|
|
384
|
+
</div>
|
|
385
|
+
}
|
|
333
386
|
|
|
334
387
|
{(initialValues[TicketKeys.firstName] || initialValues[TicketKeys.lastName] || initialValues[TicketKeys.company].name) &&
|
|
335
388
|
<div className="column is-full pb-5">
|
|
@@ -341,11 +394,13 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
341
394
|
<div className="column is-full pt-5">
|
|
342
395
|
<h4 className="pb-2">{t("ticket_popup.edit_preferences")}</h4>
|
|
343
396
|
<ExtraQuestionsForm
|
|
397
|
+
// This key is added to trigger a new render when the extra questions are resetted on delegation
|
|
398
|
+
key={formik.values[TicketKeys.extraQuestions].length}
|
|
344
399
|
ref={formRef}
|
|
345
400
|
extraQuestions={extraQuestions}
|
|
346
401
|
userAnswers={formik.values[TicketKeys.extraQuestions]}
|
|
347
402
|
onAnswerChanges={onExtraQuestionsAnswersSet}
|
|
348
|
-
allowExtraQuestionsEdit={canEditTicketData}
|
|
403
|
+
allowExtraQuestionsEdit={canEditTicketData || isDelegating}
|
|
349
404
|
questionContainerClassName={`columns is-multiline extra-question pt-3`}
|
|
350
405
|
questionLabelContainerClassName={'column is-full pb-0'}
|
|
351
406
|
questionControlContainerClassName={`column is-full pt-0`}
|
|
@@ -403,6 +458,11 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
403
458
|
onAccept={handleConfirmAccept}
|
|
404
459
|
onReject={handleConfirmReject}
|
|
405
460
|
/>
|
|
461
|
+
<DelegatePopup
|
|
462
|
+
isOpen={showDelegate}
|
|
463
|
+
onAccept={handleDelegateAccept}
|
|
464
|
+
onReject={handleDelegateReject}
|
|
465
|
+
/>
|
|
406
466
|
</div>
|
|
407
467
|
);
|
|
408
468
|
};
|
|
@@ -38,6 +38,7 @@ export const GET_TICKETS_BY_ORDER = 'GET_TICKETS_BY_ORDER';
|
|
|
38
38
|
export const GET_TICKETS_BY_ORDER_ERROR = 'GET_TICKETS_BY_ORDER_ERROR';
|
|
39
39
|
export const GET_ORDER_TICKET_DETAILS = 'GET_ORDER_TICKET_DETAILS';
|
|
40
40
|
export const GET_TICKET_DETAILS = 'GET_TICKET_DETAILS';
|
|
41
|
+
export const DELEGATE_TICKET = 'DELEGATE_TICKET';
|
|
41
42
|
|
|
42
43
|
export const TICKET_ATTENDEE_KEYS = {
|
|
43
44
|
email: 'attendee_email',
|
|
@@ -90,9 +91,9 @@ export const getUserTickets = ({ page = 1, perPage = 5 }) => async (dispatch, ge
|
|
|
90
91
|
|
|
91
92
|
const params = {
|
|
92
93
|
access_token: accessToken,
|
|
93
|
-
expand: 'order,
|
|
94
|
+
expand: 'order,owner,owner.manager,promo_code,ticket_type',
|
|
94
95
|
order: '-id',
|
|
95
|
-
fields: 'order.id,order.owner_first_name,order.owner_last_name,order.owner_email,owner.first_name,owner.last_name,owner.status',
|
|
96
|
+
fields: 'order.id,order.owner_first_name,order.owner_last_name,order.owner_email,owner.first_name,owner.last_name,owner.email,owner.company,owner.status,owner.manager.id',
|
|
96
97
|
'filter[]': [`status==Paid`, `order_owner_id<>${userProfile.id}`],
|
|
97
98
|
relations: 'none',
|
|
98
99
|
page: page,
|
|
@@ -130,7 +131,7 @@ export const getTicketById = ({order, ticket}) => async (dispatch, getState, { g
|
|
|
130
131
|
|
|
131
132
|
const params = {
|
|
132
133
|
access_token: accessToken,
|
|
133
|
-
expand: `${fromOrderList ? 'order' : ''},
|
|
134
|
+
expand: `${fromOrderList ? 'order' : ''},owner,owner.extra_questions,badge,badge.features,refund_requests,promo_code,ticket_type`,
|
|
134
135
|
fields: 'order.id, order.owner_first_name, order.owner_last_name, order.owner_email'
|
|
135
136
|
};
|
|
136
137
|
|
|
@@ -148,16 +149,16 @@ export const getTicketById = ({order, ticket}) => async (dispatch, getState, { g
|
|
|
148
149
|
};
|
|
149
150
|
|
|
150
151
|
export const getTicketsByOrder = ({ orderId, page = 1, perPage = 5 }) => async (dispatch, getState, { getAccessToken, apiBaseUrl, loginUrl }) => {
|
|
151
|
-
|
|
152
|
+
|
|
152
153
|
dispatch(startLoading());
|
|
153
|
-
|
|
154
|
+
|
|
154
155
|
const accessToken = await getAccessToken().catch(_ => history.replace(loginUrl));
|
|
155
156
|
|
|
156
157
|
if (!accessToken) return;
|
|
157
158
|
|
|
158
159
|
const params = {
|
|
159
|
-
access_token: accessToken,
|
|
160
|
-
expand: 'refund_requests,
|
|
160
|
+
access_token: accessToken,
|
|
161
|
+
expand: 'refund_requests,owner,owner.extra_questions,badge,badge.features,promo_code,ticket_type',
|
|
161
162
|
order: '+id',
|
|
162
163
|
page: page,
|
|
163
164
|
per_page: perPage
|
|
@@ -166,7 +167,7 @@ export const getTicketsByOrder = ({ orderId, page = 1, perPage = 5 }) => async (
|
|
|
166
167
|
return getRequest(
|
|
167
168
|
null,
|
|
168
169
|
createAction(GET_TICKETS_BY_ORDER),
|
|
169
|
-
`${apiBaseUrl}/api/v1/summits/all/orders/${orderId}/tickets`,
|
|
170
|
+
`${apiBaseUrl}/api/v1/summits/all/orders/${orderId}/tickets`,
|
|
170
171
|
authErrorHandler
|
|
171
172
|
)(params)(dispatch).then(() => {
|
|
172
173
|
dispatch(stopLoading());
|
|
@@ -300,10 +301,12 @@ export const editOwnedTicket = ({
|
|
|
300
301
|
`${apiBaseUrl}/api/v1/summits/all/orders/all/tickets/${ticket.id}`,
|
|
301
302
|
normalizedEntity,
|
|
302
303
|
authErrorHandler
|
|
303
|
-
)(params)(dispatch).then(async () => {
|
|
304
|
+
)(params)(dispatch).then(async () => {
|
|
305
|
+
const hasManager = ticket.owner?.manager?.id || ticket.owner?.manager_id;
|
|
304
306
|
// email should match ( only update my profile is ticket belongs to me!)
|
|
307
|
+
// and if the ticket doesn't have a manager
|
|
305
308
|
// Check if there's changes in the ticket data to update the profile
|
|
306
|
-
if (userProfile.email == attendee_email && (
|
|
309
|
+
if (userProfile.email == attendee_email && !hasManager && (
|
|
307
310
|
attendee_company.name !== company ||
|
|
308
311
|
attendee_first_name !== userProfile.first_name ||
|
|
309
312
|
attendee_last_name !== userProfile.last_name)) {
|
|
@@ -314,7 +317,6 @@ export const editOwnedTicket = ({
|
|
|
314
317
|
company: attendee_company.name
|
|
315
318
|
};
|
|
316
319
|
dispatch(updateProfile(newProfile));
|
|
317
|
-
|
|
318
320
|
}
|
|
319
321
|
|
|
320
322
|
// Note: make sure we re-fetch the user profile for the parent app.
|
|
@@ -324,7 +326,7 @@ export const editOwnedTicket = ({
|
|
|
324
326
|
if (context === 'ticket-list') {
|
|
325
327
|
dispatch(getUserTickets({ page: ticketPage }));
|
|
326
328
|
} else {
|
|
327
|
-
dispatch(getUserOrders({ page: orderPage })).then(() =>
|
|
329
|
+
dispatch(getUserOrders({ page: orderPage })).then(() =>
|
|
328
330
|
dispatch(getTicketsByOrder({ orderId: ticket.order_id, page: orderTicketsCurrentPage }))
|
|
329
331
|
);
|
|
330
332
|
}
|
|
@@ -529,6 +531,67 @@ export const refundTicket = ({ ticket, order }) => async (dispatch, getState, {
|
|
|
529
531
|
});
|
|
530
532
|
};
|
|
531
533
|
|
|
534
|
+
export const delegateTicket = ({
|
|
535
|
+
ticket,
|
|
536
|
+
context,
|
|
537
|
+
data: {
|
|
538
|
+
attendee_email,
|
|
539
|
+
attendee_first_name,
|
|
540
|
+
attendee_last_name,
|
|
541
|
+
attendee_company,
|
|
542
|
+
disclaimer_accepted,
|
|
543
|
+
extra_questions,
|
|
544
|
+
}
|
|
545
|
+
}) => async (dispatch, getState, { getAccessToken, apiBaseUrl, loginUrl }) => {
|
|
546
|
+
const accessToken = await getAccessToken().catch(_ => history.replace(loginUrl));
|
|
547
|
+
|
|
548
|
+
if (!accessToken) return;
|
|
549
|
+
|
|
550
|
+
dispatch(startLoading());
|
|
551
|
+
|
|
552
|
+
const {
|
|
553
|
+
orderState: { current_page: orderPage },
|
|
554
|
+
ticketState: { current_page: ticketPage, orderTickets: { current_page : orderTicketsCurrentPage }},
|
|
555
|
+
summitState: { summit: { id : summitId } }
|
|
556
|
+
} = getState();
|
|
557
|
+
|
|
558
|
+
const orderId = ticket.order ? ticket.order.id : ticket.order_id;
|
|
559
|
+
|
|
560
|
+
const params = {
|
|
561
|
+
access_token: accessToken
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
const normalizedEntity = normalizeTicket({
|
|
565
|
+
attendee_email,
|
|
566
|
+
attendee_first_name,
|
|
567
|
+
attendee_last_name,
|
|
568
|
+
attendee_company,
|
|
569
|
+
disclaimer_accepted,
|
|
570
|
+
extra_questions
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
return putRequest(
|
|
574
|
+
null,
|
|
575
|
+
createAction(DELEGATE_TICKET),
|
|
576
|
+
`${apiBaseUrl}/api/v1/summits/${summitId}/orders/${orderId}/tickets/${ticket.id}/delegate`,
|
|
577
|
+
normalizedEntity,
|
|
578
|
+
authErrorHandler
|
|
579
|
+
)(params)(dispatch).then(() => {
|
|
580
|
+
dispatch(stopLoading());
|
|
581
|
+
// Note: refresh the list view after updating the ticket.
|
|
582
|
+
if (context === 'ticket-list') {
|
|
583
|
+
dispatch(getUserTickets({ page: ticketPage }));
|
|
584
|
+
} else {
|
|
585
|
+
dispatch(getUserOrders({ page: orderPage })).then(() =>
|
|
586
|
+
dispatch(getTicketsByOrder({ orderId: ticket.order_id, page: orderTicketsCurrentPage }))
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
}).catch(e => {
|
|
590
|
+
dispatch(stopLoading());
|
|
591
|
+
throw (e);
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
|
|
532
595
|
const normalizeTicket = (entity) => {
|
|
533
596
|
const normalizedEntity = {...entity};
|
|
534
597
|
|
|
@@ -541,4 +604,4 @@ const normalizeTicket = (entity) => {
|
|
|
541
604
|
|
|
542
605
|
return normalizedEntity;
|
|
543
606
|
|
|
544
|
-
}
|
|
607
|
+
}
|
|
@@ -19,12 +19,14 @@ export const useTicketDetails = ({ ticket, summit }) => {
|
|
|
19
19
|
|
|
20
20
|
const status = getTicketStatusData(ticket, isPast);
|
|
21
21
|
const role = getTicketRole(ticket);
|
|
22
|
-
const type = summit.ticket_types.find(type => type.id == ticket.
|
|
22
|
+
const type = summit.ticket_types.find(type => type.id == ticket.ticket_type.id);
|
|
23
23
|
|
|
24
24
|
const isActive = ticket.is_active && status.type !== STATUS_CANCELLED;
|
|
25
25
|
const isUnassigned = status.type === STATUS_UNASSIGNED;
|
|
26
26
|
const isRefundable = ticket.final_amount > 0 && ticket.final_amount > ticket.refunded_amount;
|
|
27
27
|
|
|
28
|
+
const allowsDelegate = (ticket.ticket_type.allows_to_delegate || ticket.promo_code?.allows_to_delegate) && !isUnassigned && !ticket.owner?.manager?.id && !ticket.owner?.manager_id;
|
|
29
|
+
|
|
28
30
|
const togglePopup = () => setShowPopup(!showPopup);
|
|
29
31
|
|
|
30
32
|
const handleClick = () => {
|
|
@@ -45,6 +47,7 @@ export const useTicketDetails = ({ ticket, summit }) => {
|
|
|
45
47
|
isUnassigned,
|
|
46
48
|
isReassignable,
|
|
47
49
|
isRefundable,
|
|
50
|
+
allowsDelegate,
|
|
48
51
|
formattedDate,
|
|
49
52
|
formattedReassignDate,
|
|
50
53
|
daysUntilReassignDeadline,
|
|
@@ -5,10 +5,16 @@
|
|
|
5
5
|
|
|
6
6
|
@import 'colors.scss';
|
|
7
7
|
|
|
8
|
+
.modal {
|
|
9
|
+
z-index: 100000;
|
|
10
|
+
background-color: rgba(0,0,0,0.8);
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
.modal-card {
|
|
9
14
|
background-color: var(--color_background_light);
|
|
10
15
|
color: var(--color_text_dark);
|
|
11
16
|
margin: 0 5rem 0 auto;
|
|
17
|
+
border: 1px solid var(--color_input_border_color_dark);
|
|
12
18
|
|
|
13
19
|
.modal-card-head {
|
|
14
20
|
padding: 10px 20px;
|
package/src/styles/style.scss
CHANGED
|
@@ -506,4 +506,14 @@ div.event-feedback-container {
|
|
|
506
506
|
}
|
|
507
507
|
}
|
|
508
508
|
|
|
509
|
+
.button-text {
|
|
510
|
+
border: none;
|
|
511
|
+
background-color: transparent;
|
|
512
|
+
cursor: pointer;
|
|
513
|
+
font-weight: bold;
|
|
514
|
+
&:hover {
|
|
515
|
+
text-decoration: underline;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
509
519
|
@import "~openstack-uicore-foundation/lib/css/components/extra-questions.css";
|