diff options
34 files changed, 901 insertions, 1286 deletions
diff --git a/addons/test_event_full/__manifest__.py b/addons/test_event_full/__manifest__.py index bd0263e341c..8423fc06d7f 100644 --- a/addons/test_event_full/__manifest__.py +++ b/addons/test_event_full/__manifest__.py @@ -21,7 +21,6 @@ automatic lead generation, full Online support, ... 'website_event_sale', 'website_event_track', 'website_event_track_exhibitor', - 'website_event_track_session', 'website_event_track_live', 'website_event_track_quiz', ], diff --git a/addons/website_event_track/controllers/event_track.py b/addons/website_event_track/controllers/event_track.py index e338f384580..782b1e839ee 100644 --- a/addons/website_event_track/controllers/event_track.py +++ b/addons/website_event_track/controllers/event_track.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from ast import literal_eval from datetime import timedelta +from pytz import timezone, utc from werkzeug.exceptions import Forbidden, NotFound import babel @@ -9,13 +11,28 @@ import babel.dates import base64 import pytz -from odoo import exceptions, http, fields +from odoo import exceptions, http, fields, _ from odoo.http import request -from odoo.tools import plaintext2html, html2plaintext +from odoo.osv import expression +from odoo.tools import is_html_empty, plaintext2html class EventTrackController(http.Controller): + def _get_event_tracks_base_domain(self, event): + """ Base domain for displaying tracks. Restrict to accepted or published + tracks for people not managing events. Unpublished tracks may be displayed + but not reachable for teasing purpose. """ + search_domain_base = [ + ('event_id', '=', event.id), + ] + if not request.env.user.has_group('event.group_event_user'): + search_domain_base = expression.AND([ + search_domain_base, + ['|', ('is_published', '=', True), ('is_accepted', '=', True)] + ]) + return search_domain_base + # ------------------------------------------------------------ # TRACK LIST VIEW # ------------------------------------------------------------ @@ -24,27 +41,110 @@ class EventTrackController(http.Controller): '''/event/<model("event.event"):event>/track''', '''/event/<model("event.event"):event>/track/tag/<model("event.track.tag"):tag>''' ], type='http', auth="public", website=True, sitemap=False) - def event_tracks(self, event, tag=None, **post): - if not event.can_access_from_current_website() or (tag and tag.color == 0): + def event_tracks(self, event, tag=None, **searches): + """ Main route + + :param event: event whose tracks are about to be displayed; + :param tag: deprecated: search for a specific tag + :param searches: frontend search dict, containing + + * 'search': search string; + * 'tags': list of tag IDs for filtering; + """ + if not event.can_access_from_current_website(): raise NotFound() + return request.render( + "website_event_track.tracks_session", + self._event_tracks_get_values(event, tag=tag, **searches) + ) + + def _event_tracks_get_values(self, event, tag=None, **searches): + # init and process search terms + searches.setdefault('search', '') + searches.setdefault('search_wishlist', '') + searches.setdefault('tags', '') + search_domain = self._get_event_tracks_base_domain(event) + + # search on content + if searches.get('search'): + search_domain = expression.AND([ + search_domain, + [('name', 'ilike', searches['search'])] + ]) + + # search on tags + search_tags = self._get_search_tags(searches['tags']) + if not search_tags and tag: # backward compatibility + search_tags = tag + if search_tags: + # Example: You filter on age: 10-12 and activity: football. + # Doing it this way allows to only get events who are tagged "age: 10-12" AND "activity: football". + # Add another tag "age: 12-15" to the search and it would fetch the ones who are tagged: + # ("age: 10-12" OR "age: 12-15") AND "activity: football + grouped_tags = dict() + for search_tag in search_tags: + grouped_tags.setdefault(search_tag.category_id, list()).append(search_tag) + search_domain_items = [ + [('tag_ids', 'in', [tag.id for tag in grouped_tags[group]])] + for group in grouped_tags + ] + search_domain = expression.AND([ + search_domain, + *search_domain_items + ]) + + # fetch data to display with TZ set for both event and tracks + now_tz = utc.localize(fields.Datetime.now().replace(microsecond=0), is_dst=False).astimezone(timezone(event.date_tz)) + today_tz = now_tz.date() event = event.with_context(tz=event.date_tz or 'UTC') - searches = {} - if tag: - searches.update(tag=tag.id) - tracks = event.track_ids.filtered(lambda track: tag in track.tag_ids) - else: - tracks = event.track_ids - - values = { + tracks_sudo = event.env['event.track'].sudo().search(search_domain, order='date asc') + tag_categories = request.env['event.track.tag.category'].sudo().search([]) + + # filter on wishlist (as post processing due to costly search on is_reminder_on) + if searches.get('search_wishlist'): + tracks_sudo = tracks_sudo.filtered(lambda track: track.is_reminder_on) + + # organize categories for display: announced, live, soon and day-based + tracks_announced = tracks_sudo.filtered(lambda track: not track.date) + tracks_wdate = tracks_sudo - tracks_announced + date_begin_tz_all = list(set( + dt.date() + for dt in self._get_dt_in_event_tz(tracks_wdate.mapped('date'), event) + )) + date_begin_tz_all.sort() + tracks_sudo_live = tracks_wdate.filtered(lambda track: track.is_published and track.is_track_live) + tracks_sudo_soon = tracks_wdate.filtered(lambda track: track.is_published and not track.is_track_live and track.is_track_soon) + tracks_by_day = [] + for display_date in date_begin_tz_all: + matching_tracks = tracks_wdate.filtered(lambda track: self._get_dt_in_event_tz([track.date], event)[0].date() == display_date) + tracks_by_day.append({'date': display_date, 'name': display_date, 'tracks': matching_tracks}) + if tracks_announced: + tracks_announced = tracks_announced.sorted('wishlisted_by_default', reverse=True) + tracks_by_day.append({'date': False, 'name': _('Coming soon'), 'tracks': tracks_announced}) + + # return rendering values + return { + # event information 'event': event, 'main_object': event, - 'tracks': tracks, - 'tags': event.tracks_tag_ids, + # tracks display information + 'tracks': tracks_sudo, + 'tracks_by_day': tracks_by_day, + 'tracks_live': tracks_sudo_live, + 'tracks_soon': tracks_sudo_soon, + 'today_tz': today_tz, + # search information 'searches': searches, - 'html2plaintext': html2plaintext + 'search_key': searches['search'], + 'search_wishlist': searches['search_wishlist'], + 'search_tags': search_tags, + 'tag_categories': tag_categories, + # environment + 'is_html_empty': is_html_empty, + 'hostname': request.httprequest.host.split(':')[0], + 'user_event_manager': request.env.user.has_group('event.group_event_manager'), } - return request.render("website_event_track.tracks", values) # ------------------------------------------------------------ # AGENDA VIEW @@ -219,14 +319,41 @@ class EventTrackController(http.Controller): # TRACK PAGE VIEW # ------------------------------------------------------------ - @http.route(['''/event/<model("event.event"):event>/track/<model("event.track", "[('event_id','=',event.id)]"):track>'''], type='http', auth="public", website=True, sitemap=True) - def event_track_view(self, event, track, **post): - if not event.can_access_from_current_website(): - raise NotFound() + @http.route('''/event/<model("event.event", "[('website_track', '=', True)]"):event>/track/<model("event.track", "[('event_id', '=', event.id)]"):track>''', + type='http', auth="public", website=True, sitemap=True) + def event_track_page(self, event, track, **options): + track = self._fetch_track(track.id, allow_is_accepted=False) - track = track.sudo().with_context(tz=event.date_tz or 'UTC') - values = {'track': track, 'event': track.event_id, 'main_object': track} - return request.render("website_event_track.track_view", values) + return request.render( + "website_event_track.event_track_main", + self._event_track_page_get_values(event, track.sudo(), **options) + ) + + def _event_track_page_get_values(self, event, track, **options): + track = track.sudo() + + option_widescreen = options.get('widescreen', False) + option_widescreen = bool(option_widescreen) if option_widescreen != '0' else False + # search for tracks list + tracks_other = track._get_track_suggestions( + restrict_domain=self._get_event_tracks_base_domain(track.event_id), + limit=10 + ) + + return { + # event information + 'event': event, + 'main_object': track, + 'track': track, + # sidebar + 'tracks_other': tracks_other, + # options + 'option_widescreen': option_widescreen, + # environment + 'is_html_empty': is_html_empty, + 'hostname': request.httprequest.host.split(':')[0], + 'user_event_manager': request.env.user.has_group('event.group_event_manager'), + } @http.route("/event/track/toggle_reminder", type="json", auth="public", website=True) def track_reminder_toggle(self, track_id, set_reminder_on): @@ -330,3 +457,21 @@ class EventTrackController(http.Controller): raise Forbidden() return track + + def _get_search_tags(self, tag_search): + # TDE FIXME: make me generic (slides, event, ...) + try: + tag_ids = literal_eval(tag_search) + except Exception: + tags = request.env['event.track.tag'].sudo() + else: + # perform a search to filter on existing / valid tags implicitly + tags = request.env['event.track.tag'].sudo().search([('id', 'in', tag_ids)]) + return tags + + def _get_dt_in_event_tz(self, datetimes, event): + tz_name = event.date_tz + return [ + utc.localize(dt, is_dst=False).astimezone(timezone(tz_name)) + for dt in datetimes + ] diff --git a/addons/website_event_track/data/event_track_demo.xml b/addons/website_event_track/data/event_track_demo.xml index 4eeead8b65f..71308eb0736 100644 --- a/addons/website_event_track/data/event_track_demo.xml +++ b/addons/website_event_track/data/event_track_demo.xml @@ -344,6 +344,10 @@ <field name="duration">2</field> <field name="user_id" ref="base.user_admin"/> <field name="partner_id" ref="base.res_partner_address_15"/> + <field name="website_cta" eval="True"/> + <field name="website_cta_title">Try Now</field> + <field name="website_cta_url">http://www.example.com</field> + <field name="website_cta_delay">10</field> </record> <record id="event_7_track_2" model="event.track"> <field name="name">First Day Wrapup</field> @@ -387,6 +391,10 @@ <field name="duration">2</field> <field name="user_id" ref="base.user_admin"/> <field name="partner_id" ref="base.res_partner_address_15"/> + <field name="website_cta" eval="True"/> + <field name="website_cta_title">Try Now</field> + <field name="website_cta_url">http://www.example.com</field> + <field name="website_cta_delay">10</field> </record> <!-- Location 2 --> <record id="event_7_track_5" model="event.track"> diff --git a/addons/website_event_track/models/event_track.py b/addons/website_event_track/models/event_track.py index 2ec57bddde4..9c44d2d290d 100644 --- a/addons/website_event_track/models/event_track.py +++ b/addons/website_event_track/models/event_track.py @@ -2,6 +2,8 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from datetime import timedelta +from pytz import utc +from random import randint from odoo import api, fields, models from odoo.addons.http_routing.models.ir_http import slug @@ -78,6 +80,27 @@ class Track(models.Model): 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.") + is_track_live = fields.Boolean( + 'Is Track Live', compute='_compute_track_time_data', + help="Track has started and is ongoing") + is_track_soon = fields.Boolean( + 'Is Track Soon', compute='_compute_track_time_data', + help="Track begins soon") + is_track_today = fields.Boolean( + 'Is Track Today', compute='_compute_track_time_data', + help="Track begins today") + is_track_upcoming = fields.Boolean( + 'Is Track Upcoming', compute='_compute_track_time_data', + help="Track is not yet started") + is_track_done = fields.Boolean( + 'Is Track Done', compute='_compute_track_time_data', + help="Track is finished") + track_start_remaining = fields.Integer( + 'Minutes before track starts', compute='_compute_track_time_data', + help="Remaining time before track starts (seconds)") + track_start_relative = fields.Integer( + 'Minutes compare to track start', compute='_compute_track_time_data', + help="Relative time compared to track start (seconds)") # frontend description website_image = fields.Image(string="Website Image", max_width=1024, max_height=1024) website_image_url = fields.Char( @@ -100,6 +123,18 @@ class Track(models.Model): 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.""") + # Call to action + website_cta = fields.Boolean('Magic Button') + website_cta_title = fields.Char('Button Title') + website_cta_url = fields.Char('Button Target URL') + website_cta_delay = fields.Integer('Button appears') + # time information for CTA + is_website_cta_live = fields.Boolean( + 'Is CTA Live', compute='_compute_cta_time_data', + help="CTA button is available") + website_cta_start_remaining = fields.Integer( + 'Minutes before CTA starts', compute='_compute_cta_time_data', + help="Remaining time before CTA starts (seconds)") @api.depends('name') def _compute_website_url(self): @@ -219,12 +254,61 @@ class Track(models.Model): ]) return [('id', 'in', track_visitors.track_id.ids)] + # TIME + + @api.depends('date', 'date_end') + def _compute_track_time_data(self): + """ Compute start and remaining time for track itself. Do everything in + UTC as we compute only time deltas here. """ + now_utc = utc.localize(fields.Datetime.now().replace(microsecond=0)) + for track in self: + if not track.date: + track.is_track_live = track.is_track_soon = track.is_track_today = track.is_track_upcoming = track.is_track_done = False + track.track_start_relative = track.track_start_remaining = 0 + continue + date_begin_utc = utc.localize(track.date, is_dst=False) + date_end_utc = utc.localize(track.date_end, is_dst=False) + track.is_track_live = date_begin_utc <= now_utc < date_end_utc + track.is_track_soon = (date_begin_utc - now_utc).total_seconds() < 30*60 if date_begin_utc > now_utc else False + track.is_track_today = date_begin_utc.date() == now_utc.date() + track.is_track_upcoming = date_begin_utc > now_utc + track.is_track_done = date_end_utc <= now_utc + if date_begin_utc >= now_utc: + track.track_start_relative = int((date_begin_utc - now_utc).total_seconds()) + track.track_start_remaining = track.track_start_relative + else: + track.track_start_relative = int((now_utc - date_begin_utc).total_seconds()) + track.track_start_remaining = 0 + + @api.depends('date', 'date_end', 'website_cta', 'website_cta_delay') + def _compute_cta_time_data(self): + """ Compute start and remaining time for track itself. Do everything in + UTC as we compute only time deltas here. """ + now_utc = utc.localize(fields.Datetime.now().replace(microsecond=0)) + for track in self: + if not track.website_cta: + track.is_website_cta_live = track.website_cta_start_remaining = False + continue + + date_begin_utc = utc.localize(track.date, is_dst=False) + timedelta(minutes=track.website_cta_delay or 0) + date_end_utc = utc.localize(track.date_end, is_dst=False) + track.is_website_cta_live = date_begin_utc <= now_utc <= date_end_utc + if date_begin_utc >= now_utc: + td = date_begin_utc - now_utc + track.website_cta_start_remaining = int(td.total_seconds()) + else: + track.website_cta_start_remaining = 0 + # ------------------------------------------------------------ # CRUD # ------------------------------------------------------------ @api.model_create_multi def create(self, vals_list): + for values in vals_list: + if values.get('website_cta_url'): + values['website_cta_url'] = self.env['res.partner']._clean_website(values['website_cta_url']) + tracks = super(Track, self).create(vals_list) for track in tracks: @@ -239,6 +323,8 @@ class Track(models.Model): return tracks def write(self, vals): + if vals.get('website_cta_url'): + vals['website_cta_url'] = self.env['res.partner']._clean_website(vals['website_cta_url']) if 'stage_id' in vals and 'kanban_state' not in vals: vals['kanban_state'] = 'normal' if vals.get('stage_id'): @@ -317,6 +403,9 @@ class Track(models.Model): 'type': 'ir.actions.act_window', } + def get_backend_menu_id(self): + return self.env.ref('event.event_main_menu').id + # ------------------------------------------------------------ # TOOLS # ------------------------------------------------------------ @@ -352,3 +441,52 @@ class Track(models.Model): } for track in missing]) return track_visitors + + def _get_track_suggestions(self, restrict_domain=None, limit=None): + """ Returns the next tracks suggested after going to the current one + given by self. Tracks always belong to the same event. + + Heuristic is + + * live first; + * then ordered by start date, finished being sent to the end; + * wishlisted (manually or by default); + * tag matching with current track; + * location matching with current track; + * finally a random to have an "equivalent wave" randomly given; + + :param restrict_domain: an additional domain to restrict candidates; + :param limit: number of tracks to return; + """ + self.ensure_one() + + base_domain = [ + '&', + ('event_id', '=', self.event_id.id), + ('id', '!=', self.id), + ] + if restrict_domain: + base_domain = expression.AND([ + base_domain, + restrict_domain + ]) + + track_candidates = self.search(base_domain, limit=None, order='date asc') + if not track_candidates: + return track_candidates + + track_candidates = track_candidates.sorted( + lambda track: + (track.is_published, + track.is_track_live, + track.track_start_remaining > 0, + -1 * track.track_start_remaining, + track.is_reminder_on, + not track.wishlisted_by_default, + len(track.tag_ids & self.tag_ids), + track.location_id == self.location_id, + randint(0, 20), + ), reverse=True + ) + + return track_candidates[:limit] diff --git a/addons/website_event_track_session/static/src/scss/event_track_templates.scss b/addons/website_event_track/static/src/scss/event_track_templates_online.scss index a37a0a380cb..a37a0a380cb 100644 --- a/addons/website_event_track_session/static/src/scss/event_track_templates.scss +++ b/addons/website_event_track/static/src/scss/event_track_templates_online.scss diff --git a/addons/website_event_track/tests/__init__.py b/addons/website_event_track/tests/__init__.py index 12b9da864c8..aac974d7656 100644 --- a/addons/website_event_track/tests/__init__.py +++ b/addons/website_event_track/tests/__init__.py @@ -2,4 +2,5 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import common +from . import test_track_internals from . import test_website_event diff --git a/addons/website_event_track_session/tests/test_track_internals.py b/addons/website_event_track/tests/test_track_internals.py index e2af8c0c6fe..e2af8c0c6fe 100644 --- a/addons/website_event_track_session/tests/test_track_internals.py +++ b/addons/website_event_track/tests/test_track_internals.py diff --git a/addons/website_event_track/views/assets.xml b/addons/website_event_track/views/assets.xml index 120f828839d..c94ee9ece00 100644 --- a/addons/website_event_track/views/assets.xml +++ b/addons/website_event_track/views/assets.xml @@ -5,6 +5,7 @@ <xpath expr="//link[last()]" position="after"> <link rel="stylesheet" href="/website_event_track/static/src/css/website_event_track.css"/> <link rel="stylesheet" type="text/scss" href="/website_event_track/static/src/scss/event_track_templates.scss"/> + <link rel="stylesheet" type="text/scss" href="/website_event_track/static/src/scss/event_track_templates_online.scss"/> <link rel="stylesheet" type="text/scss" href="/website_event_track/static/src/scss/pwa_frontend.scss"/> </xpath> <xpath expr="//script[last()]" position="after"> diff --git a/addons/website_event_track/views/event_track_templates_agenda.xml b/addons/website_event_track/views/event_track_templates_agenda.xml index d7ddf00da0b..1608924587c 100644 --- a/addons/website_event_track/views/event_track_templates_agenda.xml +++ b/addons/website_event_track/views/event_track_templates_agenda.xml @@ -150,6 +150,9 @@ <template id="agenda_main_track" name="Track Agenda: Track"> <div class="d-flex flex-column h-100"> <div class="d-flex justify-content-end flex-wrap-reverse 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 + </small> <small t-if="not track.website_published and user_event_manager and track.stage_id.is_accepted" title="Unpublished" class="ml-1 badge badge-danger o_wevent_online_badge_unpublished">Unpublished</small> diff --git a/addons/website_event_track/views/event_track_templates_list.xml b/addons/website_event_track/views/event_track_templates_list.xml index 35cdf9d24ca..85059f44c71 100644 --- a/addons/website_event_track/views/event_track_templates_list.xml +++ b/addons/website_event_track/views/event_track_templates_list.xml @@ -1,93 +1,374 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> -<template id="tracks" track="True"> +<template id="tracks_session" name="Event Tracks"> <t t-call="website_event.layout"> - <div class="oe_structure" id="oe_structure_website_event_track_tracks_1"/> - <section class="pt48 pb48"> - <div class="container"> + <div class="o_wevent_online o_wesession_index"> + <!-- Options --> + <t t-set="option_track_wishlist" t-value="not event.is_done and request.website.viewref('website_event_track.session_topbar_wishlist').active"/> + <!-- Topbar --> + <t t-call="website_event_track.session_topbar"/> + <!-- Drag/Drop Area --> + <div id="oe_structure_wesession_index_1" class="oe_structure"/> + <!-- Content --> + <div class="o_wesession_container container"> <div class="row"> - <div id="left_column"> + <t t-call="website_event_track.tracks_search"/> + </div> + <div class="row"> + <t t-call="website_event_track.tracks_main"/> + </div> + </div> + <!-- Drag/Drop Area --> + <div id="oe_structure_wesession_index_2" class="oe_structure mb-5"/> + </div> + </t> +</template> + +<!-- ============================================================ --> +<!-- TOPBAR: BASE NAVIGATION --> +<!-- ============================================================ --> + +<!-- Main topbar --> +<template id="session_topbar" name="Tracks Tools"> + <nav class="navbar navbar-light border-top shadow-sm d-print-none"> + <div class="container"> + <div class="d-flex flex-column flex-sm-row justify-content-between w-100"> + <ul class="o_wesession_topbar_filters o_wevent_index_topbar_filters nav"> + <!-- Optional wishlist filter --> + <li t-if="option_track_wishlist" class="nav-item dropdown mr-2 my-1"> + <a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown"> + <i class="fa fa-folder-open"/> Wishlist + </a> + <div class="dropdown-menu"> + <a t-att-href="'/event/%s/track?%s' % ( + slug(event), + keep_query('*', search_wishlist='') + )" + class="dropdown-item d-flex align-items-center justify-content-between"> + All Talks + </a> + <a t-att-href="'/event/%s/track?%s' % ( + slug(event), + keep_query('*', search_wishlist='1') + )" + t-attf-class="dropdown-item d-flex align-items-center justify-content-between #{'active' if search_wishlist else ''}"> + Wishlisted + </a> + </div> + </li> + </ul> + <div class="d-flex align-items-center flex-wrap pl-sm-3 pr-0"> + <t t-call="website_event.events_search_box"> + <t t-set="_searches" t-value="searches"/> + <t t-set="action" t-value="'/event/%s/track' % (slug(event))"/> + <t t-set="_placeholder" t-value="'Search a talk ...'"/> + </t> + </div> + </div> + </div> + </nav> +</template> + +<!-- Option: Topbar: optional tags filters --> +<template id="session_topbar_tag" + inherit_id="website_event_track.session_topbar" + name="Filter by Tags" + active="True" + customize_show="True"> + <xpath expr="//ul[hasclass('o_wesession_topbar_filters')]" position="inside"> + <t t-foreach="tag_categories" t-as="tag_category"> + <li t-if="tag_category.tag_ids and any(tag.color for tag in tag_category.tag_ids)" class="nav-item dropdown mr-2 my-1"> + <a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown"> + <i class="fa fa-folder-open"/> + <t t-esc="tag_category.name"/> + </a> + <div class="dropdown-menu"> + <t t-foreach="tag_category.tag_ids" t-as="tag"> + <a t-att-href="'/event/%s/track?%s' % ( + slug(event), + keep_query('*', tags=str((search_tags - tag).ids if tag in search_tags else (tag | search_tags).ids)) + )" + t-if="tag.color" + t-attf-class="dropdown-item d-flex align-items-center justify-content-between #{'active' if tag in search_tags else ''}"> + <t t-esc="tag.name"/> + </a> + </t> + </div> + </li> + </t> + </xpath> +</template> + +<!-- Option: Tracks display: optional wishlist --> +<template id="session_topbar_wishlist" + inherit_id="website_event_track.session_topbar" + name="Allow Wishlists" + active="True" + customize_show="True"> + <xpath expr="//ul[hasclass('o_wesession_topbar_filters')]" position="inside"> + </xpath> +</template> + +<!-- ============================================================ --> +<!-- CONTENT: MAIN TEMPLATES --> +<!-- ============================================================ --> + +<!-- Tracks Main Display --> +<template id="tracks_main" name="Tracks: Main Display"> + <!-- No tracks --> + <t t-if="not tracks"> + <div class="col-12"> + <div class="h2 mb-3">No track found.</div> + <div t-if="search_key" class="alert alert-info text-center"> + <p class="m-0">We did not find any track matching your <strong t-esc="search_key"/> search.</p> + </div> + <div t-else="" class="alert alert-info text-center" groups="event.group_event_manager"> + <p class="m-0">Schedule some tracks to get started !</p> + </div> + </div> + </t> + <!-- Cards --> + <div class="col-12" t-call="website_event_track.tracks_display_cards"/> + <!-- List --> + <div class="col-12" t-call="website_event_track.tracks_display_list"/> +</template> + +<!-- Tracks: Cards-based display --> +<template id="tracks_display_cards" name="Tracks: Cards Display"> + <div class="row mb-3" t-if="tracks_live"> + <div class="col-12"> + <h5 class="m-0 text-danger">Live Now</h5> + <hr class="mt-2 pb-1 mb-1"/> + </div> + <div t-foreach="tracks_live" t-as="track" class="col-md-6 col-lg-3 mb-4"> + <t t-call="website_event_track.tracks_cards_track"/> + </div> + </div> + <div class="row mb-3" t-if="tracks_soon"> + <div class="col-12"> + <h5 class="m-0 text-danger">Coming soon ...</h5> + <hr class="mt-2 pb-1 mb-1"/> + </div> + <div t-foreach="tracks_soon" t-as="track" class="col-md-6 col-lg-3 mb-4"> + <t t-call="website_event_track.tracks_cards_track"/> + </div> + </div> +</template> + +<!-- Tracks: List-based display --> +<template id="tracks_display_list" name="Tracks: List Display"> + <div t-if="tracks" class="o_wesession_list mb-3"> + <ul class="list-unstyled"> + <li t-foreach="tracks_by_day" t-as="tracks_info" + class="mb-5"> + <t t-set="tracks_date" t-value="tracks_info['date']"/> + <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"> + <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"> + <span class="font-weight-bold" t-esc="tracks_date" + t-options="{'widget': 'date', 'format': 'MMMM'}"/> + <span class="font-weight-bold" t-esc="tracks_date" + t-options="{'widget': 'date', 'format': 'YYYY'}"/> + </div> + </div> + <div t-elif="tracks_header_name"> + <span class="h1 m-0 font-weight-bold" + t-esc="tracks_header_name"/> </div> - <div class="col-lg-9"> - <div class="alert alert-warning" t-if="not len(tracks)" role="alert"> - No tracks found! + <hr class="mt-2 pb-1 mb-1"/> + </div> + <!-- DAY TRACKS LIST --> + <div t-foreach="tracks" t-as="track" class="row mt8 o_wesession_list_item"> + <div class="col-md-7"> + <span class="h5 mb0"> + <a t-if="track.is_published or user_event_manager" + t-att-href="track.website_url"> + <span t-field="track.name"/> + </a> + <t t-else=""> + <span t-field="track.name"/> + </t> + <span t-if="not track.is_published and user_event_manager" + class="badge badge-danger ml-2 o_wevent_online_badge_unpublished"> + Unpublished + </span> + </span> + <div class="text-muted"> + <span class="text-muted" t-esc="track.partner_name"/> + <t t-if="track.partner_name"> &bull; </t> + <span t-esc="track.duration" + t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'hour', 'round': 'minute'}"/> </div> - <div class="row mb-2" t-foreach="tracks" t-as="track"> - <div class="col-md-2"> - <t t-if="track.image"> - <span t-field="track.image" - t-options='{"widget": "image", "class": "rounded-circle"}'/> + </div> + <div class="col-md-5"> + <div t-if="not event.is_done" class="float-right"> + <t t-if="tracks_date and today_tz <= tracks_date"> + <span t-if="track.is_track_live and not track.is_track_done" + class="badge badge-danger">Live</span> + <span t-elif="not track.is_track_done and track.is_track_soon"> + <span t-esc="track.track_start_remaining" + t-options="{'widget': 'duration', 'digital': False, 'format': 'narrow', + 'add_direction': True, 'unit': 'second', 'round': 'minute'}"/> + </span> + <t t-elif="not track.is_track_done and not track.is_track_soon"> + <span + class="mr-2" + t-esc="track.date" + t-options="{'widget': 'datetime', 'time_only': True, 'format': 'short'}"/> + <t t-if="option_track_wishlist" + t-call="website_event_track.track_widget_reminder"> + <t t-set="reminder_small" t-value="True"/> + </t> + </t> + <t t-else=""> + <span class="badge badge-info">Finished</span> </t> - </div> - <div class="col-md-10"> - <h3 class="mt0 mb0"> - <a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }" class="text-secondary"><span t-field="track.name"> </span></a> - <small t-if="not track.website_published" class="badge badge-danger">unpublished</small> - </h3> - <ul class="list-inline mb0"> - <li t-if="track.partner_id" class="list-inline-item"> - <i class="fa fa-user text-primary"/> - <t t-esc="track.partner_id.sudo().name"/> - </li> - <li t-if="track.date" class="list-inline-item"> - <i class="fa fa-calendar text-primary"/> - <span t-field="track.date" t-options='{"hide_seconds":"True"}'/> - </li> - <li class="list-inline-item" t-if="track.location_id"> - <i class="fa fa-map-marker"/> - <span t-field="track.location_id"/> - </li> - </ul> - <ul class="list-inline"> - <li t-foreach="track.tag_ids" t-as="tag_id" class="list-inline-item fa fa-tags" t-if="tag_id.color != 0"> - <a t-attf-href="/event/#{ slug(event) }/track/tag/#{ slug(tag_id) }"> - <i class="fa fa-tags"/> - <span t-field="tag_id.name"/> - </a> - </li> - </ul> - <p class="mt8"><t t-esc="html2plaintext(track.description or '')[0:500]"/><t t-if="track.description">...</t></p> - </div> + </t> + <t t-elif="not track.date and option_track_wishlist" + t-call="website_event_track_online.track_widget_reminder"> + <t t-set="reminder_small" t-value="True"/> + </t> </div> + <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> + </li> + </ul> + </div> +</template> + +<!-- ============================================================ --> +<!-- TOOL TEMPLATES --> +<!-- ============================================================ --> + +<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 '')" + itemscope="itemscope" itemtype="http://schema.org/Event"> + <div class="h-100 row no-gutters"> + <header class="overflow-hidden bg-secondary col-12 rounded-top"> + <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> + + <div t-if="track.website_image_url" class="card-img-top" + t-attf-style="padding-top: 50%; background-image: url(#{track.website_image_url}); background-size: cover; background-position:center"> + <span t-if="option_track_wishlist and not track.is_track_live" class="position-absolute h3 mt-2 mr-2" style="right: 0; top: 0;"> + <t t-call="website_event_track.track_widget_reminder"> + <t t-set="reminder_light" t-value="True"/> + <t t-set="light_theme" t-value="True"/> + </t> + </span> + </div> + <div t-else="" class="o_wesession_gradient card-img-top position-relative" + style="padding-top: 50%;"> + <span t-if="option_track_wishlist" class="position-absolute h3 mt-2 mr-2" style="right: 0; top: 0;"> + <t t-call="website_event_track.track_widget_reminder"> + <t t-set="reminder_light" t-value="True"/> + </t> + </span> + <i class="fa fa-glass fa-2x mx-2 mb-3 position-absolute text-white-75" style="right:0; bottom: 0;"/> + </div> + </header> + <div class="col-12"> + <main class="card-body"> + <!-- Title --> + <h5 class="card-title mt-0 mb-0 text-truncate"> + <span t-field="track.name" itemprop="name"/> + </h5> + <!-- Tags> --> + <div> + <t t-foreach="track.tag_ids" t-as="tag"> + <t t-if="tag.color" t-call="website_event_track.track_tag_badge_info"/> + </t> + </div> + </main> + </div> + <!-- Footer --> + <footer class="small align-self-end w-100 card-footer"> + <div class="d-flex justify-content-between align-items-center"> + <!-- Speaker --> + <span class="text-muted text-truncate" t-field="track.partner_name" itemprop="performer"/> + <!-- Starts --> + <span class="text-muted ml-auto"> + <t t-if="track.is_track_upcoming > 0">In + <span class="text-muted ml-auto" t-field="track.track_start_remaining" itemprop="duration" + t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'second', 'round': 'minute'}"/> + </t> + <t t-else=""> + <span class="text-muted ml-auto" t-field="track.track_start_relative" itemprop="duration" + t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'second', 'round': 'minute'}"/> + ago + </t> + </span> + </div> + </footer> </div> - </section> - <div class="oe_structure" id="oe_structure_website_event_track_tracks_2"/> - </t> + </article> + </a> </template> -<template id="tracks_filter" inherit_id="website_event_track.tracks" customize_show="True" name="Filter on Tags"> - <xpath expr="//div[@id='left_column']" position="inside"> - <ul class="nav nav-pills flex-column"> - <li class="nav-item"><a t-attf-href="/event/#{ slug(event) }/track" t-attf-class="nav-link #{'' if searches.get('tag') else ' active'}">All Tags</a></li> - <t t-foreach="tags" t-as="tag"> - <li class="nav-item"> - <a t-attf-href="/event/#{ slug(event) }/track/tag/#{ slug(tag) }" t-attf-class="nav-link#{searches.get('tag') == tag.id and ' active' or ''}"> - <t t-esc="tag.name"/> - </a> - </li> - </t> - </ul> - </xpath> - <xpath expr="//div[@id='left_column']" position="attributes"> - <attribute name="class">col-lg-3 css_no_print</attribute> - </xpath> +<!-- Searched tags --> +<template id="tracks_search" name="Tracks: search tags"> + <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 + <a t-att-href="'/event/%s/track?%s' % (slug(event), keep_query('*', search_wishlist=''))" + class="btn border-0 py-1"> + × + </a> + </span> + + <t t-foreach="search_tags" t-as="tag"> + <span class="align-items-baseline border d-inline-flex pl-2 mt-3 rounded ml16 mb-2 bg-white"> + <i class="fa fa-tag mr-2 text-muted"/> + <t t-esc="tag.display_name"/> + <a t-att-href="'/event/%s/track?%s' % (slug(event), keep_query('*', tags=str((search_tags - tag).ids)))" + class="btn border-0 py-1"> + × + </a> + </span> + </t> + </div> </template> -<!-- Add wishlist button on tracks / track templates --> -<template id="tracks_wishlist" - name="Wishlist on Tracks" - inherit_id="website_event_track.tracks" - customize_show="True"> - <xpath expr="//h3" position="replace"> - <h3 class="mt0 mb0 d-flex"> - <a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }" class="text-secondary"><span t-field="track.name"> </span></a> - <small t-if="not track.website_published" class="badge badge-danger">unpublished</small> - <t t-call="website_event_track.track_widget_reminder"/> - </h3> - </xpath> +<!-- ============================================================ --> +<!-- MISC TOOLS --> +<!-- ============================================================ --> + +<template id="track_tag_badge_link" name="Track: Tag Badge Link"> + <a t-if="search_tags" + t-att-href="'/event/%s/track?%s'% ( + slug(event), + keep_query('*', tags=str((search_tags - tag).ids if tag in search_tags else (tag | search_tags).ids)) + )" + t-att-class="'badge %s' % ('badge-primary' if tag in search_tags else 'o_tag_color_hovered_0')" + t-esc="tag.name"/> + <a t-else="" + t-att-href="'/event/%s/track?%s'% ( + slug(event), + keep_query('*', tags=str(tag.ids)) + )" + t-att-class="'badge o_tag_color_hovered_%s' % (tag.color)" + t-esc="tag.name"/> +</template> + +<template id="track_tag_badge_info" name="Track: Tag Badge Info"> + <span t-if="search_tags" + t-att-class="'badge %s' % ('badge-primary' if tag in search_tags else 'o_tag_color_0')" + t-esc="tag.name"/> + <span t-else="" + t-att-class="'badge o_tag_color_%s' % (tag.color)" + t-esc="tag.name"/> </template> </odoo> diff --git a/addons/website_event_track/views/event_track_templates_page.xml b/addons/website_event_track/views/event_track_templates_page.xml index 5d4b5617b29..c8cbed11e45 100644 --- a/addons/website_event_track/views/event_track_templates_page.xml +++ b/addons/website_event_track/views/event_track_templates_page.xml @@ -1,99 +1,216 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> -<template id="track_view" track="True"> +<template id="event_track_main" name="Event Exhibitor"> <t t-call="website_event.layout"> - <section class="pt48"> - <div class="container"> - <div class="row"> - <div class="col-12"> - <h1 t-field="track.name"/> - <small>Proposed by - <span t-if="track.partner_id" t-field="track.partner_id.sudo().name"/> - <span t-if="not track.partner_id" t-field="track.partner_name"/> - </small> - <ul t-if="track.tag_ids" class="text-center text-muted list-inline"> - <li t-foreach="track.tag_ids" t-as="tag_id" class="list-inline-item" t-if="tag_id.color != 0"> - <span class="fa fa-tags"></span> - <a t-attf-href="/event/#{ slug(event) }/track/tag/#{ slug(tag_id) }"> - <span t-field="tag_id.name"/> - </a> - </li> - </ul> - </div> + <div class="o_wevent_online o_wevent_online_bg o_wesession_index"> + <!-- Options --> + <t t-set="option_widescreen" t-value="option_widescreen or False"/> + <t t-set="option_track_wishlist" t-value="not event.is_done and request.website.viewref('website_event_track.session_topbar_wishlist').active"/> + <!-- Drag/Drop Area --> + <div id="oe_structure_wesession_track_index_1" class="oe_structure"/> + <!-- Content --> + <div t-att-class="'o_wevent_online_page_container %s' % ('container pb-3' if not option_widescreen else 'pb-3')"> + <div class="row mb-5 mx-0"> + <t t-call="website_event_track.event_track_aside"/> + <t t-call="website_event_track.event_track_content"/> </div> </div> - </section> - <section class="pt32"> - <div class="container"> - <div class="row"> - <div class="col-lg-8"> - <div t-field="track.description"/> - <h3>About The Speaker</h3> - <div t-field="track.partner_biography"/> - <div t-if="track.partner_id" class="row mt32"> - <div class="col-md-2"> - <span t-if="track.image" t-field="track.image" t-options="{'widget': 'image', 'class': 'rounded-circle'}"/> - <span t-else="" t-field="track.partner_id.sudo().image_128" t-options='{"widget": "image", "class": "rounded-circle"}'/> - </div> - <div class="col-md-10"> - <h4 t-field="track.partner_id.name" class="mb4"/> - <div class="mb16" t-if="track.partner_id.website"> - <i class="fa fa-home mr-2"/><a t-att-href="track.partner_id.website"><span t-field="track.partner_id.website"/></a> - </div> - <div t-field="track.partner_id.website_description"/> - </div> - </div> + <!-- Drag/Drop Area --> + <div id="oe_structure_wesession_track_index_2" class="oe_structure"/> + </div> + </t> +</template> + +<!-- ============================================================ --> +<!-- CONTENT: MAIN TEMPLATES --> +<!-- ============================================================ --> + +<template id="event_track_content" name="Track: Main Description"> + <div name="o_wesession_track_main" + t-att-class="'col-12 o_wevent_online_page_main o_wesession_track_main bg-white p-0 %s' % ('col-md-9 col-lg-10' if option_widescreen else 'col-md-8 col-lg-9')"> + <!-- LIVE INFORMATIONS --> + <div t-if="not track.event_id.is_ongoing" class="pt-3"> + <div class="mx-3 alert alert-warning"> + Event <span t-esc="track.event_id.name" class="font-weight-bold"/> + <span t-if="track.event_id.start_today"> + starts in + <span t-esc="track.event_id.start_remaining" + t-options="{'widget': 'duration', 'digital': False, 'unit': 'minute', 'round': 'minute'}"/> + </span> + <span t-else=""> + starts at + <span t-field="track.event_id.with_context(tz=track.event_id.date_tz).date_begin" + t-options="{'format': 'long', 'tz_name': track.event_id.date_tz, 'hide_seconds': True}"/> + </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> + <!-- TRACK DESCRIPTION --> + <div class="o_wesession_track_main_description"> + <div class="mx-3 pt-3 mb-3 d-flex justify-content-between flex-column flex-md-row"> + <div class="d-flex flex-column"> + <span class="h4 mb-0" t-esc="track.name"/> + <div> + <t t-foreach="track.tag_ids" t-as="tag"> + <span t-if="tag.color" + t-att-class="'badge o_tag_color_hovered_%s' % (tag.color)" + t-esc="tag.name"/> + </t> </div> - <div class="col-lg-4" id="right_column"> - <div class="card"> - <h4 class="card-header">Practical Info</h4> - <div class="card-body"> - <b>Date</b><br/> - <t t-if="track.date"> - <span t-field="track.date" t-options='{"hide_seconds":"True", "format": "short"}'/> - <t t-if="event.date_tz"> - (<span t-field="track.date" t-options='{"format": "zzz"}'/>) - </t> - </t> - <t t-else=""> - <span>To be scheduled</span> - </t> - <br/> - <b>Duration</b><br/> - <span t-field="track.duration" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/><br/> - <b>Location</b><br/> - <span t-field="track.location_id"/><br/> - </div> + </div> + <div class="o_we_track_action_buttons d-flex justify-content-md-end align-items-center flex-wrap"> + <div class="o_we_track_reminder_button my-1"> + <div t-if="option_track_wishlist and not track.is_track_done" + t-call="website_event_track.track_widget_reminder"> + <t t-set="reminder_small" t-value="False"/> + <t t-set="reminder_light" t-value="False"/> </div> + </div> + </div> + </div> + <div class="mx-3 text-muted"> + <t t-if="track.location_id"> + <strong>Location:</strong> <span t-field="track.location_id"/> + <span> - </span> + </t> + <t t-if="track.date"> + <span t-field="track.date" + t-options='{"hide_seconds":"True", "format": "short"}'/> + - + <span t-field="track.date_end" + t-options='{"hide_seconds":"True", "format": "short"}'/> + <t t-if="event.date_tz"> + (<span t-field="track.date_end" t-options='{"format": "zzz"}'/>) + </t> + </t> + <t t-if="track.duration"> + (<span t-field="track.duration" + t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/>) + </t> + </div> + + <hr class="mt-2 mb-0"/> - <div class="card" t-if="False"> - <h4 class="card-header">Documents</h4> - <div class="card-body"> - Put here the list of documents, like slides of - the presentations. Remove the above t-if when - it's implemented. - </div> - </div> + <!-- ABOUT AUTHOR --> + <div class="mx-3"> + <div class="mt-2 d-flex"> + <span t-if="track.image" t-field="track.image" class="o_wevent_online_page_avatar" + t-options="{'widget': 'image', 'class': 'rounded-circle', 'max_width': '96'}"/> + <div class="pl-2 pr-0 pr-md-2 d-flex flex-column"> + <span t-field="track.partner_name" class="font-weight-bold mb-2"/> + <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_function"> + <i class="fa fa-briefcase mr-2"/><span t-esc="track.partner_function"/> + <t t-if="track.partner_company_name"> + <span>&nbsp;at&nbsp;</span><span t-esc="track.partner_company_name"/> + </t> + </span> + <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_id.website"> + <i class="fa fa-home mr-2"/><a t-att-href="track.partner_id.website"><span t-field="track.partner_id.website"/></a> + </span> + <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_email"> + <i class="fa fa-envelope mr-2"/><a t-att-mailto="track.partner_email"><span t-field="track.partner_email"/></a> + </span> + <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_phone"> + <i class="fa fa-phone mr-2"/><span t-field="track.partner_phone"/> + </span> </div> </div> + <div t-field="track.partner_biography" class="oe_no_empty"/> + <hr t-if="not is_html_empty(track.description)" class="mt-2 pb-1 mb-1"/> </div> - </section> - </t> + <div t-field="track.description" class="my-2 mx-3 oe_no_empty"/> + </div> + </div> +</template> + +<!-- ============================================================ --> +<!-- ASIDE: CONTROL PANEL --> +<!-- ============================================================ --> + +<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 class="bg-white pt-0 pt-md-3 o_wevent_online_page_aside_content"> + <div class="mx-2" t-if="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"> + <t t-set="pre_remaining_time" t-value="int(track.track_start_remaining)"/> + <!--<t t-set="pre_countdown_text" t-value="'Talk starts in'"/>--> + <t t-set="pre_countdown_display" t-value="bool(False)"/> + <t t-set="main_remaining_time" t-value="int(track.website_cta_start_remaining)"/> + <!--<t t-set="main_countdown_text" t-value="'Magic happens in'"/>--> + <t t-set="main_countdown_display" t-value="bool(False)"/> + <t t-set="display_class" t-value="'.o_event_cta_action'"/> + </t> + </div> + <div t-att-class="'o_event_cta_action %s' % ('d-none' if cta_coundown else '')"> + <a t-att-href="track.website_cta_url" + target="_blank" + class="btn btn-primary w-100 mb-3 mt-2 mt-md-0"> + <span t-esc="track.website_cta_title"/> + </a> + </div> + </div> + <div class="d-flex align-items-center justify-content-between mx-2"> + <ul class="nav nav-tabs o_wesession_track_aside_nav d-flex border-0" role="tablist"> + <li class="nav-item flex-grow-1"> + <a href="#track_list" aria-controls="track_list" class="nav-link active" role="tab" data-toggle="tab"> + Talks + </a> + </li> + </ul> + <a href="#collapse_track_aside" data-toggle="collapse" class="d-md-none p-2 text-decoration-none o_wevent_online_page_aside_collapse collapsed"> + <i class="fa fa-chevron-down d-md-none"/> + </a> + </div> + <div id="collapse_track_aside" + class="tab-content collapse d-md-block o_wesession_track_aside_tabs"> + <div class="tab-pane fade show active" id="track_list" role="tabpanel"> + <ul class="list-unstyled mb-0"> + <li t-foreach="tracks_other" t-as="track_other" class="w-100"> + <a t-if="user_event_manager or track_other.is_published" + class="d-block w-100 h-100 px-2 pt-2 pb-1 text-decoration-none" + t-att-href="track_other.website_url"> + <t t-call="website_event_track.event_track_aside_other_track"/> + </a> + <div t-else="" class="text-muted px-2 pt-2 pb-1"> + <t t-call="website_event_track.event_track_aside_other_track"/> + </div> + </li> + </ul> + </div> + </div> + </div> + </div> </template> -<template id="track_view_wishlist" - name="Wishlist on Track" - inherit_id="website_event_track.track_view" - customize_show="True"> - <xpath expr="//h1" position="replace"> - <div class="d-flex"> - <h1 t-field="track.name"/> - <div class="ml-2 pt-1"> - <t t-call="website_event_track.track_widget_reminder"/> +<template id="event_track_aside_other_track"> + <span t-esc="track_other.name" class="w-100"/> + <div class="d-flex align-items-center"> + <small class="text-muted" t-esc="track_other.partner_name"/> + <div class="d-inline-block ml-auto o_wesession_track_aside_info text-truncate"> + <small t-if="track_other.is_track_live and not track_other.is_track_done" + class="badge badge-danger">Live</small> + <small t-elif="track_other.is_track_done" + class="badge badge-light">Done</small> + <small t-elif="track_other.is_track_today and track_other.track_start_remaining" + class="badge badge-light"> + <span t-esc="track_other.track_start_remaining" + t-options="{'widget': 'duration', 'digital': False, 'add_direction': True, + 'unit': 'second', 'round': 'minute', 'format': 'narrow'}"/> + </small> + <div t-elif="track_other.date" class="badge badge-light"> + <span t-esc="track_other.date" t-options="{'widget': 'datetime', 'tz_name': track_other.event_id.date_tz, 'format': 'MMM. dd'}"/> </div> </div> - </xpath> + </div> </template> </odoo> diff --git a/addons/website_event_track/views/event_track_views.xml b/addons/website_event_track/views/event_track_views.xml index 3ff98ac1132..58ff291a2a4 100644 --- a/addons/website_event_track/views/event_track_views.xml +++ b/addons/website_event_track/views/event_track_views.xml @@ -183,6 +183,25 @@ <page string="Description" name="description"> <field name="description"/> </page> + <page string="Interactivity" name="interactivity"> + <group> + <group name="event_track_cta_group"> + <field name="website_cta"/> + <field name="website_cta_title" placeholder="e.g. Get Yours Now !" + attrs="{'invisible': [('website_cta', '=', False)], + 'required': [('website_cta', '=', True)]}"/> + <field name="website_cta_url" placeholder="e.g. http://www.example.com" + attrs="{'invisible': [('website_cta', '=', False)], + 'required': [('website_cta', '=', True)]}"/> + <label for="website_cta_delay" + attrs="{'invisible': [('website_cta', '=', False)]}"/> + <div attrs="{'invisible': [('website_cta', '=', False)]}"> + <field name="website_cta_delay" class="oe_inline" + attrs="{'required': [('website_cta', '=', True)]}"/> minutes after talk start + </div> + </group> + </group> + </page> </notebook> </sheet> <div class="oe_chatter"> diff --git a/addons/website_event_track_live/__manifest__.py b/addons/website_event_track_live/__manifest__.py index 3574deefbc9..be28bb71b0b 100644 --- a/addons/website_event_track_live/__manifest__.py +++ b/addons/website_event_track_live/__manifest__.py @@ -12,7 +12,6 @@ 'description': "", 'depends': [ 'website_event_track', - 'website_event_track_session', ], 'data': [ 'views/assets.xml', diff --git a/addons/website_event_track_live/controllers/session.py b/addons/website_event_track_live/controllers/session.py index 9d6381e6300..ea8cc5411a4 100644 --- a/addons/website_event_track_live/controllers/session.py +++ b/addons/website_event_track_live/controllers/session.py @@ -3,11 +3,11 @@ import re -from odoo.addons.website_event_track_session.controllers.session import WebsiteEventSessionController +from odoo.addons.website_event_track.controllers.event_track import EventTrackController from odoo.http import request -class WebsiteEventSessionLiveController(WebsiteEventSessionController): +class WebsiteEventSessionLiveController(EventTrackController): def _event_track_page_get_values(self, event, track, **options): if 'widescreen' not in options: diff --git a/addons/website_event_track_live/views/event_track_templates_list.xml b/addons/website_event_track_live/views/event_track_templates_list.xml index 9f6236b6bfb..844620dd44f 100644 --- a/addons/website_event_track_live/views/event_track_templates_list.xml +++ b/addons/website_event_track_live/views/event_track_templates_list.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> -<template id="tracks_display_list" inherit_id="website_event_track_session.tracks_display_list"> +<template id="tracks_display_list" inherit_id="website_event_track.tracks_display_list"> <!-- TRACK LIST: ADD REPLAY TAG FOR FINISHED TRACKS --> <xpath expr="//div[hasclass('o_wesession_list_item')]/div[hasclass('col-md-5')]//t[@t-elif='not track.is_track_done and not track.is_track_soon']" position="after"> <a t-elif="track.youtube_video_url and (track.is_published or user_event_manager)" diff --git a/addons/website_event_track_live/views/event_track_templates_page.xml b/addons/website_event_track_live/views/event_track_templates_page.xml index f72152f6e71..1ac7dfd2748 100644 --- a/addons/website_event_track_live/views/event_track_templates_page.xml +++ b/addons/website_event_track_live/views/event_track_templates_page.xml @@ -2,7 +2,7 @@ <odoo> <!-- MAIN: REMOVE HEADER/FOOTER IF WIDESCREEN --> -<template id="event_track_main" inherit_id="website_event_track_session.event_track_main"> +<template id="event_track_main" inherit_id="website_event_track.event_track_main"> <xpath expr="//t[@t-call='website_event.layout']" position="before"> <t t-set="no_header" t-value="option_widescreen"/> <t t-set="no_footer" t-value="option_widescreen"/> @@ -10,7 +10,7 @@ </template> <!-- MAIN: ADD VIDEO --> -<template id="event_track_content" inherit_id="website_event_track_session.event_track_content"> +<template id="event_track_content" inherit_id="website_event_track.event_track_content"> <!-- Do not display "starting in" in case of replay mode as video is already available --> <xpath expr="//div[@t-elif='track.track_start_remaining']" position="attributes"> <attribute name="t-elif">track.track_start_remaining and not track.is_youtube_replay</attribute> @@ -31,7 +31,7 @@ </template> <!-- ASIDE: ADD CHAT TAB FOR VIDEOS --> -<template id="event_track_aside" inherit_id="website_event_track_session.event_track_aside"> +<template id="event_track_aside" inherit_id="website_event_track.event_track_aside"> <xpath expr="//ul[hasclass('o_wesession_track_aside_nav')]" position="inside"> <li t-if="track.is_youtube_chat_available and not is_mobile_chat_disabled" class="nav-item flex-grow-1"> <a href="#track_chat" aria-controls="track_chat" class="nav-link" role="tab" data-toggle="tab"> diff --git a/addons/website_event_track_quiz/__manifest__.py b/addons/website_event_track_quiz/__manifest__.py index 4aaacbe69f4..e1e71980282 100644 --- a/addons/website_event_track_quiz/__manifest__.py +++ b/addons/website_event_track_quiz/__manifest__.py @@ -12,7 +12,7 @@ 'description': "", 'depends': [ 'website_profile', - 'website_event_track_session', + 'website_event_track', ], 'data': [ 'security/ir.model.access.csv', diff --git a/addons/website_event_track_quiz/controllers/event_track_quiz.py b/addons/website_event_track_quiz/controllers/event_track_quiz.py index 2942313a680..f734952d147 100644 --- a/addons/website_event_track_quiz/controllers/event_track_quiz.py +++ b/addons/website_event_track_quiz/controllers/event_track_quiz.py @@ -2,11 +2,11 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import http -from odoo.addons.website_event_track_session.controllers.session import WebsiteEventSessionController +from odoo.addons.website_event_track.controllers.event_track import EventTrackController from odoo.http import request -class WebsiteEventTrackQuiz(WebsiteEventSessionController): +class WebsiteEventTrackQuiz(EventTrackController): # QUIZZES IN PAGE # ---------------------------------------------------------- diff --git a/addons/website_event_track_quiz/views/event_track_templates_page.xml b/addons/website_event_track_quiz/views/event_track_templates_page.xml index e448cfd35dc..2a50df5e61c 100644 --- a/addons/website_event_track_quiz/views/event_track_templates_page.xml +++ b/addons/website_event_track_quiz/views/event_track_templates_page.xml @@ -3,7 +3,7 @@ <template id="event_track_content" name="Track: Main Description: add quiz" - inherit_id="website_event_track_session.event_track_content"> + inherit_id="website_event_track.event_track_content"> <xpath expr="//div[hasclass('o_wesession_track_main_description')]" position="after"> <div id="we_track_quiz_container" t-if="track.quiz_id" t-att-class="'o_quiz_js_quiz_container o_quiz_main border-top bg-white px-2 pt-4 pb-4 col-12 %s' % ('' if track.is_quiz_completed else 'd-none')" diff --git a/addons/website_event_track_quiz/views/event_track_views.xml b/addons/website_event_track_quiz/views/event_track_views.xml index d8d2f190735..13a0ceac999 100644 --- a/addons/website_event_track_quiz/views/event_track_views.xml +++ b/addons/website_event_track_quiz/views/event_track_views.xml @@ -3,7 +3,7 @@ <record id="event_track_view_form" model="ir.ui.view" > <field name="name">event.track.view.form.inherit.event.track.quiz</field> <field name="model">event.track</field> - <field name="inherit_id" ref="website_event_track_session.event_track_view_form"/> + <field name="inherit_id" ref="website_event_track.view_event_track_form"/> <field name="arch" type="xml"> <xpath expr="//group[@name='event_track_cta_group']" position="after"> <group name="event_track_quiz_group"> diff --git a/addons/website_event_track_session/__init__.py b/addons/website_event_track_session/__init__.py deleted file mode 100644 index 5a31f331a2a..00000000000 --- a/addons/website_event_track_session/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import controllers -from . import models -from . import tests diff --git a/addons/website_event_track_session/__manifest__.py b/addons/website_event_track_session/__manifest__.py deleted file mode 100644 index 5d012021c15..00000000000 --- a/addons/website_event_track_session/__manifest__.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - - -{ - 'name': 'Event Live Sessions', - 'category': 'Marketing/Events', - 'sequence': 1005, - 'version': '1.0', - 'summary': 'Event: live session on tracks', - 'website': 'https://www.odoo.com/page/events', - 'description': "", - 'depends': [ - 'website_event_track', - ], - 'data': [ - 'views/assets.xml', - 'views/event_track_templates_agenda.xml', - 'views/event_track_templates_list.xml', - 'views/event_track_templates_misc.xml', - 'views/event_track_templates_page.xml', - 'views/event_track_views.xml', - ], - 'demo': [ - 'data/event_track_demo.xml', - ], - 'application': False, - 'installable': True, -} diff --git a/addons/website_event_track_session/controllers/__init__.py b/addons/website_event_track_session/controllers/__init__.py deleted file mode 100644 index 1c2ee57c54f..00000000000 --- a/addons/website_event_track_session/controllers/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import session diff --git a/addons/website_event_track_session/controllers/session.py b/addons/website_event_track_session/controllers/session.py deleted file mode 100644 index a59e0e500eb..00000000000 --- a/addons/website_event_track_session/controllers/session.py +++ /dev/null @@ -1,207 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from ast import literal_eval -from pytz import timezone, utc -from werkzeug.exceptions import NotFound - -from odoo import fields, http, _ -from odoo.addons.website_event_track.controllers.event_track import EventTrackController -from odoo.http import request -from odoo.osv import expression -from odoo.tools import is_html_empty - - -class WebsiteEventSessionController(EventTrackController): - - def _get_event_tracks_base_domain(self, event): - """ Base domain for displaying tracks. Restrict to accepted or published - tracks for people not managing events. Unpublished tracks may be displayed - but not reachable for teasing purpose. """ - search_domain_base = [ - ('event_id', '=', event.id), - ] - if not request.env.user.has_group('event.group_event_user'): - search_domain_base = expression.AND([ - search_domain_base, - ['|', ('is_published', '=', True), ('is_accepted', '=', True)] - ]) - return search_domain_base - - # ------------------------------------------------------------ - # MAIN PAGE - # ------------------------------------------------------------ - - @http.route([ - '''/event/<model("event.event", "[('website_track', '=', True)]"):event>/track''', - '''/event/<model("event.event", "[('website_track', '=', True)]"):event>/track/tag/<model("event.track.tag"):tag>''' - ], type='http', auth="public", website=True, sitemap=False) - def event_tracks(self, event, tag=None, **searches): - """ Main route - - :param event: event whose tracks are about to be displayed; - :param tag: deprecated: search for a specific tag - :param searches: frontend search dict, containing - - * 'search': search string; - * 'tags': list of tag IDs for filtering; - """ - if not event.can_access_from_current_website(): - raise NotFound() - - return request.render( - "website_event_track.tracks", - self._event_tracks_get_values(event, tag=tag, **searches) - ) - - def _event_tracks_get_values(self, event, tag=None, **searches): - # init and process search terms - searches.setdefault('search', '') - searches.setdefault('search_wishlist', '') - searches.setdefault('tags', '') - search_domain = self._get_event_tracks_base_domain(event) - - # search on content - if searches.get('search'): - search_domain = expression.AND([ - search_domain, - [('name', 'ilike', searches['search'])] - ]) - - # search on tags - search_tags = self._get_search_tags(searches['tags']) - if not search_tags and tag: # backward compatibility - search_tags = tag - if search_tags: - # Example: You filter on age: 10-12 and activity: football. - # Doing it this way allows to only get events who are tagged "age: 10-12" AND "activity: football". - # Add another tag "age: 12-15" to the search and it would fetch the ones who are tagged: - # ("age: 10-12" OR "age: 12-15") AND "activity: football - grouped_tags = dict() - for search_tag in search_tags: - grouped_tags.setdefault(search_tag.category_id, list()).append(search_tag) - search_domain_items = [ - [('tag_ids', 'in', [tag.id for tag in grouped_tags[group]])] - for group in grouped_tags - ] - search_domain = expression.AND([ - search_domain, - *search_domain_items - ]) - - # fetch data to display with TZ set for both event and tracks - now_tz = utc.localize(fields.Datetime.now().replace(microsecond=0), is_dst=False).astimezone(timezone(event.date_tz)) - today_tz = now_tz.date() - event = event.with_context(tz=event.date_tz or 'UTC') - tracks_sudo = event.env['event.track'].sudo().search(search_domain, order='date asc') - tag_categories = request.env['event.track.tag.category'].sudo().search([]) - - # filter on wishlist (as post processing due to costly search on is_reminder_on) - if searches.get('search_wishlist'): - tracks_sudo = tracks_sudo.filtered(lambda track: track.is_reminder_on) - - # organize categories for display: announced, live, soon and day-based - tracks_announced = tracks_sudo.filtered(lambda track: not track.date) - tracks_wdate = tracks_sudo - tracks_announced - date_begin_tz_all = list(set( - dt.date() - for dt in self._get_dt_in_event_tz(tracks_wdate.mapped('date'), event) - )) - date_begin_tz_all.sort() - tracks_sudo_live = tracks_wdate.filtered(lambda track: track.is_published and track.is_track_live) - tracks_sudo_soon = tracks_wdate.filtered(lambda track: track.is_published and not track.is_track_live and track.is_track_soon) - tracks_by_day = [] - for display_date in date_begin_tz_all: - matching_tracks = tracks_wdate.filtered(lambda track: self._get_dt_in_event_tz([track.date], event)[0].date() == display_date) - tracks_by_day.append({'date': display_date, 'name': display_date, 'tracks': matching_tracks}) - if tracks_announced: - tracks_announced = tracks_announced.sorted('wishlisted_by_default', reverse=True) - tracks_by_day.append({'date': False, 'name': _('Coming soon'), 'tracks': tracks_announced}) - - # return rendering values - return { - # event information - 'event': event, - 'main_object': event, - # tracks display information - 'tracks': tracks_sudo, - 'tracks_by_day': tracks_by_day, - 'tracks_live': tracks_sudo_live, - 'tracks_soon': tracks_sudo_soon, - 'today_tz': today_tz, - # search information - 'searches': searches, - 'search_key': searches['search'], - 'search_wishlist': searches['search_wishlist'], - 'search_tags': search_tags, - 'tag_categories': tag_categories, - # environment - 'is_html_empty': is_html_empty, - 'hostname': request.httprequest.host.split(':')[0], - 'user_event_manager': request.env.user.has_group('event.group_event_manager'), - } - - # ------------------------------------------------------------ - # PAGE VIEW - # ------------------------------------------------------------ - - @http.route('''/event/<model("event.event", "[('website_track', '=', True)]"):event>/track/<model("event.track", "[('event_id', '=', event.id)]"):track>''', - type='http', auth="public", website=True, sitemap=True) - def event_track_page(self, event, track, **options): - track = self._fetch_track(track.id, allow_is_accepted=False) - - return request.render( - "website_event_track_session.event_track_main", - self._event_track_page_get_values(event, track.sudo(), **options) - ) - - def event_track_view(self, event, track, **post): - return self.event_track_page(event, track, **post) - - def _event_track_page_get_values(self, event, track, **options): - track = track.sudo() - - option_widescreen = options.get('widescreen', False) - option_widescreen = bool(option_widescreen) if option_widescreen != '0' else False - # search for tracks list - tracks_other = track._get_track_suggestions( - restrict_domain=self._get_event_tracks_base_domain(track.event_id), - limit=10 - ) - - return { - # event information - 'event': event, - 'main_object': track, - 'track': track, - # sidebar - 'tracks_other': tracks_other, - # options - 'option_widescreen': option_widescreen, - # environment - 'is_html_empty': is_html_empty, - 'hostname': request.httprequest.host.split(':')[0], - 'user_event_manager': request.env.user.has_group('event.group_event_manager'), - } - - # ------------------------------------------------------------ - # TOOLS - # ------------------------------------------------------------ - - def _get_search_tags(self, tag_search): - # TDE FIXME: make me generic (slides, event, ...) - try: - tag_ids = literal_eval(tag_search) - except Exception: - tags = request.env['event.track.tag'].sudo() - else: - # perform a search to filter on existing / valid tags implicitly - tags = request.env['event.track.tag'].sudo().search([('id', 'in', tag_ids)]) - return tags - - def _get_dt_in_event_tz(self, datetimes, event): - tz_name = event.date_tz - return [ - utc.localize(dt, is_dst=False).astimezone(timezone(tz_name)) - for dt in datetimes - ] diff --git a/addons/website_event_track_session/data/event_track_demo.xml b/addons/website_event_track_session/data/event_track_demo.xml deleted file mode 100644 index c9fd08ccd84..00000000000 --- a/addons/website_event_track_session/data/event_track_demo.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo><data> - - <record id="website_event_track.event_7_track_1" model="event.track"> - <field name="website_cta" eval="True"/> - <field name="website_cta_title">Try Now</field> - <field name="website_cta_url">http://www.example.com</field> - <field name="website_cta_delay">10</field> - </record> - <record id="website_event_track.event_7_track_4" model="event.track"> - <field name="website_cta" eval="True"/> - <field name="website_cta_title">Try Now</field> - <field name="website_cta_url">http://www.example.com</field> - <field name="website_cta_delay">10</field> - </record> - -</data></odoo> diff --git a/addons/website_event_track_session/models/__init__.py b/addons/website_event_track_session/models/__init__.py deleted file mode 100644 index e3798014924..00000000000 --- a/addons/website_event_track_session/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import event_track diff --git a/addons/website_event_track_session/models/event_track.py b/addons/website_event_track_session/models/event_track.py deleted file mode 100644 index 7e012156e38..00000000000 --- a/addons/website_event_track_session/models/event_track.py +++ /dev/null @@ -1,155 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from datetime import timedelta -from random import randint -from pytz import utc - -from odoo import api, fields, models -from odoo.osv import expression - - -class EventTrack(models.Model): - _inherit = "event.track" - - # Call to action - website_cta = fields.Boolean('Magic Button') - website_cta_title = fields.Char('Button Title') - website_cta_url = fields.Char('Button Target URL') - website_cta_delay = fields.Integer('Button appears') - # time information for track - is_track_live = fields.Boolean( - 'Is Track Live', compute='_compute_track_time_data', - help="Track has started and is ongoing") - is_track_soon = fields.Boolean( - 'Is Track Soon', compute='_compute_track_time_data', - help="Track begins soon") - is_track_today = fields.Boolean( - 'Is Track Today', compute='_compute_track_time_data', - help="Track begins today") - is_track_upcoming = fields.Boolean( - 'Is Track Upcoming', compute='_compute_track_time_data', - help="Track is not yet started") - is_track_done = fields.Boolean( - 'Is Track Done', compute='_compute_track_time_data', - help="Track is finished") - track_start_remaining = fields.Integer( - 'Minutes before track starts', compute='_compute_track_time_data', - help="Remaining time before track starts (seconds)") - track_start_relative = fields.Integer( - 'Minutes compare to track start', compute='_compute_track_time_data', - help="Relative time compared to track start (seconds)") - # time information for CTA - is_website_cta_live = fields.Boolean( - 'Is CTA Live', compute='_compute_cta_time_data', - help="CTA button is available") - website_cta_start_remaining = fields.Integer( - 'Minutes before CTA starts', compute='_compute_cta_time_data', - help="Remaining time before CTA starts (seconds)") - - @api.depends('date', 'date_end') - def _compute_track_time_data(self): - """ Compute start and remaining time for track itself. Do everything in - UTC as we compute only time deltas here. """ - now_utc = utc.localize(fields.Datetime.now().replace(microsecond=0)) - for track in self: - if not track.date: - track.is_track_live = track.is_track_soon = track.is_track_today = track.is_track_upcoming = track.is_track_done = False - track.track_start_relative = track.track_start_remaining = 0 - continue - date_begin_utc = utc.localize(track.date, is_dst=False) - date_end_utc = utc.localize(track.date_end, is_dst=False) - track.is_track_live = date_begin_utc <= now_utc < date_end_utc - track.is_track_soon = (date_begin_utc - now_utc).total_seconds() < 30*60 if date_begin_utc > now_utc else False - track.is_track_today = date_begin_utc.date() == now_utc.date() - track.is_track_upcoming = date_begin_utc > now_utc - track.is_track_done = date_end_utc <= now_utc - if date_begin_utc >= now_utc: - track.track_start_relative = int((date_begin_utc - now_utc).total_seconds()) - track.track_start_remaining = track.track_start_relative - else: - track.track_start_relative = int((now_utc - date_begin_utc).total_seconds()) - track.track_start_remaining = 0 - - @api.depends('date', 'date_end', 'website_cta', 'website_cta_delay') - def _compute_cta_time_data(self): - """ Compute start and remaining time for track itself. Do everything in - UTC as we compute only time deltas here. """ - now_utc = utc.localize(fields.Datetime.now().replace(microsecond=0)) - for track in self: - if not track.website_cta: - track.is_website_cta_live = track.website_cta_start_remaining = False - continue - - date_begin_utc = utc.localize(track.date, is_dst=False) + timedelta(minutes=track.website_cta_delay or 0) - date_end_utc = utc.localize(track.date_end, is_dst=False) - track.is_website_cta_live = date_begin_utc <= now_utc <= date_end_utc - if date_begin_utc >= now_utc: - td = date_begin_utc - now_utc - track.website_cta_start_remaining = int(td.total_seconds()) - else: - track.website_cta_start_remaining = 0 - - @api.model_create_multi - def create(self, values_list): - for values in values_list: - if values.get('website_cta_url'): - values['website_cta_url'] = self.env['res.partner']._clean_website(values['website_cta_url']) - return super(EventTrack, self).create(values_list) - - def write(self, values): - if values.get('website_cta_url'): - values['website_cta_url'] = self.env['res.partner']._clean_website(values['website_cta_url']) - return super(EventTrack, self).write(values) - - def _get_track_suggestions(self, restrict_domain=None, limit=None): - """ Returns the next tracks suggested after going to the current one - given by self. Tracks always belong to the same event. - - Heuristic is - - * live first; - * then ordered by start date, finished being sent to the end; - * wishlisted (manually or by default); - * tag matching with current track; - * location matching with current track; - * finally a random to have an "equivalent wave" randomly given; - - :param restrict_domain: an additional domain to restrict candidates; - :param limit: number of tracks to return; - """ - self.ensure_one() - - base_domain = [ - '&', - ('event_id', '=', self.event_id.id), - ('id', '!=', self.id), - ] - if restrict_domain: - base_domain = expression.AND([ - base_domain, - restrict_domain - ]) - - track_candidates = self.search(base_domain, limit=None, order='date asc') - if not track_candidates: - return track_candidates - - track_candidates = track_candidates.sorted( - lambda track: - (track.is_published, - track.is_track_live, - track.track_start_remaining > 0, - -1 * track.track_start_remaining, - track.is_reminder_on, - not track.wishlisted_by_default, - len(track.tag_ids & self.tag_ids), - track.location_id == self.location_id, - randint(0, 20), - ), reverse=True - ) - - return track_candidates[:limit] - - def get_backend_menu_id(self): - return self.env.ref('event.event_main_menu').id diff --git a/addons/website_event_track_session/tests/__init__.py b/addons/website_event_track_session/tests/__init__.py deleted file mode 100644 index c4e08033d49..00000000000 --- a/addons/website_event_track_session/tests/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import test_track_internals diff --git a/addons/website_event_track_session/views/assets.xml b/addons/website_event_track_session/views/assets.xml deleted file mode 100644 index fd9b752732e..00000000000 --- a/addons/website_event_track_session/views/assets.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo> - - <template id="assets_frontend" inherit_id="website.assets_frontend" name="Event Sessions Assets Frontend"> - <xpath expr="//link[last()]" position="after"> - <link rel="stylesheet" type="text/scss" href="/website_event_track_session/static/src/scss/event_track_templates.scss"/> - </xpath> - </template> - -</odoo> diff --git a/addons/website_event_track_session/views/event_track_templates_agenda.xml b/addons/website_event_track_session/views/event_track_templates_agenda.xml deleted file mode 100644 index 09ca68fa467..00000000000 --- a/addons/website_event_track_session/views/event_track_templates_agenda.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo> - -<template id="agenda_main_track" name="Track Agenda: Track (Session)" - inherit_id="website_event_track.agenda_main_track"> - <xpath expr="//div[hasclass('o_weagenda_track_badges')]/small[1]" position="before"> - <small t-if="track.is_track_live and not track.is_track_done and track.website_published" - class="mx-1 badge badge-danger">Live - </small> - </xpath> -</template> - -</odoo> diff --git a/addons/website_event_track_session/views/event_track_templates_list.xml b/addons/website_event_track_session/views/event_track_templates_list.xml deleted file mode 100644 index c841201cab7..00000000000 --- a/addons/website_event_track_session/views/event_track_templates_list.xml +++ /dev/null @@ -1,380 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo> - -<template id="tracks_session" - inherit_id="website_event_track.tracks"> - <!-- New main layout --> - <xpath expr="//div[@id='oe_structure_website_event_track_tracks_1']" position="before"> - <div class="o_wevent_online o_wesession_index"> - <!-- Options --> - <t t-set="option_track_wishlist" t-value="not event.is_done and request.website.viewref('website_event_track_session.session_topbar_wishlist').active"/> - <!-- Topbar --> - <t t-call="website_event_track_session.session_topbar"/> - <!-- Drag/Drop Area --> - <div id="oe_structure_wesession_index_1" class="oe_structure"/> - <!-- Content --> - <div class="o_wesession_container container"> - <div class="row"> - <t t-call="website_event_track_session.tracks_search"/> - </div> - <div class="row"> - <t t-call="website_event_track_session.tracks_main"/> - </div> - </div> - <!-- Drag/Drop Area --> - <div id="oe_structure_wesession_index_2" class="oe_structure mb-5"/> - </div> - </xpath> - <!-- Reset existing template as nothing to keep --> - <xpath expr="//div[@id='oe_structure_website_event_track_tracks_1']" position="replace"/> - <xpath expr="//section" position="replace"/> - <xpath expr="//div[@id='oe_structure_website_event_track_tracks_2']" position="replace"/> -</template> - -<!-- ============================================================ --> -<!-- TOPBAR: BASE NAVIGATION --> -<!-- ============================================================ --> - -<!-- Main topbar --> -<template id="session_topbar" name="Tracks Tools"> - <nav class="navbar navbar-light border-top shadow-sm d-print-none"> - <div class="container"> - <div class="d-flex flex-column flex-sm-row justify-content-between w-100"> - <ul class="o_wesession_topbar_filters o_wevent_index_topbar_filters nav"> - <!-- Optional wishlist filter --> - <li t-if="option_track_wishlist" class="nav-item dropdown mr-2 my-1"> - <a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown"> - <i class="fa fa-folder-open"/> Wishlist - </a> - <div class="dropdown-menu"> - <a t-att-href="'/event/%s/track?%s' % ( - slug(event), - keep_query('*', search_wishlist='') - )" - class="dropdown-item d-flex align-items-center justify-content-between"> - All Talks - </a> - <a t-att-href="'/event/%s/track?%s' % ( - slug(event), - keep_query('*', search_wishlist='1') - )" - t-attf-class="dropdown-item d-flex align-items-center justify-content-between #{'active' if search_wishlist else ''}"> - Wishlisted - </a> - </div> - </li> - </ul> - <div class="d-flex align-items-center flex-wrap pl-sm-3 pr-0"> - <t t-call="website_event.events_search_box"> - <t t-set="_searches" t-value="searches"/> - <t t-set="action" t-value="'/event/%s/track' % (slug(event))"/> - <t t-set="_placeholder" t-value="'Search a talk ...'"/> - </t> - </div> - </div> - </div> - </nav> -</template> - -<!-- Option: Topbar: optional tags filters --> -<template id="session_topbar_tag" - inherit_id="website_event_track_session.session_topbar" - name="Filter by Tags" - active="True" - customize_show="True"> - <xpath expr="//ul[hasclass('o_wesession_topbar_filters')]" position="inside"> - <t t-foreach="tag_categories" t-as="tag_category"> - <li t-if="tag_category.tag_ids and any(tag.color for tag in tag_category.tag_ids)" class="nav-item dropdown mr-2 my-1"> - <a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown"> - <i class="fa fa-folder-open"/> - <t t-esc="tag_category.name"/> - </a> - <div class="dropdown-menu"> - <t t-foreach="tag_category.tag_ids" t-as="tag"> - <a t-att-href="'/event/%s/track?%s' % ( - slug(event), - keep_query('*', tags=str((search_tags - tag).ids if tag in search_tags else (tag | search_tags).ids)) - )" - t-if="tag.color" - t-attf-class="dropdown-item d-flex align-items-center justify-content-between #{'active' if tag in search_tags else ''}"> - <t t-esc="tag.name"/> - </a> - </t> - </div> - </li> - </t> - </xpath> -</template> - -<!-- Option: Tracks display: optional wishlist --> -<template id="session_topbar_wishlist" - inherit_id="website_event_track_session.session_topbar" - name="Allow Wishlists" - active="True" - customize_show="True"> - <xpath expr="//ul[hasclass('o_wesession_topbar_filters')]" position="inside"> - </xpath> -</template> - -<!-- ============================================================ --> -<!-- CONTENT: MAIN TEMPLATES --> -<!-- ============================================================ --> - -<!-- Tracks Main Display --> -<template id="tracks_main" name="Tracks: Main Display"> - <!-- No tracks --> - <t t-if="not tracks"> - <div class="col-12"> - <div class="h2 mb-3">No track found.</div> - <div t-if="search_key" class="alert alert-info text-center"> - <p class="m-0">We did not find any track matching your <strong t-esc="search_key"/> search.</p> - </div> - <div t-else="" class="alert alert-info text-center" groups="event.group_event_manager"> - <p class="m-0">Schedule some tracks to get started !</p> - </div> - </div> - </t> - <!-- Cards --> - <div class="col-12" t-call="website_event_track_session.tracks_display_cards"/> - <!-- List --> - <div class="col-12" t-call="website_event_track_session.tracks_display_list"/> -</template> - -<!-- Tracks: Cards-based display --> -<template id="tracks_display_cards" name="Tracks: Cards Display"> - <div class="row mb-3" t-if="tracks_live"> - <div class="col-12"> - <h5 class="m-0 text-danger">Live Now</h5> - <hr class="mt-2 pb-1 mb-1"/> - </div> - <div t-foreach="tracks_live" t-as="track" class="col-md-6 col-lg-3 mb-4"> - <t t-call="website_event_track_session.tracks_cards_track"/> - </div> - </div> - <div class="row mb-3" t-if="tracks_soon"> - <div class="col-12"> - <h5 class="m-0 text-danger">Coming soon ...</h5> - <hr class="mt-2 pb-1 mb-1"/> - </div> - <div t-foreach="tracks_soon" t-as="track" class="col-md-6 col-lg-3 mb-4"> - <t t-call="website_event_track_session.tracks_cards_track"/> - </div> - </div> -</template> - -<!-- Tracks: List-based display --> -<template id="tracks_display_list" name="Tracks: List Display"> - <div t-if="tracks" class="o_wesession_list mb-3"> - <ul class="list-unstyled"> - <li t-foreach="tracks_by_day" t-as="tracks_info" - class="mb-5"> - <t t-set="tracks_date" t-value="tracks_info['date']"/> - <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"> - <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"> - <span class="font-weight-bold" t-esc="tracks_date" - t-options="{'widget': 'date', 'format': 'MMMM'}"/> - <span class="font-weight-bold" t-esc="tracks_date" - t-options="{'widget': 'date', 'format': 'YYYY'}"/> - </div> - </div> - <div t-elif="tracks_header_name"> - <span class="h1 m-0 font-weight-bold" - t-esc="tracks_header_name"/> - </div> - <hr class="mt-2 pb-1 mb-1"/> - </div> - <!-- DAY TRACKS LIST --> - <div t-foreach="tracks" t-as="track" class="row mt8 o_wesession_list_item"> - <div class="col-md-7"> - <span class="h5 mb0"> - <a t-if="track.is_published or user_event_manager" - t-att-href="track.website_url"> - <span t-field="track.name"/> - </a> - <t t-else=""> - <span t-field="track.name"/> - </t> - <span t-if="not track.is_published and user_event_manager" - class="badge badge-danger ml-2 o_wevent_online_badge_unpublished"> - Unpublished - </span> - </span> - <div class="text-muted"> - <span class="text-muted" t-esc="track.partner_name"/> - <t t-if="track.partner_name"> &bull; </t> - <span t-esc="track.duration" - t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'hour', 'round': 'minute'}"/> - </div> - </div> - <div class="col-md-5"> - <div t-if="not event.is_done" class="float-right"> - <t t-if="tracks_date and today_tz <= tracks_date"> - <span t-if="track.is_track_live and not track.is_track_done" - class="badge badge-danger">Live</span> - <span t-elif="not track.is_track_done and track.is_track_soon"> - <span t-esc="track.track_start_remaining" - t-options="{'widget': 'duration', 'digital': False, 'format': 'narrow', - 'add_direction': True, 'unit': 'second', 'round': 'minute'}"/> - </span> - <t t-elif="not track.is_track_done and not track.is_track_soon"> - <span - class="mr-2" - t-esc="track.date" - t-options="{'widget': 'datetime', 'time_only': True, 'format': 'short'}"/> - <t t-if="option_track_wishlist" - t-call="website_event_track.track_widget_reminder"> - <t t-set="reminder_small" t-value="True"/> - </t> - </t> - <t t-else=""> - <span class="badge badge-info">Finished</span> - </t> - </t> - <t t-elif="not track.date and option_track_wishlist" - t-call="website_event_track_online.track_widget_reminder"> - <t t-set="reminder_small" t-value="True"/> - </t> - </div> - <t t-foreach="track.tag_ids" t-as="tag"> - <t t-if="tag.color" t-call="website_event_track_session.track_tag_badge_link"/> - </t> - </div> - </div> - </li> - </ul> - </div> -</template> - -<!-- ============================================================ --> -<!-- TOOL TEMPLATES --> -<!-- ============================================================ --> - -<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 '')" - itemscope="itemscope" itemtype="http://schema.org/Event"> - <div class="h-100 row no-gutters"> - <header class="overflow-hidden bg-secondary col-12 rounded-top"> - <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> - - <div t-if="track.website_image_url" class="card-img-top" - t-attf-style="padding-top: 50%; background-image: url(#{track.website_image_url}); background-size: cover; background-position:center"> - <span t-if="option_track_wishlist and not track.is_track_live" class="position-absolute h3 mt-2 mr-2" style="right: 0; top: 0;"> - <t t-call="website_event_track.track_widget_reminder"> - <t t-set="reminder_light" t-value="True"/> - <t t-set="light_theme" t-value="True"/> - </t> - </span> - </div> - <div t-else="" class="o_wesession_gradient card-img-top position-relative" - style="padding-top: 50%;"> - <span t-if="option_track_wishlist" class="position-absolute h3 mt-2 mr-2" style="right: 0; top: 0;"> - <t t-call="website_event_track.track_widget_reminder"> - <t t-set="reminder_light" t-value="True"/> - </t> - </span> - <i class="fa fa-glass fa-2x mx-2 mb-3 position-absolute text-white-75" style="right:0; bottom: 0;"/> - </div> - </header> - <div class="col-12"> - <main class="card-body"> - <!-- Title --> - <h5 class="card-title mt-0 mb-0 text-truncate"> - <span t-field="track.name" itemprop="name"/> - </h5> - <!-- Tags> --> - <div> - <t t-foreach="track.tag_ids" t-as="tag"> - <t t-if="tag.color" t-call="website_event_track_session.track_tag_badge_info"/> - </t> - </div> - </main> - </div> - <!-- Footer --> - <footer class="small align-self-end w-100 card-footer"> - <div class="d-flex justify-content-between align-items-center"> - <!-- Speaker --> - <span class="text-muted text-truncate" t-field="track.partner_name" itemprop="performer"/> - <!-- Starts --> - <span class="text-muted ml-auto"> - <t t-if="track.is_track_upcoming > 0">In - <span class="text-muted ml-auto" t-field="track.track_start_remaining" itemprop="duration" - t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'second', 'round': 'minute'}"/> - </t> - <t t-else=""> - <span class="text-muted ml-auto" t-field="track.track_start_relative" itemprop="duration" - t-options="{'widget': 'duration', 'digital': False, 'format': 'short', 'unit': 'second', 'round': 'minute'}"/> - ago - </t> - </span> - </div> - </footer> - </div> - </article> - </a> -</template> - -<!-- Searched tags --> -<template id="tracks_search" name="Tracks: search tags"> - <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 - <a t-att-href="'/event/%s/track?%s' % (slug(event), keep_query('*', search_wishlist=''))" - class="btn border-0 py-1"> - × - </a> - </span> - - <t t-foreach="search_tags" t-as="tag"> - <span class="align-items-baseline border d-inline-flex pl-2 mt-3 rounded ml16 mb-2 bg-white"> - <i class="fa fa-tag mr-2 text-muted"/> - <t t-esc="tag.display_name"/> - <a t-att-href="'/event/%s/track?%s' % (slug(event), keep_query('*', tags=str((search_tags - tag).ids)))" - class="btn border-0 py-1"> - × - </a> - </span> - </t> - </div> -</template> - -<!-- ============================================================ --> -<!-- MISC TOOLS --> -<!-- ============================================================ --> - -<template id="track_tag_badge_link" name="Track: Tag Badge Link"> - <a t-if="search_tags" - t-att-href="'/event/%s/track?%s'% ( - slug(event), - keep_query('*', tags=str((search_tags - tag).ids if tag in search_tags else (tag | search_tags).ids)) - )" - t-att-class="'badge %s' % ('badge-primary' if tag in search_tags else 'o_tag_color_hovered_0')" - t-esc="tag.name"/> - <a t-else="" - t-att-href="'/event/%s/track?%s'% ( - slug(event), - keep_query('*', tags=str(tag.ids)) - )" - t-att-class="'badge o_tag_color_hovered_%s' % (tag.color)" - t-esc="tag.name"/> -</template> - -<template id="track_tag_badge_info" name="Track: Tag Badge Info"> - <span t-if="search_tags" - t-att-class="'badge %s' % ('badge-primary' if tag in search_tags else 'o_tag_color_0')" - t-esc="tag.name"/> - <span t-else="" - t-att-class="'badge o_tag_color_%s' % (tag.color)" - t-esc="tag.name"/> -</template> - -</odoo> diff --git a/addons/website_event_track_session/views/event_track_templates_misc.xml b/addons/website_event_track_session/views/event_track_templates_misc.xml deleted file mode 100644 index 1f20d5868bf..00000000000 --- a/addons/website_event_track_session/views/event_track_templates_misc.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo><data> - - <!-- De-activate old customize --> - <record id="website_event_track.tracks_filter" model="ir.ui.view"> - <field name="active" eval="False"/> - <field name="customize_show" eval="False"/> - </record> - <record id="website_event_track.tracks_wishlist" model="ir.ui.view"> - <field name="active" eval="False"/> - <field name="customize_show" eval="False"/> - </record> - <record id="website_event_track.track_view_wishlist" model="ir.ui.view"> - <field name="active" eval="False"/> - <field name="customize_show" eval="False"/> - </record> - -</data></odoo> diff --git a/addons/website_event_track_session/views/event_track_templates_page.xml b/addons/website_event_track_session/views/event_track_templates_page.xml deleted file mode 100644 index bcc4078c647..00000000000 --- a/addons/website_event_track_session/views/event_track_templates_page.xml +++ /dev/null @@ -1,216 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo> - -<template id="event_track_main" name="Event Exhibitor"> - <t t-call="website_event.layout"> - <div class="o_wevent_online o_wevent_online_bg o_wesession_index"> - <!-- Options --> - <t t-set="option_widescreen" t-value="option_widescreen or False"/> - <t t-set="option_track_wishlist" t-value="not event.is_done and request.website.viewref('website_event_track_session.session_topbar_wishlist').active"/> - <!-- Drag/Drop Area --> - <div id="oe_structure_wesession_track_index_1" class="oe_structure"/> - <!-- Content --> - <div t-att-class="'o_wevent_online_page_container %s' % ('container pb-3' if not option_widescreen else 'pb-3')"> - <div class="row mb-5 mx-0"> - <t t-call="website_event_track_session.event_track_aside"/> - <t t-call="website_event_track_session.event_track_content"/> - </div> - </div> - <!-- Drag/Drop Area --> - <div id="oe_structure_wesession_track_index_2" class="oe_structure"/> - </div> - </t> -</template> - -<!-- ============================================================ --> -<!-- CONTENT: MAIN TEMPLATES --> -<!-- ============================================================ --> - -<template id="event_track_content" name="Track: Main Description"> - <div name="o_wesession_track_main" - t-att-class="'col-12 o_wevent_online_page_main o_wesession_track_main bg-white p-0 %s' % ('col-md-9 col-lg-10' if option_widescreen else 'col-md-8 col-lg-9')"> - <!-- LIVE INFORMATIONS --> - <div t-if="not track.event_id.is_ongoing" class="pt-3"> - <div class="mx-3 alert alert-warning"> - Event <span t-esc="track.event_id.name" class="font-weight-bold"/> - <span t-if="track.event_id.start_today"> - starts in - <span t-esc="track.event_id.start_remaining" - t-options="{'widget': 'duration', 'digital': False, 'unit': 'minute', 'round': 'minute'}"/> - </span> - <span t-else=""> - starts at - <span t-field="track.event_id.with_context(tz=track.event_id.date_tz).date_begin" - t-options="{'format': 'long', 'tz_name': track.event_id.date_tz, 'hide_seconds': True}"/> - </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> - <!-- TRACK DESCRIPTION --> - <div class="o_wesession_track_main_description"> - <div class="mx-3 pt-3 mb-3 d-flex justify-content-between flex-column flex-md-row"> - <div class="d-flex flex-column"> - <span class="h4 mb-0" t-esc="track.name"/> - <div> - <t t-foreach="track.tag_ids" t-as="tag"> - <span t-if="tag.color" - t-att-class="'badge o_tag_color_hovered_%s' % (tag.color)" - t-esc="tag.name"/> - </t> - </div> - </div> - <div class="o_we_track_action_buttons d-flex justify-content-md-end align-items-center flex-wrap"> - <div class="o_we_track_reminder_button my-1"> - <div t-if="option_track_wishlist and not track.is_track_done" - t-call="website_event_track.track_widget_reminder"> - <t t-set="reminder_small" t-value="False"/> - <t t-set="reminder_light" t-value="False"/> - </div> - </div> - </div> - </div> - <div class="mx-3 text-muted"> - <t t-if="track.location_id"> - <strong>Location:</strong> <span t-field="track.location_id"/> - <span> - </span> - </t> - <t t-if="track.date"> - <span t-field="track.date" - t-options='{"hide_seconds":"True", "format": "short"}'/> - - - <span t-field="track.date_end" - t-options='{"hide_seconds":"True", "format": "short"}'/> - <t t-if="event.date_tz"> - (<span t-field="track.date_end" t-options='{"format": "zzz"}'/>) - </t> - </t> - <t t-if="track.duration"> - (<span t-field="track.duration" - t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/>) - </t> - </div> - - <hr class="mt-2 mb-0"/> - - <!-- ABOUT AUTHOR --> - <div class="mx-3"> - <div class="mt-2 d-flex"> - <span t-if="track.image" t-field="track.image" class="o_wevent_online_page_avatar" - t-options="{'widget': 'image', 'class': 'rounded-circle', 'max_width': '96'}"/> - <div class="pl-2 pr-0 pr-md-2 d-flex flex-column"> - <span t-field="track.partner_name" class="font-weight-bold mb-2"/> - <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_function"> - <i class="fa fa-briefcase mr-2"/><span t-esc="track.partner_function"/> - <t t-if="track.partner_company_name"> - <span>&nbsp;at&nbsp;</span><span t-esc="track.partner_company_name"/> - </t> - </span> - <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_id.website"> - <i class="fa fa-home mr-2"/><a t-att-href="track.partner_id.website"><span t-field="track.partner_id.website"/></a> - </span> - <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_email"> - <i class="fa fa-envelope mr-2"/><a t-att-mailto="track.partner_email"><span t-field="track.partner_email"/></a> - </span> - <span class="mb-1 d-flex align-items-baseline text-break" t-if="track.partner_phone"> - <i class="fa fa-phone mr-2"/><span t-field="track.partner_phone"/> - </span> - </div> - </div> - <div t-field="track.partner_biography" class="oe_no_empty"/> - <hr t-if="not is_html_empty(track.description)" class="mt-2 pb-1 mb-1"/> - </div> - <div t-field="track.description" class="my-2 mx-3 oe_no_empty"/> - </div> - </div> -</template> - -<!-- ============================================================ --> -<!-- ASIDE: CONTROL PANEL --> -<!-- ============================================================ --> - -<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 class="bg-white pt-0 pt-md-3 o_wevent_online_page_aside_content"> - <div class="mx-2" t-if="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"> - <t t-set="pre_remaining_time" t-value="int(track.track_start_remaining)"/> - <!--<t t-set="pre_countdown_text" t-value="'Talk starts in'"/>--> - <t t-set="pre_countdown_display" t-value="bool(False)"/> - <t t-set="main_remaining_time" t-value="int(track.website_cta_start_remaining)"/> - <!--<t t-set="main_countdown_text" t-value="'Magic happens in'"/>--> - <t t-set="main_countdown_display" t-value="bool(False)"/> - <t t-set="display_class" t-value="'.o_event_cta_action'"/> - </t> - </div> - <div t-att-class="'o_event_cta_action %s' % ('d-none' if cta_coundown else '')"> - <a t-att-href="track.website_cta_url" - target="_blank" - class="btn btn-primary w-100 mb-3 mt-2 mt-md-0"> - <span t-esc="track.website_cta_title"/> - </a> - </div> - </div> - <div class="d-flex align-items-center justify-content-between mx-2"> - <ul class="nav nav-tabs o_wesession_track_aside_nav d-flex border-0" role="tablist"> - <li class="nav-item flex-grow-1"> - <a href="#track_list" aria-controls="track_list" class="nav-link active" role="tab" data-toggle="tab"> - Talks - </a> - </li> - </ul> - <a href="#collapse_track_aside" data-toggle="collapse" class="d-md-none p-2 text-decoration-none o_wevent_online_page_aside_collapse collapsed"> - <i class="fa fa-chevron-down d-md-none"/> - </a> - </div> - <div id="collapse_track_aside" - class="tab-content collapse d-md-block o_wesession_track_aside_tabs"> - <div class="tab-pane fade show active" id="track_list" role="tabpanel"> - <ul class="list-unstyled mb-0"> - <li t-foreach="tracks_other" t-as="track_other" class="w-100"> - <a t-if="user_event_manager or track_other.is_published" - class="d-block w-100 h-100 px-2 pt-2 pb-1 text-decoration-none" - t-att-href="track_other.website_url"> - <t t-call="website_event_track_session.event_track_aside_other_track"/> - </a> - <div t-else="" class="text-muted px-2 pt-2 pb-1"> - <t t-call="website_event_track_session.event_track_aside_other_track"/> - </div> - </li> - </ul> - </div> - </div> - </div> - </div> -</template> - -<template id="event_track_aside_other_track"> - <span t-esc="track_other.name" class="w-100"/> - <div class="d-flex align-items-center"> - <small class="text-muted" t-esc="track_other.partner_name"/> - <div class="d-inline-block ml-auto o_wesession_track_aside_info text-truncate"> - <small t-if="track_other.is_track_live and not track_other.is_track_done" - class="badge badge-danger">Live</small> - <small t-elif="track_other.is_track_done" - class="badge badge-light">Done</small> - <small t-elif="track_other.is_track_today and track_other.track_start_remaining" - class="badge badge-light"> - <span t-esc="track_other.track_start_remaining" - t-options="{'widget': 'duration', 'digital': False, 'add_direction': True, - 'unit': 'second', 'round': 'minute', 'format': 'narrow'}"/> - </small> - <div t-elif="track_other.date" class="badge badge-light"> - <span t-esc="track_other.date" t-options="{'widget': 'datetime', 'tz_name': track_other.event_id.date_tz, 'format': 'MMM. dd'}"/> - </div> - </div> - </div> -</template> - -</odoo> diff --git a/addons/website_event_track_session/views/event_track_views.xml b/addons/website_event_track_session/views/event_track_views.xml deleted file mode 100644 index a80870faf2d..00000000000 --- a/addons/website_event_track_session/views/event_track_views.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0"?> -<odoo> - - <record id="event_track_view_form" model="ir.ui.view"> - <field name="name">event.track.view.form.inherit.session</field> - <field name="model">event.track</field> - <field name="inherit_id" ref="website_event_track.view_event_track_form"/> - <field name="arch" type="xml"> - <xpath expr="//page[@name='description']" position="after"> - <page string="Interactivity" name="interactivity"> - <group> - <group name="event_track_cta_group"> - <field name="website_cta"/> - <field name="website_cta_title" placeholder="e.g. Get Yours Now !" - attrs="{'invisible': [('website_cta', '=', False)], - 'required': [('website_cta', '=', True)]}"/> - <field name="website_cta_url" placeholder="e.g. http://www.example.com" - attrs="{'invisible': [('website_cta', '=', False)], - 'required': [('website_cta', '=', True)]}"/> - <label for="website_cta_delay" - attrs="{'invisible': [('website_cta', '=', False)]}"/> - <div attrs="{'invisible': [('website_cta', '=', False)]}"> - <field name="website_cta_delay" class="oe_inline" - attrs="{'required': [('website_cta', '=', True)]}"/> minutes after talk start - </div> - </group> - </group> - </page> - </xpath> - </field> - </record> - -</odoo> |
