summaryrefslogtreecommitdiff
path: root/addons/website_event_track_live/static/src
diff options
context:
space:
mode:
authorAurélien Warnon <awa@odoo.com>2020-06-30 12:29:03 +0000
committerThibault Delavallée <tde@odoo.com>2020-08-04 14:28:29 +0000
commitfab82c73a5aeb31a3be970dfe31ac754597dbb78 (patch)
tree59e9e1e7b074a011f08134230603950f9e63899d /addons/website_event_track_live/static/src
parente73ec2ddb90b105bfad72a018726eaf3ac38e21c (diff)
[ADD] website_event_track_live: configure Youtube videos / streams on event.tracks
RATIONALE Events are sometimes held online, gathering a community. In this merge we improve Event application to better support full-online events with improved tracks, wishlists, chat rooms, ... PURPOSE Allow to include a youtube video / live stream on event tracks and update the interface to show "online" capabilities. SPECIFICATIONS This commit improves the existing event.tracks to include the possibility to configure a Youtube live stream or video. The frontend view of the track was adapted accordingly to show the stream / video instead of the track description when available. At the end of the video, the track view will automatically suggest a next track to the attendee in order to keep him looping through interesting tracks. Those suggestions are based on an algorithm that tries to select the track that would be the most interesting to this attendee based on his wishlist, similar tags with current track, same room, ... In addition, we automatically fallback to a Youtube thumbnail for tracks website image when available. We support two youtube modes * streaming: start and end of video is detected based on youtube API; * replay: boolean flag on track, telling the video is a static one, allowing to know by advance the end of video, and to pre-compute thumbnail and give early access if necessary; KNOWN LIMITATIONS Tracks do not hold any protection for payment-based tickets. Everything that is published is available using standard ACLs. Content protection based on tickets is currently not supported. LINKS Task ID-2252655 (Main Online Event task) Task ID-2283735 (Talks -> Session upgrade) Task ID-2283729 (Live/Youtube Tracks) Co-Authored-By: Aurélien Warnon <awa@odoo.com> Co-Authored-By: David Beguin <dbe@odoo.com> Co-Authored-By: Thibault Delavallée <tde@odoo.com>
Diffstat (limited to 'addons/website_event_track_live/static/src')
-rw-r--r--addons/website_event_track_live/static/src/js/website_event_track_live.js121
-rw-r--r--addons/website_event_track_live/static/src/js/website_event_track_suggestion.js81
-rw-r--r--addons/website_event_track_live/static/src/scss/website_event_track_live.scss42
-rw-r--r--addons/website_event_track_live/static/src/xml/website_event_track_live_templates.xml33
4 files changed, 277 insertions, 0 deletions
diff --git a/addons/website_event_track_live/static/src/js/website_event_track_live.js b/addons/website_event_track_live/static/src/js/website_event_track_live.js
new file mode 100644
index 00000000000..a330308de63
--- /dev/null
+++ b/addons/website_event_track_live/static/src/js/website_event_track_live.js
@@ -0,0 +1,121 @@
+var onYouTubeIframeAPIReady;
+
+odoo.define('website_event_track_live.website_event_youtube_embed', function (require) {
+'use strict';
+
+var publicWidget = require('web.public.widget');
+var TrackSuggestionWidget = require('website_event_track_live.website_event_track_suggestion');
+
+var YOUTUBE_VIDEO_ENDED = 0;
+var YOUTUBE_VIDEO_PLAYING = 1;
+var YOUTUBE_VIDEO_PAUSED = 2;
+
+publicWidget.registry.websiteEventTrackLive = publicWidget.Widget.extend({
+ selector: '.o_wevent_event_track_live',
+ custom_events: _.extend({}, publicWidget.Widget.prototype.custom_events, {
+ 'video-ended': '_onVideoEnded'
+ }),
+
+ start: function () {
+ var self = this;
+ return this._super(...arguments).then(function () {
+ self._setupYoutubePlayer();
+ self.isFullScreen = !!document.fullscreenElement;
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ _onPlayerReady: function () {
+ $(window).on('resize', this._onResize.bind(this));
+ this.$('.o_wevent_event_track_live_loading').remove();
+ },
+
+ _onPlayerStateChange: function (event) {
+ if (event.data === YOUTUBE_VIDEO_ENDED) {
+ this.trigger('video-ended');
+ } else if (event.data === YOUTUBE_VIDEO_PLAYING) {
+ this.trigger('video-playing');
+ } else if (event.data === YOUTUBE_VIDEO_PAUSED) {
+ this.trigger('video-paused');
+ }
+ },
+
+ _onVideoEnded: function () {
+ var self = this;
+ this._rpc({
+ route: '/event_track/get_track_suggestion',
+ params: {
+ track_id: this.$el.data('trackId'),
+ }
+ }).then(function (suggestion) {
+ self.nextSuggestion = suggestion;
+ self._showSuggestion();
+ });
+ },
+
+ _onReplay: function () {
+ this.youtubePlayer.seekTo(0);
+ this.youtubePlayer.playVideo();
+ if (this.trackSuggestion) {
+ delete this.trackSuggestion;
+ }
+ },
+
+ /**
+ * The 'fullscreenchange' event is probably a better fit but it is unfortunately
+ * not triggered when Youtube enters fullscreen mode.
+ * However, the global window 'resize' is.
+ */
+ _onResize: function () {
+ this.isFullScreen = !!document.fullscreenElement;
+ this._showSuggestion();
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ _setupYoutubePlayer: function () {
+ var self = this;
+
+ var youtubeId = self.$el.data('youtubeVideoId');
+ var $youtubeElement = $('<script/>', {src: 'https://www.youtube.com/iframe_api'});
+ $(document.head).append($youtubeElement);
+
+ onYouTubeIframeAPIReady = function () {
+ self.youtubePlayer = new YT.Player('o_wevent_youtube_iframe_container', {
+ height: '100%',
+ width: '100%',
+ videoId: youtubeId,
+ playerVars: {
+ autoplay: 1,
+ enablejsapi: 1,
+ rel: 0,
+ origin: window.location.origin,
+ widget_referrer: window.location.origin,
+ },
+ events: {
+ 'onReady': self._onPlayerReady.bind(self),
+ 'onStateChange': self._onPlayerStateChange.bind(self)
+ }
+ });
+ };
+ },
+
+ /**
+ * Automatically launches the next suggested track when this one ends
+ * and the user is not in fullscreen mode.
+ */
+ _showSuggestion: function () {
+ if (this.nextSuggestion && !this.isFullScreen && !this.trackSuggestion) {
+ this.trackSuggestion = new TrackSuggestionWidget(this, this.nextSuggestion);
+ this.trackSuggestion.appendTo(this.$el);
+ this.trackSuggestion.on('replay', null, this._onReplay.bind(this));
+ }
+ }
+});
+
+});
diff --git a/addons/website_event_track_live/static/src/js/website_event_track_suggestion.js b/addons/website_event_track_live/static/src/js/website_event_track_suggestion.js
new file mode 100644
index 00000000000..e6583c22509
--- /dev/null
+++ b/addons/website_event_track_live/static/src/js/website_event_track_suggestion.js
@@ -0,0 +1,81 @@
+odoo.define('website_event_track_live.website_event_track_suggestion', function (require) {
+'use strict';
+
+var Widget = require('web.Widget');
+
+var WebsiteEventTrackSuggestion = Widget.extend({
+ template: 'website_event_track_live.website_event_track_suggestion',
+ xmlDependencies: ['/website_event_track_live/static/src/xml/website_event_track_live_templates.xml'],
+ events: {
+ 'click .owevent_track_suggestion_next': '_onNextTrackClick',
+ 'click .owevent_track_suggestion_close': '_onCloseClick',
+ 'click .owevent_track_suggestion_replay': '_onReplayClick'
+ },
+
+ init: function (parent, options) {
+ this._super(...arguments);
+
+ this.currentTrack = {
+ 'name': options.current_track.name,
+ 'imageSrc': options.current_track.website_image_url,
+ };
+ this.suggestion = {
+ 'name': options.suggestion.name,
+ 'speakerName': options.suggestion.speaker_name,
+ 'trackUrl': options.suggestion.website_url,
+ };
+ },
+
+ start: function () {
+ var self = this;
+ this._super(...arguments).then(function () {
+ self.timerInterval = setInterval(self._updateTimer.bind(self), 1000);
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * If the user clicks on replay, remove this suggestion window and send an
+ * event to the parent so that it can rewind the video to the beginning.
+ */
+ _onReplayClick: function () {
+ this.trigger_up('replay');
+ clearInterval(this.timerInterval);
+ this.destroy();
+ },
+
+ _onCloseClick: function () {
+ clearInterval(this.timerInterval);
+ this.$('.owevent_track_suggestion_next').addClass('invisible');
+ },
+
+ _onNextTrackClick: function (ev) {
+ if ($(ev.target).hasClass('owevent_track_suggestion_close')) {
+ return;
+ }
+
+ window.location = this.suggestion.trackUrl;
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ _updateTimer: function () {
+ var secondsLeft = parseInt(this.$('.owevent_track_suggestion_timer_text').text());
+
+ if (secondsLeft > 1) {
+ secondsLeft -= 1;
+ this.$('.owevent_track_suggestion_timer_text').text(secondsLeft);
+ } else {
+ window.location = this.suggestion.trackUrl;
+ }
+ }
+});
+
+return WebsiteEventTrackSuggestion;
+
+});
diff --git a/addons/website_event_track_live/static/src/scss/website_event_track_live.scss b/addons/website_event_track_live/static/src/scss/website_event_track_live.scss
new file mode 100644
index 00000000000..28571e01ffa
--- /dev/null
+++ b/addons/website_event_track_live/static/src/scss/website_event_track_live.scss
@@ -0,0 +1,42 @@
+.o_wesession_track_aside_tab_chat {
+ height: 70vh;
+}
+
+#o_wevent_youtube_iframe_container, .o_wevent_event_track_live_loading {
+ height: 85vh;
+}
+
+.o_wevent_event_track_live_loading {
+ background-color: #888888;
+
+ i {
+ bottom: 1px;
+ }
+}
+
+.owevent_track_suggestion {
+ background-color: #888888;
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ height: 85vh;
+ top: 0px;
+ left: 0px;
+
+ .owevent_track_suggestion_content {
+ background-color: rgba(0,0,0,.5);
+
+ .owevent_track_suggestion_next {
+ background-color: rgba(0,0,0,.5);
+ transition: background-color .3s linear;
+ &:hover {
+ cursor: pointer;
+ background-color: rgba(0,0,0,.9);
+ }
+
+ .owevent_track_suggestion_close {
+ top: .5rem;
+ right: .5rem;
+ }
+ }
+ }
+}
diff --git a/addons/website_event_track_live/static/src/xml/website_event_track_live_templates.xml b/addons/website_event_track_live/static/src/xml/website_event_track_live_templates.xml
new file mode 100644
index 00000000000..1784afae39c
--- /dev/null
+++ b/addons/website_event_track_live/static/src/xml/website_event_track_live_templates.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<templates xml:space="preserve">
+
+<div t-name="website_event_track_live.website_event_track_suggestion"
+ class="owevent_track_suggestion position-absolute w-100"
+ t-attf-style="background-image: url('#{widget.currentTrack.imageSrc}');">
+ <div class="h-100 w-100 p-4 d-flex flex-column align-items-center owevent_track_suggestion_content">
+ <div class="flex-grow-1 pt-5 d-flex flex-column align-items-center justify-content-center">
+ <div class="text-white">You just watched:</div>
+ <div class="h1 text-white" t-esc="widget.currentTrack.name"/>
+ <div>
+ <a href="#" class="owevent_track_suggestion_replay font-weight-bold">
+ <span>Replay Video</span>
+ </a>
+ </div>
+ </div>
+ <div class="d-flex w-100 flex-column align-items-end">
+ <div class="p-2 rounded owevent_track_suggestion_next position-relative">
+ <div class="text-white text-right owevent_track_suggestion_close_wrapper">
+ <i class="fa fa-remove owevent_track_suggestion_close position-absolute"/>
+ </div>
+ <span class="text-white">Up Next:</span>
+ <span class="text-primary font-weight-bold pr-4" t-esc="widget.suggestion.name"/>
+ <div class="text-white owevent_track_suggestion_timer_text_wrapper">
+ <span>Starts in</span>
+ <span class="owevent_track_suggestion_timer_text">30</span>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+</templates>