@icvdeveloper/common-module 1.0.3 → 1.0.4

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 (35) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/module.json +1 -1
  3. package/dist/runtime/@types/components.d.ts +77 -0
  4. package/dist/runtime/components/core/AttendeeList.vue +386 -0
  5. package/dist/runtime/components/core/SvgIcon.vue +12 -0
  6. package/dist/runtime/components/events/ListEvents.vue +15 -2
  7. package/dist/runtime/components/media/components/CeCreditNotification.vue +137 -87
  8. package/dist/runtime/components/media/components/DocumentsPanel.vue +104 -27
  9. package/dist/runtime/components/media/components/SponsorsPanel.vue +192 -68
  10. package/dist/runtime/composables/usePusher.d.ts +15 -0
  11. package/dist/runtime/composables/usePusher.mjs +52 -0
  12. package/dist/runtime/models/attendeeList.d.ts +10 -0
  13. package/dist/runtime/models/attendeeList.mjs +0 -0
  14. package/dist/runtime/models/conference.d.ts +15 -0
  15. package/dist/runtime/models/conversation.d.ts +18 -0
  16. package/dist/runtime/models/conversation.mjs +0 -0
  17. package/dist/runtime/models/icons.d.ts +2 -0
  18. package/dist/runtime/models/pagination.d.ts +14 -0
  19. package/dist/runtime/models/pagination.mjs +1 -0
  20. package/dist/runtime/models/user.d.ts +17 -0
  21. package/dist/runtime/models/user.mjs +0 -0
  22. package/dist/runtime/plugin.mjs +1 -1
  23. package/dist/runtime/store/attendeeList.d.ts +27 -0
  24. package/dist/runtime/store/attendeeList.mjs +74 -0
  25. package/dist/runtime/store/auth.d.ts +1 -0
  26. package/dist/runtime/store/auth.mjs +21 -4
  27. package/dist/runtime/store/conversations.d.ts +10 -0
  28. package/dist/runtime/store/conversations.mjs +26 -0
  29. package/dist/runtime/store/navigationConfig.d.ts +1 -1
  30. package/dist/runtime/store/user.d.ts +7 -0
  31. package/dist/runtime/store/user.mjs +23 -0
  32. package/package.json +6 -1
  33. package/dist/runtime/components/media/components/CeCreditNotification.vue.d.ts +0 -28
  34. package/dist/runtime/components/media/components/DocumentsPanel.vue.d.ts +0 -7
  35. package/dist/runtime/components/media/components/SponsorsPanel.vue.d.ts +0 -27
package/CHANGELOG.md CHANGED
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 1.0.4 - 2023-09-21
11
+
10
12
  ## 1.0.3 - 2023-06-20
11
13
 
12
14
  ## 1.0.2 - 2023-06-20
package/dist/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "v3plus-common-module",
3
3
  "configKey": "v3plusCommonModule",
4
- "version": "1.0.3"
4
+ "version": "1.0.4"
5
5
  }
@@ -174,6 +174,57 @@ export type OverviewPanelClassObj = {
174
174
  htmlElement?: string | null;
175
175
  noOverviewElement?: string | null;
176
176
  };
