[IMP] website_event_online: add display-timer widget

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, ...

SPECIFICATIONS

Add a timer widget that allows to display a DOM element at the end of a given
time. The widget can be configured with two steps

  * main timer: countdown to display the DOM element;
  * pre-countdown: countdown to display the main timer;

For example, in the context of a event track (talk), the pre-timer can be used
to announce when the talk will start. The main timer will then be displayed
once the pre-timer is over. At the end of the main timer, the DOM element is
finally displayed.

[Talk start in 03:45] -> [Survey available in 05:00] -> [Take the Survey!]

LINKS

Community PR #53540
Enterprise PR odoo/enterprise#11384

Task ID-2252655 (Main Online Event task)
Task ID-2283735 (Talks -> Session upgrade)
This commit is contained in:
David Beguin
2020-08-04 14:28:29 +00:00
committed by Thibault Delavallée
parent a0892ad39e
commit 6e15f7d113
3 changed files with 140 additions and 0 deletions
@@ -0,0 +1,111 @@
odoo.define('website_event_online.display_timer_widget', function (require) {
'use strict';
var core = require('web.core');
var _t = core._t;
var publicWidget = require('web.public.widget');
publicWidget.registry.displayTimerWidget = publicWidget.Widget.extend({
selector: '.o_display_timer',
/**
* This widget allows to display a dom element at the end of a certain time laps.
* There are 2 timers available:
* - The main-timer: display the DOM element (using the displayClass) at the end of this timer.
* - The pre-timer: additional timer to display the main-timer. This pre-timer can be invisible or visible,
* depending of the startCountdownDisplay option. Once the pre-timer is over,
the main-timer is displayed.
* @override
*/
start: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
self.options = self.$target.data();
self.preCountdownDisplay = self.options["preCountdownDisplay"];
self.preCountdownTime = self.options["preCountdownTime"];
self.preCountdownText = self.options["preCountdownText"];
self.mainCountdownTime = self.options["mainCountdownTime"];
self.mainCountdownText = self.options["mainCountdownText"];
self.mainCountdownDisplay = self.options["mainCountdownDisplay"];
self.displayClass = self.options["displayClass"];
if (self.preCountdownDisplay) {
$(self.$el).parent().removeClass('d-none');
}
self._checkTimer();
self.interval = setInterval(function () { self._checkTimer(); }, 1000);
});
},
/**
* This method removes 1 second to the current timer (pre-timer or main-timer)
* and call the method to update the DOM, unless main-timer is over. In that last case,
* the DOM element to show is displayed.
*
* @private
*/
_checkTimer: function () {
var now = new Date();
var remainingPreSeconds = this.preCountdownTime - (now.getTime()/1000);
if (remainingPreSeconds <= 1) {
this.$('.o_countdown_text').text(this.mainCountdownText);
if (this.mainCountdownDisplay) {
$(this.$el).parent().removeClass('d-none');
}
var remainingMainSeconds = this.mainCountdownTime - (now.getTime()/1000);
if (remainingMainSeconds <= 1) {
clearInterval(this.interval);
$(this.displayClass).removeClass('d-none');
$(this.$el).parent().addClass('d-none');
} else {
this._updateCountdown(remainingMainSeconds);
}
} else {
this._updateCountdown(remainingPreSeconds);
}
},
/**
* This method update the DOM to display the remaining time.
* from seconds, the method extract the number of days, hours, minutes and seconds and
* override the different DOM elements values.
*
* @private
*/
_updateCountdown: function (remainingTime) {
var remainingSeconds = remainingTime;
var days = Math.floor(remainingSeconds / 86400);
remainingSeconds = remainingSeconds % 86400;
var hours = Math.floor(remainingSeconds / 3600);
remainingSeconds = remainingSeconds % 3600;
var minutes = Math.floor(remainingSeconds / 60);
remainingSeconds = Math.floor(remainingSeconds % 60);
this.$("span.o_timer_days").text(days);
this.$("span.o_timer_hours").text(this._zeroPad(hours, 2));
this.$("span.o_timer_minutes").text(this._zeroPad(minutes, 2));
this.$("span.o_timer_seconds").text(this._zeroPad(remainingSeconds, 2));
},
/**
* Small tool to add leading zéros to the given number, in function of the needed number of leading zéros.
*
* @private
*/
_zeroPad: function (num, places) {
var zero = places - num.toString().length + 1;
return new Array(+(zero > 0 && zero)).join("0") + num;
},
});
return publicWidget.registry.countdownWidget;
});
@@ -5,6 +5,9 @@
<xpath expr="//link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/website_event_online/static/src/scss/website_event_templates.scss"/>
</xpath>
<xpath expr="//script[last()]" position="after">
<script type="text/javascript" src="/website_event_online/static/src/js/display_timer_widget.js"></script>
</xpath>
</template>
</odoo>
@@ -20,4 +20,30 @@
</xpath>
</template>
<!-- TDE FIXME: move in a separate file -->
<template id="display_timer_widget" name="Display Timer Widget">
<t t-set="pre_countdown_display" t-value="bool(pre_countdown_text) or pre_countdown_display"/>
<t t-set="pre_countdown_time" t-value="datetime.datetime.now().timestamp() + int(pre_remaining_time)"/>
<div class="o_display_timer"
t-att-data-display-class="display_class"
t-att-data-main-countdown-time="datetime.datetime.now().timestamp() + int(main_remaining_time)"
t-att-data-main-countdown-text="main_countdown_text"
t-att-data-main-countdown-display="main_countdown_display"
t-att-data-pre-countdown-time="pre_countdown_time"
t-att-data-pre-countdown-display="pre_countdown_display"
t-att-data-pre-countdown-text="pre_countdown_text">
<t t-set="remaining_time" t-value="pre_remaining_time if pre_remaining_time else main_remaining_time"/>
<span class="o_display_timer_countdown d-flex justify-content-center">
<span class="o_countdown_text pr-1" t-esc="pre_countdown_text if pre_countdown_text else main_countdown_text if not pre_countdown_display else ''"/>
<div t-if="int(remaining_time) > 86400"
class="o_countdown_metric_container"><span class="o_countdown_remaining o_timer_days pr-1">0</span><span class="o_countdown_metric pr-1">days</span></div>
<div t-if="int(remaining_time) > 3600"
class="o_countdown_metric_container"><span class="o_countdown_remaining o_timer_hours">00</span><span class="o_countdown_metric">:</span></div>
<div class="o_countdown_metric_container"><span class="o_countdown_remaining o_timer_minutes">00</span><span class="o_countdown_metric">:</span></div>
<div class="o_countdown_metric_container"><span class="o_countdown_remaining o_timer_seconds">00</span><span class="o_countdown_metric"></span></div>
</span>
</div>
</template>
</odoo>