@openeventkit/event-site 2.0.143 → 2.0.145

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.
Files changed (41) hide show
  1. package/package.json +6 -6
  2. package/src/actions/fetch-entities-actions.js +17 -2
  3. package/src/actions/update-data-actions.js +17 -1
  4. package/src/actions/user-actions.js +17 -5
  5. package/src/components/AttendeeToAttendeeWidgetComponent.js +14 -8
  6. package/src/components/AuthComponent.js +5 -2
  7. package/src/components/ClockComponent.js +7 -10
  8. package/src/components/DisqusComponent.js +69 -94
  9. package/src/components/FullSchedule.js +1 -1
  10. package/src/components/Interstitial/index.js +61 -0
  11. package/src/components/LiteScheduleComponent.js +2 -2
  12. package/src/components/LiveEventWidgetComponent.js +2 -3
  13. package/src/components/PrePostEventSlide/index.js +66 -0
  14. package/src/components/UpcomingEventsComponent.js +2 -2
  15. package/src/components/VimeoPlayer.js +2 -0
  16. package/src/components/summit-my-orders-tickets/components/TicketPopup/TicketPopupEditDetailsForm/TicketPopupEditDetailsForm.js +173 -175
  17. package/src/pages/maintenance.js +2 -4
  18. package/src/reducers/event-reducer.js +14 -1
  19. package/src/routes/ShowOpenRoute.js +5 -5
  20. package/src/routes/WithAuthzRoute.js +5 -5
  21. package/src/routes/WithBadgeRoute.js +5 -5
  22. package/src/routes/WithTicketRoute.js +3 -3
  23. package/src/routes/authorization-callback-route.js +4 -4
  24. package/src/styles/colors.scss +6 -6
  25. package/src/styles/fonts.scss +16 -11
  26. package/src/styles/style.scss +4 -18
  27. package/src/templates/event-page.js +26 -29
  28. package/src/templates/extra-questions-page.js +4 -3
  29. package/src/templates/full-profile-page.js +1 -1
  30. package/src/templates/lobby-page.js +1 -1
  31. package/src/templates/marketing-page-template/MainColumn.js +1 -1
  32. package/src/templates/poster-detail-page.js +5 -5
  33. package/src/templates/sponsor-page.js +3 -3
  34. package/src/templates/ticket-error-page.js +4 -4
  35. package/src/templates/token-expire-page.js +8 -13
  36. package/src/utils/withScheduleData.js +4 -4
  37. package/src/workers/sync_strategies/speaker_synch_strategy.js +7 -7
  38. package/src/components/EventHeroComponent.js +0 -34
  39. package/src/components/HeroComponent.js +0 -23
  40. package/src/components/NoTalkComponent.js +0 -33
  41. package/src/styles/event-hero.module.scss +0 -92
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.143",
4
+ "version": "2.0.145",
5
5
  "author": "Tipit LLC",