177
+ export type CeCreditPanelClassObj = {
178
+ container?: string | null;
179
+ containerInner?: string | null;
180
+ timeRemaining?: string | null;
181
+ timeInSeconds?: string | null;
182
+ promptText?: string | null;
183
+ buttonContainer?: string | null;
184
+ acceptButton?: string | null;
185
+ };
186
+ export type DocumentsPanelClassObj = {
187
+ container?: string | null;
188
+ documentList?: string | null;
189
+ listElement?: string | null;
190
+ lastElement?: string | null;
191
+ elementLink?: string | null;
192
+ elementText?: string | null;
193
+ elementDescription?: string | null;
194
+ noDocumentsElement?: string | null;
195
+ noDocumentsText?: string | null;
196
+ };
197
+ export type PresentersPanelClassObj = {
198
+ container?: string | null;
199
+ presenterList?: string | null;
200
+ listElement?: string | null;
201
+ lastElement?: string | null;
202
+ elementLink?: string | null;
203
+ elementText?: string | null;
204
+ elementDescription?: string | null;
205
+ noPresentersElement?: string | null;
206
+ noPresentersText?: string | null;
207
+ };
208
+ export type SponsorsPanelClassObj = {
209
+ container?: string | null;
210
+ sessionSponsorsContainer?: string | null;
211
+ sessionSponsorsHeader?: string | null;
212
+ sessionSponsorsInner?: string | null;
213
+ sessionSponsor?: string | null;
214
+ sponsorLink?: string | null;
215
+ sponsorImage?: string | null;
216
+ trackSponsorsContainer?: string | null;
217
+ trackSponsorsHeader?: string | null;
218
+ trackSponsorsInner?: string | null;
219
+ trackSponsor?: string | null;
220
+ trackLink?: string | null;
221
+ trackImage?: string | null;
222
+ noSponsorsElement?: string | null;
223
+ noSponsorsText?: string | null;
224
+ };
225
+ export type ContentAccordionClassObj = {
226
+ container?: string | null;
227
+ };
177
228
  export type ContentTabsClassObj = {
178
229
  container?: string | null;
179
230
  fullContainer?: string | null;
@@ -301,3 +352,29 @@ export type ProfileClassObj = {
301
352
  contentName?: string | null;
302
353
  components?: ProfileCompObj;
303
354
  };
355
+ export type AttendeeListCompObj = {};
356
+ export type AttendeeListClassObj = {
357
+ container?: string | null;
358
+ searchContainer?: string | null;
359
+ searchContainerInner?: string | null;
360
+ searchField?: string | null;
361
+ closeContainer?: string | null;
362
+ contentContainer?: string | null;
363
+ attendeeElement?: string | null;
364
+ attendeeContent?: string | null;
365
+ imageContainer?: string | null;
366
+ attendeeImage?: string | null;
367
+ attendeeContentInner?: string | null;
368
+ attendeeText?: string | null;
369
+ attendeeNameEmail?: string | null;
370
+ statusContainer?: string | null;
371
+ statusText?: string | null;
372
+ attendeeTitle?: string | null;
373
+ attendeeCompany?: string | null;
374
+ socialContainer?: string | null;
375
+ socialLink?: string | null;
376
+ buttonsContainer?: string | null;
377
+ buttonsContainerInner?: string | null;
378
+ chatButton?: string | null;
379
+ videoChatButton?: string | null;
380
+ };
@@ -0,0 +1,386 @@
1
+ <script lang="ts" setup>
2
+ import { ref, onBeforeUnmount } from "vue";
3
+ import { storeToRefs } from "pinia";
4
+ import { debounce } from "lodash-es";
5
+ import { VueEternalLoading, LoadAction } from "@ts-pro/vue-eternal-loading";
6
+ import { User } from "../../models/user";
7
+ import { PAGE_LENGTH } from "../../models/pagination";
8
+ import { useAttendeeListStore } from "../../store/attendeeList";
9
+ import { useConversationStore } from "../../store/conversations";
10
+ import { useUserStore } from "../../store/user";
11
+ import { usePusher } from "../../composables/usePusher";
12
+ import { useClassBinding } from "../../composables/useClassBinding";
13
+ import {
14
+ AttendeeListClassObj,
15
+ AttendeeListCompObj,
16
+ } from "../../@types/components";
17
+
18
+ type Props = {
19
+ classObject?: AttendeeListClassObj;
20
+ };
21
+
22
+ const props = withDefaults(defineProps<Props>(), {
23
+ classObject: () => {
24
+ return {
25
+ container: "",
26
+ components: ref<AttendeeListCompObj>({}),
27
+ };
28
+ },
29
+ });
30
+
31
+ const { getAttendeeList, clearAttendeeList } = useAttendeeListStore();
32
+ const { toggleChat, createConversation } = useConversationStore();
33
+
34
+ const { currentUser } = storeToRefs(useUserStore());
35
+ const { isLoggedIn } = storeToRefs(useAuthStore());
36
+ const { chatOpen } = storeToRefs(useConversationStore());
37
+
38
+ const { classObject } = toRefs(props);
39
+
40
+ const { joinPresenceChannel } = usePusher();
41
+ const { classBinding } = useClassBinding();
42
+
43
+ const search = ref<string>("");
44
+ const currentPage = ref(1);
45
+ const isInitial = ref(true);
46
+ const loadedUsersRef = ref<User[]>([]);
47
+
48
+ // // emits
49
+ const emit = defineEmits<{
50
+ (event: "createVideoChat", value: User): void;
51
+ }>();
52
+
53
+ // // methods
54
+ const filterUsers = debounce(async () => {
55
+ clearAttendeeList();
56
+ clearLoadedUsers();
57
+ currentPage.value = 1;
58
+ const loadedItems = await getAttendeeList({
59
+ pageNumber: currentPage.value,
60
+ searchParams: search.value,
61
+ });
62
+ loadedUsersRef.value = loadedItems.data;
63
+ }, 500);
64
+
65
+ const load = async ({ loaded }: LoadAction): Promise<void> => {
66
+ currentPage.value += 1;
67
+ const existingList: User[] = loadedUsersRef.value;
68
+ const loadedItems = await getAttendeeList({
69
+ pageNumber: currentPage.value,
70
+ searchParams: search.value,
71
+ });
72
+ loadedUsersRef.value = [...existingList, ...loadedItems.data];
73
+ loaded(loadedItems.data.length, PAGE_LENGTH);
74
+ };
75
+
76
+ const clearSearchValue = () => {
77
+ search.value = "";
78
+ };
79
+
80
+ const clearLoadedUsers = () => {
81
+ loadedUsersRef.value = [];
82
+ };
83
+
84
+ const resetAll = async () => {
85
+ clearSearchValue();
86
+ clearAttendeeList();
87
+ clearLoadedUsers();
88
+ currentPage.value = 1;
89
+ const loadedItems = await getAttendeeList({
90
+ pageNumber: currentPage.value,
91
+ searchParams: search.value,
92
+ });
93
+ loadedUsersRef.value = loadedItems.data;
94
+ isInitial.value = true;
95
+ };
96
+
97
+ const createChatConversation = async (user: User) => {
98
+ const users: User[] = [];
99
+ users.push(user);
100
+
101
+ await createConversation(users);
102
+
103
+ if (!chatOpen) {
104
+ toggleChat();
105
+ }
106
+ };
107
+
108
+ // lifecycle
109
+ clearAttendeeList();
110
+ const loadedItems = await getAttendeeList({
111
+ pageNumber: currentPage.value,
112
+ searchParams: search.value,
113
+ });
114
+ loadedUsersRef.value = loadedItems.data;
115
+
116
+ onBeforeUnmount(() => {
117
+ resetAll();
118
+ });
119
+
120
+ watch(isLoggedIn, () => {
121
+ if (isLoggedIn.value) {
122
+ joinPresenceChannel();
123
+ }
124
+ });
125
+ </script>
126
+
127
+ <template>
128
+ <div :class="classBinding(classObject, 'container', 'flex flex-col h-full')">
129
+ <div
130
+ :class="
131
+ classBinding(
132
+ classObject,
133
+ 'searchContainer',
134
+ 'flex w-full justify-end border p-3'
135
+ )
136
+ "
137
+ >
138
+ <div
139
+ :class="
140
+ classBinding(
141
+ classObject,
142
+ 'searchContainerInner',
143
+ 'flex-1 md:flex-initial flex flex-row items-center w-64'
144
+ )
145
+ "
146
+ >
147
+ <input
148
+ v-model="search"
149
+ type="text"
150
+ :class="
151
+ classBinding(classObject, 'searchField', 'w-full px-2 border py-3')
152
+ "
153
+ placeholder="Search..."
154
+ @input="filterUsers"
155
+ />
156
+ <span
157
+ :class="
158
+ classBinding(classObject, 'closeContainer', 'ml-2 cursor-pointer')
159
+ "
160
+ @click="resetAll()"
161
+ >
162
+ <CommonSvgIcon
163
+ icon="close"
164
+ class="fill-current text-black flex items-center justify-center"
165
+ ></CommonSvgIcon>
166
+ </span>
167
+ </div>
168
+ </div>
169
+ <div
170
+ :class="
171
+ classBinding(
172
+ classObject,
173
+ 'contentContainer',
174
+ 'user-container flex flex-col border-l border-r border-b md:p-5 overflow-y-auto'
175
+ )
176
+ "
177
+ >
178
+ <div
179
+ v-for="(user, index) in loadedUsersRef"
180
+ :key="index"
181
+ :class="
182
+ classBinding(
183
+ classObject,
184
+ 'attendeeElement',
185
+ 'user-list-item flex flex-col md:flex-row border p-4 md:mt-3 justify-between'
186
+ )
187
+ "
188
+ >
189
+ <div
190
+ :class="
191
+ classBinding(
192
+ classObject,
193
+ 'attendeeContent',
194
+ 'flex-initial flex flex-row items-center'
195
+ )
196
+ "
197
+ >
198
+ <div
199
+ :class="
200
+ classBinding(
201
+ classObject,
202
+ 'imageContainer',
203
+ 'aspect-square flex-initial flex items-center md:mr-5'
204
+ )
205
+ "
206
+ >
207
+ <img
208
+ :class="
209
+ classBinding(
210
+ classObject,
211
+ 'attendeeImage',
212
+ 'w-full max-w-100 aspect-square'
213
+ )
214
+ "
215
+ :src="user.profile_image"
216
+ alt=""
217
+ />
218
+ </div>
219
+
220
+ <div :class="classBinding(classObject, 'attendeeContentInner', '')">
221
+ <p
222
+ :class="
223
+ classBinding(
224
+ classObject,
225
+ 'attendeeText',
226
+ 'mb-0 pb-1 text-base md:text-lg text-left'
227
+ )
228
+ "
229
+ >
230
+ <span
231
+ v-if="user.name"
232
+ :class="classBinding(classObject, 'attendeeNameEmail', 'pl-2')"
233
+ >{{ user.name }}</span
234
+ >
235
+ <span
236
+ v-else
237
+ :class="classBinding(classObject, 'attendeeNameEmail', 'pl-2')"
238
+ >{{ user.email }}</span
239
+ >
240
+ <span
241
+ v-if="isLoggedIn"
242
+ :class="
243
+ classBinding(classObject, 'statusContainer', 'block text-sm')
244
+ "
245
+ >
246
+ <CommonSvgIcon
247
+ :icon="[user.online ? 'online' : 'offline']"
248
+ width="0"
249
+ class="w-4 my-0 mr-1 inline-block"
250
+ ></CommonSvgIcon>
251
+ <span
252
+ :class="
253
+ classBinding(classObject, 'statusText', 'inline-block')
254
+ "
255
+ >{{ user.online ? "online" : "offline" }}</span
256
+ >
257
+ </span>
258
+ </p>
259
+
260
+ <p
261
+ v-if="user.title"
262
+ :class="
263
+ classBinding(
264
+ classObject,
265
+ 'attendeeTitle',
266
+ 'pl-2 mb-0 min-height-paragraph leading-tight'
267
+ )
268
+ "
269
+ >
270
+ {{ user.title }}
271
+ </p>
272
+ <p
273
+ v-if="user.company"
274
+ :class="
275
+ classBinding(
276
+ classObject,
277
+ 'attendeeCompany',
278
+ 'pl-2 min-height-paragraph leading-tight'
279
+ )
280
+ "
281
+ >
282
+ {{ user.company }}
283
+ </p>
284
+
285
+ <span :class="classBinding(classObject, 'socialContainer', 'flex')">
286
+ <a
287
+ v-if="user.twitter_url"
288
+ :href="user.twitter_url"
289
+ target="_blank"
290
+ :class="classBinding(classObject, 'socialLink', 'mr-2')"
291
+ :aria-label="user.name + ` Twitter Page`"
292
+ >
293
+ <span><CommonSvgIcon icon="twitter"></CommonSvgIcon></span>
294
+ </a>
295
+
296
+ <a
297
+ v-if="user.linkedin_url"
298
+ :href="user.linkedin_url"
299
+ target="_blank"
300
+ :class="classBinding(classObject, 'socialLink', 'mr-2')"
301
+ :aria-label="user.name + ` LinkedIn Page`"
302
+ >
303
+ <span><CommonSvgIcon icon="linkedin"></CommonSvgIcon></span>
304
+ </a>
305
+ </span>
306
+ </div>
307
+ </div>
308
+
309
+ <div
310
+ :class="
311
+ classBinding(
312
+ classObject,
313
+ 'buttonsContainer',
314
+ 'flex items-end h-full'
315
+ )
316
+ "
317
+ >
318
+ <div
319
+ :class="
320
+ classBinding(
321
+ classObject,
322
+ 'buttonsContainerInner',
323
+ 'w-full flex justify-end md:justify-start'
324
+ )
325
+ "
326
+ >
327
+ <button
328
+ v-if="isLoggedIn && user.id !== currentUser.id"
329
+ :class="
330
+ classBinding(
331
+ classObject,
332
+ 'chatButton',
333
+ 'text-white bg-green-500 px-3 py-1 border border-green-700 mr-2'
334
+ )
335
+ "
336
+ @click="createChatConversation(user)"
337
+ >
338
+ Chat
339
+ </button>
340
+ <button
341
+ v-if="
342
+ isLoggedIn &&
343
+ user.id !== currentUser.id &&
344
+ user.online &&
345
+ user.video_chat
346
+ "
347
+ :class="
348
+ classBinding(
349
+ classObject,
350
+ 'videoChatButton',
351
+ 'text-white bg-green-500 px-3 py-1 border border-green-700'
352
+ )
353
+ "
354
+ @click="emit('createVideoChat', user)"
355
+ >
356
+ Video Chat
357
+ </button>
358
+ </div>
359
+ </div>
360
+ </div>
361
+ <VueEternalLoading
362
+ v-model:is-initial="isInitial"
363
+ :load="load"
364
+ ></VueEternalLoading>
365
+ </div>
366
+ </div>
367
+ </template>
368
+
369
+ <style>
370
+ .user-container {
371
+ max-height: 400px;
372
+ height: 400px;
373
+ }
374
+
375
+ .user-list-item {
376
+ border-top: 6px solid rgb(31, 60, 249);
377
+ }
378
+
379
+ .min-height-paragraph {
380
+ min-height: 1em;
381
+ }
382
+
383
+ .max-w-100 {
384
+ max-width: 100px;
385
+ }
386
+ </style>
@@ -99,6 +99,18 @@ const icons: Icons = {
99
99
  () => import("../../assets/svg/icon-circle-minus.svg")
100
100
  ),
101
101
  },
