[FW][MERGE] (website_)event: improve Online features display and use
PURPOSE Add a few minor usability features as well as a few layout adjustments for the 'event' modules. SPECIFICATIONS Add "Hide and show" feature for the tracks. Add a dynamic countdown for the tracks. Provide various changes and improvements on frontend layout display next to intensive user testing and feedback. See underlying commits for more details. LINKS Task-2347597 COM PR odoo/odoo#69102 ENT PR odoo/enterprise#17612 closes odoo/odoo#69117 Forward-port-of: odoo/odoo#69102 Related: odoo/enterprise#17621 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -480,17 +480,6 @@ class EventEvent(models.Model):
|
||||
if event.date_end < event.date_begin:
|
||||
raise ValidationError(_('The closing date cannot be earlier than the beginning date.'))
|
||||
|
||||
@api.depends('name', 'date_begin', 'date_end')
|
||||
def name_get(self):
|
||||
result = []
|
||||
for event in self:
|
||||
date_begin = fields.Datetime.from_string(event.date_begin)
|
||||
date_end = fields.Datetime.from_string(event.date_end)
|
||||
dates = [fields.Date.to_string(fields.Datetime.context_timestamp(event, dt)) for dt in [date_begin, date_end] if dt]
|
||||
dates = sorted(set(dates))
|
||||
result.append((event.id, '%s (%s)' % (event.name, ' - '.join(dates))))
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def _read_group_stage_ids(self, stages, domain, order):
|
||||
return self.env['event.stage'].search([])
|
||||
|
||||
@@ -72,6 +72,8 @@
|
||||
.dropdown-menu {
|
||||
margin-top: $navbar-padding-y;
|
||||
min-width: 12rem;
|
||||
max-height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.dropdown-item {
|
||||
&.active .badge { // Invert badge display when the item is active
|
||||
@@ -137,13 +139,6 @@
|
||||
}
|
||||
|
||||
.o_wevent_online_page_container {
|
||||
// Widescreen mode
|
||||
@include media-breakpoint-up(md) {
|
||||
&:not(.container) {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Main panel
|
||||
.o_wevent_online_page_main {
|
||||
|
||||
@@ -163,10 +163,10 @@
|
||||
<!-- List -->
|
||||
<div t-foreach="event_ids" t-as="event" t-attf-class=" #{opt_event_size} mb-4">
|
||||
<a t-attf-href="/event/#{ slug(event) }/#{(not event.menu_id) and 'register'}" class="text-decoration-none">
|
||||
<article t-attf-class="h-100 #{opt_events_list_cards and 'card border-0 shadow-sm'}" itemscope="itemscope" itemtype="http://schema.org/Event">
|
||||
<article t-attf-class="h-100 #{opt_events_list_cards and 'card rounded-0 border-0 shadow-sm'}" itemscope="itemscope" itemtype="http://schema.org/Event">
|
||||
<div class="h-100 row no-gutters">
|
||||
<!-- Header -->
|
||||
<header t-attf-class="overflow-hidden bg-secondary #{opt_events_list_columns and 'col-12 rounded-top' or 'col-sm-4 col-lg-3 rounded-left'} #{(not opt_events_list_cards) and 'rounded shadow'} #{(not opt_events_list_cards and not opt_events_list_columns) and 'rounded-top'}">
|
||||
<header t-attf-class="overflow-hidden bg-secondary #{opt_events_list_columns and 'col-12' or 'col-sm-4 col-lg-3'} #{(not opt_events_list_cards) and 'shadow'}">
|
||||
<!-- Image + Link -->
|
||||
<div class="d-block h-100 w-100">
|
||||
<t t-call="website.record_cover">
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<t t-else="">
|
||||
<nav class="navbar navbar-light border-top shadow-sm navbar-expand-md">
|
||||
<div class="container align-items-baseline">
|
||||
<a href="#" t-field="event.name" class="navbar-brand h4 my-0 mr-0 mr-md-4"/>
|
||||
<a t-att-href="event.website_url" t-field="event.name" class="navbar-brand h4 my-0 mr-0 mr-md-4"/>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#o_wevent_event_submenu" aria-controls="o_wevent_event_submenu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
@@ -78,4 +78,13 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="display_timer_alert_widget" name="Display Countdown widget">
|
||||
<div class="o_we_track_timer alert alert-warning alert-dismissible fade show d-none mx-3 mt-3 mb-0" role="alert" t-att-data-time-to-live="time_to_live">
|
||||
Starts <span />
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<i class="fa fa-times"/>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -150,11 +150,11 @@
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<template id="exhibitor_card" name="Exhibitor Card">
|
||||
<article t-att-class="'h-100 card border-0 shadow-sm o_wesponsor_card %s' % ('o_wesponsor_card_unpublished' if not sponsor.is_published else '')"
|
||||
<article t-att-class="'h-100 card rounded-0 border-0 shadow-sm o_wesponsor_card %s' % ('o_wesponsor_card_unpublished' if not sponsor.is_published else '')"
|
||||
itemscope="itemscope" itemtype="http://schema.org/Event">
|
||||
<div class="h-100 row no-gutters">
|
||||
<t t-set="sponsor_image_url" t-value="sponsor.website_image_url"/>
|
||||
<header t-att-class="'overflow-hidden col-12 rounded-top %s' % ('bg-secondary' if not sponsor_image_url else '')">
|
||||
<header t-att-class="'overflow-hidden col-12 %s' % ('bg-secondary' if not sponsor_image_url else '')">
|
||||
<div class="d-block h-100 w-100 o_wesponsor_js_connect"
|
||||
t-att-data-sponsor-url="sponsor.website_url"
|
||||
t-attf-data-register-url="/event/#{slug(event)}/register?from_sponsor_id=#{sponsor.id}"
|
||||
@@ -202,8 +202,8 @@
|
||||
<div class="col-12 h-100">
|
||||
<main class="card-body">
|
||||
<!-- Title -->
|
||||
<h5 class="card-title mt-0 mb-0 text-truncate d-flex align-items-top">
|
||||
<span t-field="sponsor.name" itemprop="name"/>
|
||||
<h5 class="card-title mt-0 mb-0 d-flex align-items-start">
|
||||
<span t-field="sponsor.name" itemprop="name" class="text-break"/>
|
||||
<span t-if="sponsor.is_in_opening_hours and sponsor.chat_room_id"
|
||||
class="ml-auto badge badge-danger">Live
|
||||
</span>
|
||||
|
||||
@@ -89,10 +89,10 @@
|
||||
</t>
|
||||
</div>
|
||||
<!-- SPONSOR DESCRIPTION -->
|
||||
<span class="h5 d-inline-block mx-3 mt-3 mb-0">
|
||||
<div class="h5 m-3">
|
||||
About <t t-esc="sponsor.name"/>
|
||||
</span>
|
||||
<hr class="mt-2 mb-0"/>
|
||||
</div>
|
||||
<hr class="my-0"/>
|
||||
<div class="ml-3 clearfix">
|
||||
<div class="float-left pt-3">
|
||||
<span t-if="sponsor.image_512" t-field="sponsor.image_512" class="o_wevent_online_page_avatar"
|
||||
@@ -149,7 +149,7 @@
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<template id="exhibitor_aside" name="Exhibitor: Aside">
|
||||
<div t-att-class="'col-12 pl-0 pr-0 pr-md-3 o_wevent_online_page_aside o_wesponsor_exhibitor_aside %s' % ('col-md-3 col-lg-2' if option_widescreen else 'col-md-4 col-lg-3')">
|
||||
<div t-att-class="'col-12 pl-0 pr-0 o_wevent_online_page_aside o_wesponsor_exhibitor_aside %s' % ('col-md-3 col-lg-2' if option_widescreen else 'col-md-4 col-lg-3')">
|
||||
<div class="bg-white o_wevent_online_page_aside_content">
|
||||
<div class="d-flex align-items-center justify-content-between mx-2">
|
||||
<span class="h5 mb-0 pt-0 pt-md-3 pb-0 pb-md-2">Other exhibitors</span>
|
||||
|
||||
@@ -162,9 +162,11 @@
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_global_click overflow-hidden">
|
||||
<div class="row my-auto">
|
||||
<img t-att-src="kanban_image('event.sponsor', 'image_128', record.id.raw_value)" alt="Sponsor image" class="col-4"/>
|
||||
<div class="col-8 d-flex flex-column">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="w-25 d-flex justify-content-center">
|
||||
<img t-att-src="kanban_image('event.sponsor', 'image_128', record.id.raw_value)" class="img-fluid" alt="Sponsor image"/>
|
||||
</div>
|
||||
<div class="w-75 d-flex flex-column ml-3">
|
||||
<h1 class="o_kanban_record_title"><field name="name"/></h1>
|
||||
<strong>Level: <field name="sponsor_type_id"/></strong>
|
||||
<span class="text-muted"><field name="exhibitor_type"/></span>
|
||||
|
||||
@@ -135,10 +135,10 @@ class WebsiteEventMeetController(EventCommunityController):
|
||||
)
|
||||
|
||||
def _event_meeting_room_page_get_values(self, event, meeting_room):
|
||||
# search for meeting room list
|
||||
# search for meeting room list. Set a limit to 6 because it is better than 5 or 7
|
||||
meeting_rooms_other = request.env['event.meeting.room'].sudo().search([
|
||||
('event_id', '=', event.id), ('id', '!=', meeting_room.id), ('is_published', '=', True),
|
||||
])
|
||||
], limit=6)
|
||||
|
||||
if not request.env.user.has_group("event.group_event_manager"):
|
||||
# only the event manager can see meeting rooms which are full
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
t-att-data-meeting-room-id="meeting_room.id"
|
||||
t-att-data-open-room="opened"
|
||||
t-att-data-is-event-manager="int(is_event_user)"
|
||||
t-attf-class="card o_wevent_meeting_room_card w-100 my-2 bg-light d-block text-decoration-none"
|
||||
t-attf-class="card o_wevent_meeting_room_card w-100 my-2 bg-light d-block text-decoration-none rounded-0"
|
||||
t-att-href="meeting_room_href"
|
||||
t-att-data-toggle="meeting_room_data_toggle"
|
||||
t-att-data-target="meeting_room_data_target">
|
||||
|
||||
@@ -81,11 +81,12 @@
|
||||
</div>
|
||||
<!-- ROOM DESCRIPTION -->
|
||||
<div class="mx-3">
|
||||
<span class="h5 d-inline-block mt-3 mb-1" t-esc="meeting_room.name"/>
|
||||
<br/>
|
||||
<span class="text-muted">A chat among <span class="font-weight-bold" t-esc="meeting_room.target_audience"/></span>
|
||||
<div class="h5 my-3" t-esc="meeting_room.name"/>
|
||||
<div t-if="meeting_room.room_participant_count > 0" class="text-muted mb-3">
|
||||
A chat among <t t-esc="meeting_room.room_participant_count"/> <span class="font-weight-bold" t-esc="meeting_room.target_audience"/>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="mt-2 mb-0"/>
|
||||
<hr class="my-0"/>
|
||||
<div t-field="meeting_room.summary" class="my-2 mx-3 oe_no_empty"/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -95,9 +96,9 @@
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<template id="meeting_room_aside" name="Meeting Room: Aside">
|
||||
<div t-att-class="'col-12 pl-0 pr-0 pr-md-3 o_wevent_online_page_aside %s' % ('col-md-3 col-lg-2' if option_widescreen else 'col-md-4 col-lg-3')">
|
||||
<div t-att-class="'col-12 pl-0 pr-0 o_wevent_online_page_aside %s' % ('col-md-3 col-lg-2' if option_widescreen else 'col-md-4 col-lg-3')">
|
||||
<div class="bg-white o_wevent_online_page_aside_content">
|
||||
<div class="d-flex align-items-center justify-content-between mx-2 py-1">
|
||||
<div class="d-flex align-items-center justify-content-between mx-2">
|
||||
<span class="h5 mb-0 pt-0 pt-md-3 pb-0 pb-md-2">Other Rooms</span>
|
||||
<a href="#collapse_meet_room_aside" data-toggle="collapse" class="d-lg-none p-2 text-decoration-none o_wevent_online_page_aside_collapse collapsed">
|
||||
<i class="fa fa-chevron-down d-lg-none"/>
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
'website_event_track/static/src/js/website_event_track_proposal_form.js',
|
||||
'website_event_track/static/src/js/website_event_track_proposal_form_tags.js',
|
||||
'website_event_track/static/src/js/event_track_reminder.js',
|
||||
'website_event_track/static/src/js/event_track_timer.js',
|
||||
'website_event_track/static/src/js/website_event_pwa_widget.js',
|
||||
'website_event_track/static/lib/idb-keyval/idb-keyval.js',
|
||||
],
|
||||
|
||||
@@ -121,6 +121,13 @@ class EventTrackController(http.Controller):
|
||||
tracks_announced = tracks_announced.sorted('wishlisted_by_default', reverse=True)
|
||||
tracks_by_day.append({'date': False, 'name': _('Coming soon'), 'tracks': tracks_announced})
|
||||
|
||||
for tracks_group in tracks_by_day:
|
||||
# the tracks group is folded if all tracks are done (and if it's not "today")
|
||||
tracks_group['default_collapsed'] = (today_tz != tracks_group['date']) and all(
|
||||
track.is_track_done and not track.is_track_live
|
||||
for track in tracks_group['tracks']
|
||||
)
|
||||
|
||||
# return rendering values
|
||||
return {
|
||||
# event information
|
||||
@@ -353,11 +360,11 @@ class EventTrackController(http.Controller):
|
||||
@http.route("/event/track/toggle_reminder", type="json", auth="public", website=True)
|
||||
def track_reminder_toggle(self, track_id, set_reminder_on):
|
||||
""" Set a reminder a track for current visitor. Track visitor is created or updated
|
||||
if it already exists. Exception made if un-wishlisting and no track_visitor
|
||||
if it already exists. Exception made if un-favoriting and no track_visitor
|
||||
record found (should not happen unless manually done).
|
||||
|
||||
:param boolean set_reminder_on:
|
||||
If True, set as a wishlist, otherwise un-wishlist track;
|
||||
If True, set as a favorite, otherwise un-favorite track;
|
||||
If the track is a Key Track (wishlisted_by_default):
|
||||
if set_reminder_on = False, blacklist the track_partner
|
||||
otherwise, un-blacklist the track_partner
|
||||
|
||||
@@ -74,8 +74,11 @@ class Track(models.Model):
|
||||
partner_company_name = fields.Char(
|
||||
'Company Name', compute='_compute_partner_company_name',
|
||||
readonly=False, store=True)
|
||||
partner_tag_line = fields.Char(
|
||||
'Tag Line', compute='_compute_partner_tag_line',
|
||||
help='Description of the partner (name, function and company name)')
|
||||
image = fields.Image(
|
||||
string="Speaker Photo", compute="_compute_speaker_image",
|
||||
string="Speaker Photo", compute="_compute_partner_image",
|
||||
readonly=False, store=True,
|
||||
max_width=256, max_height=256)
|
||||
# contact information
|
||||
@@ -91,7 +94,7 @@ class Track(models.Model):
|
||||
# time information
|
||||
date = fields.Datetime('Track Date')
|
||||
date_end = fields.Datetime('Track End Date', compute='_compute_end_date', store=True)
|
||||
duration = fields.Float('Duration', default=1.5, help="Track duration in hours.")
|
||||
duration = fields.Float('Duration', default=0.5, help="Track duration in hours.")
|
||||
is_track_live = fields.Boolean(
|
||||
'Is Track Live', compute='_compute_track_time_data',
|
||||
help="Track has started and is ongoing")
|
||||
@@ -134,7 +137,7 @@ class Track(models.Model):
|
||||
groups="event.group_event_user")
|
||||
wishlisted_by_default = fields.Boolean(
|
||||
string='Always Wishlisted',
|
||||
help="""If set, the talk will be starred for each attendee registered to the event. The attendee won't be able to un-star this talk.""")
|
||||
help="""If set, the talk will be set as favorite for each attendee registered to the event.""")
|
||||
# Call to action
|
||||
website_cta = fields.Boolean('Magic Button',
|
||||
help="Display a Call to Action button to your Attendees while they watch your Track.")
|
||||
@@ -199,8 +202,32 @@ class Track(models.Model):
|
||||
elif not track.partner_company_name:
|
||||
track.partner_company_name = track.partner_id.parent_id.name
|
||||
|
||||
@api.depends('partner_name', 'partner_function', 'partner_company_name')
|
||||
def _compute_partner_tag_line(self):
|
||||
for track in self:
|
||||
if not track.partner_name:
|
||||
track.partner_tag_line = False
|
||||
continue
|
||||
|
||||
tag_line = track.partner_name
|
||||
if track.partner_function:
|
||||
if track.partner_company_name:
|
||||
tag_line = _('%(name)s, %(function)s at %(company)s',
|
||||
name=track.partner_name,
|
||||
function=track.partner_function,
|
||||
company=track.partner_company_name
|
||||
)
|
||||
else:
|
||||
tag_line = '%s, %s' % (track.partner_name, track.partner_function)
|
||||
elif track.partner_company_name:
|
||||
tag_line = _('%(name)s from %(company)s',
|
||||
name=tag_line,
|
||||
company=track.partner_company_name
|
||||
)
|
||||
track.partner_tag_line = tag_line
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_speaker_image(self):
|
||||
def _compute_partner_image(self):
|
||||
for track in self:
|
||||
if not track.image:
|
||||
track.image = track.partner_id.image_256
|
||||
|
||||
@@ -21,7 +21,7 @@ class TrackVisitor(models.Model):
|
||||
'event.track', string='Track',
|
||||
index=True, required=True, ondelete='cascade')
|
||||
is_wishlisted = fields.Boolean(string="Is Wishlisted")
|
||||
is_blacklisted = fields.Boolean(string="Is reminder off", help="As key track cannot be un-wishlisted, this field store the partner choice to remove the reminder for key tracks.")
|
||||
is_blacklisted = fields.Boolean(string="Is reminder off", help="As key track cannot be un-favorited, this field store the partner choice to remove the reminder for key tracks.")
|
||||
|
||||
@api.depends('visitor_id')
|
||||
def _compute_partner_id(self):
|
||||
|
||||
@@ -63,6 +63,13 @@ publicWidget.registry.websiteEventTrackReminder = publicWidget.Widget.extend({
|
||||
type: 'info',
|
||||
title: message
|
||||
});
|
||||
if (self.reminderOn) {
|
||||
core.bus.trigger('open_notification_request', 'add_track_to_favorite', {
|
||||
title: _t('Allow push notifications?'),
|
||||
body: _t('You have to enable push notifications to get reminders for your favorite tracks.'),
|
||||
delay: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
if (result.visitor_uuid) {
|
||||
utils.set_cookie('visitor_uuid', result.visitor_uuid);
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
odoo.define('website_event_track.website_event_track_timer', function (require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
const publicWidget = require('web.public.widget');
|
||||
|
||||
/*
|
||||
* Simple implementation of a timer widget that uses a "time to live" configuration
|
||||
* value to countdown seconds on a target element.
|
||||
* Will be used to visually countdown the time before a talk starts.
|
||||
* When the timer reaches 0, the element destroys itself.
|
||||
*/
|
||||
publicWidget.registry.websiteEventTrackTimer = publicWidget.Widget.extend({
|
||||
|
||||
selector: '.o_we_track_timer',
|
||||
events: {
|
||||
'click .close': '_onCloseClick',
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
return this._super.apply(this, arguments).then(() => {
|
||||
let timeToLive = this.$el.data('time-to-live');
|
||||
let deadline = moment().add(timeToLive, 'seconds');
|
||||
let remainingMs = deadline.diff(moment());
|
||||
if (remainingMs > 0) {
|
||||
this._updateTimerDisplay(remainingMs);
|
||||
this.$el.removeClass('d-none');
|
||||
this.deadline = deadline;
|
||||
this.timer = setInterval(this._refreshTimer.bind(this), 1000);
|
||||
} else {
|
||||
this.destroy();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function() {
|
||||
this.$el.parent().remove();
|
||||
clearInterval(this.timer);
|
||||
this._super(...arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_onCloseClick: function () {
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
* The function will trigger an update if the timer has not yet expired.
|
||||
* Otherwise, the component will be destroyed.
|
||||
*/
|
||||
_refreshTimer: function () {
|
||||
let remainingMs = this.deadline.diff(moment());
|
||||
if (remainingMs > 0) {
|
||||
this._updateTimerDisplay(remainingMs);
|
||||
} else {
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The function will have the responsibility to update the text indicating
|
||||
* the time remaining before the counter expires. The function will use
|
||||
* MomentJS to transform the remaining time in more a human friendly format
|
||||
* Example: "in 32 minutes", "in 17 hours", etc.
|
||||
* @param {integer} remainingMs - Time remaining before the counter expires (in ms).
|
||||
*/
|
||||
_updateTimerDisplay: function (remainingMs) {
|
||||
let $timerTextEl = this.$el.find('span');
|
||||
let str = moment.duration(remainingMs, 'ms').humanize(true);
|
||||
if (str !== $timerTextEl.text()) {
|
||||
$timerTextEl.text(str);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return publicWidget.registry.websiteEventTrackTimer;
|
||||
|
||||
});
|
||||
@@ -81,12 +81,12 @@
|
||||
}
|
||||
div.o_we_agenda_card_content {
|
||||
height: 100%;
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
.o_we_agenda_card_title, small {
|
||||
word-break: break-word;
|
||||
}
|
||||
.badge:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.badge {
|
||||
height: fit-content;
|
||||
@@ -180,6 +180,13 @@
|
||||
/*
|
||||
* EVENT TOOL: DATE
|
||||
*/
|
||||
.o_wevent_event .o_we_track_day_header > div > span.h1 {
|
||||
font-size: xx-large;
|
||||
.o_wevent_event {
|
||||
.o_we_track_day_header {
|
||||
& > div > span.h1 {
|
||||
font-size: xx-large;
|
||||
}
|
||||
a.collapsed {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
<button name="%(action_event_track_from_event)d"
|
||||
type="action"
|
||||
class="oe_stat_button"
|
||||
icon="fa-microphone"
|
||||
context="{'default_date': date_begin}">
|
||||
icon="fa-microphone">
|
||||
<field name="track_count" string="Tracks" widget="statinfo"/>
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Add a shortcut to wishlist / talks after registration -->
|
||||
<!-- Add a shortcut to favorites / tracks after registration -->
|
||||
<template id="registration_complete" inherit_id="website_event.registration_complete">
|
||||
<xpath expr="//div[hasclass('row')][last()]" position="after">
|
||||
<div t-if="event.website_track" class="row mt-5 mb256">
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<!-- Option: Tracks display: optional wishlist -->
|
||||
<!-- Option: Tracks display: optional favorites -->
|
||||
<template id="agenda_topbar_wishlist"
|
||||
inherit_id="website_event_track.agenda_topbar"
|
||||
name="Allow Wishlists"
|
||||
@@ -157,13 +157,13 @@
|
||||
<div class="d-flex flex-column h-100">
|
||||
<div class="d-flex justify-content-end flex-wrap-reverse align-items-center o_weagenda_track_badges">
|
||||
<small t-if="track.is_track_live and not track.is_track_done and track.website_published"
|
||||
class="mx-1 badge badge-danger">Live
|
||||
class="mx-1 badge badge-danger rounded-sm">Live
|
||||
</small>
|
||||
<small t-if="not track.website_published and is_event_user and track.stage_id.is_accepted"
|
||||
title="Unpublished"
|
||||
class="ml-1 badge badge-danger o_wevent_online_badge_unpublished">Unpublished</small>
|
||||
class="ml-1 badge badge-danger o_wevent_online_badge_unpublished rounded-sm">Unpublished</small>
|
||||
<small t-if="not track.stage_id.is_accepted" title="Not Accepted"
|
||||
class="ml-1 badge badge-danger o_wevent_online_badge_unpublished">Not Accepted</small>
|
||||
class="ml-1 badge badge-danger o_wevent_online_badge_unpublished rounded-sm">Not Accepted</small>
|
||||
<span t-if="option_track_wishlist">
|
||||
<t t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_light" t-value="True"/>
|
||||
@@ -174,14 +174,20 @@
|
||||
</div>
|
||||
|
||||
<div class="o_we_agenda_card_content d-flex flex-column justify-content-center my-1">
|
||||
<div t-att-class="'text-black' if track.website_published or is_event_user else 'text-muted'"
|
||||
t-att-onclick="'window.location=\'/event/%s/track/%s\'' % (slug(event), slug(track))
|
||||
if track.website_published or is_event_user else ''">
|
||||
<span class="o_we_agenda_card_title text-bold" t-esc="track.name"/>
|
||||
<div class="o_we_agenda_card_title">
|
||||
<t t-if="track.website_published or is_event_user">
|
||||
<a t-att-href="'/event/%s/track/%s' % (slug(event), slug(track))" class="text-black text-bold">
|
||||
<t t-esc="track.name"/>
|
||||
</a>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span class="text-muted text-bold">
|
||||
<t t-esc="track.name"/>
|
||||
</span>
|
||||
</t>
|
||||
</div>
|
||||
<div class="text-muted text-center">
|
||||
<small t-if="track.partner_id or track.partner_name">
|
||||
<t t-esc="track.partner_id.sudo().name or track.partner_name"/></small>
|
||||
<div class="text-muted text-center" t-if="track.partner_tag_line">
|
||||
<small t-esc="track.partner_tag_line"/>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-wrap">
|
||||
<t t-foreach="track.tag_ids" t-as="tag">
|
||||
|
||||
@@ -170,8 +170,8 @@
|
||||
<t t-set="tracks_header_name" t-value="tracks_info['name']"/>
|
||||
<t t-set="tracks" t-value="tracks_info['tracks']"/>
|
||||
<!-- DAY HEADER -->
|
||||
<div class="o_we_track_day_header w-100">
|
||||
<div t-if="tracks_date" class="d-flex">
|
||||
<div class="o_we_track_day_header d-flex">
|
||||
<div class="d-flex flex-grow-1" t-if="tracks_date">
|
||||
<span class="h1 m-0 font-weight-bold" t-esc="tracks_date"
|
||||
t-options="{'widget': 'date', 'format': 'EEEE dd'}"/>
|
||||
<div class="d-flex flex-column ml-2">
|
||||
@@ -181,102 +181,112 @@
|
||||
t-options="{'widget': 'date', 'format': 'YYYY'}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div t-elif="tracks_header_name">
|
||||
<div class="d-flex flex-grow-1" t-elif="tracks_header_name">
|
||||
<span class="h1 m-0 font-weight-bold"
|
||||
t-esc="tracks_header_name"/>
|
||||
</div>
|
||||
<a t-attf-class="ml-auto align-self-start text-black {{ 'collapsed' if tracks_info['default_collapsed'] else '' }}"
|
||||
t-attf-href="#collapse_session_list_{{ tracks_info_index }}"
|
||||
t-attf-aria-controls="collapse_session_list_{{ tracks_info_index }}"
|
||||
t-att-aria-expanded="'false' if tracks_info['default_collapsed'] else 'true'"
|
||||
data-toggle="collapse">
|
||||
<i class="fa fa-2x fa-chevron-down"/>
|
||||
</a>
|
||||
<hr class="mt-2 pb-1 mb-1"/>
|
||||
</div>
|
||||
<!-- DAY TRACKS LIST -->
|
||||
<div t-foreach="tracks" t-as="track"
|
||||
t-att-class="'o_wesession_list_item px-2 py-2 event_color_%d' % (track.color)">
|
||||
<!-- Side information in a floating div (desktop only) -->
|
||||
<div t-if="not event.is_done and (not track.date or today_tz <= tracks_date) and option_track_wishlist"
|
||||
class="float-right d-none d-md-block ml-2">
|
||||
<t t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_small" t-value="False"/>
|
||||
<t t-set="reminder_light" t-value="False"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="row no-gutters">
|
||||
<!-- Main column: name, speaker -->
|
||||
<div class="col-md-7">
|
||||
<!-- Reminder widget: directly in line to gain space, mobile only -->
|
||||
<div t-if="not event.is_done and (not track.date or today_tz <= tracks_date) and option_track_wishlist"
|
||||
class="float-right d-block d-md-none ml-2">
|
||||
<t t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_small" t-value="True"/>
|
||||
<t t-set="reminder_light" t-value="False"/>
|
||||
</t>
|
||||
</div>
|
||||
<span class="h5 mb0">
|
||||
<a t-if="track.is_published or is_event_user"
|
||||
class="mr-2"
|
||||
t-att-href="track.website_url">
|
||||
<span t-field="track.name"/>
|
||||
</a>
|
||||
<t t-else="">
|
||||
<span class="mr-2" t-field="track.name"/>
|
||||
</t>
|
||||
<span t-if="not track.is_published and is_event_user"
|
||||
class="badge badge-danger o_wevent_online_badge_unpublished">
|
||||
Unpublished
|
||||
</span>
|
||||
</span>
|
||||
<div class="text-muted d-flex align-items-center">
|
||||
<span class="text-muted" t-esc="track.partner_name"/>
|
||||
<t t-if="tracks_date and today_tz <= tracks_date">
|
||||
<!-- Hour: Live > Remaining > Hour: mobile only -->
|
||||
<div class="d-block d-md-none">
|
||||
<span t-if="track.partner_name" class="ml-2">&bull;</span>
|
||||
<span t-if="track.is_track_live and not track.is_track_done"
|
||||
class="badge badge-danger ml-2">Live</span>
|
||||
<span t-elif="not track.is_track_done and track.is_track_soon"
|
||||
class="ml-2">
|
||||
<span t-esc="track.track_start_remaining"
|
||||
t-options="{'widget': 'duration', 'digital': False, 'format': 'narrow',
|
||||
'add_direction': True, 'unit': 'second', 'round': 'minute'}"/>
|
||||
</span>
|
||||
<span t-elif="not track.is_track_done and not track.is_track_soon"
|
||||
class="ml-2"
|
||||
t-esc="track.date"
|
||||
t-options="{'widget': 'datetime', 'time_only': True, 'format': 'short'}"/>
|
||||
<span t-else="" class="badge badge-info ml-2">Finished</span>
|
||||
</div>
|
||||
<!-- Duration (desktop only) -->
|
||||
<t t-if="track.duration and not track.is_track_done and not track.is_track_done">
|
||||
<span class="d-none d-md-block ml-2">&bull;</span>
|
||||
<span class="d-none d-md-block ml-2"
|
||||
t-esc="track.duration"
|
||||
t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'hour', 'round': 'minute'}"/>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
<div t-attf-class="collapse {{ '' if tracks_info['default_collapsed'] else 'show' }}"
|
||||
t-attf-id="collapse_session_list_{{ tracks_info_index }}">
|
||||
<div t-foreach="tracks" t-as="track"
|
||||
t-att-class="'o_wesession_list_item px-2 py-2 event_color_%d' % (track.color)">
|
||||
<!-- Side information in a floating div (desktop only) -->
|
||||
<div t-if="not event.is_done and (not track.date or today_tz <= tracks_date) and option_track_wishlist"
|
||||
class="float-right d-none d-md-block ml-2">
|
||||
<t t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_small" t-value="False"/>
|
||||
<t t-set="reminder_light" t-value="False"/>
|
||||
</t>
|
||||
</div>
|
||||
<!-- Aside column: date, tags -->
|
||||
<div class="col-md-5">
|
||||
<!-- Hour: Live > Remaining > Hour: desktop only -->
|
||||
<div t-if="tracks_date and today_tz <= tracks_date"
|
||||
class="d-none d-md-block float-right">
|
||||
<span t-if="track.is_track_live and not track.is_track_done"
|
||||
class="badge badge-danger ml-2">Live</span>
|
||||
<span t-elif="not track.is_track_done and track.is_track_soon"
|
||||
class="ml-2">
|
||||
<span t-esc="track.track_start_remaining"
|
||||
t-options="{'widget': 'duration', 'digital': False, 'format': 'narrow',
|
||||
'add_direction': True, 'unit': 'second', 'round': 'minute'}"/>
|
||||
<div class="row no-gutters">
|
||||
<!-- Main column: name, speaker -->
|
||||
<div class="col-md-7">
|
||||
<!-- Reminder widget: directly in line to gain space, mobile only -->
|
||||
<div t-if="not event.is_done and (not track.date or today_tz <= tracks_date) and option_track_wishlist"
|
||||
class="float-right d-block d-md-none ml-2">
|
||||
<t t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_small" t-value="True"/>
|
||||
<t t-set="reminder_light" t-value="False"/>
|
||||
</t>
|
||||
</div>
|
||||
<span class="h5 mb0">
|
||||
<a t-if="track.is_published or is_event_user"
|
||||
class="mr-2"
|
||||
t-att-href="track.website_url">
|
||||
<span t-field="track.name"/>
|
||||
</a>
|
||||
<t t-else="">
|
||||
<span class="mr-2" t-field="track.name"/>
|
||||
</t>
|
||||
<span t-if="not track.is_published and is_event_user"
|
||||
class="badge badge-danger o_wevent_online_badge_unpublished">
|
||||
Unpublished
|
||||
</span>
|
||||
</span>
|
||||
<span t-elif="not track.is_track_done and not track.is_track_soon"
|
||||
class="ml-2"
|
||||
t-esc="track.date"
|
||||
t-options="{'widget': 'datetime', 'time_only': True, 'format': 'short'}"/>
|
||||
<span t-else="" class="badge badge-info ml-2">Finished</span>
|
||||
<div class="text-muted d-flex align-items-center">
|
||||
<span class="text-muted" t-esc="track.partner_tag_line"/>
|
||||
<t t-if="tracks_date and today_tz <= tracks_date">
|
||||
<!-- Hour: Live > Remaining > Hour: mobile only -->
|
||||
<div class="d-block d-md-none">
|
||||
<span t-if="track.partner_tag_line" class="ml-2">&bull;</span>
|
||||
<span t-if="track.is_track_live and not track.is_track_done"
|
||||
class="badge badge-danger ml-2">Live</span>
|
||||
<span t-elif="not track.is_track_done and track.is_track_soon"
|
||||
class="ml-2">
|
||||
<span t-esc="track.track_start_remaining"
|
||||
t-options="{'widget': 'duration', 'digital': False, 'format': 'narrow',
|
||||
'add_direction': True, 'unit': 'second', 'round': 'minute'}"/>
|
||||
</span>
|
||||
<span t-elif="not track.is_track_done and not track.is_track_soon"
|
||||
class="ml-2"
|
||||
t-esc="track.date"
|
||||
t-options="{'widget': 'datetime', 'time_only': True, 'format': 'short'}"/>
|
||||
<span t-else="" class="badge badge-info ml-2">Finished</span>
|
||||
</div>
|
||||
<!-- Duration (desktop only) -->
|
||||
<t t-if="track.duration and not track.is_track_done and not track.is_track_done">
|
||||
<span class="d-none d-md-block ml-2">&bull;</span>
|
||||
<span class="d-none d-md-block ml-2"
|
||||
t-esc="track.duration"
|
||||
t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'hour', 'round': 'minute'}"/>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Tags: desktop only -->
|
||||
<div class="d-none d-md-block">
|
||||
<t t-foreach="track.tag_ids" t-as="tag">
|
||||
<t t-if="tag.color" t-call="website_event_track.track_tag_badge_link"/>
|
||||
</t>
|
||||
<!-- Aside column: date, tags -->
|
||||
<div class="col-md-5">
|
||||
<!-- Hour: Live > Remaining > Hour: desktop only -->
|
||||
<div t-if="tracks_date and today_tz <= tracks_date"
|
||||
class="d-none d-md-block float-right">
|
||||
<span t-if="track.is_track_live and not track.is_track_done"
|
||||
class="badge badge-danger ml-2">Live</span>
|
||||
<span t-elif="not track.is_track_done and track.is_track_soon"
|
||||
class="ml-2">
|
||||
<span t-esc="track.track_start_remaining"
|
||||
t-options="{'widget': 'duration', 'digital': False, 'format': 'narrow',
|
||||
'add_direction': True, 'unit': 'second', 'round': 'minute'}"/>
|
||||
</span>
|
||||
<span t-elif="not track.is_track_done and not track.is_track_soon"
|
||||
class="ml-2"
|
||||
t-esc="track.date"
|
||||
t-options="{'widget': 'datetime', 'time_only': True, 'format': 'short'}"/>
|
||||
<span t-else="" class="badge badge-info ml-2">Finished</span>
|
||||
</div>
|
||||
<!-- Tags: desktop only -->
|
||||
<div class="d-none d-md-block">
|
||||
<t t-foreach="track.tag_ids" t-as="tag">
|
||||
<t t-if="tag.color" t-call="website_event_track.track_tag_badge_link"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -292,10 +302,10 @@
|
||||
|
||||
<template id="tracks_cards_track" name="Track Card">
|
||||
<a t-att-href="'/event/%s/track/%s' % (slug(track.event_id), slug(track))" class="text-decoration-none">
|
||||
<article t-att-class="'h-100 card border-0 shadow-sm o_wesession_track_card %s' % ('o_wesession_track_card_unpublished' if not track.is_published else '')"
|
||||
<article t-att-class="'h-100 card rounded-0 border-0 shadow-sm o_wesession_track_card %s' % ('o_wesession_track_card_unpublished' if not track.is_published else '')"
|
||||
itemscope="itemscope" itemtype="http://schema.org/Event">
|
||||
<div class="h-100 row no-gutters">
|
||||
<header class="overflow-hidden bg-secondary col-12 rounded-top">
|
||||
<header class="overflow-hidden bg-secondary col-12">
|
||||
<small t-if="not track.is_published" class="o_wesession_track_card_header_badge bg-danger">
|
||||
<i class="fa fa-ban mr-2"/>Unpublished
|
||||
</small>
|
||||
@@ -362,7 +372,7 @@
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<span t-if="search_wishlist"
|
||||
class="align-items-baseline border d-inline-flex pl-2 mt-3 rounded ml16 mb-2 bg-white">
|
||||
<i class="fa fa-bell mr-2 text-muted"/> Wishlisted Talks
|
||||
<i class="fa fa-bell mr-2 text-muted"/> Favorite Talks
|
||||
<a t-att-href="'/event/%s/track?%s' % (slug(event), keep_query('*', search_wishlist=''))"
|
||||
class="btn border-0 py-1">
|
||||
×
|
||||
|
||||
@@ -45,12 +45,10 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div t-elif="track.track_start_remaining" class="pt-3">
|
||||
<div class="mx-3 alert alert-warning">
|
||||
Starting in
|
||||
<span t-esc="track.track_start_remaining"
|
||||
t-options="{'widget': 'duration', 'digital': False, 'unit': 'second', 'round': 'minute'}"/>
|
||||
</div>
|
||||
<div t-elif="track.track_start_remaining">
|
||||
<t t-call="website_event.display_timer_alert_widget">
|
||||
<t t-set="time_to_live" t-value="track.track_start_remaining"/>
|
||||
</t>
|
||||
</div>
|
||||
<!-- TRACK DESCRIPTION -->
|
||||
<div class="o_wesession_track_main_description overflow-auto">
|
||||
@@ -135,9 +133,9 @@
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<template id="event_track_aside" name="Track: Aside">
|
||||
<div t-att-class="'col-12 pl-0 pr-0 pr-md-3 o_wevent_online_page_aside o_wesession_track_aside %s' % ('col-md-3 col-lg-2' if option_widescreen else 'col-md-4 col-lg-3')">
|
||||
<div t-att-class="'col-12 pl-0 pr-0 o_wevent_online_page_aside o_wesession_track_aside %s' % ('col-md-3 col-lg-2' if option_widescreen else 'col-md-4 col-lg-3')">
|
||||
<div class="bg-white pt-0 pt-md-3 o_wevent_online_page_aside_content">
|
||||
<div class="mx-2" t-if="track.website_cta">
|
||||
<div class="mx-2" t-if="track.date and track.website_cta">
|
||||
<t t-set="cta_coundown" t-value="bool(track.website_cta_start_remaining)"/>
|
||||
<div t-if="cta_coundown" class="text-center mt-2 mt-md-0 w-100 btn btn-primary d-none">
|
||||
<t t-call="website_event.display_timer_widget">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<field name="domain">[('event_track_wishlisted_ids', 'in', [active_id])]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Wait for visitors to wishlist your tracks
|
||||
Wait for visitors to add this track to their list of favorites
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -292,7 +292,7 @@
|
||||
<field name="domain">[('wishlist_visitor_ids', 'in', [active_id])]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
No track wishlisted by this visitor
|
||||
No track favorited by this visitor
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
'assets': {
|
||||
'web.assets_frontend': [
|
||||
'website_event_track_live/static/src/scss/website_event_track_live.scss',
|
||||
'website_event_track_live/static/src/js/website_event_track_replay_suggestion.js',
|
||||
'website_event_track_live/static/src/js/website_event_track_suggestion.js',
|
||||
'website_event_track_live/static/src/js/website_event_track_live.js',
|
||||
],
|
||||
|
||||
@@ -5,10 +5,7 @@ odoo.define('website_event_track_live.website_event_youtube_embed', function (re
|
||||
|
||||
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;
|
||||
var ReplaySuggestionWidget = require('website_event_track_live.website_event_track_replay_suggestion');
|
||||
|
||||
publicWidget.registry.websiteEventTrackLive = publicWidget.Widget.extend({
|
||||
selector: '.o_wevent_event_track_live',
|
||||
@@ -20,7 +17,6 @@ publicWidget.registry.websiteEventTrackLive = publicWidget.Widget.extend({
|
||||
var self = this;
|
||||
return this._super(...arguments).then(function () {
|
||||
self._setupYoutubePlayer();
|
||||
self.isFullScreen = !!document.fullscreenElement;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -29,30 +25,27 @@ publicWidget.registry.websiteEventTrackLive = publicWidget.Widget.extend({
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_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');
|
||||
}
|
||||
switch (event.data) {
|
||||
case YT.PlayerState.ENDED:
|
||||
this.trigger('video-ended');
|
||||
return;
|
||||
case YT.PlayerState.PLAYING:
|
||||
this.trigger('video-playing');
|
||||
return;
|
||||
case YT.PlayerState.PAUSED:
|
||||
this.trigger('video-paused');
|
||||
return;
|
||||
};
|
||||
},
|
||||
|
||||
_onVideoEnded: function () {
|
||||
if (this.$el.data('hasNextSuggestion')) {
|
||||
// if we have an upcoming suggestion, add a covering block to avoid
|
||||
// showing Youtube suggestions while we fetch the appropriate suggestion
|
||||
// using a rpc. This allows avoiding a 'flicker' effect.
|
||||
this.$el.append($('<div/>', {
|
||||
class:'owevent_track_suggestion_loading position-absolute w-100'
|
||||
}));
|
||||
}
|
||||
|
||||
this.$el.append($('<div/>', {
|
||||
class: 'owevent_track_suggestion_loading position-absolute w-100'
|
||||
}));
|
||||
var self = this;
|
||||
this._rpc({
|
||||
route: '/event_track/get_track_suggestion',
|
||||
@@ -69,21 +62,11 @@ publicWidget.registry.websiteEventTrackLive = publicWidget.Widget.extend({
|
||||
this.youtubePlayer.seekTo(0);
|
||||
this.youtubePlayer.playVideo();
|
||||
this.$('.owevent_track_suggestion_loading').remove();
|
||||
if (this.trackSuggestion) {
|
||||
delete this.trackSuggestion;
|
||||
if (this.outro) {
|
||||
delete this.outro;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -116,14 +99,26 @@ publicWidget.registry.websiteEventTrackLive = publicWidget.Widget.extend({
|
||||
},
|
||||
|
||||
/**
|
||||
* Automatically launches the next suggested track when this one ends
|
||||
* and the user is not in fullscreen mode.
|
||||
* If a new suggestion has been found, a cover containing a replay button
|
||||
* as well as a suggestion will automatically be placed over the Youtube
|
||||
* player when the video ends (in non-full screen mode). If no suggestion
|
||||
* has been found, the cover will only contain a replay button.
|
||||
*/
|
||||
_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));
|
||||
if (!this.outro) {
|
||||
if (this.nextSuggestion) {
|
||||
this.outro = new TrackSuggestionWidget(this, this.nextSuggestion);
|
||||
} else {
|
||||
var data = this.$el.data();
|
||||
this.outro = new ReplaySuggestionWidget(this, {
|
||||
current_track: {
|
||||
name: data.trackName,
|
||||
website_image_url: data.trackWebsiteImageUrl
|
||||
}
|
||||
});
|
||||
}
|
||||
this.outro.appendTo(this.$el);
|
||||
this.outro.on('replay', null, this._onReplay.bind(this));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
odoo.define('website_event_track_live.website_event_track_replay_suggestion', function (require) {
|
||||
'use strict';
|
||||
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
/**
|
||||
* The widget will have the responsibility to manage the interactions between the
|
||||
* Youtube player and the cover containing a replay button. This widget will
|
||||
* be used when no suggestion can be found in order to hide the Youtube suggestions.
|
||||
*/
|
||||
var WebsiteEventReplaySuggestion = Widget.extend({
|
||||
template: 'website_event_track_live.website_event_track_replay_suggestion',
|
||||
xmlDependencies: ['/website_event_track_live/static/src/xml/website_event_track_live_templates.xml'],
|
||||
events: {
|
||||
'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,
|
||||
};
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* If the user clicks on the replay button, the function will remove the
|
||||
* cover and send a new event to the parent to replay the video from the
|
||||
* beginning.
|
||||
*/
|
||||
_onReplayClick: function () {
|
||||
this.trigger_up('replay');
|
||||
this.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
return WebsiteEventReplaySuggestion;
|
||||
});
|
||||
@@ -1,6 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<div t-name="website_event_track_live.website_event_track_replay_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>
|
||||
</div>
|
||||
|
||||
<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}');">
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
<t t-set="show_youtube_frame" t-value="track.youtube_video_url and (track.is_youtube_replay or track.is_track_soon or track.is_track_live or track.is_track_done)" />
|
||||
<div t-if="show_youtube_frame" class="flex-grow-1 o_wevent_event_track_live"
|
||||
t-att-data-track-id="track.id"
|
||||
t-att-data-youtube-video-id="track.youtube_video_id"
|
||||
t-att-data-has-next-suggestion="bool(track._get_track_suggestions(restrict_domain=[('youtube_video_url', '!=', False), ('is_published', '=', True)], limit=1))">
|
||||
t-att-data-track-name="track.name"
|
||||
t-att-data-track-website-image-url="track.website_image_url"
|
||||
t-att-data-youtube-video-id="track.youtube_video_id">
|
||||
<div class="position-absolute o_wevent_event_track_live_loading w-100 d-flex align-items-center justify-content-center text-white h4">
|
||||
<i class="fa fa-spin fa-spinner position-relative"/>
|
||||
<span class="pl-2">Loading Video...</span>
|
||||
|
||||
Reference in New Issue
Block a user