6
6
  "dependencies": {
7
7
  "@fortawesome/fontawesome-svg-core": "^6.5.2",
@@ -30,7 +30,7 @@
30
30
  "@vimeo/player": "^2.16.3",
31
31
  "ably": "^1.2.34",
32
32
  "assert": "^2.1.0",
33
- "attendee-to-attendee-widget": "3.1.1-beta.34",
33
+ "attendee-to-attendee-widget": "3.2.1-beta.6",
34
34
  "autoprefixer": "10.4.14",
35
35
  "awesome-bootstrap-checkbox": "^1.0.1",
36
36
  "axios": "^0.19.2",
@@ -78,14 +78,14 @@
78
78
  "jsdom": "^24.1.0",
79
79
  "klaro": "^0.7.21",
80
80
  "lite-schedule-widget": "3.0.3",
81
- "live-event-widget": "4.0.2",
81
+ "live-event-widget": "4.0.4",
82
82
  "lodash": "^4.17.19",
83
83
  "lz-string": "^1.4.4",
84
84
  "markdown-it": "^12.0.0",
85
85
  "moment": "^2.27.0",
86
86
  "moment-timezone": "^0.5.31",
87
87
  "object.assign": "^4.1.5",
88
- "openstack-uicore-foundation": "4.1.76",
88
+ "openstack-uicore-foundation": "4.1.90",
89
89
  "path-browserify": "^1.0.1",
90
90
  "prop-types": "^15.6.0",
91
91
  "react": "^18.2.0",
@@ -130,10 +130,10 @@
130
130
  "stream-browserify": "^3.0.0",
131
131
  "stream-chat": "^2.7.2",
132
132
  "stream-chat-react": "3.1.7",
133
- "summit-registration-lite": "5.0.37",
133
+ "summit-registration-lite": "5.0.41",
134
134
  "superagent": "8.0.9",
135
135
  "sweetalert2": "^9.17.0",
136
- "upcoming-events-widget": "3.0.5",
136
+ "upcoming-events-widget": "3.0.7",
137
137
  "urijs": "^1.19.2",
138
138
  "use-fit-text": "^2.4.0",
139
139
  "uuid": "^7.0.0",
@@ -163,7 +163,8 @@ export const fetchSpeakerById = async(summitId, speakerId, accessToken = null) =
163
163
  apiUrl.addQuery('fields', speakers_fields.join(','));
164
164
 
165
165
  return fetch(apiUrl.toString(), {
166
- method: 'GET'
166
+ method: 'GET',
167
+ cache: "no-store",
167
168
  }).then(async (response) => {
168
169
  if (response.status === 200) {
169
170
  return await response.json();
@@ -181,7 +182,21 @@ export const fetchSpeakerById = async(summitId, speakerId, accessToken = null) =
181
182
  export const fetchSummitById = async(summitId, accessToken = null) => {
182
183
  let apiUrl = URI(`${process.env.GATSBY_SUMMIT_API_BASE_URL}/api/public/v1/summits/${summitId}`);
183
184
 
184
- apiUrl.addQuery('expand', 'event_types,tracks,track_groups,presentation_levels,locations.rooms,locations.floors,order_extra_questions.values,schedule_settings,schedule_settings.filters,schedule_settings.pre_filters');
185
+ const expand = [
186
+ 'event_types',
187
+ 'tracks',
188
+ 'tracks.subtracks',
189
+ 'track_groups',
190
+ 'presentation_levels',
191
+ 'locations.rooms',
192
+ 'locations.floors',
193
+ 'order_extra_questions.values',
194
+ 'schedule_settings',
195
+ 'schedule_settings.filters',
196
+ 'schedule_settings.pre_filters',
197
+ ]
198
+
199
+ apiUrl.addQuery('expand', expand.join(','));
185
200
 
186
201
  return fetch(apiUrl.toString(), {
187
202
  method: 'GET'
@@ -239,4 +239,20 @@ export const synchEntityData = (
239
239
  dispatch(createAction(RELOAD_EVENT_STATE)(entity));
240
240
  }
241
241
 
242
- }
242
+ // check if it's a presentation to reload event state
243
+ if (entity && entity_type === 'PresentationSpeaker' && entity_operator === 'UPDATE' && event &&
244
+ (
245
+ // current loaded event is a presentation on where speakers is a presenter
246
+ (entity.all_presentations && entity.all_presentations.find(id => id == event?.id))
247
+ ||
248
+ // current loaded event is a presentation on where speakers is a moderator
249
+ (entity.all_moderated_presentations && entity.all_moderated_presentations.find(id => id == event?.id))
250
+ )
251
+ )
252
+ {
253
+ const idx = allIDXEvents[event?.id];
254
+ const updatedEvent = eventsData[idx];
255
+ dispatch(createAction(RELOAD_EVENT_STATE)(updatedEvent));
256
+ }
257
+
258
+ }
@@ -9,6 +9,8 @@ import {
9
9
  stopLoading,
10
10
  } from 'openstack-uicore-foundation/lib/utils/actions';
11
11
 
12
+ import {putOnLocalStorage, getFromLocalStorage} from 'openstack-uicore-foundation/lib/utils/methods';
13
+
12
14
  import {
13
15
  getAccessToken,
14
16
  clearAccessToken,
@@ -23,6 +25,7 @@ import { navigate } from 'gatsby';
23
25
  import { customErrorHandler, customBadgeHandler, voidErrorHandler } from '../utils/customErrorHandler';
24
26
  import { getEnvVariable, SUMMIT_API_BASE_URL, SUMMIT_ID } from "../utils/envVariables";
25
27
  import expiredToken from "../utils/expiredToken";
28
+ import * as Sentry from "@sentry/react";
26
29
 
27
30
  export const GET_DISQUS_SSO = 'GET_DISQUS_SSO';
28
31
  export const GET_USER_PROFILE = 'GET_USER_PROFILE';
@@ -55,11 +58,15 @@ export const REQUEST_INVITATION = 'REQUEST_INVITATION';
55
58
  export const RECEIVE_INVITATION = 'RECEIVE_INVITATION';
56
59
  export const REJECT_INVITATION = 'REJECT_INVITATION';
57
60
 
61
+ const DISQUS_SSO_EXPIRATION = "DISQUS_SSO_EXPIRATION";
62
+
58
63
  // shortName is the unique identifier assigned to a Disqus site.
59
64
  export const getDisqusSSO = (shortName) => async (dispatch, getState) => {
60
65
  const { userState: { disqusSSO } } = getState();
66
+ const almostTwoHours = 1000 * 60 * 60 * 1.9;
67
+ const disqusSsoExpiration = parseInt(getFromLocalStorage(DISQUS_SSO_EXPIRATION)) || 0;
61
68
 
62
- if (disqusSSO !== null) return;
69
+ if (disqusSSO && disqusSsoExpiration > Date.now()) return;
63
70
 
64
71
  let accessToken;
65
72
  try {
@@ -74,11 +81,16 @@ export const getDisqusSSO = (shortName) => async (dispatch, getState) => {
74
81
  createAction(GET_DISQUS_SSO),
75
82
  `${window.IDP_BASE_URL}/api/v1/sso/disqus/${shortName}/profile?access_token=${accessToken}`,
76
83
  customErrorHandler
77
- )({})(dispatch).catch(e => {
78
- console.log('ERROR: ', e);
79
- clearAccessToken();
84
+ )({})(dispatch)
85
+ .then(() => {
86
+ putOnLocalStorage(DISQUS_SSO_EXPIRATION, Date.now() + almostTwoHours)
87
+ })
88
+ .catch(e => {
89
+ console.log('ERROR: ', e);
90
+ Sentry.captureException(e)
91
+ clearAccessToken();
80
92
 
81
- return Promise.reject(e);
93
+ return Promise.reject(e);
82
94
  });
83
95
  }
84
96
 
@@ -34,7 +34,7 @@ const sbAuthProps = {
34
34
 
35
35
  const adminGroups = ["administrators", "super-admins"];
36
36
 
37
- const AttendeesWidgetComponent = ({ user, event, chatSettings }) => {
37
+ const AttendeesWidgetComponent = ({ user, event, summit, chatSettings }) => {
38
38
  const [loading, setLoading] = useState(true);
39
39
 
40
40
  //Deep linking support
@@ -127,11 +127,14 @@ const AttendeesWidgetComponent = ({ user, event, chatSettings }) => {
127
127
  twitterName: twitter_name,
128
128
  wechatUser: wechat_user,
129
129
  },
130
- getBadgeFeatures: () =>
131
- summit_tickets
130
+ getBadgeFeatures: () => {
131
+ const attendeeBadgeFeatureIds = [...new Set(summit_tickets
132
132
  .filter((st) => st.badge)
133
133
  .flatMap((st) => st.badge.features)
134
- .filter((v, i, a) => a.map((item) => item.id).indexOf(v.id) === i),
134
+ .map((feature) => feature.id))]
135
+
136
+ return summit.badge_features_types.filter((bft) => attendeeBadgeFeatureIds.includes(bft.id));
137
+ },
135
138
  bio: bio,
136
139
  showEmail: public_profile_show_email === true,
137
140
  allowChatWithMe: public_profile_allow_chat_with_me === true,
@@ -170,7 +173,7 @@ const AttendeesWidgetComponent = ({ user, event, chatSettings }) => {
170
173
  }
171
174
  },
172
175
  },
173
- summitId: parseInt(getEnvVariable(SUMMIT_ID)),
176
+ summit: summit,
174
177
  height: 400,
175
178
  defaultScope: chatSettings?.defaultScope || scopes.PAGE, //Default attendees filter scope (scopes.PAGE | scopes.SHOW)
176
179
  ...chatProps,
@@ -197,7 +200,7 @@ const mapState = ({ settingState }) => ({
197
200
 
198
201
  export const AttendeesWidget = connect(mapState)(AttendeesWidgetComponent);
199
202
 
200
- const AccessTracker = ({ user, isLoggedUser, summitPhase, chatSettings }) => {
203
+ const AccessTracker = ({ user, isLoggedUser, summitPhase, chatSettings, updateChatProfileEnabled=false }) => {
201
204
  const chatProps = {
202
205
  streamApiKey: getEnvVariable(STREAM_IO_API_KEY),
203
206
  apiBaseUrl: getEnvVariable(IDP_BASE_URL),
@@ -297,8 +300,11 @@ const AccessTracker = ({ user, isLoggedUser, summitPhase, chatSettings }) => {
297
300
  showSocialInfo: public_profile_show_social_media_info === true,
298
301
  showBio: public_profile_show_bio === true
299
302
  },
300
- summitId: parseInt(getEnvVariable(SUMMIT_ID)),
303
+ summit: {
304
+ id: parseInt(getEnvVariable(SUMMIT_ID)),
305
+ },
301
306
  keepAliveEnabled: true,
307
+ updateChatProfileEnabled: updateChatProfileEnabled,
302
308
  ...chatProps,
303
309
  ...sbAuthProps
304
310
  };
@@ -312,7 +318,7 @@ const mapStateToProps = ({ loggedUserState, userState, clockState, settingState
312
318
  isLoggedUser: loggedUserState.isLoggedUser,
313
319
  user: userState,
314
320
  summitPhase: clockState.summit_phase,
315
- chatSettings: settingState.widgets.chat,
321
+ chatSettings: settingState.widgets.chat
316
322
  });
317
323
 
318
324
  export default connect(mapStateToProps)(AccessTracker);
@@ -129,10 +129,13 @@ const AuthComponent = ({
129
129
 
130
130
  const sendCode = (email) => {
131
131
  setUserEmail(email);
132
- getPasswordlessCode(email).then(({ response }) => {
132
+ return getPasswordlessCode(email).then(({ response }) => {
133
133
  setOtpLength(response.otp_length);
134
134
  setOtpLogin(true);
135
- });
135
+ }).catch((err) => {
136
+ const errorMessage = err.response?.body?.error || err.message;
137
+ return Promise.reject(new Error(errorMessage));
138
+ })
136
139
  }
137
140
 
138
141
  const siteSettings = useSiteSettings();
@@ -1,20 +1,17 @@
1
- import React from 'react';
2
- import { connect } from 'react-redux';
3
- import Clock from 'openstack-uicore-foundation/lib/components/clock';
4
- import { updateClock } from '../actions/clock-actions';
1
+ import React from "react";
2
+ import { connect } from "react-redux";
3
+ import Clock from "openstack-uicore-foundation/lib/components/clock";
4
+ import { updateClock } from "../actions/clock-actions";
5
5
 
6
6
  const ClockComponent = ({
7
7
  active,
8
8
  summit,
9
9
  updateClock
10
10
  }) => {
11
+ if (!active || !summit) return null;
11
12
  return (
12
- <div>
13
- {active && summit &&
14
- <Clock onTick={(timestamp) => updateClock(timestamp)} timezone={summit.time_zone_id} />
15
- }
16
- </div>
13
+ <Clock onTick={(timestamp) => updateClock(timestamp)} timezone={summit.time_zone_id} />
17
14
  );
18
15
  }
19
16
 
20
- export default connect(null, { updateClock })(ClockComponent);
17
+ export default connect(null, { updateClock })(ClockComponent);
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, {useEffect, useState} from "react";
2
2
  import { connect } from "react-redux";
3
3
  import { DiscussionEmbed } from "disqus-react";
4
4
  import { withMarketingSettings, MARKETING_SETTINGS_KEYS } from "@utils/useMarketingSettings";
@@ -6,61 +6,53 @@ import { getEnvVariable, DISQUS_SHORTNAME } from "@utils/envVariables";
6
6
  import { getDisqusSSO } from "../actions/user-actions";
7
7
  import PropTypes from "prop-types";
8
8
 
9
- const DisqusComponent = class extends React.Component {
9
+ const DisqusComponent = ({summit, sponsor, event, disqusSSO, hideMobile, title, style, className, page, skipTo, ...props}) => {
10
+ const [isMobile, setIsMobile] = useState(false);
11
+ const shortname = getEnvVariable(DISQUS_SHORTNAME);
12
+ const { auth: remoteAuthS3, public_key: apiKey } = disqusSSO || {};
13
+ const almostTwoHours = 1000 * 60 * 60 * 1.9;
10
14
 
11
- constructor(props) {
12
- super(props);
15
+ useEffect(() => {
16
+ // Resize Handler
17
+ window.addEventListener('resize', onResize);
18
+ setIsMobile(window.innerWidth <= 768);
13
19
 
14
- this.state = {
15
- isMobile: false
16
- };
20
+ return () => {
21
+ window.removeEventListener('resize', onResize);
22
+ }
23
+ }, []);
17
24
 
18
- this.getIdentifier = this.getIdentifier.bind(this);
19
- this.getTitle = this.getTitle.bind(this);
20
- }
25
+ // check Disqus SSO on every render
26
+ useEffect(() => {
27
+ let disqusSsoInterval = null;
21
28
 
22
- componentWillUnmount() {
23
- window.removeEventListener('resize', this.onResize);
24
- }
29
+ if (shortname) {
30
+ props.getDisqusSSO(shortname);
25
31
 
26
- componentDidMount() {
27
- const shortname = getEnvVariable(DISQUS_SHORTNAME);
28
- if (shortname)
29
- this.props.getDisqusSSO(shortname).catch((e) => console.log(e));
30
-
31
- window.addEventListener('resize', this.onResize);
32
- if (window.innerWidth <= 768) {
33
- this.setState({ isMobile: true })
34
- } else {
35
- this.setState({ isMobile: false })
32
+ // Edge case: if component has not rendered for more than 2hrs, we need to force a SSO token refresh.
33
+ disqusSsoInterval = setInterval(() => {
34
+ props.getDisqusSSO(shortname);
35
+ }, almostTwoHours);
36
36
  }
37
- }
38
37
 
39
- onResize = () => {
40
- if (window.innerWidth <= 768 && this.state.isMobile === false) {
41
- this.setState({ isMobile: true })
42
- }
43
- if (window.innerWidth > 768 && this.state.isMobile === true) {
44
- this.setState({ isMobile: false })
38
+ return () => {
39
+ if (disqusSsoInterval) {
40
+ clearInterval(disqusSsoInterval);
41
+ }
45
42
  }
46
- };
47
-
48
- getIdentifier() {
49
- const {
50
- summit,
51
- page,
52
- sponsor,
53
- event,
54
- getMarketingSettingByKey
55
- } = this.props;
43
+ });
56
44
 
57
- let threadsBy = getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusThreadsBy) ?? "event";
45
+ const onResize = () => {
46
+ setIsMobile(window.innerWidth <= 768);
47
+ };
58
48
 
49
+ const getIdentifier = () => {
50
+ const threadsBy = props.getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusThreadsBy) ?? "event";
59
51
  let identifier = null;
60
52
 
61
53
  if (event) {
62
- let eventExcludes = getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusExcludeEvents) ?? [];
63
- let trackExcludes = getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusExcludeTracks) ?? [];
54
+ const eventExcludes = props.getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusExcludeEvents) ?? [];
55
+ const trackExcludes = props.getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusExcludeTracks) ?? [];
64
56
 
65
57
  identifier = eventExcludes.includes(event.id) ? `summit/${summit.id}/event/${event.id}` : null;
66
58
 
@@ -95,20 +87,12 @@ const DisqusComponent = class extends React.Component {
95
87
  return identifier;
96
88
  }
97
89
 
98
- getTitle() {
99
- const {
100
- summit,
101
- page,
102
- sponsor,
103
- event,
104
- getMarketingSettingByKey
105
- } = this.props;
106
-
90
+ const getTitle = () => {
107
91
  let suffix = '';
108
- const threadsBy = getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusThreadsBy) ?? "event";
92
+ const threadsBy = props.getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusThreadsBy) ?? "event";
109
93
 
110
94
  if (event) {
111
- const trackExcludes = getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusExcludeTracks) ?? [];
95
+ const trackExcludes = props.getMarketingSettingByKey(MARKETING_SETTINGS_KEYS.disqusExcludeTracks) ?? [];
112
96
  if (event.track && event.track.id && (threadsBy === 'track' || trackExcludes.includes(event.track.id))) {
113
97
  suffix += ' - ';
114
98
  suffix += event.track.name;
@@ -133,49 +117,40 @@ const DisqusComponent = class extends React.Component {
133
117
  return `${summit.name}${suffix}`;
134
118
  }
135
119
 
136
- render() {
137
- const { isMobile } = this.state || null;
138
- const { disqusSSO, hideMobile = null } = this.props;
139
-
140
- if (!disqusSSO || (hideMobile !== null && hideMobile === isMobile)) {
141
- return null;
142
- }
120
+ if (!disqusSSO || (hideMobile !== null && hideMobile === isMobile)) {
121
+ return null;
122
+ }
143
123
 
144
- const { auth: remoteAuthS3, public_key: apiKey } = disqusSSO;
145
- const shortname = getEnvVariable(DISQUS_SHORTNAME);
124
+ if (!remoteAuthS3 || !apiKey || !shortname) {
125
+ let error = 'Disqus misconfiguration: ';
126
+ if (!remoteAuthS3) error = ` ${error} ${!remoteAuthS3 ? 'SSO remoteAuthS3 missing' : ''}`;
127
+ if (!apiKey) error = ` ${error} ${!apiKey ? 'SSO apiKey missing' : ''}`;
128
+ if (!shortname) error = ` ${error} ${!shortname ? 'DISQUS_SHORTNAME env var missing' : ''}`;
129
+ return error;
130
+ }
146
131
 
147
- if (!remoteAuthS3 || !apiKey || !shortname) {
148
- let error = 'Disqus misconfiguration: ';
149
- if (!remoteAuthS3) error = ` ${error} ${!remoteAuthS3 ? 'SSO remoteAuthS3 missing' : ''}`;
150
- if (!apiKey) error = ` ${error} ${!apiKey ? 'SSO apiKey missing' : ''}`;
151
- if (!shortname) error = ` ${error} ${!shortname ? 'DISQUS_SHORTNAME env var missing' : ''}`;
152
- return error;
153
- }
132
+ const disqusConfig = {
133
+ url: window.location.href,
134
+ identifier: getIdentifier(),
135
+ title: getTitle(),
136
+ remoteAuthS3: remoteAuthS3,
137
+ apiKey: apiKey
138
+ };
154
139
 
155
- const disqusConfig = {
156
- url: window.location.href,
157
- identifier: this.getIdentifier(),
158
- title: this.getTitle(),
159
- remoteAuthS3: remoteAuthS3,
160
- apiKey: apiKey
161
- };
162
-
163
- const { title, style, className, page, skipTo } = this.props;
164
- const sectionClass = className ? className : style || page === 'marketing-site' ? '' : 'disqus-container';
165
-
166
- return (
167
- <section aria-labelledby={title ? 'disqus-title' : ''} className={sectionClass} style={style}>
168
- <div className="disqus-header">
169
- {skipTo && <a className="sr-only skip-to-next" href={skipTo}>Skip to next section</a>}
170
- {title && <h2 id="disqus-title" className="title">{title}</h2>}
171
- </div>
172
- <DiscussionEmbed
173
- shortname={shortname}
174
- config={disqusConfig}
175
- />
176
- </section>
177
- );
178
- }
140
+ const sectionClass = className ? className : style || page === 'marketing-site' ? '' : 'disqus-container';
141
+
142
+ return (
143
+ <section aria-labelledby={title ? 'disqus-title' : ''} className={sectionClass} style={style}>
144
+ <div className="disqus-header">
145
+ {skipTo && <a className="sr-only skip-to-next" href={skipTo}>Skip to next section</a>}
146
+ {title && <h2 id="disqus-title" className="title">{title}</h2>}
147
+ </div>
148
+ <DiscussionEmbed
149
+ shortname={shortname}
150
+ config={disqusConfig}
151
+ />
152
+ </section>
153
+ );
179
154
  };
180
155
 
181
156
  const mapStateToProps = ({ summitState, userState }) => ({
@@ -27,7 +27,7 @@ const FullSchedule = ({
27
27
  ...rest
28
28
  }) => {
29
29
  const { getSettingByKey } = useMarketingSettings();
30
- const defaultImage = getSettingByKey(MARKETING_SETTINGS_KEYS.schedultDefaultImage);
30
+ const defaultImage = getSettingByKey(MARKETING_SETTINGS_KEYS.scheduleDefaultImage);
31
31
  const summitLogoPrint = getSettingByKey(MARKETING_SETTINGS_KEYS.fullScheduleSummitLogoPrint);
32
32
  const componentProps = {
33
33
  title: "Schedule",
@@ -0,0 +1,61 @@
1
+ import React, { useEffect } from "react";
2
+ import { navigate } from "gatsby";
3
+ import { Box, Typography } from "@mui/material";
4
+
5
+ const containerStyles = (contained) => ({
6
+ display: "flex",
7
+ flexDirection: "column",
8
+ justifyContent: "center",
9
+ width: "100%",
10
+ height: contained ? "100%" : "100vh"
11
+ });
12
+
13
+ const titleStyle = {
14
+ color: "var(--color_text_dark)",
15
+ fontFamily: "var(--font_family)",
16
+ fontSize: "2rem",
17
+ fontWeight: 600,
18
+ lineHeight: 1.125,
19
+ };
20
+
21
+ const subtitleStyle = {
22
+ color: "var(--color_text_dark)",
23
+ fontFamily: "var(--font_family)",
24
+ fontSize: "1.25rem",
25
+ fontWeight: 400,
26
+ lineHeight: 1.25,
27
+ };
28
+
29
+ const Interstitial = ({
30
+ children,
31
+ title,
32
+ subtitle,
33
+ navigateTo,
34
+ navigateOptions = {},
35
+ timeout = 3000,
36
+ contained = false
37
+ }) => {
38
+ useEffect(() => {
39
+ if (navigateTo) {
40
+ const timer = setTimeout(() => navigate(navigateTo, navigateOptions), timeout);
41
+ return () => clearTimeout(timer);
42
+ }
43
+ }, [navigateTo, navigateOptions, timeout]);
44
+
45
+ return (
46
+ <Box sx={containerStyles(contained)}>
47
+ {children ? (
48
+ children
49
+ ) : (
50
+ <Box sx={{ width: "100%", textAlign: "center" }}>
51
+ <Typography sx={titleStyle} gutterBottom>
52
+ {title}
53
+ </Typography>
54
+ <Typography sx={subtitleStyle}>{subtitle}</Typography>
55
+ </Box>
56
+ )}
57
+ </Box>
58
+ );
59
+ };
60
+
61
+ export default Interstitial;
@@ -5,7 +5,7 @@ import {connect} from "react-redux";
5
5
  // these two libraries are client-side only
6
6
  import LiteSchedule from "lite-schedule-widget/dist";
7
7
  import "lite-schedule-widget/dist/index.css";
8
- // awesome-bootstrap-checkbox css dependency
8
+ // awesome-bootstrap-checkbox css dependency
9
9
  // https://cdnjs.cloudflare.com/ajax/libs/awesome-bootstrap-checkbox/1.0.2/awesome-bootstrap-checkbox.min.css
10
10
  // injected through HeadComponents
11
11
 
@@ -26,7 +26,7 @@ const LiteScheduleComponent = ({
26
26
  ...rest
27
27
  }) => {
28
28
  const { getSettingByKey } = useMarketingSettings();
29
- const defaultImage = getSettingByKey(MARKETING_SETTINGS_KEYS.schedultDefaultImage);
29
+ const defaultImage = getSettingByKey(MARKETING_SETTINGS_KEYS.scheduleDefaultImage);
30
30
  const scheduleState = schedules?.find( s => s.key === schedKey);
31
31
 
32
32
  const componentProps = {
@@ -5,7 +5,7 @@ import {connect} from "react-redux";
5
5
  // these two libraries are client-side only
6
6
  import LiveEventWidget from 'live-event-widget/dist/index.js';
7
7
  import 'live-event-widget/dist/index.css';
8
- // awesome-bootstrap-checkbox css dependency
8
+ // awesome-bootstrap-checkbox css dependency
9
9
  // https://cdnjs.cloudflare.com/ajax/libs/awesome-bootstrap-checkbox/1.0.2/awesome-bootstrap-checkbox.min.css
10
10
  // injected through HeadComponents
11
11
 
@@ -20,9 +20,8 @@ const LiveEventWidgetComponent = ({
20
20
  ...rest
21
21
  }) => {
22
22
  const { getSettingByKey } = useMarketingSettings();
23
- const defaultImage = getSettingByKey(MARKETING_SETTINGS_KEYS.schedultDefaultImage);
23
+ const defaultImage = getSettingByKey(MARKETING_SETTINGS_KEYS.scheduleDefaultImage);
24
24
  const scheduleState = schedules?.find( s => s.key === 'schedule-main');
25
-
26
25
  const widgetProps = {
27
26
  title: "",
28
27
  defaultImage: defaultImage,
@@ -0,0 +1,66 @@
1
+ import * as React from "react";
2
+ import { Box, Typography } from "@mui/material";
3
+ import { epochToMomentTimeZone } from "openstack-uicore-foundation/lib/utils/methods";
4
+ import { PHASES } from "@utils/phasesUtils";
5
+
6
+ const containerStyles = {
7
+ display: "flex",
8
+ flexDirection: "column",
9
+ justifyContent: "center",
10
+ color: "var(--color_text_light)",
11
+ backgroundColor: "var(--color_secondary)",
12
+ aspectRatio: "auto 16/9",
13
+ px: 3,
14
+ py: 5
15
+ };
16
+
17
+ const titleStyle = {
18
+ color: "var(--color_text_light)",
19
+ fontFamily: "var(--font_family)",
20
+ fontSize: "42px",
21
+ fontWeight: 600,
22
+ lineHeight: 1.125
23
+ };
24
+
25
+ const subtitleStyle = {
26
+ color: "var(--color_text_light)",
27
+ fontFamily: "var(--font_family)",
28
+ fontSize: "36px",
29
+ fontWeight: 400,
30
+ lineHeight: 1.25
31
+ };
32
+
33
+ const getSubtitle = (eventClassName, eventPhase, streamingUrl, startDate, timeZoneId) => {
34
+ if (eventClassName !== "Presentation") {
35
+ return "Next session will start soon...";
36
+ }
37
+
38
+ if (eventPhase === PHASES.AFTER && !streamingUrl) {
39
+ return "Session is over. Recording will be available soon.";
40
+ }
41
+
42
+ if (eventPhase < PHASES.DURING || !streamingUrl) {
43
+ const formattedTime = epochToMomentTimeZone(startDate, timeZoneId).format("MMMM D hh:mm A (z)");
44
+ return `This session will be available on ${formattedTime}`;
45
+ }
46
+
47
+ return "";
48
+ };
49
+
50
+ const PrePostEventSlide = ({ summit, event, eventPhase }) => {
51
+ const { title, class_name: eventClassName, start_date: startDate, streaming_url: streamingUrl } = event;
52
+ const { time_zone_id: timeZoneId } = summit;
53
+
54
+ const subtitle = getSubtitle(eventClassName, eventPhase, streamingUrl, startDate, timeZoneId);
55
+
56
+ return (
57
+ <Box sx={containerStyles}>
58
+ <Typography gutterBottom sx={titleStyle}>
59
+ {title}
60
+ </Typography>
61
+ <Typography sx={subtitleStyle}>{subtitle}</Typography>
62
+ </Box>
63
+ );
64
+ };
65
+
66
+ export default PrePostEventSlide;