102
+ online: {
103
+ color: "#22c55e",
104
+ component: defineAsyncComponent(
105
+ () => import("../../assets/svg/icon-online.svg")
106
+ ),
107
+ },
108
+ offline: {
109
+ color: "#696665",
110
+ component: defineAsyncComponent(
111
+ () => import("../../assets/svg/icon-offline.svg")
112
+ ),
113
+ },
102
114
  };
103
115
 
104
116
  type Props = {
@@ -1,7 +1,7 @@
1
1
  <script lang="ts" setup>
2
2
  import { ref, toRefs, computed } from "vue";
3
3
  import { storeToRefs } from "pinia";
4
- import { get } from "lodash-es";
4
+ import { get, reverse } from "lodash-es";
5
5
  import { useConferencesStore } from "../../store/conferences";
6
6
  import { useTemplateConfigsStore } from "../../store/templateConfigs";
7
7
  import { useConferenceHelpers } from "../../composables/useConferenceHelpers";
@@ -31,6 +31,7 @@ interface Props {
31
31
  registerPathPrefix?: string;
32
32
  liveButtonOpensStream?: boolean;
33
33
  isUpcoming?: boolean;
34
+ isReversed?: boolean;
34
35
  showEventImage?: boolean;
35
36
  sponsorPosition?: Position;
36
37
  borderPosition?: Position;
@@ -50,6 +51,7 @@ const props = withDefaults(defineProps<Props>(), {
50
51
  registerPathPrefix: "",
51
52
  liveButtonOpensStream: true,
52
53
  isUpcoming: true,
54
+ isReversed: true,
53
55
  showEventImage: true,
54
56
  sponsorPosition: Position.RIGHT,
55
57
  borderPosition: Position.MIDDLE,
@@ -75,6 +77,7 @@ const {
75
77
  loginButton,
76
78
  viewInfoButton,
77
79
  isUpcoming,
80
+ isReversed,
78
81
  showEventImage,
79
82
  sponsorPosition,
80
83
  borderPosition,
@@ -143,7 +146,17 @@ const eventPathPrefix = computed(() => {
143
146
  });
144
147
 
145
148
  const eventType = computed((): Conference[] => {
146
- return isUpcoming.value ? upcomingEvents.value : pastEvents.value;
149
+ if (isUpcoming?.value) {
150
+ if (isReversed?.value) {
151
+ return reverse(upcomingEvents.value);
152
+ } else {
153
+ return upcomingEvents.value;
154
+ }
155
+ } else if (isReversed?.value) {
156
+ return reverse(pastEvents.value);
157
+ } else {
158
+ return pastEvents.value;
159
+ }
147
160
  });
148
161
 
149
162
  const showLoginButton = computed((): boolean => {