@icvdeveloper/common-module 0.0.33 → 0.0.36

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.
@@ -0,0 +1,472 @@
1
+ <script lang="ts" setup>
2
+ import { storeToRefs } from "pinia";
3
+ import { useDateFormat } from "../../composables/useDateFormat";
4
+ import { useConferenceHelpers } from "../../composables/useConferenceHelpers";
5
+ import { useEvents } from "../../composables/useEvents";
6
+ import { useClassBinding } from "../../composables/useClassBinding";
7
+ import CommonSponsor from "../agenda/components/Sponsor.vue";
8
+ import { Conference } from "../../models/conference";
9
+ import { Position } from "../../enums/general";
10
+ import { listEventsClassObj } from "../../@types/components";
11
+
12
+ interface Props {
13
+ showSponsors?: boolean;
14
+ showBrand?: boolean;
15
+ showCountdown?: boolean;
16
+ mediaButton?: boolean;
17
+ registerButton?: boolean;
18
+ loginButton?: boolean;
19
+ viewInfoButton?: boolean;
20
+ isUpcoming?: boolean;
21
+ showEventImage?: boolean;
22
+ sponsorPosition?: Position;
23
+ borderPosition?: Position;
24
+ countdownPosition?: Position;
25
+ classObject?: listEventsClassObj;
26
+ }
27
+
28
+ const props = withDefaults(defineProps<Props>(), {
29
+ showSponsors: true,
30
+ showBrand: true,
31
+ showCountdown: true,
32
+ mediaButton: true,
33
+ registerButton: true,
34
+ loginButton: true,
35
+ viewInfoButton: true,
36
+ isUpcoming: true,
37
+ showEventImage: true,
38
+ sponsorPosition: Position.RIGHT,
39
+ borderPosition: Position.MIDDLE,
40
+ countdownPosition: Position.BOTTOM,
41
+ classObject: () => {
42
+ return {};
43
+ },
44
+ });
45
+
46
+ const {
47
+ showSponsors,
48
+ showBrand,
49
+ showCountdown,
50
+ mediaButton,
51
+ registerButton,
52
+ loginButton,
53
+ viewInfoButton,
54
+ isUpcoming,
55
+ showEventImage,
56
+ sponsorPosition,
57
+ borderPosition,
58
+ countdownPosition,
59
+ classObject,
60
+ } = toRefs(props);
61
+
62
+ // data
63
+ const { pastEvents, upcomingEvents } = storeToRefs(useConferencesStore());
64
+
65
+ // methods
66
+ const { globalConfigValue, pagesConfigValue } = storeToRefs(
67
+ useTemplateConfigsStore()
68
+ );
69
+ const { formatDate } = useDateFormat();
70
+ const {
71
+ isSingleDayEvent,
72
+ showConferenceViewButton,
73
+ getConferenceWebcastUrl,
74
+ getConferenceWebcastButtonText,
75
+ showViewArchiveButton,
76
+ getViewArchiveUrl,
77
+ getViewArchiveButtonText,
78
+ getConferenceRegUrl,
79
+ getConferenceRegText,
80
+ showConferenceRegButton,
81
+ } = useConferenceHelpers();
82
+
83
+ const {
84
+ isLoggedIn,
85
+ loginModalVisible,
86
+ conferenceToLoginTo,
87
+ goEventPage,
88
+ setConferenceToLoginTo,
89
+ buttonClass,
90
+ orderAffiliates,
91
+ getBrand,
92
+ isHomePage,
93
+ } = useEvents();
94
+
95
+ const { classBinding } = useClassBinding();
96
+
97
+ const showViewButton = (_conference: Conference): boolean => {
98
+ return isUpcoming.value
99
+ ? showConferenceViewButton(_conference)
100
+ : showViewArchiveButton(_conference);
101
+ };
102
+
103
+ const getVideoUrl = (_conference: Conference): string => {
104
+ return isUpcoming.value
105
+ ? getConferenceWebcastUrl(_conference)
106
+ : getViewArchiveUrl(_conference);
107
+ };
108
+
109
+ const getVideoButtonText = (_conference: Conference): string => {
110
+ return isUpcoming.value
111
+ ? getConferenceWebcastButtonText(_conference)
112
+ : getViewArchiveButtonText(_conference);
113
+ };
114
+
115
+ // computed
116
+ const eventType = computed((): Conference[] => {
117
+ return isUpcoming.value ? upcomingEvents.value : pastEvents.value;
118
+ });
119
+
120
+ const showLoginButton = computed((): boolean => {
121
+ const archivedHomepage: boolean =
122
+ isUpcoming.value || (!isUpcoming.value && isHomePage.value);
123
+ return (
124
+ archivedHomepage &&
125
+ loginButton.value &&
126
+ !isLoggedIn.value &&
127
+ !globalConfigValue.value("townhall_registration_enabled")
128
+ );
129
+ });
130
+ </script>
131
+
132
+ <template>
133
+ <!-- list container -->
134
+ <div class="flex w-full flex-col">
135
+ <!-- list container -->
136
+ <div
137
+ :class="
138
+ classBinding(classObject, 'listContainer', 'container flex-1 mx-auto')
139
+ "
140
+ >
141
+ <!-- individual event container -->
142
+ <div
143
+ v-for="conference in eventType"
144
+ :key="conference.id"
145
+ :class="[
146
+ {
147
+ 'border-1 border-t border-color-accent-2':
148
+ borderPosition === Position.TOP,
149
+ },
150
+ classBinding(
151
+ classObject,
152
+ 'eventContainer',
153
+ 'flex flex-col items-center md:flex-row py-4'
154
+ ),
155
+ ]"
156
+ >
157
+ <!-- event image -->
158
+ <div
159
+ v-if="showEventImage"
160
+ :class="
161
+ classBinding(
162
+ classObject,
163
+ 'eventImageContainer',
164
+ 'flex w-full md:w-1/3 pb-3 px-3 md:px-6 overflow-hidden'
165
+ )
166
+ "
167
+ >
168
+ <img
169
+ :class="
170
+ classBinding(
171
+ classObject,
172
+ 'eventImage',
173
+ 'flex-1 self-center mx-auto w-full'
174
+ )
175
+ "
176
+ :src="conference.photo"
177
+ />
178
+ </div>
179
+ <!-- event details container -->
180
+ <div
181
+ :class="[
182
+ { 'md:w-2/3': showEventImage },
183
+ classBinding(
184
+ classObject,
185
+ 'eventContentContainer',
186
+ 'flex flex-col justify-center text-center w-full md:pr-6 md:text-left md:justify-start md:items-start'
187
+ ),
188
+ ]"
189
+ >
190
+ <!-- event brand, name, date and countdown container -->
191
+ <div
192
+ :class="[
193
+ {
194
+ 'border-1 border-b border-color-accent-2 mb-6':
195
+ borderPosition === Position.MIDDLE,
196
+ },
197
+ classBinding(
198
+ classObject,
199
+ 'eventDetailsContainer',
200
+ 'w-full flex flex-col lg:flex-row'
201
+ ),
202
+ ]"
203
+ >
204
+ <!-- event details -->
205
+ <div
206
+ :class="classBinding(classObject, 'eventDetails', 'flex-grow')"
207
+ >
208
+ <h3
209
+ v-if="showBrand && getBrand(conference.affiliates).length"
210
+ :class="
211
+ classBinding(
212
+ classObject,
213
+ 'eventBrand',
214
+ 'text-base font-bold leading-tight tracking-wide mb-3'
215
+ )
216
+ "
217
+ >
218
+ {{ getBrand(conference.affiliates) }}
219
+ </h3>
220
+ <nuxt-link
221
+ :to="`/${isUpcoming ? 'upcoming-events' : 'past-events'}/${
222
+ conference.id
223
+ }`"
224
+ class="no-underline"
225
+ >
226
+ <h2
227
+ :class="
228
+ classBinding(
229
+ classObject,
230
+ 'eventName',
231
+ 'text-2xl lg:text-3xl font-medium mb-2 conf-name-alignment'
232
+ )
233
+ "
234
+ >
235
+ {{ conference.name }}
236
+ </h2>
237
+ </nuxt-link>
238
+ <p
239
+ :class="
240
+ classBinding(
241
+ classObject,
242
+ 'eventDate',
243
+ 'text-base leading-normal tracking-wide font-light uppercase md:text-md lg:text-lg'
244
+ )
245
+ "
246
+ >
247
+ {{ formatDate(conference.start_date) }}
248
+ <span v-if="!isSingleDayEvent(conference)">
249
+ - {{ formatDate(conference.end_date) }}</span
250
+ >
251
+ </p>
252
+ </div>
253
+ <!-- countdown timer - top-aligned -->
254
+ <div
255
+ v-if="
256
+ isUpcoming &&
257
+ showCountdown &&
258
+ countdownPosition === Position.TOP &&
259
+ pagesConfigValue('main.countdown_timer')
260
+ "
261
+ :class="
262
+ classBinding(
263
+ classObject,
264
+ 'countdownContainerTop',
265
+ 'flex-auto flex items-center self-center mb-4 lg:mb-0'
266
+ )
267
+ "
268
+ >
269
+ <CommonCountdownTimer
270
+ :date="conference.start_date"
271
+ :is-compact="true"
272
+ :class-object="classObject.components.countdownTimer"
273
+ ></CommonCountdownTimer>
274
+ </div>
275
+ </div>
276
+ <!-- event button, countdown timer, and sponsors container -->
277
+ <div
278
+ :class="
279
+ classBinding(
280
+ classObject,
281
+ 'buttonCountdownSponsorsContainer',
282
+ 'flex flex-col w-full'
283
+ )
284
+ "
285
+ >
286
+ <div
287
+ :class="
288
+ classBinding(
289
+ classObject,
290
+ 'buttonCountdownContainer',
291
+ 'flex-1 flex flex-col justify-between xl:flex-row w-full'
292
+ )
293
+ "
294
+ >
295
+ <div
296
+ :class="
297
+ classBinding(
298
+ classObject,
299
+ 'buttonContainer',
300
+ 'flex-auto mr-0 xl:mr-4'
301
+ )
302
+ "
303
+ >
304
+ <!-- view info button -->
305
+ <button
306
+ v-if="viewInfoButton"
307
+ :class="classBinding(classObject, 'buttonItem', buttonClass)"
308
+ @click="goEventPage(conference)"
309
+ >
310
+ View Info
311
+ </button>
312
+ <!-- view live/preview archive button -->
313
+ <a
314
+ v-if="mediaButton && showViewButton(conference)"
315
+ :href="getVideoUrl(conference)"
316
+ :target="
317
+ /^http/.test(!isUpcoming && getVideoUrl(conference))
318
+ ? '_blank'
319
+ : '_self'
320
+ "
321
+ >
322
+ <button
323
+ :class="
324
+ classBinding(classObject, 'buttonItem', buttonClass)
325
+ "
326
+ >
327
+ {{ getVideoButtonText(conference) }}
328
+ </button>
329
+ </a>
330
+
331
+ <!-- login button -->
332
+ <button
333
+ v-if="showLoginButton"
334
+ :class="classBinding(classObject, 'buttonItem', buttonClass)"
335
+ @click="setConferenceToLoginTo(conference)"
336
+ >
337
+ Log In
338
+ </button>
339
+
340
+ <!-- register button -->
341
+ <a
342
+ v-if="registerButton && showConferenceRegButton(conference)"
343
+ :href="getConferenceRegUrl(conference)"
344
+ :target="
345
+ /^http/.test(getConferenceRegUrl(conference))
346
+ ? '_blank'
347
+ : '_self'
348
+ "
349
+ >
350
+ <button
351
+ :class="
352
+ classBinding(classObject, 'buttonItem', buttonClass)
353
+ "
354
+ >
355
+ {{ getConferenceRegText(conference) }}
356
+ </button>
357
+ </a>
358
+ </div>
359
+ <!-- countdown timer - right-aligned -->
360
+ <div
361
+ v-if="
362
+ isUpcoming &&
363
+ showCountdown &&
364
+ countdownPosition === Position.RIGHT &&
365
+ pagesConfigValue('main.countdown_timer')
366
+ "
367
+ class="flex-auto md:flex mt-3 md:mt-2"
368
+ :class="
369
+ classBinding(
370
+ classObject,
371
+ 'countdownContainerRight',
372
+ 'flex-auto flex items-center self-center mb-4 lg:mb-0'
373
+ )
374
+ "
375
+ >
376
+ <CommonCountdownTimer
377
+ :date="conference.start_date"
378
+ :is-compact="true"
379
+ :class-object="classObject.components.countdownTimer"
380
+ ></CommonCountdownTimer>
381
+ </div>
382
+ </div>
383
+ <!-- countdown timer - bottom-aligned -->
384
+ <div
385
+ v-if="
386
+ isUpcoming &&
387
+ showCountdown &&
388
+ countdownPosition === Position.BOTTOM &&
389
+ pagesConfigValue('main.countdown_timer')
390
+ "
391
+ :class="
392
+ classBinding(
393
+ classObject,
394
+ 'countdownContainerBottom',
395
+ 'flex-auto md:flex my-3 md:my-2'
396
+ )
397
+ "
398
+ >
399
+ <CommonCountdownTimer
400
+ :date="conference.start_date"
401
+ :is-compact="true"
402
+ :class-object="classObject.components.countdownTimer"
403
+ ></CommonCountdownTimer>
404
+ </div>
405
+ <!-- sponsors container - bottom-aligned -->
406
+ <div
407
+ v-if="showSponsors && sponsorPosition === Position.BOTTOM"
408
+ class=""
409
+ :class="
410
+ classBinding(
411
+ classObject,
412
+ 'sponsorsContainer',
413
+ 'grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-y-1.5 gap-x-3'
414
+ )
415
+ "
416
+ >
417
+ <!-- individual sponsor -->
418
+ <template
419
+ v-for="affiliate in orderAffiliates(conference.affiliates)"
420
+ >
421
+ <CommonSponsor
422
+ v-if="affiliate.role == 'sponsor'"
423
+ :key="affiliate.id"
424
+ :sponsor="affiliate"
425
+ :class-object="classObject.components.sponsor"
426
+ ></CommonSponsor>
427
+ </template>
428
+ </div>
429
+ </div>
430
+ </div>
431
+ <!-- sponsors container - right-aligned -->
432
+ <div
433
+ v-if="showSponsors && sponsorPosition === Position.RIGHT"
434
+ class="flex flex-col"
435
+ >
436
+ <!-- individual sponsor -->
437
+ <template v-for="affiliate in orderAffiliates(conference.affiliates)">
438
+ <CommonSponsor
439
+ v-if="affiliate.role == 'sponsor'"
440
+ :key="affiliate.id"
441
+ :sponsor="affiliate"
442
+ :class-object="classObject.components.sponsor"
443
+ ></CommonSponsor>
444
+ </template>
445
+ </div>
446
+ </div>
447
+ </div>
448
+ <!-- login modal -->
449
+ <CommonModal
450
+ :visible="loginModalVisible"
451
+ :class="classObject.components.modal"
452
+ @trigger="loginModalVisible = false"
453
+ >
454
+ <template #modal-body>
455
+ <CommonLoginFullWidth
456
+ :conference="conferenceToLoginTo"
457
+ :class="classObject.components.login"
458
+ />
459
+ </template>
460
+ </CommonModal>
461
+ </div>
462
+ </template>
463
+
464
+ <style lang="scss" scoped>
465
+ .leading-tight {
466
+ line-height: 1.25rem;
467
+ }
468
+
469
+ .mr-4 {
470
+ margin-right: 1rem;
471
+ }
472
+ </style>
@@ -2,29 +2,53 @@
2
2
  import { toRefs } from "vue";
3
3
  import { Presenter } from "../../models/conference";
4
4
  import { usePresenter } from "../../composables/usePresenter";
5
+ import { useClassBinding } from "../../composables/useClassBinding";
6
+ import { presenterListingClassObj } from "../../@types/components";
7
+ import { Position } from "../../enums/general";
5
8
 
6
9
  type Props = {
7
10
  presenter: Presenter;
8
- textClass?: string;
9
- linkClass?: string;
10
11
  enableBio?: boolean;
11
12
  showBio?: boolean;
12
13
  isSmallGroupedTrack?: boolean;
14
+ bioLinkOnName?: boolean;
15
+ bioLinkText?: string;
16
+ bioLinkPosition?: Position;
17
+ imagePosition?: Position;
18
+ classObject?: presenterListingClassObj;
13
19
  };
14
20
 
15
21
  const props = withDefaults(defineProps<Props>(), {
16
- textClass: "font-medium text-lg",
17
- linkClass: "",
18
22
  enableBio: true,
19
23
  showBio: false,
20
24
  isSmallGroupedTrack: false,
25
+ bioLinkOnName: true,
26
+ bioLinkText: "Read More >",
27
+ bioLinkPosition: Position.BOTTOM,
28
+ imagePosition: Position.LEFT,
29
+ classObject: () => {
30
+ return {
31
+ container: "",
32
+ presenterImageContainer: "",
33
+ presenterImage: "",
34
+ presenterContainer: "",
35
+ presenterTextContainer: "",
36
+ presenterNameLink: "",
37
+ presenterName: "",
38
+ presenterRole: "",
39
+ presenterTitle: "",
40
+ presenterBio: "",
41
+ presenterBioLink: "",
42
+ };
43
+ },
21
44
  });
22
45
 
23
46
  const emit = defineEmits(["clicked"]);
24
47
 
25
- const { presenter, textClass, linkClass, enableBio, isSmallGroupedTrack } =
48
+ const { presenter, enableBio, isSmallGroupedTrack, classObject } =
26
49
  toRefs(props);
27
50
  const { fullName, titleCompany } = usePresenter(presenter);
51
+ const { classBinding } = useClassBinding();
28
52
 
29
53
  // methods
30
54
  const handleClick = () => {
@@ -35,34 +59,105 @@ const handleClick = () => {
35
59
  </script>
36
60
 
37
61
  <template>
38
- <div :class="textClass">
39
- <p class="my-1">
40
- <a
41
- v-if="enableBio"
42
- class="cursor-pointer"
43
- :class="linkClass"
44
- @click="handleClick()"
45
- >{{ fullName }}</a
62
+ <div>
63
+ <div
64
+ :class="[
65
+ { 'flex-col': imagePosition !== Position.RIGHT },
66
+ { 'md:flex-row': imagePosition !== Position.TOP },
67
+ { 'flex-col-reverse': imagePosition === Position.RIGHT },
68
+ classBinding(
69
+ classObject,
70
+ 'presenterContainer',
71
+ 'flex-1 flex content-center items-center md:items-start'
72
+ ),
73
+ ]"
74
+ >
75
+ <div
76
+ v-if="presenter.photo.length && imagePosition !== Position.RIGHT"
77
+ :class="
78
+ classBinding(classObject, 'presenterImageContainer', 'shrink p-2')
79
+ "
46
80
  >
47
- <span v-else>{{ fullName }}</span>
48
- <span
49
- v-if="presenter.role == 'moderator'"
50
- class="text-grey-dark"
51
- :class="isSmallGroupedTrack ? 'new-line' : 'no-new-line'"
52
- >Moderator</span
81
+ <img
82
+ :src="presenter.photo"
83
+ :class="classBinding(classObject, 'presenterImage', '')"
84
+ />
85
+ </div>
86
+ <div
87
+ :class="
88
+ classBinding(
89
+ classObject,
90
+ 'presenterTextContainer',
91
+ 'flex flex-col text-center md:text-left self-center'
92
+ )
93
+ "
53
94
  >
54
- <span
55
- v-if="titleCompany"
56
- class="font-light paragraph-color-1"
57
- :class="isSmallGroupedTrack ? 'new-line' : 'new-line-responsive'"
58
- >{{ titleCompany }}</span
95
+ <p class="my-1">
96
+ <a
97
+ v-if="enableBio && bioLinkOnName"
98
+ class="cursor-pointer"
99
+ :class="classBinding(classObject, 'presenterNameLink', '')"
100
+ @click="handleClick()"
101
+ ><span :class="classBinding(classObject, 'presenterName', '')">
102
+ {{ fullName }}</span
103
+ ></a
104
+ >
105
+ <span v-else :class="classBinding(classObject, 'presenterName', '')">
106
+ {{ fullName }}
107
+ </span>
108
+ <span
109
+ v-if="presenter.role == 'moderator'"
110
+ :class="[
111
+ isSmallGroupedTrack ? 'new-line' : 'no-new-line',
112
+ classBinding(classObject, 'presenterRole', 'text-grey-dark'),
113
+ ]"
114
+ >Moderator</span
115
+ >
116
+ <span
117
+ v-if="titleCompany"
118
+ :class="[
119
+ isSmallGroupedTrack ? 'new-line' : 'new-line-responsive',
120
+ classBinding(
121
+ classObject,
122
+ 'presenterTitle',
123
+ 'font-light paragraph-color-1'
124
+ ),
125
+ ]"
126
+ >{{ titleCompany }}</span
127
+ >
128
+ </p>
129
+ <p
130
+ v-if="showBio && presenter.biography"
131
+ :class="
132
+ classBinding(
133
+ classObject,
134
+ 'presenterBio',
135
+ 'font-light text-base paragraph-color-1'
136
+ )
137
+ "
138
+ v-html="presenter.biography"
139
+ ></p>
140
+ <div v-if="enableBio && !bioLinkOnName" class="shrink">
141
+ <a
142
+ class="cursor-pointer"
143
+ :class="classBinding(classObject, 'presenterBioLink', '')"
144
+ @click="handleClick()"
145
+ >{{ bioLinkText }}
146
+ </a>
147
+ </div>
148
+ </div>
149
+ <div
150
+ v-if="presenter.photo.length && imagePosition === Position.RIGHT"
151
+ :class="
152
+ classBinding(classObject, 'presenterImageContainer', 'shrink p-2')
153
+ "
59
154
  >
60
- </p>
61
- <p
62
- v-if="showBio && presenter.biography"
63
- class="font-light text-base paragraph-color-1"
64
- v-html="presenter.biography"
65
- ></p>
155
+ <img
156
+ :src="presenter.photo"
157
+ :class="classBinding(classObject, 'presenterImage', '')"
158
+ />
159
+ </div>
160
+ </div>
66
161
  </div>
67
162
  </template>
68
163
 
@@ -24,14 +24,18 @@ const { fullName, presenterImageStyle, itemWidthStyle, isGrayScale } =
24
24
  <template>
25
25
  <div>
26
26
  <div v-if="useIcon" class="presenter-icon cursor-pointer">
27
- <CommonSvgIcon icon="info" :greyscale="isGrayScale"></CommonSvgIcon>
27
+ <CommonSvgIcon
28
+ icon="info"
29
+ :greyscale="isGrayScale"
30
+ @click="modalVisible = true"
31
+ ></CommonSvgIcon>
28
32
  </div>
29
33
 
30
34
  <CommonPresenterListing
31
35
  v-else
32
36
  :presenter="presenter"
33
37
  :enable-bio="true"
34
- :show-bio="false"
38
+ :show-bio="true"
35
39
  text-class="font-bold text-base"
36
40
  link-class="agenda-presenter-color"
37
41
  :is-small-grouped-track="isSmallGroupedTrack"