@icvdeveloper/common-module 0.0.75 → 0.0.78

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/dist/module.json +1 -1
  2. package/dist/module.mjs +5 -0
  3. package/dist/runtime/@types/components.d.ts +89 -1
  4. package/dist/runtime/components/agenda/AgendaList.vue +149 -19
  5. package/dist/runtime/components/agenda/AgendaTabbed.vue +9 -0
  6. package/dist/runtime/components/agenda/components/AgendaListAccordion.vue +31 -4
  7. package/dist/runtime/components/agenda/components/Calendar.vue +89 -0
  8. package/dist/runtime/components/media/PlayerAndContentContainer.vue +170 -0
  9. package/dist/runtime/components/media/WebcastVideoPlayer.vue +167 -0
  10. package/dist/runtime/components/media/components/AgendaPanel.vue +53 -0
  11. package/dist/runtime/components/media/components/CeCreditNotification.vue +99 -0
  12. package/dist/runtime/components/media/components/CeCreditNotification.vue.d.ts +28 -0
  13. package/dist/runtime/components/media/components/ContentAccordion.vue +65 -0
  14. package/dist/runtime/components/media/components/ContentAccordion.vue.d.ts +29 -0
  15. package/dist/runtime/components/media/components/ContentArea.vue +175 -0
  16. package/dist/runtime/components/media/components/ContentTabs.vue +263 -0
  17. package/dist/runtime/components/media/components/DocumentsPanel.vue +52 -0
  18. package/dist/runtime/components/media/components/DocumentsPanel.vue.d.ts +7 -0
  19. package/dist/runtime/components/media/components/JsonApi.vue +33 -0
  20. package/dist/runtime/components/media/components/JsonApi.vue.d.ts +16 -0
  21. package/dist/runtime/components/media/components/MediaContainer.vue +104 -0
  22. package/dist/runtime/components/media/components/OverviewPanel.vue +51 -0
  23. package/dist/runtime/components/media/components/PresentersPanel.vue +65 -0
  24. package/dist/runtime/components/media/components/PresentersPanel.vue.d.ts +32 -0
  25. package/dist/runtime/components/media/components/SessionReporting.vue +96 -0
  26. package/dist/runtime/components/media/components/SessionReporting.vue.d.ts +35 -0
  27. package/dist/runtime/components/media/components/SponsorsPanel.vue +85 -0
  28. package/dist/runtime/components/media/components/SponsorsPanel.vue.d.ts +27 -0
  29. package/dist/runtime/components/media/components/WindowContent.vue +118 -0
  30. package/dist/runtime/components/media/components/WindowContent.vue.d.ts +50 -0
  31. package/dist/runtime/components/media/components/WindowSlide.vue +92 -0
  32. package/dist/runtime/components/media/components/WindowSlide.vue.d.ts +36 -0
  33. package/dist/runtime/composables/useStream.d.ts +15 -0
  34. package/dist/runtime/composables/useStream.mjs +89 -0
  35. package/dist/runtime/enums/general.d.ts +7 -0
  36. package/dist/runtime/enums/general.mjs +8 -0
  37. package/dist/runtime/models/conference.d.ts +17 -0
  38. package/dist/runtime/models/pagesConfig.d.ts +2 -0
  39. package/dist/runtime/store/presentations.d.ts +11 -0
  40. package/dist/runtime/store/presentations.mjs +10 -0
  41. package/package.json +3 -1
@@ -0,0 +1,167 @@
1
+ <script lang="ts" setup>
2
+ import { toRefs, computed, onMounted, nextTick } from "vue";
3
+ import { get } from "lodash-es";
4
+ import { getUnixTime } from "date-fns";
5
+ import { Presentation, Stream, PlayerObj } from "../../models/conference";
6
+ import { WebcastPlayerClassObj } from "../../@types/components";
7
+ import { useScripts } from "../../composables/useScripts";
8
+ import { useClassBinding } from "../../composables/useClassBinding";
9
+
10
+ type Props = {
11
+ stream: Stream;
12
+ presentation: Presentation;
13
+ classObject?: WebcastPlayerClassObj;
14
+ };
15
+
16
+ const props = withDefaults(defineProps<Props>(), {
17
+ classObject: () => {
18
+ return {
19
+ container: "",
20
+ playerElement: "",
21
+ embedElement: "",
22
+ };
23
+ },
24
+ });
25
+
26
+ const { stream, presentation } = toRefs(props);
27
+
28
+ const { loadScripts } = useScripts();
29
+ const { classBinding } = useClassBinding();
30
+
31
+ // data
32
+ let icvPlayerObj: PlayerObj = {
33
+ autostart: false,
34
+ format: "hls",
35
+ playerDiv: "mediaPlayer",
36
+ loadCustomStream: () => {},
37
+ };
38
+ let timeInterval: NodeJS.Timer | null = null;
39
+
40
+ // emits
41
+ const emit = defineEmits<{
42
+ (event: "time", value: Number): void;
43
+ }>();
44
+
45
+ // computed
46
+ const isHtml = computed(() => {
47
+ return stream.value.type === "embed";
48
+ });
49
+
50
+ const isHls = computed(() => {
51
+ return stream.value.type === "hls";
52
+ });
53
+
54
+ // methods
55
+ const setupMediaPlayer = () => {
56
+ if (icvPlayerObj) {
57
+ icvPlayerObj = <PlayerObj>{};
58
+ }
59
+ if (isHls.value) {
60
+ nextTick(() => {
61
+ icvPlayerObj = new window.ICVDMStreamPlayer();
62
+ icvPlayerObj.format = stream.value.type;
63
+ icvPlayerObj.playerDiv = "mediaPlayer";
64
+ icvPlayerObj.autostart = true;
65
+ playStream();
66
+ });
67
+ }
68
+ };
69
+
70
+ const playStream = () => {
71
+ if (isHls.value) {
72
+ icvPlayerObj.format = ["audio", "audio_slide"].includes(stream.value.type)
73
+ ? "audio"
74
+ : "video";
75
+ icvPlayerObj.loadCustomStream({
76
+ file: stream.value.hls_url,
77
+ });
78
+ }
79
+ };
80
+
81
+ const checkStreamTime = () => {
82
+ const defaultStreamUt = getUnixTime(Date.now()) - 40;
83
+ const maxStreamDelay = defaultStreamUt - 20;
84
+ let streamUt = get(icvPlayerObj, "stream_ut", defaultStreamUt);
85
+
86
+ if (streamUt > maxStreamDelay) {
87
+ streamUt = defaultStreamUt;
88
+ }
89
+ emit("time", streamUt);
90
+ };
91
+
92
+ const cleanup = () => {
93
+ if (icvPlayerObj) {
94
+ icvPlayerObj = <PlayerObj>{};
95
+ }
96
+ clearInterval(timeInterval);
97
+ };
98
+
99
+ // watchers
100
+
101
+ watch(
102
+ presentation,
103
+ (_oldPresentation: Presentation, _newPresentation: Presentation) => {
104
+ if (_oldPresentation.type !== _newPresentation.type) {
105
+ setupMediaPlayer();
106
+ }
107
+ }
108
+ );
109
+
110
+ watch(stream, (_oldStream, _newStream) => {
111
+ if (_oldStream !== _newStream) {
112
+ setupMediaPlayer();
113
+ }
114
+ });
115
+
116
+ // on mount
117
+ // @todo figure out why ICVDMStreamPlayer doesn't load when loadScripts is run asynchroniously
118
+ onMounted(() => {
119
+ const _script = document.createElement("script");
120
+ _script.setAttribute(
121
+ "src",
122
+ "https://cdn.v3mediaportal.com/streaming-player/js/icvdm.player.min.js?_id=75"
123
+ );
124
+ document.head.appendChild(_script);
125
+ _script.onload = () => {
126
+ if (get(window, "ICVDMStreamPlayer", false)) {
127
+ setupMediaPlayer();
128
+ timeInterval = setInterval(checkStreamTime, 1000);
129
+ }
130
+ };
131
+ });
132
+ </script>
133
+
134
+ <template>
135
+ <div
136
+ id="webcast-player-container"
137
+ :class="classBinding(classObject, 'container', 'text-center')"
138
+ >
139
+ <div
140
+ v-if="isHls"
141
+ id="mediaPlayer"
142
+ ref="mediaPlayer"
143
+ :class="classBinding(classObject, 'playerElement', '')"
144
+ ></div>
145
+ <span
146
+ v-if="isHtml"
147
+ :v-html="stream.embed_html"
148
+ :class="classBinding(classObject, 'embedElement', '')"
149
+ ></span>
150
+ </div>
151
+ </template>
152
+
153
+ <style>
154
+ #webcast-player-container > span {
155
+ padding-bottom: 56.25%;
156
+ height: 0;
157
+ position: relative;
158
+ display: block;
159
+ }
160
+ #webcast-player-container > span > iframe {
161
+ position: absolute;
162
+ top: 0;
163
+ left: 0;
164
+ height: 100%;
165
+ width: 100%;
166
+ }
167
+ </style>
@@ -0,0 +1,53 @@
1
+ <script lang="ts" setup>
2
+ import { toRefs } from "vue";
3
+ import { Conference } from "../../../models/conference";
4
+ import {
5
+ AgendaPanelClassObj,
6
+ AgendaPanelCompObj,
7
+ AgendaListClassObj,
8
+ } from "../../../@types/components";
9
+ import { useClassBinding } from "../../../composables/useClassBinding";
10
+
11
+ type Props = {
12
+ conference: Conference | null;
13
+ classObject?: AgendaPanelClassObj;
14
+ };
15
+
16
+ const props = withDefaults(defineProps<Props>(), {
17
+ classObject: () => {
18
+ return {
19
+ container: "",
20
+ components: ref<AgendaPanelCompObj>({
21
+ agendaList: ref<AgendaListClassObj>({}),
22
+ }),
23
+ };
24
+ },
25
+ });
26
+
27
+ const { conference } = toRefs(props);
28
+
29
+ const { classBinding } = useClassBinding();
30
+ </script>
31
+
32
+ <template>
33
+ <div :class="classBinding(classObject, 'container', '')">
34
+ <CommonAgendaList
35
+ :conference="conference"
36
+ :class-object="classObject.components.agendaList"
37
+ style="margin-top: 0; margin-bottom: 0; border: none"
38
+ />
39
+ </div>
40
+ </template>
41
+
42
+ <style scoped>
43
+ .sponsor-grid {
44
+ display: grid;
45
+ grid-template-columns: 1fr 1fr 1fr;
46
+ gap: 10px;
47
+ }
48
+ .sponsor-grid .grid-item {
49
+ align-items: center;
50
+ align-self: center;
51
+ justify-self: center;
52
+ }
53
+ </style>
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <transition name="slide-fade">
3
+ <div v-if="visible" class="flex bg-yellow-lightest shadow text-grey-darker py-6 px-10">
4
+ <div class="flex-1 text-center mx-auto">
5
+ <p>
6
+ Time Remaining <span :class="timeRemainingClass">{{ displayFor }} seconds </span>
7
+ </p>
8
+ <p v-text="promptText"></p>
9
+ <p>
10
+ <button class="btn btn-secondary" @click="acceptClick" v-text="buttonText"></button>
11
+ </p>
12
+ </div>
13
+ </div>
14
+ </transition>
15
+ </template>
16
+
17
+ <script>
18
+ import Echo from 'laravel-echo';
19
+ window.Pusher = require('pusher-js');
20
+
21
+ /**
22
+ @todo Extract the wsHost and app ID out so that this can run in multiple environments (local, staging, production)
23
+ */
24
+
25
+ window.Echo = new Echo({
26
+ key: '07Ve4MlR6FmN0Il8Wy',
27
+ broadcaster: 'pusher',
28
+ cluster: 'us2',
29
+ wsHost: 'socket.v3plusportal.com',
30
+ wsPort: 6001,
31
+ wssPort: 6002,
32
+ disableStats: false,
33
+ encrypted: true,
34
+ enabledTransports: ['ws', 'wss'],
35
+ });
36
+
37
+ export default {
38
+ data() {
39
+ return {
40
+ pusher: null,
41
+ channel: null,
42
+ displayFor: 0,
43
+ promptText: '',
44
+ buttonText: '',
45
+ visible: false,
46
+ countdownLoopId: null,
47
+ };
48
+ },
49
+ computed: {
50
+ timeRemainingClass() {
51
+ if (this.displayFor > 10) {
52
+ return 'font-bold text-green-dark';
53
+ }
54
+ return 'font-bold text-red';
55
+ },
56
+ },
57
+ props: {
58
+ conferenceId: {
59
+ type: Number,
60
+ required: true,
61
+ },
62
+ },
63
+ methods: {
64
+ handleNotification(_conference) {
65
+ clearInterval(this.countdownLoopId);
66
+ window.scrollTo({ top: 0, behavior: 'smooth' });
67
+ this.visible = true;
68
+ this.displayFor = parseInt(_conference.ce_credit_config.display_for) || 30;
69
+ this.promptText = _conference.ce_credit_config.prompt_text;
70
+ this.buttonText = _conference.ce_credit_config.button_text;
71
+ this.countdownLoopId = setInterval(this.countdownLoop, 1000);
72
+ },
73
+ countdownLoop() {
74
+ if (this.displayFor > 0) {
75
+ this.displayFor--;
76
+ } else {
77
+ this.closeNotification();
78
+ }
79
+ },
80
+ acceptClick() {
81
+ this.closeNotification();
82
+ },
83
+ closeNotification() {
84
+ this.displayFor = 0;
85
+ this.visible = false;
86
+ clearInterval(this.countdownLoopId);
87
+ },
88
+ },
89
+ created() {
90
+ window.Echo.channel(`ce-notification.${this.conferenceId}`).listen('CeCreditNotification', event => {
91
+ this.handleNotification(event.conference);
92
+ });
93
+ },
94
+ };
95
+ </script>
96
+
97
+ <style scoped>
98
+
99
+ </style>
@@ -0,0 +1,28 @@
1
+ declare namespace _default {
2
+ function data(): {
3
+ pusher: null;
4
+ channel: null;
5
+ displayFor: number;
6
+ promptText: string;
7
+ buttonText: string;
8
+ visible: boolean;
9
+ countdownLoopId: null;
10
+ };
11
+ namespace computed {
12
+ function timeRemainingClass(): "font-bold text-green-dark" | "font-bold text-red";
13
+ }
14
+ namespace props {
15
+ namespace conferenceId {
16
+ const type: NumberConstructor;
17
+ const required: boolean;
18
+ }
19
+ }
20
+ namespace methods {
21
+ function handleNotification(_conference: any): void;
22
+ function countdownLoop(): void;
23
+ function acceptClick(): void;
24
+ function closeNotification(): void;
25
+ }
26
+ function created(): void;
27
+ }
28
+ export default _default;
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <div>
3
+ <accordion :content-object="currentPresentation" v-for="item in tabArray" :tab-content="item">
4
+ <div class="content flex flex-1 accordion-slot overflow-x-hidden">
5
+ <overview-panel v-if="item.type == 'overview'"></overview-panel>
6
+ <presenters-panel v-if="item.type == 'presenters'" layout-format="PresenterItemCard" item-width="90"></presenters-panel>
7
+ <documents-panel v-if="item.type == 'documents'"></documents-panel>
8
+ <sponsors-panel v-if="item.type == 'sponsors'"></sponsors-panel>
9
+ <chat v-if="item.type == 'chatroom'"></chat>
10
+ <dynamic-html v-if="item.type == 'html'" :template="item.content"></dynamic-html>
11
+ </div>
12
+ </accordion>
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+ import { mapState } from "vuex";
18
+
19
+ import Accordion from '@/components/common/Accordion';
20
+ import OverviewPanel from "./OverviewPanel";
21
+ import PresentersPanel from "./PresentersPanel";
22
+ import DocumentsPanel from "./DocumentsPanel";
23
+ import SponsorsPanel from "./SponsorsPanel";
24
+ import Chat from "@/components/common/Chat";
25
+
26
+ export default {
27
+ components: {
28
+ Accordion,
29
+ OverviewPanel,
30
+ PresentersPanel,
31
+ DocumentsPanel,
32
+ SponsorsPanel,
33
+ Chat
34
+ },
35
+ data() {
36
+ return {};
37
+ },
38
+ props: {
39
+ currentPresentation: {
40
+ type: Object,
41
+ default: () => {
42
+ return {};
43
+ }
44
+ },
45
+ tabArray: {
46
+ type: Array,
47
+ default: () => {
48
+ return [];
49
+ }
50
+ }
51
+ },
52
+ computed: {
53
+ ...mapState("playerConfig", ["selectedContent"])
54
+ },
55
+ methods: {
56
+ }
57
+ };
58
+ </script>
59
+
60
+ <style>
61
+ .accordion-slot {
62
+ max-height: 32rem;
63
+ overflow-y: scroll;
64
+ }
65
+ </style>
@@ -0,0 +1,29 @@
1
+ declare namespace _default {
2
+ namespace components {
3
+ export { Accordion };
4
+ export { OverviewPanel };
5
+ export { PresentersPanel };
6
+ export { DocumentsPanel };
7
+ export { SponsorsPanel };
8
+ export { Chat };
9
+ }
10
+ function data(): {};
11
+ namespace props {
12
+ namespace currentPresentation {
13
+ export const type: ObjectConstructor;
14
+ function _default(): {};
15
+ export { _default as default };
16
+ }
17
+ namespace tabArray {
18
+ const type_1: ArrayConstructor;
19
+ export { type_1 as type };
20
+ function _default_1(): never[];
21
+ export { _default_1 as default };
22
+ }
23
+ }
24
+ namespace computed {
25
+ const selectedContent: import("vuex").Computed;
26
+ }
27
+ const methods: {};
28
+ }
29
+ export default _default;
@@ -0,0 +1,175 @@
1
+ <script lang="ts" setup>
2
+ import { toRefs } from "vue";
3
+ import { storeToRefs } from "pinia";
4
+ import { get, filter } from "lodash-es";
5
+ import { SelectedContent } from "../../../enums/general";
6
+ import {
7
+ ContentAreaClassObj,
8
+ ContentAreaCompObj,
9
+ OverviewPanelClassObj,
10
+ AgendaPanelClassObj,
11
+ } from "../../../@types/components";
12
+ import { Conference, Presentation, Sponsor } from "../../../models/conference";
13
+ import { useClassBinding } from "../../../composables/useClassBinding";
14
+ import { useTemplateConfigsStore } from "../../../store";
15
+
16
+ type Props = {
17
+ selectedContent?: { label: string; type: SelectedContent; content: string };
18
+ expandEnabled?: boolean;
19
+ presentation: Presentation;
20
+ webcastConference: Conference;
21
+ classObject?: ContentAreaClassObj;
22
+ };
23
+
24
+ const props = withDefaults(defineProps<Props>(), {
25
+ selectedContent: () => {
26
+ return { label: "Overview", type: SelectedContent.OVERVIEW, content: "" };
27
+ },
28
+ expandEnabled: false,
29
+ classObject: () => {
30
+ return {
31
+ container: "",
32
+ htmlElement: "",
33
+ trackHtmlElement: "",
34
+ noTrackHtmlElement: "",
35
+ noTrackHtmlText: "",
36
+ components: ref<ContentAreaCompObj>({
37
+ overviewPanel: ref<OverviewPanelClassObj>({}),
38
+ agendaPanel: ref<AgendaPanelClassObj>({}),
39
+ }),
40
+ };
41
+ },
42
+ });
43
+
44
+ const { expandEnabled, presentation, webcastConference } = toRefs(props);
45
+
46
+ const { classBinding } = useClassBinding();
47
+
48
+ const { pagesConfigValue } = storeToRefs(useTemplateConfigsStore());
49
+
50
+ // reactive data
51
+ let sponsors = ref<Array<Sponsor>>([]);
52
+
53
+ // computed
54
+ const trackEmbedHtml = computed((): string | null => {
55
+ get(presentation, "tracks[0].embed_html", null);
56
+ });
57
+
58
+ // methods
59
+ const getFeaturedSponsors = () => {
60
+ const featuredSponsorLevel = get(
61
+ pagesConfigValue,
62
+ "webcast.featured_sponsor_level.value",
63
+ 0
64
+ );
65
+ if (featuredSponsorLevel != 0) {
66
+ const url = `conferences/${webcastConference.value.id}/affiliates?filters[level]=${featuredSponsorLevel}`;
67
+ fetch(url)
68
+ .then((response) => {
69
+ return response.json();
70
+ })
71
+ .then((data) => {
72
+ sponsors = filter(data, { role: "sponsor" });
73
+ });
74
+ }
75
+ };
76
+
77
+ // mounted
78
+ onMounted(() => {
79
+ getFeaturedSponsors();
80
+ });
81
+ </script>
82
+
83
+ <template>
84
+ <div :class="classBinding(classObject, 'container', 'flex flex-col')">
85
+ <CommonComponentsOverviewPanel
86
+ v-if="selectedContent.type == 'overview'"
87
+ :class="
88
+ classBinding(
89
+ classObject.components.overviewPanel,
90
+ 'container',
91
+ 'overflow-y-scroll no-scrollbar h-full'
92
+ )
93
+ "
94
+ :presentation="presentation"
95
+ :class-object="classObject.components.overviewPanel"
96
+ ></CommonComponentsOverviewPanel>
97
+ <CommonComponentsAgendaPanel
98
+ v-if="selectedContent.type == 'agenda'"
99
+ :class="
100
+ classBinding(
101
+ classObject.components.agendaPanel,
102
+ 'container',
103
+ 'overflow-y-scroll no-scrollbar h-full'
104
+ )
105
+ "
106
+ :conference="webcastConference"
107
+ :class-object="classObject.components.agendaPanel"
108
+ ></CommonComponentsAgendaPanel>
109
+ <span
110
+ v-if="selectedContent.type == 'html'"
111
+ :class="
112
+ classBinding(
113
+ classObject,
114
+ 'htmlElement',
115
+ 'overflow-y-scroll no-scrollbar h-full'
116
+ )
117
+ "
118
+ v-html="selectedContent.content"
119
+ ></span>
120
+ <template v-if="selectedContent.type == 'track_html'">
121
+ <span
122
+ v-if="trackEmbedHtml != null"
123
+ :class="
124
+ classBinding(
125
+ classObject,
126
+ 'trackHtmlElement',
127
+ 'overflow-y-scroll no-scrollbar h-full'
128
+ )
129
+ "
130
+ v-html="trackEmbedHtml"
131
+ ></span>
132
+ <div
133
+ v-if="trackEmbedHtml === null"
134
+ :class="
135
+ classBinding(
136
+ classObject,
137
+ 'noTrackHtmlElement',
138
+ 'text-grey-800 px-2 py-4'
139
+ )
140
+ "
141
+ >
142
+ <p
143
+ :class="
144
+ classBinding(
145
+ classObject,
146
+ 'noTrackHtmlText',
147
+ 'text-base leading-normal font-light'
148
+ )
149
+ "
150
+ >
151
+ There is no additional content for this track.
152
+ </p>
153
+ </div>
154
+ </template>
155
+ </div>
156
+ </template>
157
+
158
+ <style scoped>
159
+ .content {
160
+ position: relative;
161
+ }
162
+
163
+ .content-expand-overlay {
164
+ justify-content: flex-end;
165
+ align-items: flex-start;
166
+ font-size: 1em;
167
+ line-height: 1em;
168
+ z-index: 40;
169
+ position: absolute;
170
+ transition: 0.4s ease;
171
+ }
172
+ .content-expand-overlay:hover {
173
+ opacity: 0.7;
174
+ }
175
+ </style>