[REM] website_event_track_online: merge into website_event_track
PURPOSE Clean organization and models linked to Event Online feature introduced in semi stable saas-13.3 at odoo/odoo@981f95bbf4 and odoo/enterprise@14722028ae Also clean website event menu not being available in website event but only in website event track, which implies some extra-code to manage it. In short: merge website_event_online in website_event, website_event_track _(online/session) in website_event_track. RATIONALE _online modules have been added to extend content of website_event and website_event_track without having any impact on those module. First step of cleaning is to move this content directly in base module. track_session module is mainly a rewrite of track module. Second step of cleaning is to move its content directly in website_event_track. SPECIFICATIONS Move remaining content of website event track online to website event track. Agenda notably is completely replaced by the new one developed within track_online module. Update dependencies accordingly. LINKS Task ID-2319779 COM odoo/odoo#56067 ENT odoo/enterprise#12520 UPG odoo/upgrade#1654
This commit is contained in:
@@ -111,7 +111,7 @@ var LivechatButton = Widget.extend({
|
||||
this.$el.css('color', this.options.button_text_color);
|
||||
}
|
||||
|
||||
// If website_event_track_online installed, put the livechat banner above the PWA banner.
|
||||
// If website_event_track installed, put the livechat banner above the PWA banner.
|
||||
var pwaBannerHeight = $('.o_pwa_install_banner').outerHeight(true);
|
||||
if (pwaBannerHeight) {
|
||||
this.$el.css('bottom', pwaBannerHeight + 'px');
|
||||
|
||||
@@ -20,7 +20,6 @@ automatic lead generation, full Online support, ...
|
||||
'website_event_meet',
|
||||
'website_event_sale',
|
||||
'website_event_track',
|
||||
'website_event_track_online',
|
||||
'website_event_track_exhibitor',
|
||||
'website_event_track_session',
|
||||
'website_event_track_live',
|
||||
|
||||
@@ -23,6 +23,10 @@ class EventDtPatcher(SavepointCase):
|
||||
'odoo.addons.event.models.event_event.fields.Datetime',
|
||||
wraps=FieldsDatetime
|
||||
)
|
||||
cls.wevent_dt = patch(
|
||||
'odoo.addons.website_event.models.event_event.fields.Datetime',
|
||||
wraps=FieldsDatetime
|
||||
)
|
||||
cls.wevent_main_dt = patch(
|
||||
'odoo.addons.website_event.controllers.main.fields.Datetime',
|
||||
wraps=FieldsDatetime
|
||||
@@ -36,14 +40,17 @@ class EventDtPatcher(SavepointCase):
|
||||
wraps=FieldsDate
|
||||
)
|
||||
cls.mock_event_dt = cls.event_dt.start()
|
||||
cls.mock_wevent_dt = cls.wevent_dt.start()
|
||||
cls.mock_wevent_main_dt = cls.wevent_main_dt.start()
|
||||
cls.mock_event_date = cls.event_date.start()
|
||||
cls.mock_wevent_main_date = cls.wevent_main_date.start()
|
||||
cls.mock_event_dt.now.return_value = cls.reference_now
|
||||
cls.mock_wevent_dt.now.return_value = cls.reference_now
|
||||
cls.mock_wevent_main_dt.now.return_value = cls.reference_now
|
||||
cls.mock_event_date.today.return_value = cls.reference_today
|
||||
cls.mock_wevent_main_date.today.return_value = cls.reference_today
|
||||
cls.addClassCleanup(cls.event_dt.stop)
|
||||
cls.addClassCleanup(cls.wevent_dt.stop)
|
||||
cls.addClassCleanup(cls.wevent_main_dt.stop)
|
||||
cls.addClassCleanup(cls.event_date.stop)
|
||||
cls.addClassCleanup(cls.wevent_main_date.stop)
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
'data/event_data.xml',
|
||||
'data/event_track_data.xml',
|
||||
'views/assets.xml',
|
||||
'views/event_templates.xml',
|
||||
'views/event_track_templates_agenda.xml',
|
||||
'views/event_track_templates_list.xml',
|
||||
'views/event_track_templates_misc.xml',
|
||||
'views/event_track_templates_reminder.xml',
|
||||
'views/event_track_templates_page.xml',
|
||||
'views/event_track_templates_proposal.xml',
|
||||
'views/website_templates.xml',
|
||||
@@ -24,9 +26,11 @@
|
||||
'views/event_track_location_views.xml',
|
||||
'views/event_track_tag_views.xml',
|
||||
'views/event_track_stage_views.xml',
|
||||
'views/event_track_visitor_views.xml',
|
||||
'views/event_sponsor_views.xml',
|
||||
'views/event_event_views.xml',
|
||||
'views/event_type_views.xml',
|
||||
'views/website_visitor_views.xml',
|
||||
'views/event_menus.xml',
|
||||
],
|
||||
'demo': [
|
||||
@@ -36,5 +40,6 @@
|
||||
'data/event_track_tag_demo.xml',
|
||||
'data/event_track_demo.xml',
|
||||
'data/event_track_demo_description.xml',
|
||||
'data/event_track_visitor_demo.xml',
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import main
|
||||
from . import event_track
|
||||
from . import webmanifest
|
||||
|
||||
+200
-144
@@ -1,85 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import json
|
||||
|
||||
from werkzeug.exceptions import Forbidden, NotFound
|
||||
from datetime import timedelta
|
||||
from werkzeug.exceptions import Forbidden, NotFound
|
||||
|
||||
import babel
|
||||
import babel.dates
|
||||
import base64
|
||||
import pytz
|
||||
|
||||
from odoo import exceptions, http, fields
|
||||
from odoo.addons.http_routing.models.ir_http import url_for
|
||||
from odoo.addons.website_event_track.controllers.main import WebsiteEventTrackController
|
||||
from odoo.http import request
|
||||
from odoo.modules.module import get_module_resource
|
||||
from odoo.tools import ustr
|
||||
from odoo.tools.translate import _
|
||||
from odoo.tools import plaintext2html, html2plaintext
|
||||
|
||||
|
||||
class EventTrackOnlineController(WebsiteEventTrackController):
|
||||
class EventTrackController(http.Controller):
|
||||
|
||||
def _event_agenda_get_tracks(self, event):
|
||||
tracks_sudo = event.sudo().track_ids.filtered(lambda track: track.date)
|
||||
if not request.env.user.has_group('event.group_event_manager'):
|
||||
tracks_sudo = tracks_sudo.filtered(lambda track: track.is_published or track.stage_id.is_accepted)
|
||||
return tracks_sudo
|
||||
# ------------------------------------------------------------
|
||||
# TRACK LIST VIEW
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def time_slot_rounder(self, time, rounded_minutes):
|
||||
""" Rounds to nearest hour by adding a timedelta hour if minute >= rounded_minutes
|
||||
E.g. : If rounded_minutes = 15 -> 09:26:00 becomes 09:30:00
|
||||
09:17:00 becomes 09:15:00
|
||||
"""
|
||||
return (time.replace(second=0, microsecond=0, minute=0, hour=time.hour)
|
||||
+ timedelta(minutes=rounded_minutes * (time.minute // rounded_minutes)))
|
||||
@http.route([
|
||||
'''/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):
|
||||
raise NotFound()
|
||||
|
||||
def _split_track_by_days(self, track, local_tz):
|
||||
"""
|
||||
Based on the track start_date and the duration,
|
||||
split the track duration into :
|
||||
start_time by day : number of time slot (15 minutes) that the track takes on that day.
|
||||
E.g. : start date = 01-01-2000 10:00 PM and duration = 3 hours
|
||||
return {
|
||||
01-01-2000 10:00:00 PM: 8 (2 * 4),
|
||||
01-02-2000 00:00:00 AM: 4 (1 * 4)
|
||||
}
|
||||
Also return a set of all the time slots
|
||||
"""
|
||||
start_date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
||||
start_datetime = self.time_slot_rounder(start_date, 15)
|
||||
end_datetime = self.time_slot_rounder(start_datetime + timedelta(hours=(track.duration or 0.25)), 15)
|
||||
time_slots_count = int(((end_datetime - start_datetime).total_seconds() / 3600) * 4)
|
||||
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
|
||||
|
||||
time_slots_by_day_start_time = {start_datetime: 0}
|
||||
for i in range(0, time_slots_count):
|
||||
# If the new time slot is still on the current day
|
||||
next_day = (start_datetime + timedelta(days=1)).date()
|
||||
if (start_datetime + timedelta(minutes=15*i)).date() <= next_day:
|
||||
time_slots_by_day_start_time[start_datetime] += 1
|
||||
else:
|
||||
start_datetime = next_day.datetime()
|
||||
time_slots_by_day_start_time[start_datetime] = 0
|
||||
values = {
|
||||
'event': event,
|
||||
'main_object': event,
|
||||
'tracks': tracks,
|
||||
'tags': event.tracks_tag_ids,
|
||||
'searches': searches,
|
||||
'html2plaintext': html2plaintext
|
||||
}
|
||||
return request.render("website_event_track.tracks", values)
|
||||
|
||||
return time_slots_by_day_start_time
|
||||
# ------------------------------------------------------------
|
||||
# AGENDA VIEW
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _get_occupied_cells(self, track, rowspan, locations, local_tz):
|
||||
"""
|
||||
In order to use only once the cells that the tracks will occupy, we need to reserve those cells
|
||||
(time_slot, location) coordinate. Those coordinated will be given to the template to avoid adding
|
||||
blank cells where already occupied by a track.
|
||||
"""
|
||||
occupied_cells = []
|
||||
@http.route(['''/event/<model("event.event"):event>/agenda'''], type='http', auth="public", website=True, sitemap=False)
|
||||
def event_agenda(self, event, tag=None, **post):
|
||||
if not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
|
||||
start_date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
||||
start_date = self.time_slot_rounder(start_date, 15)
|
||||
for i in range(0, rowspan):
|
||||
time_slot = start_date + timedelta(minutes=15*i)
|
||||
if track.location_id:
|
||||
occupied_cells.append((time_slot, track.location_id))
|
||||
# when no location, reserve all locations
|
||||
else:
|
||||
occupied_cells += [(time_slot, location) for location in locations if location]
|
||||
event = event.with_context(tz=event.date_tz or 'UTC')
|
||||
vals = {
|
||||
'event': event,
|
||||
'main_object': event,
|
||||
'tag': tag,
|
||||
'user_event_manager': request.env.user.has_group('event.group_event_manager'),
|
||||
}
|
||||
|
||||
return occupied_cells
|
||||
vals.update(self._prepare_calendar_values(event))
|
||||
|
||||
return request.render("website_event_track.agenda_online", vals)
|
||||
|
||||
def _prepare_calendar_values(self, event):
|
||||
"""
|
||||
@@ -157,48 +143,90 @@ class EventTrackOnlineController(WebsiteEventTrackController):
|
||||
'locations': locations
|
||||
}
|
||||
|
||||
@http.route(['''/event/<model("event.event"):event>/agenda'''], type='http', auth="public", website=True, sitemap=False)
|
||||
def event_agenda(self, event, tag=None, **post):
|
||||
def _event_agenda_get_tracks(self, event):
|
||||
tracks_sudo = event.sudo().track_ids.filtered(lambda track: track.date)
|
||||
if not request.env.user.has_group('event.group_event_manager'):
|
||||
tracks_sudo = tracks_sudo.filtered(lambda track: track.is_published or track.stage_id.is_accepted)
|
||||
return tracks_sudo
|
||||
|
||||
def _get_locale_time(self, dt_time, lang_code):
|
||||
""" Get locale time from datetime object
|
||||
|
||||
:param dt_time: datetime object
|
||||
:param lang_code: language code (eg. en_US)
|
||||
"""
|
||||
locale = babel.Locale.parse(lang_code)
|
||||
return babel.dates.format_time(dt_time, format='short', locale=locale)
|
||||
|
||||
def time_slot_rounder(self, time, rounded_minutes):
|
||||
""" Rounds to nearest hour by adding a timedelta hour if minute >= rounded_minutes
|
||||
E.g. : If rounded_minutes = 15 -> 09:26:00 becomes 09:30:00
|
||||
09:17:00 becomes 09:15:00
|
||||
"""
|
||||
return (time.replace(second=0, microsecond=0, minute=0, hour=time.hour)
|
||||
+ timedelta(minutes=rounded_minutes * (time.minute // rounded_minutes)))
|
||||
|
||||
def _split_track_by_days(self, track, local_tz):
|
||||
"""
|
||||
Based on the track start_date and the duration,
|
||||
split the track duration into :
|
||||
start_time by day : number of time slot (15 minutes) that the track takes on that day.
|
||||
E.g. : start date = 01-01-2000 10:00 PM and duration = 3 hours
|
||||
return {
|
||||
01-01-2000 10:00:00 PM: 8 (2 * 4),
|
||||
01-02-2000 00:00:00 AM: 4 (1 * 4)
|
||||
}
|
||||
Also return a set of all the time slots
|
||||
"""
|
||||
start_date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
||||
start_datetime = self.time_slot_rounder(start_date, 15)
|
||||
end_datetime = self.time_slot_rounder(start_datetime + timedelta(hours=(track.duration or 0.25)), 15)
|
||||
time_slots_count = int(((end_datetime - start_datetime).total_seconds() / 3600) * 4)
|
||||
|
||||
time_slots_by_day_start_time = {start_datetime: 0}
|
||||
for i in range(0, time_slots_count):
|
||||
# If the new time slot is still on the current day
|
||||
next_day = (start_datetime + timedelta(days=1)).date()
|
||||
if (start_datetime + timedelta(minutes=15*i)).date() <= next_day:
|
||||
time_slots_by_day_start_time[start_datetime] += 1
|
||||
else:
|
||||
start_datetime = next_day.datetime()
|
||||
time_slots_by_day_start_time[start_datetime] = 0
|
||||
|
||||
return time_slots_by_day_start_time
|
||||
|
||||
def _get_occupied_cells(self, track, rowspan, locations, local_tz):
|
||||
"""
|
||||
In order to use only once the cells that the tracks will occupy, we need to reserve those cells
|
||||
(time_slot, location) coordinate. Those coordinated will be given to the template to avoid adding
|
||||
blank cells where already occupied by a track.
|
||||
"""
|
||||
occupied_cells = []
|
||||
|
||||
start_date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
||||
start_date = self.time_slot_rounder(start_date, 15)
|
||||
for i in range(0, rowspan):
|
||||
time_slot = start_date + timedelta(minutes=15*i)
|
||||
if track.location_id:
|
||||
occupied_cells.append((time_slot, track.location_id))
|
||||
# when no location, reserve all locations
|
||||
else:
|
||||
occupied_cells += [(time_slot, location) for location in locations if location]
|
||||
|
||||
return occupied_cells
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# 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()
|
||||
|
||||
event = event.with_context(tz=event.date_tz or 'UTC')
|
||||
vals = {
|
||||
'event': event,
|
||||
'main_object': event,
|
||||
'tag': tag,
|
||||
'user_event_manager': request.env.user.has_group('event.group_event_manager'),
|
||||
}
|
||||
|
||||
vals.update(self._prepare_calendar_values(event))
|
||||
|
||||
return request.render("website_event_track_online.agenda_online", vals)
|
||||
|
||||
def _fetch_track(self, track_id, allow_is_accepted=False):
|
||||
track = request.env['event.track'].browse(track_id).exists()
|
||||
if not track:
|
||||
raise NotFound()
|
||||
try:
|
||||
track.check_access_rights('read')
|
||||
track.check_access_rule('read')
|
||||
except exceptions.AccessError:
|
||||
track_sudo = track.sudo()
|
||||
if allow_is_accepted and track_sudo.is_accepted:
|
||||
track = track_sudo
|
||||
else:
|
||||
raise Forbidden()
|
||||
|
||||
event = track.event_id
|
||||
# JSON RPC have no website in requests
|
||||
if hasattr(request, 'website_id') and not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
try:
|
||||
event.check_access_rights('read')
|
||||
event.check_access_rule('read')
|
||||
except exceptions.AccessError:
|
||||
raise Forbidden()
|
||||
|
||||
return track
|
||||
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)
|
||||
|
||||
@http.route("/event/track/toggle_reminder", type="json", auth="public", website=True)
|
||||
def track_reminder_toggle(self, track_id, set_reminder_on):
|
||||
@@ -232,45 +260,73 @@ class EventTrackOnlineController(WebsiteEventTrackController):
|
||||
|
||||
return result
|
||||
|
||||
@http.route('/event/manifest.webmanifest', type='http', auth='public', methods=['GET'], website=True, sitemap=False)
|
||||
def webmanifest(self):
|
||||
""" Returns a WebManifest describing the metadata associated with a web application.
|
||||
Using this metadata, user agents can provide developers with means to create user
|
||||
experiences that are more comparable to that of a native application.
|
||||
"""
|
||||
company = request.env.company
|
||||
website = request.website
|
||||
manifest = {
|
||||
'name': _('%s Online Events') % company.name,
|
||||
'short_name': company.name,
|
||||
'description': _('%s Online Events') % company.name,
|
||||
'scope': url_for('/event'),
|
||||
'start_url': url_for('/event'),
|
||||
'display': 'standalone',
|
||||
'background_color': '#ffffff',
|
||||
'theme_color': '#875A7B',
|
||||
}
|
||||
icon_sizes = ['192x192', '512x512']
|
||||
manifest['icons'] = [{
|
||||
'src': website.image_url(website, 'app_icon', size=size),
|
||||
'sizes': size,
|
||||
'type': 'image/png',
|
||||
} for size in icon_sizes]
|
||||
body = json.dumps(manifest, default=ustr)
|
||||
response = request.make_response(body, [
|
||||
('Content-Type', 'application/manifest+json'),
|
||||
])
|
||||
return response
|
||||
# ------------------------------------------------------------
|
||||
# TRACK PROPOSAL
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route('/event/service-worker.js', type='http', auth='public', methods=['GET'], website=True, sitemap=False)
|
||||
def service_worker(self):
|
||||
""" Returns a ServiceWorker javascript file scoped for website_event
|
||||
"""
|
||||
sw_file = get_module_resource('website_event_track_online', 'static/src/js/service_worker.js')
|
||||
with open(sw_file, 'rb') as fp:
|
||||
body = fp.read()
|
||||
response = request.make_response(body, [
|
||||
('Content-Type', 'text/javascript'),
|
||||
('Service-Worker-Allowed', url_for('/event')),
|
||||
])
|
||||
return response
|
||||
@http.route(['''/event/<model("event.event"):event>/track_proposal'''], type='http', auth="public", website=True, sitemap=False)
|
||||
def event_track_proposal(self, event, **post):
|
||||
if not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
|
||||
return request.render("website_event_track.event_track_proposal", {'event': event, 'main_object': event})
|
||||
|
||||
@http.route(['''/event/<model("event.event"):event>/track_proposal/post'''], type='http', auth="public", methods=['POST'], website=True)
|
||||
def event_track_proposal_post(self, event, **post):
|
||||
if not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
|
||||
tags = []
|
||||
for tag in event.allowed_track_tag_ids:
|
||||
if post.get('tag_' + str(tag.id)):
|
||||
tags.append(tag.id)
|
||||
|
||||
track = request.env['event.track'].sudo().create({
|
||||
'name': post['track_name'],
|
||||
'partner_name': post['partner_name'],
|
||||
'partner_email': post['email_from'],
|
||||
'partner_phone': post['phone'],
|
||||
'partner_biography': plaintext2html(post['biography']),
|
||||
'event_id': event.id,
|
||||
'tag_ids': [(6, 0, tags)],
|
||||
'user_id': False,
|
||||
'description': plaintext2html(post['description']),
|
||||
'image': base64.b64encode(post['image'].read()) if post.get('image') else False
|
||||
})
|
||||
if request.env.user != request.website.user_id:
|
||||
track.sudo().message_subscribe(partner_ids=request.env.user.partner_id.ids)
|
||||
else:
|
||||
partner = request.env['res.partner'].sudo().search([('email', '=', post['email_from'])])
|
||||
if partner:
|
||||
track.sudo().message_subscribe(partner_ids=partner.ids)
|
||||
return request.render("website_event_track.event_track_proposal", {'track': track, 'event': event})
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TOOLS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _fetch_track(self, track_id, allow_is_accepted=False):
|
||||
track = request.env['event.track'].browse(track_id).exists()
|
||||
if not track:
|
||||
raise NotFound()
|
||||
try:
|
||||
track.check_access_rights('read')
|
||||
track.check_access_rule('read')
|
||||
except exceptions.AccessError:
|
||||
track_sudo = track.sudo()
|
||||
if allow_is_accepted and track_sudo.is_accepted:
|
||||
track = track_sudo
|
||||
else:
|
||||
raise Forbidden()
|
||||
|
||||
event = track.event_id
|
||||
# JSON RPC have no website in requests
|
||||
if hasattr(request, 'website_id') and not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
try:
|
||||
event.check_access_rights('read')
|
||||
event.check_access_rule('read')
|
||||
except exceptions.AccessError:
|
||||
raise Forbidden()
|
||||
|
||||
return track
|
||||
@@ -1,185 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import babel
|
||||
import babel.dates
|
||||
import collections
|
||||
import datetime
|
||||
import pytz
|
||||
import base64
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from odoo import fields, http
|
||||
from odoo.http import request
|
||||
from odoo.tools import plaintext2html, html2plaintext
|
||||
|
||||
|
||||
class WebsiteEventTrackController(http.Controller):
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TRACK LIST VIEW
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route([
|
||||
'''/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):
|
||||
raise NotFound()
|
||||
|
||||
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 = {
|
||||
'event': event,
|
||||
'main_object': event,
|
||||
'tracks': tracks,
|
||||
'tags': event.tracks_tag_ids,
|
||||
'searches': searches,
|
||||
'html2plaintext': html2plaintext
|
||||
}
|
||||
return request.render("website_event_track.tracks", values)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# AGENDA VIEW
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _get_locale_time(self, dt_time, lang_code):
|
||||
""" Get locale time from datetime object
|
||||
|
||||
:param dt_time: datetime object
|
||||
:param lang_code: language code (eg. en_US)
|
||||
"""
|
||||
locale = babel.Locale.parse(lang_code)
|
||||
return babel.dates.format_time(dt_time, format='short', locale=locale)
|
||||
|
||||
def _prepare_calendar(self, event, event_track_ids):
|
||||
local_tz = pytz.timezone(event.date_tz or 'UTC')
|
||||
lang_code = request.env.context.get('lang')
|
||||
locations = {} # { location: [track, start_date, end_date, rowspan]}
|
||||
dates = [] # [ (date, {}) ]
|
||||
for track in event_track_ids:
|
||||
locations.setdefault(track.location_id or False, [])
|
||||
|
||||
forcetr = True
|
||||
for track in event_track_ids:
|
||||
start_date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
||||
end_date = start_date + datetime.timedelta(hours=(track.duration or 0.5))
|
||||
location = track.location_id or False
|
||||
locations.setdefault(location, [])
|
||||
|
||||
# New TR, align all events
|
||||
if forcetr or (start_date>dates[-1][0]) or not location:
|
||||
formatted_time = self._get_locale_time(start_date, lang_code)
|
||||
dates.append((start_date, {}, bool(location), formatted_time))
|
||||
for loc in list(locations):
|
||||
if locations[loc] and (locations[loc][-1][2] > start_date):
|
||||
locations[loc][-1][3] += 1
|
||||
elif not locations[loc] or locations[loc][-1][2] <= start_date:
|
||||
locations[loc].append([False, locations[loc] and locations[loc][-1][2] or dates[0][0], start_date, 1])
|
||||
dates[-1][1][loc] = locations[loc][-1]
|
||||
forcetr = not bool(location)
|
||||
|
||||
# Add event
|
||||
if locations[location] and locations[location][-1][1] > start_date:
|
||||
locations[location][-1][3] -= 1
|
||||
locations[location].append([track, start_date, end_date, 1])
|
||||
dates[-1][1][location] = locations[location][-1]
|
||||
locations = collections.OrderedDict(sorted(locations.items(), key=lambda t: t[0].id if t[0] else 0))
|
||||
return {
|
||||
'locations': locations,
|
||||
'dates': dates
|
||||
}
|
||||
|
||||
@http.route(['''/event/<model("event.event"):event>/agenda'''], type='http', auth="public", website=True, sitemap=False)
|
||||
def event_agenda(self, event, tag=None, **post):
|
||||
if not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
|
||||
event = event.with_context(tz=event.date_tz or 'UTC')
|
||||
local_tz = pytz.timezone(event.date_tz or 'UTC')
|
||||
days_tracks = collections.defaultdict(lambda: [])
|
||||
event_track_ids = self._event_agenda_get_tracks(event)
|
||||
for track in event_track_ids.sorted(lambda track: (bool(track.date), track.date, bool(track.location_id))):
|
||||
if not track.date:
|
||||
continue
|
||||
date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
||||
days_tracks[str(date)[:10]].append(track)
|
||||
|
||||
days = {}
|
||||
tracks_by_days = {}
|
||||
for day, tracks in days_tracks.items():
|
||||
tracks_by_days[day] = tracks
|
||||
days[day] = self._prepare_calendar(event, tracks)
|
||||
|
||||
return request.render("website_event_track.agenda", {
|
||||
'event': event,
|
||||
'main_object': event,
|
||||
'days': days,
|
||||
'tracks_by_days': tracks_by_days,
|
||||
'tag': tag,
|
||||
'user_event_manager': request.env.user.has_group('event.group_event_manager'),
|
||||
})
|
||||
|
||||
def _event_agenda_get_tracks(self, event):
|
||||
return event.track_ids
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# 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()
|
||||
|
||||
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)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TRACK PROPOSAL
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@http.route(['''/event/<model("event.event"):event>/track_proposal'''], type='http', auth="public", website=True, sitemap=False)
|
||||
def event_track_proposal(self, event, **post):
|
||||
if not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
|
||||
return request.render("website_event_track.event_track_proposal", {'event': event, 'main_object': event})
|
||||
|
||||
@http.route(['''/event/<model("event.event"):event>/track_proposal/post'''], type='http', auth="public", methods=['POST'], website=True)
|
||||
def event_track_proposal_post(self, event, **post):
|
||||
if not event.can_access_from_current_website():
|
||||
raise NotFound()
|
||||
|
||||
tags = []
|
||||
for tag in event.allowed_track_tag_ids:
|
||||
if post.get('tag_' + str(tag.id)):
|
||||
tags.append(tag.id)
|
||||
|
||||
track = request.env['event.track'].sudo().create({
|
||||
'name': post['track_name'],
|
||||
'partner_name': post['partner_name'],
|
||||
'partner_email': post['email_from'],
|
||||
'partner_phone': post['phone'],
|
||||
'partner_biography': plaintext2html(post['biography']),
|
||||
'event_id': event.id,
|
||||
'tag_ids': [(6, 0, tags)],
|
||||
'user_id': False,
|
||||
'description': plaintext2html(post['description']),
|
||||
'image': base64.b64encode(post['image'].read()) if post.get('image') else False
|
||||
})
|
||||
if request.env.user != request.website.user_id:
|
||||
track.sudo().message_subscribe(partner_ids=request.env.user.partner_id.ids)
|
||||
else:
|
||||
partner = request.env['res.partner'].sudo().search([('email', '=', post['email_from'])])
|
||||
if partner:
|
||||
track.sudo().message_subscribe(partner_ids=partner.ids)
|
||||
return request.render("website_event_track.event_track_proposal", {'track': track, 'event': event})
|
||||
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import json
|
||||
import pytz
|
||||
|
||||
from odoo import http
|
||||
from odoo.addons.http_routing.models.ir_http import url_for
|
||||
from odoo.http import request
|
||||
from odoo.modules.module import get_module_resource
|
||||
from odoo.tools import ustr
|
||||
from odoo.tools.translate import _
|
||||
|
||||
|
||||
class TrackManifest(http.Controller):
|
||||
|
||||
@http.route('/event/manifest.webmanifest', type='http', auth='public', methods=['GET'], website=True, sitemap=False)
|
||||
def webmanifest(self):
|
||||
""" Returns a WebManifest describing the metadata associated with a web application.
|
||||
Using this metadata, user agents can provide developers with means to create user
|
||||
experiences that are more comparable to that of a native application.
|
||||
"""
|
||||
company = request.env.company
|
||||
website = request.website
|
||||
manifest = {
|
||||
'name': _('%s Online Events') % company.name,
|
||||
'short_name': company.name,
|
||||
'description': _('%s Online Events') % company.name,
|
||||
'scope': url_for('/event'),
|
||||
'start_url': url_for('/event'),
|
||||
'display': 'standalone',
|
||||
'background_color': '#ffffff',
|
||||
'theme_color': '#875A7B',
|
||||
}
|
||||
icon_sizes = ['192x192', '512x512']
|
||||
manifest['icons'] = [{
|
||||
'src': website.image_url(website, 'app_icon', size=size),
|
||||
'sizes': size,
|
||||
'type': 'image/png',
|
||||
} for size in icon_sizes]
|
||||
body = json.dumps(manifest, default=ustr)
|
||||
response = request.make_response(body, [
|
||||
('Content-Type', 'application/manifest+json'),
|
||||
])
|
||||
return response
|
||||
|
||||
@http.route('/event/service-worker.js', type='http', auth='public', methods=['GET'], website=True, sitemap=False)
|
||||
def service_worker(self):
|
||||
""" Returns a ServiceWorker javascript file scoped for website_event
|
||||
"""
|
||||
sw_file = get_module_resource('website_event_track', 'static/src/js/service_worker.js')
|
||||
with open(sw_file, 'rb') as fp:
|
||||
body = fp.read()
|
||||
response = request.make_response(body, [
|
||||
('Content-Type', 'text/javascript'),
|
||||
('Service-Worker-Allowed', url_for('/event')),
|
||||
])
|
||||
return response
|
||||
@@ -33,14 +33,17 @@
|
||||
<record id="event_sponsor_type1" model="event.sponsor.type">
|
||||
<field name="name">Bronze</field>
|
||||
<field name="sequence">3</field>
|
||||
<field name="display_ribbon_style">Bronze</field>
|
||||
</record>
|
||||
<record id="event_sponsor_type2" model="event.sponsor.type">
|
||||
<field name="name">Silver</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="display_ribbon_style">Silver</field>
|
||||
</record>
|
||||
<record id="event_sponsor_type3" model="event.sponsor.type">
|
||||
<field name="name">Gold</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="display_ribbon_style">Gold</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_stage0" model="event.track.stage">
|
||||
@@ -58,11 +61,13 @@
|
||||
<field name="name">Announced</field>
|
||||
<field name="sequence">3</field>
|
||||
<field name="color">3</field>
|
||||
<field name="is_accepted" eval="True"/>
|
||||
</record>
|
||||
<record id="event_track_stage3" model="event.track.stage">
|
||||
<field name="name">Published</field>
|
||||
<field name="sequence">4</field>
|
||||
<field name="color">4</field>
|
||||
<field name="is_accepted" eval="True"/>
|
||||
<field name="is_done" eval="True"/>
|
||||
</record>
|
||||
<record id="event_track_stage4" model="event.track.stage">
|
||||
|
||||
@@ -333,6 +333,7 @@
|
||||
<field name="color">1</field>
|
||||
<field name="event_id" ref="event.event_7"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
<field name="wishlisted_by_default" eval="True"/>
|
||||
<field name="date" eval="(DateTime.now() - timedelta(days=1)).strftime('%Y-%m-%d 06:00:00')"></field>
|
||||
<field name="tag_ids" eval="[
|
||||
(4, ref('website_event_track.event_track_tag1')),
|
||||
@@ -474,6 +475,7 @@
|
||||
<field name="color">1</field>
|
||||
<field name="event_id" ref="event.event_7"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
<field name="wishlisted_by_default" eval="True"/>
|
||||
<field name="date" eval="DateTime.now().strftime('%Y-%m-%d 06:00:00')"></field>
|
||||
<field name="tag_ids" eval="[
|
||||
(4, ref('website_event_track.event_track_tag1')),
|
||||
@@ -519,6 +521,7 @@
|
||||
<field name="color">2</field>
|
||||
<field name="event_id" ref="event.event_7"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
<field name="wishlisted_by_default" eval="True"/>
|
||||
<field name="location_id" ref="website_event_track.event_track_location_online_1"/>
|
||||
<field name="date" eval="DateTime.now().strftime('%Y-%m-%d 12:00:00')"></field>
|
||||
<field name="tag_ids" eval="[(4, ref('website_event_track.event_track_tag3'))]"/>
|
||||
@@ -572,6 +575,7 @@
|
||||
<field name="color">7</field>
|
||||
<field name="event_id" ref="event.event_7"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
<field name="wishlisted_by_default" eval="True"/>
|
||||
<field name="location_id" ref="website_event_track.event_track_location_online_2"/>
|
||||
<field name="date" eval="DateTime.now().strftime('%Y-%m-%d 13:30:00')"></field>
|
||||
<field name="tag_ids" eval="[(4, ref('website_event_track.event_track_tag1')), (4, ref('website_event_track.event_track_tag12'))]"/>
|
||||
|
||||
@@ -1,28 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="event_track_tag_category_1" model="event.track.tag.category">
|
||||
<field name="name">Audience</field>
|
||||
<field name="sequence">10</field>
|
||||
</record>
|
||||
<record id="event_track_tag_category_2" model="event.track.tag.category">
|
||||
<field name="name">Format</field>
|
||||
<field name="sequence">20</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_tag1" model="event.track.tag">
|
||||
<field name="name">Consumers</field>
|
||||
<field name="color">1</field>
|
||||
<field name="category_id" ref="event_track_tag_category_1"/>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
<record id="event_track_tag2" model="event.track.tag">
|
||||
<field name="name">Sales</field>
|
||||
<field name="color">2</field>
|
||||
<field name="category_id" ref="event_track_tag_category_1"/>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
<record id="event_track_tag3" model="event.track.tag">
|
||||
<field name="name">Research</field>
|
||||
<field name="color">3</field>
|
||||
<field name="category_id" ref="event_track_tag_category_1"/>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
<record id="event_track_tag11" model="event.track.tag">
|
||||
<field name="name">Lightning Talks</field>
|
||||
<field name="color">4</field>
|
||||
<field name="category_id" ref="event_track_tag_category_2"/>
|
||||
<field name="sequence">11</field>
|
||||
</record>
|
||||
<record id="event_track_tag12" model="event.track.tag">
|
||||
<field name="name">Round Table</field>
|
||||
<field name="color">5</field>
|
||||
<field name="category_id" ref="event_track_tag_category_2"/>
|
||||
<field name="sequence">12</field>
|
||||
</record>
|
||||
<record id="event_track_tag13" model="event.track.tag">
|
||||
<field name="name">Keynote</field>
|
||||
<field name="color">6</field>
|
||||
<field name="category_id" ref="event_track_tag_category_2"/>
|
||||
<field name="sequence">13</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -8,6 +8,10 @@ from . import event_track
|
||||
from . import event_track_location
|
||||
from . import event_track_stage
|
||||
from . import event_track_tag
|
||||
from . import event_track_tag_category
|
||||
from . import event_track_visitor
|
||||
from . import event_type
|
||||
from . import website
|
||||
from . import website_event_menu
|
||||
from . import website_menu
|
||||
from . import website_visitor
|
||||
|
||||
@@ -2,27 +2,40 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.modules.module import get_resource_path
|
||||
|
||||
|
||||
class Sponsor(models.Model):
|
||||
_name = "event.sponsor"
|
||||
_description = 'Event Sponsor'
|
||||
_order = "sequence, sponsor_type_id"
|
||||
_rec_name = 'partner_name'
|
||||
_rec_name = 'name'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
sponsor_type_id = fields.Many2one('event.sponsor.type', 'Sponsoring Type', required=True)
|
||||
url = fields.Char('Sponsor Website', compute='_compute_url', readonly=False, store=True)
|
||||
sequence = fields.Integer('Sequence')
|
||||
active = fields.Boolean(default=True)
|
||||
# contact information
|
||||
partner_id = fields.Many2one('res.partner', 'Sponsor/Customer', required=True)
|
||||
partner_name = fields.Char('Name', related='partner_id.name')
|
||||
partner_email = fields.Char('Email', related='partner_id.email')
|
||||
partner_phone = fields.Char('Phone', related='partner_id.phone')
|
||||
partner_mobile = fields.Char('Mobile', related='partner_id.mobile')
|
||||
url = fields.Char('Sponsor Website', compute='_compute_url', readonly=False, store=True)
|
||||
sequence = fields.Integer('Sequence')
|
||||
image_128 = fields.Image(
|
||||
string="Logo", related='partner_id.image_128', store=True, readonly=False)
|
||||
active = fields.Boolean(default=True)
|
||||
name = fields.Char('Sponsor Name', compute='_compute_name', readonly=False, store=True)
|
||||
email = fields.Char('Sponsor Email', compute='_compute_email', readonly=False, store=True)
|
||||
phone = fields.Char('Sponsor Phone', compute='_compute_phone', readonly=False, store=True)
|
||||
mobile = fields.Char('Sponsor Mobile', compute='_compute_mobile', readonly=False, store=True)
|
||||
# image
|
||||
image_512 = fields.Image(
|
||||
string="Logo", max_width=512, max_height=512,
|
||||
compute='_compute_image_512', readonly=False, store=True)
|
||||
image_256 = fields.Image("Image 256", related="image_512", max_width=256, max_height=256, store=False)
|
||||
image_128 = fields.Image("Image 128", related="image_512", max_width=128, max_height=128, store=False)
|
||||
website_image_url = fields.Char(
|
||||
string='Image URL', max_width=256, max_height=256,
|
||||
compute='_compute_website_image_url', compute_sudo=True, store=False)
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_url(self):
|
||||
@@ -30,6 +43,47 @@ class Sponsor(models.Model):
|
||||
if sponsor.partner_id.website or not sponsor.url:
|
||||
sponsor.url = sponsor.partner_id.website
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_name(self):
|
||||
self._synchronize_with_partner('name')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_email(self):
|
||||
self._synchronize_with_partner('email')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_phone(self):
|
||||
self._synchronize_with_partner('phone')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_mobile(self):
|
||||
self._synchronize_with_partner('mobile')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_image_512(self):
|
||||
self._synchronize_with_partner('image_512')
|
||||
|
||||
@api.depends('image_256', 'partner_id.image_256')
|
||||
def _compute_website_image_url(self):
|
||||
for sponsor in self:
|
||||
if sponsor.image_256:
|
||||
sponsor.website_image_url = self.env['website'].image_url(sponsor, 'image_256', size=256)
|
||||
elif sponsor.partner_id.image_256:
|
||||
sponsor.website_image_url = self.env['website'].image_url(sponsor.partner_id, 'image_256', size=256)
|
||||
else:
|
||||
sponsor.website_image_url = get_resource_path('website_event_track', 'static/src/img', 'event_sponsor_default_%d.png' % (sponsor.id % 1))
|
||||
|
||||
def _synchronize_with_partner(self, fname):
|
||||
""" Synchronize with partner if not set. Setting a value does not write
|
||||
on partner as this may be event-specific information. """
|
||||
for sponsor in self:
|
||||
if not sponsor[fname]:
|
||||
sponsor[fname] = sponsor.partner_id[fname]
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# MESSAGING
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _message_get_suggested_recipients(self):
|
||||
recipients = super(Sponsor, self)._message_get_suggested_recipients()
|
||||
for sponsor in self:
|
||||
|
||||
@@ -11,3 +11,8 @@ class SponsorType(models.Model):
|
||||
|
||||
name = fields.Char('Sponsor Type', required=True, translate=True)
|
||||
sequence = fields.Integer('Sequence')
|
||||
display_ribbon_style = fields.Selection([
|
||||
('no_ribbon', 'No Ribbon'),
|
||||
('Gold', 'Gold'),
|
||||
('Silver', 'Silver'),
|
||||
('Bronze', 'Bronze')], string='Ribbon Style')
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.translate import _, html_translate
|
||||
from odoo.addons.http_routing.models.ir_http import slug
|
||||
from odoo.osv import expression
|
||||
from odoo.tools.mail import is_html_empty
|
||||
from odoo.tools.translate import _, html_translate
|
||||
|
||||
|
||||
class Track(models.Model):
|
||||
@@ -21,7 +23,6 @@ class Track(models.Model):
|
||||
# description
|
||||
name = fields.Char('Title', required=True, translate=True)
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
image = fields.Image("Image", max_width=128, max_height=128)
|
||||
active = fields.Boolean(default=True)
|
||||
user_id = fields.Many2one('res.users', 'Responsible', tracking=True, default=lambda self: self.env.user)
|
||||
company_id = fields.Many2one('res.company', related='event_id.company_id')
|
||||
@@ -38,6 +39,7 @@ class Track(models.Model):
|
||||
index=True, copy=False, default=_get_default_stage_id,
|
||||
group_expand='_read_group_stage_ids',
|
||||
required=True, tracking=True)
|
||||
is_accepted = fields.Boolean('Is Accepted', related='stage_id.is_accepted', readonly=True)
|
||||
kanban_state = fields.Selection([
|
||||
('normal', 'Grey'),
|
||||
('done', 'Green'),
|
||||
@@ -58,12 +60,46 @@ class Track(models.Model):
|
||||
partner_phone = fields.Char(
|
||||
string='Phone', compute='_compute_partner_info',
|
||||
readonly=False, store=True, tracking=30)
|
||||
partner_biography = fields.Html(string='Biography')
|
||||
partner_biography = fields.Html(
|
||||
string='Biography', compute='_compute_partner_biography',
|
||||
readonly=False, store=True)
|
||||
partner_function = fields.Char(
|
||||
'Job Position', related='partner_id.function',
|
||||
compute_sudo=True, readonly=True)
|
||||
partner_company_name = fields.Char(
|
||||
'Company Name', related='partner_id.parent_name',
|
||||
compute_sudo=True, readonly=True)
|
||||
image = fields.Image(
|
||||
string="Speaker Photo", compute="_compute_speaker_image",
|
||||
readonly=False, store=True,
|
||||
max_width=256, max_height=256)
|
||||
location_id = fields.Many2one('event.track.location', 'Location')
|
||||
# time information
|
||||
date = fields.Datetime('Track Date')
|
||||
date_end = fields.Datetime('Track End Date', compute='_compute_end_date', store=True)
|
||||
duration = fields.Float('Duration', default=1.5, help="Track duration in hours.")
|
||||
# frontend description
|
||||
website_image = fields.Image(string="Website Image", max_width=1024, max_height=1024)
|
||||
website_image_url = fields.Char(
|
||||
string='Image URL', compute='_compute_website_image_url',
|
||||
compute_sudo=True, store=False)
|
||||
# wishlist / visitors management
|
||||
event_track_visitor_ids = fields.One2many(
|
||||
'event.track.visitor', 'track_id', string="Track Visitors",
|
||||
groups="event.group_event_user")
|
||||
is_reminder_on = fields.Boolean('Is Reminder On', compute='_compute_is_reminder_on')
|
||||
wishlist_visitor_ids = fields.Many2many(
|
||||
'website.visitor', string="Visitor Wishlist",
|
||||
compute="_compute_wishlist_visitor_ids", compute_sudo=True,
|
||||
search="_search_wishlist_visitor_ids",
|
||||
groups="event.group_event_user")
|
||||
wishlist_visitor_count = fields.Integer(
|
||||
string="# Wishlisted",
|
||||
compute="_compute_wishlist_visitor_ids", compute_sudo=True,
|
||||
groups="event.group_event_user")
|
||||
wishlisted_by_default = fields.Boolean(
|
||||
string='Always Wishlisted',
|
||||
help="""If set, the talk will be starred for each attendee registered to the event. The attendee won't be able to un-star this talk.""")
|
||||
|
||||
@api.depends('name')
|
||||
def _compute_website_url(self):
|
||||
@@ -72,6 +108,8 @@ class Track(models.Model):
|
||||
if track.id:
|
||||
track.website_url = '/event/%s/track/%s' % (slug(track.event_id), slug(track))
|
||||
|
||||
# SPEAKER
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_partner_info(self):
|
||||
for track in self:
|
||||
@@ -80,6 +118,23 @@ class Track(models.Model):
|
||||
track.partner_email = track.partner_id.email
|
||||
track.partner_phone = track.partner_id.phone
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_partner_biography(self):
|
||||
for track in self:
|
||||
if not track.partner_biography:
|
||||
track.partner_biography = track.partner_id.website_description
|
||||
elif track.partner_id and is_html_empty(track.partner_biography) and \
|
||||
not is_html_empty(track.partner_id.website_description):
|
||||
track.partner_biography = track.partner_id.website_description
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_speaker_image(self):
|
||||
for track in self:
|
||||
if not track.image:
|
||||
track.image = track.partner_id.image_256
|
||||
|
||||
# TIME
|
||||
|
||||
@api.depends('date', 'duration')
|
||||
def _compute_end_date(self):
|
||||
for track in self:
|
||||
@@ -89,6 +144,85 @@ class Track(models.Model):
|
||||
else:
|
||||
track.date_end = False
|
||||
|
||||
|
||||
# FRONTEND DESCRIPTION
|
||||
|
||||
@api.depends('image', 'partner_id.image_256')
|
||||
def _compute_website_image_url(self):
|
||||
for track in self:
|
||||
if track.website_image:
|
||||
track.website_image_url = self.env['website'].image_url(track, 'website_image', size=1024)
|
||||
else:
|
||||
track.website_image_url = '/website_event_track/static/src/img/event_track_default_%d.jpeg' % (track.id % 2)
|
||||
|
||||
# WISHLIST / VISITOR MANAGEMENT
|
||||
|
||||
@api.depends('wishlisted_by_default', 'event_track_visitor_ids.visitor_id',
|
||||
'event_track_visitor_ids.partner_id', 'event_track_visitor_ids.is_wishlisted',
|
||||
'event_track_visitor_ids.is_blacklisted')
|
||||
@api.depends_context('uid')
|
||||
def _compute_is_reminder_on(self):
|
||||
current_visitor = self.env['website.visitor']._get_visitor_from_request(force_create=False)
|
||||
if self.env.user._is_public() and not current_visitor:
|
||||
for track in self:
|
||||
track.is_reminder_on = track.wishlisted_by_default
|
||||
else:
|
||||
if self.env.user._is_public():
|
||||
domain = [('visitor_id', '=', current_visitor.id)]
|
||||
elif current_visitor:
|
||||
domain = [
|
||||
'|',
|
||||
('partner_id', '=', self.env.user.partner_id.id),
|
||||
('visitor_id', '=', current_visitor.id)
|
||||
]
|
||||
else:
|
||||
domain = [('partner_id', '=', self.env.user.partner_id.id)]
|
||||
|
||||
event_track_visitors = self.env['event.track.visitor'].sudo().search_read(
|
||||
expression.AND([
|
||||
domain,
|
||||
[('track_id', 'in', self.ids)]
|
||||
]), fields=['track_id', 'is_wishlisted', 'is_blacklisted']
|
||||
)
|
||||
|
||||
wishlist_map = {
|
||||
track_visitor['track_id'][0]: {
|
||||
'is_wishlisted': track_visitor['is_wishlisted'],
|
||||
'is_blacklisted': track_visitor['is_blacklisted']
|
||||
} for track_visitor in event_track_visitors
|
||||
}
|
||||
for track in self:
|
||||
if wishlist_map.get(track.id):
|
||||
track.is_reminder_on = wishlist_map.get(track.id)['is_wishlisted'] or (track.wishlisted_by_default and not wishlist_map[track.id]['is_blacklisted'])
|
||||
else:
|
||||
track.is_reminder_on = track.wishlisted_by_default
|
||||
|
||||
@api.depends('event_track_visitor_ids.visitor_id', 'event_track_visitor_ids.is_wishlisted')
|
||||
def _compute_wishlist_visitor_ids(self):
|
||||
results = self.env['event.track.visitor'].read_group(
|
||||
[('track_id', 'in', self.ids), ('is_wishlisted', '=', True)],
|
||||
['track_id', 'visitor_id:array_agg'],
|
||||
['track_id']
|
||||
)
|
||||
visitor_ids_map = {result['track_id'][0]: result['visitor_id'] for result in results}
|
||||
for track in self:
|
||||
track.wishlist_visitor_ids = visitor_ids_map.get(track.id, [])
|
||||
track.wishlist_visitor_count = len(visitor_ids_map.get(track.id, []))
|
||||
|
||||
def _search_wishlist_visitor_ids(self, operator, operand):
|
||||
if operator == "not in":
|
||||
raise NotImplementedError("Unsupported 'Not In' operation on track wishlist visitors")
|
||||
|
||||
track_visitors = self.env['event.track.visitor'].sudo().search([
|
||||
('visitor_id', operator, operand),
|
||||
('is_wishlisted', '=', True)
|
||||
])
|
||||
return [('id', 'in', track_visitors.track_id.ids)]
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# CRUD
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
tracks = super(Track, self).create(vals_list)
|
||||
@@ -100,12 +234,16 @@ class Track(models.Model):
|
||||
subject=track.name,
|
||||
subtype_id=self.env.ref('website_event_track.mt_event_track').id,
|
||||
)
|
||||
track._synchronize_with_stage(track.stage_id)
|
||||
|
||||
return tracks
|
||||
|
||||
def write(self, vals):
|
||||
if 'stage_id' in vals and 'kanban_state' not in vals:
|
||||
vals['kanban_state'] = 'normal'
|
||||
if vals.get('stage_id'):
|
||||
stage = self.env['event.track.stage'].browse(vals['stage_id'])
|
||||
self._synchronize_with_stage(stage)
|
||||
res = super(Track, self).write(vals)
|
||||
if vals.get('partner_id'):
|
||||
self.message_subscribe([vals['partner_id']])
|
||||
@@ -116,6 +254,14 @@ class Track(models.Model):
|
||||
""" Always display all stages """
|
||||
return stages.search([], order=order)
|
||||
|
||||
def _synchronize_with_stage(self, stage):
|
||||
if stage.is_done:
|
||||
self.is_published = True
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# MESSAGING
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _track_template(self, changes):
|
||||
res = super(Track, self)._track_template(changes)
|
||||
track = self[0]
|
||||
@@ -157,6 +303,10 @@ class Track(models.Model):
|
||||
]).write({'partner_id': new_partner.id})
|
||||
return super(Track, self)._message_post_after_hook(message, msg_vals)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# ACTION
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def open_track_speakers_list(self):
|
||||
return {
|
||||
'name': _('Speakers'),
|
||||
@@ -166,3 +316,39 @@ class Track(models.Model):
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TOOLS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _get_event_track_visitors(self, force_create=False):
|
||||
self.ensure_one()
|
||||
|
||||
force_visitor_create = self.env.user._is_public()
|
||||
visitor_sudo = self.env['website.visitor']._get_visitor_from_request(force_create=force_visitor_create)
|
||||
if visitor_sudo:
|
||||
visitor_sudo._update_visitor_last_visit()
|
||||
|
||||
if self.env.user._is_public():
|
||||
domain = [('visitor_id', '=', visitor_sudo.id)]
|
||||
elif visitor_sudo:
|
||||
domain = [
|
||||
'|',
|
||||
('partner_id', '=', self.env.user.partner_id.id),
|
||||
('visitor_id', '=', visitor_sudo.id)
|
||||
]
|
||||
else:
|
||||
domain = [('partner_id', '=', self.env.user.partner_id.id)]
|
||||
|
||||
track_visitors = self.env['event.track.visitor'].sudo().search(
|
||||
expression.AND([domain, [('track_id', 'in', self.ids)]])
|
||||
)
|
||||
missing = self - track_visitors.track_id
|
||||
if missing and force_create:
|
||||
track_visitors += self.env['event.track.visitor'].sudo().create([{
|
||||
'visitor_id': visitor_sudo.id,
|
||||
'partner_id': self.env.user.partner_id.id if not self.env.user._is_public() else False,
|
||||
'track_id': track.id,
|
||||
} for track in missing])
|
||||
|
||||
return track_visitors
|
||||
|
||||
@@ -18,6 +18,12 @@ class TrackStage(models.Model):
|
||||
fold = fields.Boolean(
|
||||
string='Folded in Kanban',
|
||||
help='This stage is folded in the kanban view when there are no records in that stage to display.')
|
||||
is_done = fields.Boolean(string='Done Stage')
|
||||
is_accepted = fields.Boolean(
|
||||
string='Accepted Stage',
|
||||
help='Accepted tracks are displayed in agenda views but not accessible.')
|
||||
is_done = fields.Boolean(
|
||||
string='Done Stage',
|
||||
help='Done tracks are automatically published so that they are available in frontend.')
|
||||
is_cancel = fields.Boolean(string='Canceled Stage')
|
||||
is_done = fields.Boolean()
|
||||
color = fields.Integer(string='Color')
|
||||
|
||||
@@ -9,7 +9,7 @@ from odoo import fields, models
|
||||
class TrackTag(models.Model):
|
||||
_name = "event.track.tag"
|
||||
_description = 'Event Track Tag'
|
||||
_order = 'name'
|
||||
_order = "category_id, sequence, name"
|
||||
|
||||
def _default_color(self):
|
||||
return randint(1, 11)
|
||||
@@ -19,6 +19,8 @@ class TrackTag(models.Model):
|
||||
color = fields.Integer(
|
||||
string='Color Index', default=lambda self: self._default_color(),
|
||||
help="Note that colorless tags won't be available on the website.")
|
||||
sequence = fields.Integer('Sequence', default=10)
|
||||
category_id = fields.Many2one('event.track.tag.category', string="Category", ondelete="set null")
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', "Tag name already exists !"),
|
||||
|
||||
-8
@@ -12,11 +12,3 @@ class TrackTagCategory(models.Model):
|
||||
name = fields.Char("Name", required=True, translate=True)
|
||||
sequence = fields.Integer('Sequence', default=10)
|
||||
tag_ids = fields.One2many('event.track.tag', 'category_id', string="Tags")
|
||||
|
||||
|
||||
class TrackTag(models.Model):
|
||||
_inherit = "event.track.tag"
|
||||
_order = "category_id, sequence, name"
|
||||
|
||||
sequence = fields.Integer('Sequence', default=10)
|
||||
category_id = fields.Many2one('event.track.tag.category', string="Category", ondelete="set null")
|
||||
@@ -12,3 +12,7 @@ access_event_track_sponsor_manager,event.track.sponsor.type.public,model_event_s
|
||||
access_event_track_sponsor_public,event.track.sponsor.public,model_event_sponsor,,1,0,0,0
|
||||
access_event_track_stage_all,event.track.stage.all,model_event_track_stage,,1,0,0,0
|
||||
access_event_track_stage_event_manager,event.track.stage.event.manager,model_event_track_stage,event.group_event_manager,1,1,1,1
|
||||
event_track_visitor_access_all,event.track.visitor.access.all,model_event_track_visitor,,0,0,0,0
|
||||
event_track_visitor_access_manager,event.track.visitor.access.manager,model_event_track_visitor,event.group_event_manager,1,1,1,1
|
||||
event_track_tag_category_access_public,event.track.tag.category.access,model_event_track_tag_category,,1,0,0,0
|
||||
event_track_tag_category_access_manager,event.track.tag.category.access.manager,model_event_track_tag_category,event.group_event_manager,1,1,1,1
|
||||
|
+1
-1
@@ -1,4 +1,4 @@
|
||||
importScripts("/website_event_track_online/static/lib/idb-keyval/idb-keyval.js");
|
||||
importScripts("/website_event_track/static/lib/idb-keyval/idb-keyval.js");
|
||||
|
||||
const PREFIX = "odoo-event";
|
||||
const SYNCABLE_ROUTES = ["/event/track/toggle_reminder"];
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
odoo.define("website_event_track_online.website_event_pwa_widget", function (require) {
|
||||
odoo.define("website_event_track.website_event_pwa_widget", function (require) {
|
||||
"use strict";
|
||||
|
||||
var config = require("web.config");
|
||||
@@ -6,7 +6,7 @@ odoo.define("website_event_track_online.website_event_pwa_widget", function (req
|
||||
var utils = require("web.utils");
|
||||
|
||||
var PWAInstallBanner = publicWidget.Widget.extend({
|
||||
xmlDependencies: ["/website_event_track_online/static/src/xml/website_event_pwa.xml"],
|
||||
xmlDependencies: ["/website_event_track/static/src/xml/website_event_pwa.xml"],
|
||||
template: "pwa_install_banner",
|
||||
events: {
|
||||
"click .o_btn_install": "_onClickInstall",
|
||||
@@ -1,94 +0,0 @@
|
||||
odoo.define('website_event_track.set_customize_options', function (require) {
|
||||
"use strict";
|
||||
|
||||
var EventSpecificOptions = require('website_event.set_customize_options').EventSpecificOptions;
|
||||
|
||||
EventSpecificOptions.include({
|
||||
xmlDependencies: (EventSpecificOptions.prototype.xmlDependencies || [])
|
||||
.concat([
|
||||
'/website_event_track/static/src/xml/customize_options.xml',
|
||||
]),
|
||||
|
||||
events: _.extend({}, EventSpecificOptions.prototype.events, {
|
||||
'change #display-showcase-talks': '_onDisplayTalksChange',
|
||||
'change #allow-talk-proposal': '_onAllowTalkProposalChange',
|
||||
}),
|
||||
|
||||
start: function () {
|
||||
this.$displayTalksInput = this.$('#display-showcase-talks');
|
||||
this.$allowTalksInput = this.$('#allow-talk-proposal');
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_onAllowTalkProposalChange: function () {
|
||||
var checkboxValue = this.$allowTalksInput.is(':checked');
|
||||
this._toggleTalkProposal(checkboxValue);
|
||||
},
|
||||
|
||||
_onDisplayTalksChange: function () {
|
||||
var checkboxValue = this.$displayTalksInput.is(':checked');
|
||||
this._toggleDisplayTalks(checkboxValue);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_getCheckboxFields: function () {
|
||||
var fields = this._super();
|
||||
fields = _.union(fields, ['website_track', 'website_track_proposal']);
|
||||
return fields;
|
||||
},
|
||||
|
||||
_getCheckboxFieldMatch: function (checkboxField) {
|
||||
if (checkboxField === 'website_track') {
|
||||
return this.$displayTalksInput;
|
||||
}
|
||||
if (checkboxField === 'website_track_proposal') {
|
||||
return this.$allowTalksInput;
|
||||
}
|
||||
return this._super(checkboxField);
|
||||
},
|
||||
|
||||
_initCheckboxCallback: function (rpcData) {
|
||||
this._super(rpcData);
|
||||
var submenuInput;
|
||||
if (rpcData[0]['website_track']) {
|
||||
submenuInput = this._getCheckboxFieldMatch('website_track');
|
||||
submenuInput.attr('checked', 'checked');
|
||||
}
|
||||
if (rpcData[0]['website_track_proposal']) {
|
||||
submenuInput = this._getCheckboxFieldMatch('website_track_proposal');
|
||||
submenuInput.attr('checked', 'checked');
|
||||
}
|
||||
},
|
||||
|
||||
_toggleTalkProposal: function (val) {
|
||||
var self = this;
|
||||
this._rpc({
|
||||
model: this.modelName,
|
||||
method: 'toggle_website_track_proposal',
|
||||
args: [[this.eventId], val],
|
||||
}).then(function () {
|
||||
self._reloadEventPage();
|
||||
});
|
||||
},
|
||||
|
||||
_toggleDisplayTalks: function (val) {
|
||||
var self = this;
|
||||
this._rpc({
|
||||
model: this.modelName,
|
||||
method: 'toggle_website_track',
|
||||
args: [[this.eventId], val],
|
||||
}).then(function () {
|
||||
self._reloadEventPage();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="website_event.customize_options" t-extend="website_event.customize_options">
|
||||
<t t-jquery="a[name='display-website-menu']" t-operation="after">
|
||||
<a href="#" name="display-showcase-talks" class="dropdown-item" role="menuitem">
|
||||
<label class="o_switch" for="display-showcase-talks">
|
||||
<input id="display-showcase-talks" type="checkbox"/>
|
||||
<span/>
|
||||
Showcase Talks
|
||||
</label>
|
||||
</a>
|
||||
<a href="#" name="allow-talk-proposal" class="dropdown-item" role="menuitem">
|
||||
<label class="o_switch" for="allow-talk-proposal">
|
||||
<input id="allow-talk-proposal" type="checkbox"/>
|
||||
<span/>
|
||||
Allow Talks Proposals
|
||||
</label>
|
||||
</a>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import common
|
||||
from . import test_website_event
|
||||
|
||||
@@ -2,10 +2,16 @@
|
||||
<odoo>
|
||||
|
||||
<template id="assets_frontend" inherit_id="website.assets_frontend" name="Website Event Track Assets">
|
||||
<xpath expr="." position="inside">
|
||||
<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/pwa_frontend.scss"/>
|
||||
</xpath>
|
||||
<xpath expr="//script[last()]" position="after">
|
||||
<script type="text/javascript" src="/website_event_track/static/src/js/website_event_track.js"></script>
|
||||
<script type="text/javascript" src="/website_event_track/static/src/js/website_event_track_set_customize_options.js"></script>
|
||||
<script type="text/javascript" src="/website_event_track/static/src/js/event_track_reminder.js"></script>
|
||||
<script type="text/javascript" src="/website_event_track/static/src/js/website_event_pwa_widget.js"/>
|
||||
<script type="text/javascript" src="/website_event_track/static/lib/idb-keyval/idb-keyval.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
<field name="sponsor_count" string="Sponsors" widget="statinfo"/>
|
||||
</button>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='website_menu']" position="after">
|
||||
<label for="website_track" string="Showcase Tracks"/>
|
||||
<field name="website_track"/>
|
||||
<label for="website_track_proposal" string="Allow Track Proposals"/>
|
||||
<field name="website_track_proposal"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
groups="base.group_no_one"
|
||||
sequence="32"/>
|
||||
|
||||
<menuitem id="event_track_tag_category_menu"
|
||||
name="Track Tag Categories"
|
||||
action="event_track_tag_category_action"
|
||||
parent="event.menu_event_configuration"
|
||||
groups="base.group_no_one"
|
||||
sequence="33"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_event_track_tag"
|
||||
name="Track Tags"
|
||||
@@ -32,6 +39,13 @@
|
||||
groups="base.group_no_one"
|
||||
sequence="34"/>
|
||||
|
||||
<menuitem id="event_track_visitor_menu"
|
||||
name="Track Visitors"
|
||||
sequence="38"
|
||||
action="event_track_visitor_action"
|
||||
parent="event.menu_event_configuration"
|
||||
groups="base.group_no_one"/>
|
||||
|
||||
<menuitem id="menu_event_sponsor_type"
|
||||
name="Sponsor Types"
|
||||
action="event_sponsor_type_action"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="display_ribbon_style"/>
|
||||
<field name="sequence" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</sheet>
|
||||
@@ -24,6 +25,7 @@
|
||||
<tree editable="bottom" string="Event Sponsor Type">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="display_ribbon_style"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -40,6 +42,9 @@
|
||||
<search string="Event Sponsors">
|
||||
<field name="partner_id"/>
|
||||
<field name="event_id"/>
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<field name="phone"/>
|
||||
<filter string="Archived" name="archived" domain="[('active', '=', False)]"/>
|
||||
<group string="Group By" expand="0">
|
||||
<filter string="Event" name="group_by_event_id" domain="[]" context="{'group_by': 'event_id'}"/>
|
||||
@@ -57,18 +62,24 @@
|
||||
<sheet>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="image_128" widget="image" class="oe_avatar"/>
|
||||
<h1><field name="partner_id"/></h1>
|
||||
<field name="image_512" widget="image" class="oe_avatar"/>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only" string="Sponsor Name"/>
|
||||
<h1><field name="name" placeholder="e.g. : OpenWood Decoration"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="event_id"/>
|
||||
<field name="partner_email" widget="email"/>
|
||||
<field name="url" widget="url" string="Website"/>
|
||||
<field name="partner_id" string="Partner"/>
|
||||
<field name="email" widget="email" string="Email"
|
||||
placeholder="e.g. : open.wood.decoration@example.com"/>
|
||||
<field name="url" widget="url" string="Website"
|
||||
placeholder=">e.g. : https://www.odoo.com"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="sponsor_type_id"/>
|
||||
<field name="partner_phone" widget="phone" options="{'enable_sms': True}"/>
|
||||
<field name="partner_mobile" widget="phone" options="{'enable_sms': True}"/>
|
||||
<field name="phone" widget="phone" string="Phone" options="{'enable_sms': True}"/>
|
||||
<field name="mobile" widget="phone" string="Mobile" options="{'enable_sms': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
@@ -85,9 +96,13 @@
|
||||
<field name="name">event.sponsor.view.tree</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<tree multi_edit="1">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="partner_id" readonly="1"/>
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<field name="phone"/>
|
||||
<field name="mobile"/>
|
||||
<field name="url" string="Website"/>
|
||||
<field name="sponsor_type_id"/>
|
||||
</tree>
|
||||
@@ -133,5 +148,6 @@
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
<t t-set="pageName" t-value="'event'"/>
|
||||
<t t-set="head">
|
||||
<t t-raw="head"/>
|
||||
<t t-call="website_event_track_online.pwa_manifest"/>
|
||||
<t t-call="website_event_track.pwa_manifest"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -30,7 +30,7 @@
|
||||
<t t-set="pageName" t-value="'event'"/>
|
||||
<t t-set="head">
|
||||
<t t-raw="head"/>
|
||||
<t t-call="website_event_track_online.pwa_manifest"/>
|
||||
<t t-call="website_event_track.pwa_manifest"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -26,6 +26,7 @@
|
||||
</group>
|
||||
<group>
|
||||
<field name="fold"/>
|
||||
<field name="is_accepted"/>
|
||||
<field name="is_done"/>
|
||||
<field name="is_cancel"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
@@ -43,6 +44,9 @@
|
||||
<tree string="Track Stage">
|
||||
<field name="sequence" widget="handle" groups="event.group_event_manager"/>
|
||||
<field name="name"/>
|
||||
<field name="is_accepted"/>
|
||||
<field name="is_done"/>
|
||||
<field name="is_cancel"/>
|
||||
<field name="fold"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
||||
@@ -1,7 +1,44 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="event_track_tag_category_view_form" model="ir.ui.view">
|
||||
<field name="name">event.track.tag.category.view.form</field>
|
||||
<field name="model">event.track.tag.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Track Tag Category">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="tag_ids" context="{'default_category_id': active_id}">
|
||||
<tree string="Tags" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_tag_category_view_list" model="ir.ui.view">
|
||||
<field name="name">event.track.tag.category.view.list</field>
|
||||
<field name="model">event.track.tag.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Track Tags Category">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_tag_category_action" model="ir.actions.act_window">
|
||||
<field name="name">Track Tag Categories</field>
|
||||
<field name="res_model">event.track.tag.category</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<!-- EVENTS/CONFIGURATION/EVENT Tags -->
|
||||
<record model="ir.ui.view" id="view_event_track_tag_form">
|
||||
<field name="name">Track Tags</field>
|
||||
<field name="model">event.track.tag</field>
|
||||
@@ -10,6 +47,8 @@
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
<field name="category_id"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
@@ -21,7 +60,10 @@
|
||||
<field name="model">event.track.tag</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Event Track Tag" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
<field name="category_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -1,76 +1,194 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="agenda">
|
||||
<!-- Revamped agenda : Will need to replace agenda_online from website_event_track in master -->
|
||||
<template id="agenda_online" name="Track Online: Agenda">
|
||||
<t t-call="website_event.layout">
|
||||
<div class="oe_structure" id="oe_structure_website_event_track_agenda_1"/>
|
||||
<section class="container pt48">
|
||||
<h1 t-field="event.name"/>
|
||||
<div class="form-inline float-right">
|
||||
<label class="invisible text-muted" id="search_summary"><span id="search_number">0</span> Found </label>
|
||||
<input type="text" class="form-control" placeholder="Filter Tracks..." id="event_track_search"/>
|
||||
<div class="o_wevent_online o_weagenda_index">
|
||||
<!-- Options -->
|
||||
<t t-set="option_track_wishlist" t-value="not event.is_done and request.website.viewref('website_event_track.agenda_topbar_wishlist').active"/>
|
||||
<!-- Topbar -->
|
||||
<t t-call="website_event_track.agenda_topbar"/>
|
||||
<!-- Drag/Drop Area -->
|
||||
<div class="oe_structure" id="oe_structure_website_event_track_agenda_1"/>
|
||||
<!-- Content -->
|
||||
<div class="container">
|
||||
<div class="row mb-5">
|
||||
<t t-call="website_event_track.agenda_main"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<t t-set="dayslist" t-value="list(days.keys())"/>
|
||||
<t t-set="dayslist2" t-value="dayslist.sort()"/> <!-- display days in the right order -->
|
||||
<section class="container" t-foreach="dayslist" t-as="day">
|
||||
<t t-set="locations" t-value="days[day]['locations']"/>
|
||||
<t t-set="dates" t-value="days[day]['dates']"/>
|
||||
<h3 class="o_page_header mt0">
|
||||
<span t-field="tracks_by_days[day][0].date" t-options="{'widget': 'date'}"/>
|
||||
<small><t t-esc="len(tracks_by_days[day])"/> talks</small>
|
||||
</h3>
|
||||
<table id="table_search" class="table table-bordered table-sm">
|
||||
<!-- Drag/Drop Area -->
|
||||
<div class="oe_structure" id="oe_structure_website_event_track_agenda_2"/>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- TOPBAR: BASE NAVIGATION -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<!-- Main topbar -->
|
||||
<template id="agenda_topbar" name="Agenda 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_weagenda_topbar_filters o_wevent_index_topbar_filters nav">
|
||||
</ul>
|
||||
<div class="form-inline pl-sm-3 pr-0">
|
||||
<label class="invisible text-muted mr-2" id="search_summary"><span id="search_number" class="mr-1">0</span>Results</label>
|
||||
<input type="text" class="form-control" placeholder="Filter Tracks..." id="event_track_search"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<!-- Option: Tracks display: optional wishlist -->
|
||||
<template id="agenda_topbar_wishlist"
|
||||
inherit_id="website_event_track.agenda_topbar"
|
||||
name="Allow Wishlists"
|
||||
active="True"
|
||||
customize_show="True">
|
||||
<xpath expr="//ul[hasclass('o_weagenda_topbar_filters')]" position="inside">
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- CONTENT: MAIN TEMPLATES -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<!-- Agenda Main Display -->
|
||||
<template id="agenda_main" name="Tracks: Main Display">
|
||||
<!-- No tracks -->
|
||||
<div class="col-12" t-if="not tracks_by_days">
|
||||
<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>
|
||||
|
||||
<section t-else="" class="col-12" t-foreach="days" t-as="day">
|
||||
<!-- DAY HEADER -->
|
||||
<div class="o_we_track_day_header mt-3 w-100 d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex">
|
||||
<span class="h1 m-0 font-weight-bold" t-esc="day"
|
||||
t-options="{'widget': 'date', 'format': 'EEEE dd'}"/>
|
||||
<div class="d-flex flex-column ml-2">
|
||||
<span class="font-weight-bold" t-esc="day"
|
||||
t-options="{'widget': 'date', 'format': 'MMMM'}"/>
|
||||
<span class="font-weight-bold" t-esc="day"
|
||||
t-options="{'widget': 'date', 'format': 'YYYY'}"/>
|
||||
</div>
|
||||
</div>
|
||||
<small class="float-right text-muted align-self-end"><t t-esc="tracks_by_days[day]"/> tracks</small>
|
||||
</div>
|
||||
<hr class="mt-2 pb-1 mb-1"/>
|
||||
|
||||
<!-- Day Agenda -->
|
||||
<div class="o_we_online_agenda">
|
||||
<table id="table_search" class="table table-sm border-0">
|
||||
<!--Header-->
|
||||
<tr>
|
||||
<th/>
|
||||
<t t-foreach="locations.keys()" t-as="location">
|
||||
<th t-if="location" class="active">
|
||||
<th class="border-0 bg-white position-sticky"/>
|
||||
<t t-foreach="locations" t-as="location">
|
||||
<th t-if="location" class="active text-center">
|
||||
<span t-esc="location and location.name or 'Unknown'"/>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
<tr t-foreach="dates" t-as="dt">
|
||||
<td class="active">
|
||||
<b t-esc="dt[-1]"/>
|
||||
</td>
|
||||
<t t-if="dt[2]"> <!-- Not a multi location -->
|
||||
|
||||
<!-- Time Slots -->
|
||||
<t t-set="used_cells" t-value="[]"/>
|
||||
<t t-foreach="time_slots[day]" t-as="time_slot">
|
||||
<t t-set="is_round_hour" t-value="time_slot == time_slot.replace(minute=0)"/>
|
||||
<t t-set="is_half_hour" t-value="time_slot == time_slot.replace(minute=30)"/>
|
||||
|
||||
<tr t-att-class="'%s' % ('active' if is_round_hour else '')">
|
||||
<td class="active">
|
||||
<b t-if="is_round_hour" t-esc="time_slots[day][time_slot]['formatted_time']"/>
|
||||
</td>
|
||||
|
||||
<t t-foreach="locations" t-as="location">
|
||||
<t t-if="location and dt[1].get(location, False)">
|
||||
<t t-set="track" t-value="dt[1][location][0]"/>
|
||||
<t t-if="track">
|
||||
<td t-att-rowspan="dt[1][location][3]" t-attf-class="event_color_#{track.color} #{track and 'event_track' or ''}">
|
||||
<t t-if="track" name="track_agenda_track_cell">
|
||||
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
|
||||
<span t-esc="track and track.name"/>
|
||||
<span t-if="not track.website_published" class="badge badge-warning">unpublished</span>
|
||||
</a>
|
||||
<div class="text-muted">
|
||||
<small t-if="track.partner_id" t-esc="track.partner_id.sudo().name"/>
|
||||
<small t-if="not track.partner_id" t-esc="track.partner_name"/>
|
||||
</div>
|
||||
</t>
|
||||
</td>
|
||||
<t t-set="tracks" t-value="time_slots[day][time_slot].get(location, {})"/>
|
||||
<t t-if="tracks">
|
||||
<t t-foreach="tracks" t-as="track">
|
||||
<t t-if="track.location_id and track.location_id == location">
|
||||
<td t-att-rowspan="tracks[track]['rowspan']"
|
||||
t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''} o_location_size_#{len(locations)}">
|
||||
<t t-call="website_event_track.agenda_main_track"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td t-att-colspan="len(locations)-1"
|
||||
t-att-rowspan="tracks[track]['rowspan']"
|
||||
t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''} o_location_size_#{len(locations)}">
|
||||
<t t-call="website_event_track.agenda_main_track"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-set="used_cells" t-value="used_cells + tracks[track]['occupied_cells']"/>
|
||||
</t>
|
||||
<td t-if="not track" t-att-rowspan="dt[1][location][3]" class="event_track"/>
|
||||
</t>
|
||||
<t t-elif="location and (time_slot, location) not in used_cells">
|
||||
<td t-att-rowspan="1"
|
||||
t-att-class="'o_location_size_%s %s' % (len(locations),
|
||||
'o_we_agenda_time_slot_half' if is_half_hour else
|
||||
'o_we_agenda_time_slot_main' if is_round_hour else
|
||||
''
|
||||
)"><div/></td>
|
||||
</t>
|
||||
</t>
|
||||
</t><t t-if="not dt[2]">
|
||||
<t t-set="track" t-value="dt[1][False][0]"/>
|
||||
<td t-att-colspan="len(locations)-1" t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''}">
|
||||
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
|
||||
<span t-esc="track.name"/>
|
||||
</a>
|
||||
<div class="text-muted">
|
||||
<small t-if="track.partner_id" t-esc="track.partner_id.sudo().name"/>
|
||||
<small t-if="not track.partner_id" t-esc="track.partner_name"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<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="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>
|
||||
<small t-if="not track.stage_id.is_accepted" title="Not Accepted"
|
||||
class="ml-1 badge badge-danger o_wevent_online_badge_unpublished">Not Accepted</small>
|
||||
<span t-if="option_track_wishlist">
|
||||
<t t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_light" t-value="True"/>
|
||||
<t t-set="reminder_small" t-value="True"/>
|
||||
<t t-set="light_theme" t-value="False"/>
|
||||
</t>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
<div class="oe_structure" id="oe_structure_website_event_track_agenda_2"/>
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="o_we_agenda_card_content d-flex flex-column justify-content-center my-1">
|
||||
<div t-att-class="'text-black' if track.website_published or user_event_manager else 'text-muted'"
|
||||
t-att-onclick="'window.location=\'/event/%s/track/%s\'' % (slug(event), slug(track))
|
||||
if track.website_published or user_event_manager else ''">
|
||||
<span class="o_we_agenda_card_title text-bold" t-esc="track.name"/>
|
||||
</div>
|
||||
<div class="text-muted text-center">
|
||||
<small t-if="track.partner_id or track.partner_name">
|
||||
<t t-esc="track.partner_id.sudo().name or track.partner_name"/></small>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-wrap">
|
||||
<t t-foreach="track.tag_ids" t-as="tag">
|
||||
<span t-if="tag.color" t-att-title="tag.name"
|
||||
t-attf-class="mr-1 mt-1 badge #{'o_tag_color_'+str(tag.color)}" t-esc="tag.name"
|
||||
t-attf-onclick="
|
||||
var value = '#{tag.name}' ;
|
||||
var target = $('#event_track_search');
|
||||
if (target.val() == value) { target.val(''); } else { target.val(value); }
|
||||
target.trigger('input');
|
||||
"
|
||||
/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="tracks">
|
||||
<template id="tracks" track="True">
|
||||
<t t-call="website_event.layout">
|
||||
<div class="oe_structure" id="oe_structure_website_event_track_tracks_1"/>
|
||||
<section class="pt48 pb48">
|
||||
@@ -76,4 +76,18 @@
|
||||
</xpath>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -4,26 +4,31 @@
|
||||
<template name="Sponsors" id="event_sponsor" customize_show="True" inherit_id="website_event.layout">
|
||||
<xpath expr="//div[@id='wrap']" position="inside">
|
||||
<div class="container mt32 mb16 d-print-none" t-if="event.sponsor_ids">
|
||||
<section>
|
||||
<h2 class="text-center mb32">Our Sponsors</h2>
|
||||
</section>
|
||||
<div class="row">
|
||||
<div t-attf-class="col-sm-6 col-lg-#{(len(event.sponsor_ids) > 6) and 2 or (12 // len(event.sponsor_ids))} text-center mb16 oe_sponsor" t-foreach="event.sponsor_ids" t-as="sponsor">
|
||||
<div t-attf-class="d-flex flex-wrap mb-5 #{'' if (len(event.sponsor_ids) > 10) else 'justify-content-md-center'}">
|
||||
<t t-foreach="event.sponsor_ids" t-as="sponsor">
|
||||
<t t-if="sponsor.url">
|
||||
<a t-att-href="sponsor.url" class="bg-white o_wevent_sponsor">
|
||||
<span t-field="sponsor.image_128"
|
||||
t-options='{"widget": "image", "class": "shadow"}'/>
|
||||
<span t-field="sponsor.sponsor_type_id" t-attf-class="o_ribbon o_ribbon_right ribbon_#{sponsor.sponsor_type_id.name}"/>
|
||||
<a class="o_wevent_sponsor_card" target="_blank" t-att-href="sponsor.url">
|
||||
<div class="h-100 shadow-sm p-2">
|
||||
<span t-field="sponsor.image_128"
|
||||
t-options='{"widget": "image", "class": "img img-fluid"}'/>
|
||||
<div t-if="sponsor.sponsor_type_id.display_ribbon_style and sponsor.sponsor_type_id.display_ribbon_style != 'no_ribbon'" class="ribbon-wrapper">
|
||||
<div t-field="sponsor.sponsor_type_id" t-attf-class="ribbon ribbon_#{sponsor.sponsor_type_id.display_ribbon_style}"/>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</t>
|
||||
<t t-if="not sponsor.url">
|
||||
<span class="bg-white o_wevent_sponsor">
|
||||
<span t-field="sponsor.image_128"
|
||||
t-options='{"widget": "image", "class": "shadow"}'/>
|
||||
<span t-field="sponsor.sponsor_type_id" t-attf-class="o_ribbon o_ribbon_right ribbon_#{sponsor.sponsor_type_id.name}"/>
|
||||
</span>
|
||||
<div class="o_wevent_sponsor_card">
|
||||
<div class="h-100 shadow-sm p-2">
|
||||
<span t-field="sponsor.image_128"
|
||||
t-options='{"widget": "image", "class": "img img-fluid"}'/>
|
||||
<div t-if="sponsor.sponsor_type_id.display_ribbon_style and sponsor.sponsor_type_id.display_ribbon_style != 'no_ribbon'" class="ribbon-wrapper">
|
||||
<div t-field="sponsor.sponsor_type_id" t-attf-class="ribbon ribbon_#{sponsor.sponsor_type_id.display_ribbon_style}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="track_view">
|
||||
<template id="track_view" track="True">
|
||||
<t t-call="website_event.layout">
|
||||
<section class="pt48">
|
||||
<div class="container">
|
||||
@@ -82,4 +82,18 @@
|
||||
</t>
|
||||
</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"/>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,234 +1,268 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="website_visitor_action_from_track" model="ir.actions.act_window">
|
||||
<field name="name">Visitors Wishlist</field>
|
||||
<field name="res_model">website.visitor</field>
|
||||
<field name="view_mode">kanban,tree,form,graph</field>
|
||||
<field name="domain">[('event_track_wishlisted_ids', 'in', [active_id])]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Wait for visitors to wishlist your tracks
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Event Tracks -->
|
||||
<record model="ir.ui.view" id="view_event_track_kanban">
|
||||
<field name="name">event.track.kanban</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="stage_id">
|
||||
<templates>
|
||||
<field name="color"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="website_url"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="activity_state"/>
|
||||
<progressbar field="kanban_state" colors='{"done": "success", "blocked": "danger"}'/>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="{{!selection_mode ? 'oe_kanban_color_' + kanban_getcolor(record.color.raw_value) : ''}} oe_kanban_card oe_kanban_global_click">
|
||||
<div class="o_dropdown_kanban dropdown" groups="base.group_user">
|
||||
<record model="ir.ui.view" id="view_event_track_kanban">
|
||||
<field name="name">event.track.kanban</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="stage_id">
|
||||
<templates>
|
||||
<field name="color"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="website_url"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="activity_state"/>
|
||||
<progressbar field="kanban_state" colors='{"done": "success", "blocked": "danger"}'/>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="{{!selection_mode ? 'oe_kanban_color_' + kanban_getcolor(record.color.raw_value) : ''}} oe_kanban_card oe_kanban_global_click">
|
||||
<div class="o_dropdown_kanban dropdown" groups="base.group_user">
|
||||
|
||||
<a role="button" class="dropdown-toggle o-no-caret btn" data-toggle="dropdown" href="#" aria-label="Dropdown menu" title="Dropdown menu">
|
||||
<span class="fa fa-ellipsis-v"/>
|
||||
</a>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" t-att-href="record.website_url.value" class="dropdown-item">View Track</a>
|
||||
<t t-if="widget.editable"><a role="menuitem" type="edit" class="dropdown-item">Edit Track</a></t>
|
||||
<t t-if="widget.deletable"><a role="menuitem" type="delete" class="dropdown-item">Delete</a></t>
|
||||
<ul class="oe_kanban_colorpicker" data-field="color"/>
|
||||
</div>
|
||||
<a role="button" class="dropdown-toggle o-no-caret btn" data-toggle="dropdown" href="#" aria-label="Dropdown menu" title="Dropdown menu">
|
||||
<span class="fa fa-ellipsis-v"/>
|
||||
</a>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" t-att-href="record.website_url.value" class="dropdown-item">View Track</a>
|
||||
<t t-if="widget.editable"><a role="menuitem" type="edit" class="dropdown-item">Edit Track</a></t>
|
||||
<t t-if="widget.deletable"><a role="menuitem" type="delete" class="dropdown-item">Delete</a></t>
|
||||
<ul class="oe_kanban_colorpicker" data-field="color"/>
|
||||
</div>
|
||||
<div class="oe_kanban_content">
|
||||
<div class="o_kanban_record_top">
|
||||
<h4 class="o_kanban_record_title"><field name="name"/></h4>
|
||||
</div>
|
||||
<div class="oe_kanban_content">
|
||||
<div class="o_kanban_record_top">
|
||||
<h4 class="o_kanban_record_title"><field name="name"/></h4>
|
||||
</div>
|
||||
<div class="o_kanban_record_body">
|
||||
<t t-if="duration"><field name="duration" widget="float_time"/> hours</t>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
</div>
|
||||
<div class="o_kanban_record_bottom">
|
||||
<div class="oe_kanban_bottom_left">
|
||||
<field name="priority" widget="priority"/>
|
||||
<field name="activity_ids" widget="kanban_activity"/>
|
||||
</div>
|
||||
<div class="o_kanban_record_body">
|
||||
<t t-if="duration"><field name="duration" widget="float_time"/> hours</t>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
</div>
|
||||
<div class="o_kanban_record_bottom">
|
||||
<div class="oe_kanban_bottom_left">
|
||||
<field name="priority" widget="priority"/>
|
||||
<field name="activity_ids" widget="kanban_activity"/>
|
||||
</div>
|
||||
<div class="oe_kanban_bottom_right">
|
||||
<field name="kanban_state" widget="state_selection" groups="base.group_user"/>
|
||||
<img t-att-src="kanban_image('res.partner', 'image_128', record.partner_id.raw_value)"
|
||||
t-att-title="record.partner_id.value" t-att-alt="record.partner_id.value"
|
||||
class="oe_kanban_avatar"/>
|
||||
</div>
|
||||
<div class="oe_kanban_bottom_right">
|
||||
<field name="kanban_state" widget="state_selection" groups="base.group_user"/>
|
||||
<img t-att-src="kanban_image('res.partner', 'image_128', record.partner_id.raw_value)"
|
||||
t-att-title="record.partner_id.value" t-att-alt="record.partner_id.value"
|
||||
class="oe_kanban_avatar"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_event_track_calendar" model="ir.ui.view">
|
||||
<field name="name">event.track.calendar</field>
|
||||
<field name="model">event.track</field>
|
||||
<field eval="2" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar date_start="date" date_delay="duration" string="Event Tracks" color="location_id" event_limit="5">
|
||||
<field name="location_id" filters="1"/>
|
||||
<field name="event_id"/>
|
||||
<field name="partner_id" avatar_field="image_128"/>
|
||||
<field name="user_id" avatar_field="image_128"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_track_search">
|
||||
<field name="name">event.track.search</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Event Tracks">
|
||||
<field name="name"/>
|
||||
<field name="event_id"/>
|
||||
<field name="location_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="partner_id"/>
|
||||
<filter string="My Tracks" name="my_tracks" domain="[('user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter name="filter_date" date="date"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
|
||||
<separator/>
|
||||
<filter invisible="1" string="Late Activities" name="activities_overdue"
|
||||
domain="[('activity_ids.date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||
help="Show all records which has next action date is before today"/>
|
||||
<filter invisible="1" string="Today Activities" name="activities_today"
|
||||
domain="[('activity_ids.date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<filter invisible="1" string="Future Activities" name="activities_upcoming_all"
|
||||
domain="[('activity_ids.date_deadline', '>', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Responsible" name="responsible" context="{'group_by': 'user_id'}"/>
|
||||
<filter string="Stage" name="stage" context="{'group_by': 'stage_id'}"/>
|
||||
<filter string="Date" name="date" context="{'group_by': 'date'}"/>
|
||||
<filter string="Event" name="event" context="{'group_by': 'event_id'}"/>
|
||||
<filter string="Location" name="location" context="{'group_by': 'location_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_track_form">
|
||||
<field name="name">event.track.form</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Track">
|
||||
<header>
|
||||
<field name="stage_id" widget="statusbar" options="{'clickable': '1'}"/>
|
||||
</header>
|
||||
<sheet string="Track">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<field name="website_url" invisible="1"/>
|
||||
<field name="is_published" widget="website_redirect_button"/>
|
||||
</div>
|
||||
<widget name="web_ribbon" text="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<field name="kanban_state" widget="state_selection" class="ml-3 float-right"/>
|
||||
<field name="image" widget="image" class="oe_avatar"/>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="e.g. Inspiring Business Talk"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="date"/>
|
||||
<field name="location_id"/>
|
||||
<label for="duration"/>
|
||||
<div class="o_row">
|
||||
<field name="duration" widget="float_time"/>
|
||||
<span>hours</span>
|
||||
</div>
|
||||
<field name="active" invisible="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="user_id" domain="[('share', '=', False)]"/>
|
||||
<field name="event_id"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Speakers" name="speakers">
|
||||
<group>
|
||||
<field name="partner_id"
|
||||
domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]"
|
||||
context="{'default_phone': partner_phone, 'default_email': partner_email}"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="partner_email"/>
|
||||
<field name="partner_phone" class="o_force_ltr"/>
|
||||
<field name="partner_biography"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Description" name="description">
|
||||
<field name="description"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids" options="{'post_refresh': 'recipients'}"/>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_event_track_calendar" model="ir.ui.view">
|
||||
<field name="name">event.track.calendar</field>
|
||||
<field name="model">event.track</field>
|
||||
<field eval="2" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar date_start="date" date_delay="duration" string="Event Tracks" color="location_id" event_limit="5">
|
||||
<field name="location_id" filters="1"/>
|
||||
<field name="event_id"/>
|
||||
<field name="partner_id" avatar_field="image_128"/>
|
||||
<field name="user_id" avatar_field="image_128"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_track_search">
|
||||
<field name="name">event.track.search</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Event Tracks">
|
||||
<field name="name"/>
|
||||
<field name="event_id"/>
|
||||
<field name="location_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="partner_id"/>
|
||||
<filter string="My Tracks" name="my_tracks" domain="[('user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter string="Always Wishlisted" name="filter_wishlisted_by_default" domain="[('wishlisted_by_default', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter name="filter_date" date="date"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
|
||||
<separator/>
|
||||
<filter invisible="1" string="Late Activities" name="activities_overdue"
|
||||
domain="[('activity_ids.date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||
help="Show all records which has next action date is before today"/>
|
||||
<filter invisible="1" string="Today Activities" name="activities_today"
|
||||
domain="[('activity_ids.date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<filter invisible="1" string="Future Activities" name="activities_upcoming_all"
|
||||
domain="[('activity_ids.date_deadline', '>', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Responsible" name="responsible" context="{'group_by': 'user_id'}"/>
|
||||
<filter string="Stage" name="stage" context="{'group_by': 'stage_id'}"/>
|
||||
<filter string="Date" name="date" context="{'group_by': 'date'}"/>
|
||||
<filter string="Event" name="event" context="{'group_by': 'event_id'}"/>
|
||||
<filter string="Location" name="location" context="{'group_by': 'location_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_track_form">
|
||||
<field name="name">event.track.form</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Track">
|
||||
<header>
|
||||
<field name="stage_id" widget="statusbar" options="{'clickable': '1'}"/>
|
||||
</header>
|
||||
<sheet string="Track">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<field name="website_url" invisible="1"/>
|
||||
<button name="%(website_event_track.website_visitor_action_from_track)d"
|
||||
type="action"
|
||||
class="oe_stat_button"
|
||||
icon="fa-bell">
|
||||
<field name="wishlist_visitor_count" string="Wishlisted By" widget="statinfo"/>
|
||||
</button>
|
||||
<field name="is_published" widget="website_redirect_button"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<widget name="web_ribbon" text="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<field name="kanban_state" widget="state_selection" class="ml-3 float-right"/>
|
||||
<field name="website_image" widget="image" class="oe_avatar"/>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="e.g. Inspiring Business Talk"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="date"/>
|
||||
<field name="location_id"/>
|
||||
<label for="duration"/>
|
||||
<div class="o_row">
|
||||
<field name="duration" widget="float_time"/>
|
||||
<span>hours</span>
|
||||
</div>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="wishlisted_by_default"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="user_id" domain="[('share', '=', False)]"/>
|
||||
<field name="event_id"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Speakers" name="speakers">
|
||||
<group>
|
||||
<field name="partner_id"
|
||||
domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]"
|
||||
context="{'default_phone': partner_phone, 'default_email': partner_email}"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="partner_email"/>
|
||||
<field name="partner_phone" class="o_force_ltr"/>
|
||||
<field name="partner_biography"/>
|
||||
<field name="image" widget="image" class="oe_avatar float-left"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Description" name="description">
|
||||
<field name="description"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids" options="{'post_refresh': 'recipients'}"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_track_tree">
|
||||
<field name="name">event.track.tree</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Event Track">
|
||||
<field name="name"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="partner_id" optional="hide"/>
|
||||
<field name="partner_email"/>
|
||||
<field name="partner_phone"/>
|
||||
<field name="event_id" invisible="context.get('default_event_id')"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="color" widget="color_picker" optional="hide"/>
|
||||
<field name="activity_exception_decoration" widget="activity_exception"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="view_event_track_tree">
|
||||
<field name="name">event.track.tree</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Event Track">
|
||||
<field name="name"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="partner_id" optional="hide"/>
|
||||
<field name="partner_email"/>
|
||||
<field name="partner_phone"/>
|
||||
<field name="event_id" invisible="context.get('default_event_id')"/>
|
||||
<field name="wishlisted_by_default" optional="hide"/>
|
||||
<field name="wishlist_visitor_count" optional="hide"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="color" widget="color_picker" optional="hide"/>
|
||||
<field name="activity_exception_decoration" widget="activity_exception"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_track_graph">
|
||||
<field name="name">event.track.graph</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Tracks" type="bar" orientation="horizontal" sample="1">
|
||||
<field name="location_id"/>
|
||||
<field name="duration" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="view_event_track_graph">
|
||||
<field name="name">event.track.graph</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Tracks" type="bar" orientation="horizontal" sample="1">
|
||||
<field name="location_id"/>
|
||||
<field name="duration" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_event_track">
|
||||
<field name="name">Event Tracks</field>
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,graph,activity</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new track
|
||||
</p><p>
|
||||
Tracks define the schedule of your event.<br/>These can be a talk, a round table, a meeting, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window" id="action_event_track">
|
||||
<field name="name">Event Tracks</field>
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,graph,activity</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new track
|
||||
</p><p>
|
||||
Tracks define the schedule of your event.<br/>These can be a talk, a round table, a meeting, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_event_track_from_event">
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="name">Event Tracks</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,graph,activity</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new track
|
||||
</p><p>
|
||||
Tracks define the schedule of your event.<br/>These can be a talk, a round table, a meeting, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window" id="action_event_track_from_event">
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="name">Event Tracks</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,graph,activity</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new track
|
||||
</p><p>
|
||||
Tracks define the schedule of your event.<br/>These can be a talk, a round table, a meeting, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_action_from_visitor" model="ir.actions.act_window">
|
||||
<field name="name">Wishlisted Tracks</field>
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="domain">[('wishlist_visitor_ids', 'in', [active_id])]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
No track wishlisted by this visitor
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
<field name="inherit_id" ref="website_event.website_visitor_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[@id='w_visitor_visit_counter']" position="before">
|
||||
<button name="%(website_event_track_online.event_track_action_from_visitor)d"
|
||||
<button name="%(website_event_track.event_track_action_from_visitor)d"
|
||||
type="action"
|
||||
class="oe_stat_button" icon="fa-ticket"
|
||||
attrs="{'invisible': [('event_track_wishlisted_count', '=', 0)]}">
|
||||
@@ -11,7 +11,7 @@
|
||||
'website': 'https://www.odoo.com/page/events',
|
||||
'description': "",
|
||||
'depends': [
|
||||
'website_event_track_online',
|
||||
'website_event_track',
|
||||
'website_jitsi',
|
||||
],
|
||||
'data': [
|
||||
|
||||
@@ -6,12 +6,12 @@ from random import randint, sample
|
||||
from werkzeug.exceptions import NotFound, Forbidden
|
||||
|
||||
from odoo import exceptions, http
|
||||
from odoo.addons.website_event_track.controllers.main import WebsiteEventTrackController
|
||||
from odoo.addons.website_event_track.controllers.event_track import EventTrackController
|
||||
from odoo.http import request
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
class ExhibitorController(WebsiteEventTrackController):
|
||||
class ExhibitorController(EventTrackController):
|
||||
|
||||
def _get_event_sponsors_base_domain(self, event):
|
||||
search_domain_base = [
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import date, datetime, timedelta
|
||||
from datetime import datetime
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo.addons.website_event_track_online.tests.common import TestEventTrackOnlineCommon
|
||||
from odoo.addons.website_event_track.tests.common import TestEventTrackOnlineCommon
|
||||
from odoo.fields import Datetime as FieldsDatetime
|
||||
from odoo.tests.common import users
|
||||
|
||||
|
||||
@@ -18,6 +20,14 @@ class TestSponsorData(TestEventTrackOnlineCommon):
|
||||
'hour_to': 18.0,
|
||||
})
|
||||
|
||||
cls.wevent_exhib_dt = patch(
|
||||
'odoo.addons.website_event_track_exhibitor.models.event_sponsor.fields.Datetime',
|
||||
wraps=FieldsDatetime
|
||||
)
|
||||
cls.mock_wevent_exhib_dt = cls.wevent_exhib_dt.start()
|
||||
cls.mock_wevent_exhib_dt.now.return_value = cls.reference_now
|
||||
cls.addClassCleanup(cls.wevent_exhib_dt.stop)
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_date_computation(self):
|
||||
""" Test date computation. Pay attention that mocks returns UTC values, meaning
|
||||
@@ -29,42 +39,48 @@ class TestSponsorData(TestEventTrackOnlineCommon):
|
||||
self.assertTrue(event.is_ongoing)
|
||||
|
||||
# After hour_from (9 > 8)
|
||||
self.mock_event_online_dt.now.return_value = datetime(2020, 7, 6, 7, 0, 0)
|
||||
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 7, 0, 0)
|
||||
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 7, 0, 0)
|
||||
event.invalidate_cache(fnames=['is_ongoing'])
|
||||
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
|
||||
self.assertTrue(sponsor.is_in_opening_hours)
|
||||
self.assertTrue(event.is_ongoing)
|
||||
|
||||
# At hour_from (8 = 8)
|
||||
self.mock_event_online_dt.now.return_value = datetime(2020, 7, 6, 6, 0, 0)
|
||||
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 6, 0, 0)
|
||||
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 6, 0, 0)
|
||||
event.invalidate_cache(fnames=['is_ongoing'])
|
||||
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
|
||||
self.assertTrue(sponsor.is_in_opening_hours)
|
||||
self.assertTrue(event.is_ongoing)
|
||||
|
||||
# Started but not opened (7h59 < 8)
|
||||
self.mock_event_online_dt.now.return_value = datetime(2020, 7, 6, 5, 59, 59)
|
||||
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 5, 59, 59)
|
||||
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 5, 59, 59)
|
||||
event.invalidate_cache(fnames=['is_ongoing'])
|
||||
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
|
||||
self.assertFalse(sponsor.is_in_opening_hours)
|
||||
self.assertTrue(event.is_ongoing)
|
||||
|
||||
# Evening event is not in opening hours (20 > 18)
|
||||
self.mock_event_online_dt.now.return_value = datetime(2020, 7, 6, 18, 0, 0)
|
||||
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 18, 0, 0)
|
||||
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 18, 0, 0)
|
||||
event.invalidate_cache(fnames=['is_ongoing'])
|
||||
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
|
||||
self.assertFalse(sponsor.is_in_opening_hours)
|
||||
self.assertTrue(event.is_ongoing)
|
||||
|
||||
# First day begins later
|
||||
self.mock_event_online_dt.now.return_value = datetime(2020, 7, 5, 6, 30, 0)
|
||||
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 5, 6, 30, 0)
|
||||
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 5, 6, 30, 0)
|
||||
event.invalidate_cache(fnames=['is_ongoing'])
|
||||
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
|
||||
self.assertFalse(sponsor.is_in_opening_hours)
|
||||
self.assertFalse(event.is_ongoing)
|
||||
|
||||
# End day finished sooner
|
||||
self.mock_event_online_dt.now.return_value = datetime(2020, 7, 7, 13, 0, 1)
|
||||
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 7, 13, 0, 1)
|
||||
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 7, 13, 0, 1)
|
||||
event.invalidate_cache(fnames=['is_ongoing'])
|
||||
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
|
||||
self.assertFalse(sponsor.is_in_opening_hours)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
<record id="event_event_view_form" model="ir.ui.view">
|
||||
<field name="name">event.event.view.form.inherit.exhibitor</field>
|
||||
<field name="inherit_id" ref="website_event_track_online.event_event_view_form"/>
|
||||
<field name="inherit_id" ref="website_event_track.event_event_view_form"/>
|
||||
<field name="model">event.event</field>
|
||||
<field name="priority" eval="3"/>
|
||||
<field name="arch" type="xml">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<record id="event_sponsor_view_search" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.search.inherit.exhibitor</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="inherit_id" ref="website_event_track_online.event_sponsor_view_search"/>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_view_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='archived']" position="after">
|
||||
<separator/>
|
||||
@@ -15,7 +15,7 @@
|
||||
<record id="event_sponsor_view_tree" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.tree.inherit.exhibitor</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="inherit_id" ref="website_event_track_online.event_sponsor_view_tree"/>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='sponsor_type_id']" position="after">
|
||||
<field name="is_published" optional="show"/>
|
||||
@@ -38,7 +38,7 @@
|
||||
<record id="event_sponsor_view_form" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.form.inherit.exhibitor</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="inherit_id" ref="website_event_track_online.event_sponsor_view_form"/>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//widget[@name='web_ribbon']" position="before">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
'website': 'https://www.odoo.com/page/events',
|
||||
'description': "",
|
||||
'depends': [
|
||||
'website_event_track_online',
|
||||
'website_event_track',
|
||||
'website_event_track_session',
|
||||
],
|
||||
'data': [
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
from odoo import http
|
||||
|
||||
from odoo.addons.website_event_track_online.controllers.event_track import EventTrackOnlineController
|
||||
from odoo.addons.website_event_track.controllers.event_track import EventTrackController
|
||||
|
||||
|
||||
class EventTrackLiveController(EventTrackOnlineController):
|
||||
class EventTrackLiveController(EventTrackController):
|
||||
|
||||
@http.route('/event_track/get_track_suggestion', type='json', auth='public', website=True)
|
||||
def get_next_track_suggestion(self, track_id):
|
||||
|
||||
@@ -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
|
||||
@@ -1,46 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
|
||||
{
|
||||
'name': 'Tracks Online',
|
||||
'category': 'Marketing/Events',
|
||||
'sequence': 1003,
|
||||
'version': '1.0',
|
||||
'summary': 'Bridge module to support Online Events Tracks',
|
||||
'website': 'https://www.odoo.com/page/events',
|
||||
'description': "",
|
||||
'depends': [
|
||||
'sms',
|
||||
'website_event',
|
||||
'website_event_track',
|
||||
],
|
||||
'data': [
|
||||
'data/event_sponsor_type_data.xml',
|
||||
'data/event_track_stage_data.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/assets.xml',
|
||||
'views/event_event_views.xml',
|
||||
'views/event_sponsor_views.xml',
|
||||
'views/event_sponsor_type_views.xml',
|
||||
'views/event_templates_registration.xml',
|
||||
'views/event_track_stage_views.xml',
|
||||
'views/event_track_templates_reminder.xml',
|
||||
'views/event_track_templates.xml',
|
||||
'views/event_track_templates_agenda.xml',
|
||||
'views/event_track_templates_reminder.xml',
|
||||
'views/event_track_views.xml',
|
||||
'views/event_track_tag_views.xml',
|
||||
'views/event_track_visitor_views.xml',
|
||||
'views/website_visitor_views.xml',
|
||||
'views/event_menus.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/event_sponsor_demo.xml',
|
||||
'data/event_track_demo.xml',
|
||||
'data/event_track_tag_demo.xml',
|
||||
'data/event_track_visitor_demo.xml',
|
||||
],
|
||||
'application': False,
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import event_track
|
||||
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data>
|
||||
|
||||
<record id="website_event_track.event_7_sponsor_0" model="event.sponsor">
|
||||
<field name="partner_id" ref="base.res_partner_1"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_1" model="event.sponsor">
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_2" model="event.sponsor">
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_3" model="event.sponsor">
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_4" model="event.sponsor">
|
||||
<field name="partner_id" ref="base.res_partner_10"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_5" model="event.sponsor">
|
||||
<field name="partner_id" ref="base.res_partner_12"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_6" model="event.sponsor">
|
||||
<field name="partner_id" ref="event.res_partner_event_1"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_7" model="event.sponsor">
|
||||
<field name="partner_id" ref="event.res_partner_event_2"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_8" model="event.sponsor">
|
||||
<field name="partner_id" ref="event.res_partner_event_3"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_sponsor_9" model="event.sponsor">
|
||||
<field name="partner_id" ref="event.res_partner_event_4"/>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data>
|
||||
|
||||
<record id="website_event_track.event_sponsor_type1" model="event.sponsor.type">
|
||||
<field name="display_ribbon_style">Bronze</field>
|
||||
</record>
|
||||
<record id="website_event_track.event_sponsor_type2" model="event.sponsor.type">
|
||||
<field name="display_ribbon_style">Silver</field>
|
||||
</record>
|
||||
<record id="website_event_track.event_sponsor_type3" model="event.sponsor.type">
|
||||
<field name="display_ribbon_style">Gold</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,90 +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="wishlisted_by_default" eval="True"/>
|
||||
<field name="partner_id" ref="base.res_partner_address_15"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_2" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_28"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_3" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_16"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_4" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_15"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_5" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_28"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_6" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_15"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_7" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_3"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_8" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_4"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_l3_1" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_31"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_l3_2" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_18"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_10" model="event.track">
|
||||
<field name="wishlisted_by_default" eval="True"/>
|
||||
<field name="partner_id" ref="base.res_partner_address_28"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_11" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_16"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_12" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_15"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_13" model="event.track">
|
||||
<field name="wishlisted_by_default" eval="True"/>
|
||||
<field name="partner_id" ref="base.res_partner_address_16"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_14" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_3"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_15" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_16"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_16" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_31"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_17" model="event.track">
|
||||
<field name="wishlisted_by_default" eval="True"/>
|
||||
<field name="partner_id" ref="base.res_partner_address_17"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_l3_10" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_31"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_l3_11" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_3"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_20" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_28"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_21" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_3"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_22" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_4"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_23" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_4"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_24" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_17"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_25" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_18"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_7_track_26" model="event.track">
|
||||
<field name="partner_id" ref="base.res_partner_address_17"/>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data noupdate="1">
|
||||
|
||||
<record id="website_event_track.event_track_stage2" model="event.track.stage">
|
||||
<field name="is_accepted" eval="True"/>
|
||||
</record>
|
||||
<record id="website_event_track.event_track_stage3" model="event.track.stage">
|
||||
<field name="is_accepted" eval="True"/>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data>
|
||||
|
||||
<record id="event_track_tag_category_1" model="event.track.tag.category">
|
||||
<field name="name">Audience</field>
|
||||
<field name="sequence">10</field>
|
||||
</record>
|
||||
<record id="event_track_tag_category_2" model="event.track.tag.category">
|
||||
<field name="name">Format</field>
|
||||
<field name="sequence">20</field>
|
||||
</record>
|
||||
|
||||
<record id="website_event_track.event_track_tag1" model="event.track.tag">
|
||||
<field name="category_id" ref="website_event_track_online.event_track_tag_category_1"/>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
<record id="website_event_track.event_track_tag2" model="event.track.tag">
|
||||
<field name="category_id" ref="website_event_track_online.event_track_tag_category_1"/>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
<record id="website_event_track.event_track_tag3" model="event.track.tag">
|
||||
<field name="category_id" ref="website_event_track_online.event_track_tag_category_1"/>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
<record id="website_event_track.event_track_tag11" model="event.track.tag">
|
||||
<field name="category_id" ref="website_event_track_online.event_track_tag_category_2"/>
|
||||
<field name="sequence">11</field>
|
||||
</record>
|
||||
<record id="website_event_track.event_track_tag12" model="event.track.tag">
|
||||
<field name="category_id" ref="website_event_track_online.event_track_tag_category_2"/>
|
||||
<field name="sequence">12</field>
|
||||
</record>
|
||||
<record id="website_event_track.event_track_tag13" model="event.track.tag">
|
||||
<field name="category_id" ref="website_event_track_online.event_track_tag_category_2"/>
|
||||
<field name="sequence">13</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import event_sponsor
|
||||
from . import event_sponsor_type
|
||||
from . import event_track_visitor
|
||||
from . import event_track
|
||||
from . import event_track_stage
|
||||
from . import event_track_tag
|
||||
from . import website
|
||||
from . import website_visitor
|
||||
@@ -1,62 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.modules.module import get_resource_path
|
||||
|
||||
|
||||
class Sponsor(models.Model):
|
||||
_name = 'event.sponsor'
|
||||
_inherit = ['event.sponsor']
|
||||
|
||||
# contact information
|
||||
name = fields.Char('Sponsor Name', compute='_compute_name', readonly=False, store=True)
|
||||
email = fields.Char('Sponsor Email', compute='_compute_email', readonly=False, store=True)
|
||||
phone = fields.Char('Sponsor Phone', compute='_compute_phone', readonly=False, store=True)
|
||||
mobile = fields.Char('Sponsor Mobile', compute='_compute_mobile', readonly=False, store=True)
|
||||
# image
|
||||
image_512 = fields.Image(
|
||||
string="Logo", max_width=512, max_height=512,
|
||||
compute='_compute_image_512', readonly=False, store=True)
|
||||
image_256 = fields.Image("Image 256", related="image_512", max_width=256, max_height=256, store=False)
|
||||
image_128 = fields.Image("Image 128", related="image_512", max_width=128, max_height=128, store=False)
|
||||
website_image_url = fields.Char(
|
||||
string='Image URL', max_width=256, max_height=256,
|
||||
compute='_compute_website_image_url', compute_sudo=True, store=False)
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_name(self):
|
||||
self._synchronize_with_partner('name')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_email(self):
|
||||
self._synchronize_with_partner('email')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_phone(self):
|
||||
self._synchronize_with_partner('phone')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_mobile(self):
|
||||
self._synchronize_with_partner('mobile')
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_image_512(self):
|
||||
self._synchronize_with_partner('image_512')
|
||||
|
||||
@api.depends('image_256', 'partner_id.image_256')
|
||||
def _compute_website_image_url(self):
|
||||
for sponsor in self:
|
||||
if sponsor.image_256:
|
||||
sponsor.website_image_url = self.env['website'].image_url(sponsor, 'image_256', size=256)
|
||||
elif sponsor.partner_id.image_256:
|
||||
sponsor.website_image_url = self.env['website'].image_url(sponsor.partner_id, 'image_256', size=256)
|
||||
else:
|
||||
sponsor.website_image_url = get_resource_path('website_event_track', 'static/src/img', 'event_sponsor_default_%d.png' % (sponsor.id % 1))
|
||||
|
||||
def _synchronize_with_partner(self, fname):
|
||||
""" Synchronize with partner if not set. Setting a value does not write
|
||||
on partner as this may be event-specific information. """
|
||||
for sponsor in self:
|
||||
if not sponsor[fname]:
|
||||
sponsor[fname] = sponsor.partner_id[fname]
|
||||
@@ -1,14 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class SponsorType(models.Model):
|
||||
_inherit = "event.sponsor.type"
|
||||
|
||||
display_ribbon_style = fields.Selection([
|
||||
('no_ribbon', 'No Ribbon'),
|
||||
('Gold', 'Gold'),
|
||||
('Silver', 'Silver'),
|
||||
('Bronze', 'Bronze')], string='Ribbon Style')
|
||||
@@ -1,201 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.osv import expression
|
||||
from odoo.tools.mail import is_html_empty
|
||||
from odoo.modules.module import get_resource_path
|
||||
|
||||
|
||||
class Track(models.Model):
|
||||
_name = "event.track"
|
||||
_inherit = ['event.track']
|
||||
|
||||
# status management
|
||||
is_accepted = fields.Boolean('Is Accepted', related='stage_id.is_accepted', readonly=True)
|
||||
# speaker
|
||||
partner_biography = fields.Html(
|
||||
string='Biography', compute='_compute_partner_biography',
|
||||
readonly=False, store=True)
|
||||
partner_function = fields.Char(
|
||||
'Job Position', related='partner_id.function',
|
||||
compute_sudo=True, readonly=True)
|
||||
partner_company_name = fields.Char(
|
||||
'Company Name', related='partner_id.parent_name',
|
||||
compute_sudo=True, readonly=True)
|
||||
image = fields.Image(
|
||||
string="Speaker Photo", compute="_compute_speaker_image",
|
||||
readonly=False, store=True,
|
||||
max_width=256, max_height=256)
|
||||
# frontend description
|
||||
website_image = fields.Image(string="Website Image", max_width=1024, max_height=1024)
|
||||
website_image_url = fields.Char(
|
||||
string='Image URL', compute='_compute_website_image_url',
|
||||
compute_sudo=True, store=False)
|
||||
# wishlist / visitors management
|
||||
event_track_visitor_ids = fields.One2many(
|
||||
'event.track.visitor', 'track_id', string="Track Visitors",
|
||||
groups="event.group_event_user")
|
||||
is_reminder_on = fields.Boolean('Is Reminder On', compute='_compute_is_reminder_on')
|
||||
wishlist_visitor_ids = fields.Many2many(
|
||||
'website.visitor', string="Visitor Wishlist",
|
||||
compute="_compute_wishlist_visitor_ids", compute_sudo=True,
|
||||
search="_search_wishlist_visitor_ids",
|
||||
groups="event.group_event_user")
|
||||
wishlist_visitor_count = fields.Integer(
|
||||
string="# Wishlisted",
|
||||
compute="_compute_wishlist_visitor_ids", compute_sudo=True,
|
||||
groups="event.group_event_user")
|
||||
wishlisted_by_default = fields.Boolean(
|
||||
string='Always Wishlisted',
|
||||
help="""If set, the talk will be starred for each attendee registered to the event. The attendee won't be able to un-star this talk.""")
|
||||
|
||||
# SPEAKER
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_partner_biography(self):
|
||||
for track in self:
|
||||
if not track.partner_biography:
|
||||
track.partner_biography = track.partner_id.website_description
|
||||
elif track.partner_id and is_html_empty(track.partner_biography) and \
|
||||
not is_html_empty(track.partner_id.website_description):
|
||||
track.partner_biography = track.partner_id.website_description
|
||||
|
||||
@api.depends('partner_id')
|
||||
def _compute_speaker_image(self):
|
||||
for track in self:
|
||||
if not track.image:
|
||||
track.image = track.partner_id.image_256
|
||||
|
||||
# FRONTEND DESCRIPTION
|
||||
|
||||
@api.depends('image', 'partner_id.image_256')
|
||||
def _compute_website_image_url(self):
|
||||
for track in self:
|
||||
if track.website_image:
|
||||
track.website_image_url = self.env['website'].image_url(track, 'website_image', size=1024)
|
||||
else:
|
||||
track.website_image_url = '/website_event_track/static/src/img/event_track_default_%d.jpeg' % (track.id % 2)
|
||||
|
||||
# WISHLIST / VISITOR MANAGEMENT
|
||||
|
||||
@api.depends('wishlisted_by_default', 'event_track_visitor_ids.visitor_id',
|
||||
'event_track_visitor_ids.partner_id', 'event_track_visitor_ids.is_wishlisted',
|
||||
'event_track_visitor_ids.is_blacklisted')
|
||||
@api.depends_context('uid')
|
||||
def _compute_is_reminder_on(self):
|
||||
current_visitor = self.env['website.visitor']._get_visitor_from_request(force_create=False)
|
||||
if self.env.user._is_public() and not current_visitor:
|
||||
for track in self:
|
||||
track.is_reminder_on = track.wishlisted_by_default
|
||||
else:
|
||||
if self.env.user._is_public():
|
||||
domain = [('visitor_id', '=', current_visitor.id)]
|
||||
elif current_visitor:
|
||||
domain = [
|
||||
'|',
|
||||
('partner_id', '=', self.env.user.partner_id.id),
|
||||
('visitor_id', '=', current_visitor.id)
|
||||
]
|
||||
else:
|
||||
domain = [('partner_id', '=', self.env.user.partner_id.id)]
|
||||
|
||||
event_track_visitors = self.env['event.track.visitor'].sudo().search_read(
|
||||
expression.AND([
|
||||
domain,
|
||||
[('track_id', 'in', self.ids)]
|
||||
]), fields=['track_id', 'is_wishlisted', 'is_blacklisted']
|
||||
)
|
||||
|
||||
wishlist_map = {
|
||||
track_visitor['track_id'][0]: {
|
||||
'is_wishlisted': track_visitor['is_wishlisted'],
|
||||
'is_blacklisted': track_visitor['is_blacklisted']
|
||||
} for track_visitor in event_track_visitors
|
||||
}
|
||||
for track in self:
|
||||
if wishlist_map.get(track.id):
|
||||
track.is_reminder_on = wishlist_map.get(track.id)['is_wishlisted'] or (track.wishlisted_by_default and not wishlist_map[track.id]['is_blacklisted'])
|
||||
else:
|
||||
track.is_reminder_on = track.wishlisted_by_default
|
||||
|
||||
@api.depends('event_track_visitor_ids.visitor_id', 'event_track_visitor_ids.is_wishlisted')
|
||||
def _compute_wishlist_visitor_ids(self):
|
||||
results = self.env['event.track.visitor'].read_group(
|
||||
[('track_id', 'in', self.ids), ('is_wishlisted', '=', True)],
|
||||
['track_id', 'visitor_id:array_agg'],
|
||||
['track_id']
|
||||
)
|
||||
visitor_ids_map = {result['track_id'][0]: result['visitor_id'] for result in results}
|
||||
for track in self:
|
||||
track.wishlist_visitor_ids = visitor_ids_map.get(track.id, [])
|
||||
track.wishlist_visitor_count = len(visitor_ids_map.get(track.id, []))
|
||||
|
||||
def _search_wishlist_visitor_ids(self, operator, operand):
|
||||
if operator == "not in":
|
||||
raise NotImplementedError("Unsupported 'Not In' operation on track wishlist visitors")
|
||||
|
||||
track_visitors = self.env['event.track.visitor'].sudo().search([
|
||||
('visitor_id', operator, operand),
|
||||
('is_wishlisted', '=', True)
|
||||
])
|
||||
return [('id', 'in', track_visitors.track_id.ids)]
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# CRUD
|
||||
# -----------------------------------------------------------
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
tracks = super(Track, self).create(vals_list)
|
||||
|
||||
for track in tracks:
|
||||
track._synchronize_with_stage(track.stage_id)
|
||||
|
||||
return tracks
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('stage_id'):
|
||||
stage = self.env['event.track.stage'].browse(vals['stage_id'])
|
||||
self._synchronize_with_stage(stage)
|
||||
return super(Track, self).write(vals)
|
||||
|
||||
def _synchronize_with_stage(self, stage):
|
||||
if stage.is_done:
|
||||
self.is_published = True
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TOOLS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _get_event_track_visitors(self, force_create=False):
|
||||
self.ensure_one()
|
||||
|
||||
force_visitor_create = self.env.user._is_public()
|
||||
visitor_sudo = self.env['website.visitor']._get_visitor_from_request(force_create=force_visitor_create)
|
||||
if visitor_sudo:
|
||||
visitor_sudo._update_visitor_last_visit()
|
||||
|
||||
if self.env.user._is_public():
|
||||
domain = [('visitor_id', '=', visitor_sudo.id)]
|
||||
elif visitor_sudo:
|
||||
domain = [
|
||||
'|',
|
||||
('partner_id', '=', self.env.user.partner_id.id),
|
||||
('visitor_id', '=', visitor_sudo.id)
|
||||
]
|
||||
else:
|
||||
domain = [('partner_id', '=', self.env.user.partner_id.id)]
|
||||
|
||||
track_visitors = self.env['event.track.visitor'].sudo().search(
|
||||
expression.AND([domain, [('track_id', 'in', self.ids)]])
|
||||
)
|
||||
missing = self - track_visitors.track_id
|
||||
if missing and force_create:
|
||||
track_visitors += self.env['event.track.visitor'].sudo().create([{
|
||||
'visitor_id': visitor_sudo.id,
|
||||
'partner_id': self.env.user.partner_id.id if not self.env.user._is_public() else False,
|
||||
'track_id': track.id,
|
||||
} for track in missing])
|
||||
|
||||
return track_visitors
|
||||
@@ -1,13 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class TrackStage(models.Model):
|
||||
_inherit = 'event.track.stage'
|
||||
|
||||
is_accepted = fields.Boolean(
|
||||
string='Accepted Stage',
|
||||
help='Accepted tracks are displayed in agenda views but not accessible.')
|
||||
is_done = fields.Boolean(help='Done tracks are automatically published so that they are available in frontend.')
|
||||
@@ -1,5 +0,0 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
event_track_visitor_access_all,event.track.visitor.access.all,model_event_track_visitor,,0,0,0,0
|
||||
event_track_visitor_access_manager,event.track.visitor.access.manager,model_event_track_visitor,event.group_event_manager,1,1,1,1
|
||||
event_track_tag_category_access_public,event.track.tag.category.access,model_event_track_tag_category,,1,0,0,0
|
||||
event_track_tag_category_access_manager,event.track.tag.category.access.manager,model_event_track_tag_category,event.group_event_manager,1,1,1,1
|
||||
|
@@ -1,13 +0,0 @@
|
||||
odoo.define('website_event_track_online.set_customize_options', function (require) {
|
||||
"use strict";
|
||||
|
||||
var EventSpecificOptions = require('website_event.set_customize_options').EventSpecificOptions;
|
||||
|
||||
EventSpecificOptions.include({
|
||||
xmlDependencies: (EventSpecificOptions.prototype.xmlDependencies || [])
|
||||
.concat([
|
||||
'/website_event_track_online/static/src/xml/website_event_customize_options.xml',
|
||||
]),
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="website_event_track.customize_options" t-extend="website_event.customize_options">
|
||||
<t t-jquery="a[name='display-showcase-talks']" t-operation="replace">
|
||||
</t>
|
||||
<t t-jquery="a[name='allow-talk-proposal']" t-operation="replace">
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import common
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="assets_frontend" inherit_id="website.assets_frontend" name="Event Track Online Assets Frontend">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website_event_track_online/static/src/scss/event_track_templates.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/website_event_track_online/static/src/scss/pwa_frontend.scss"/>
|
||||
</xpath>
|
||||
<xpath expr="//script[last()]" position="after">
|
||||
<script type="text/javascript" src="/website_event_track_online/static/src/js/event_track_reminder.js"></script>
|
||||
<script type="text/javascript" src="/website_event_track_online/static/src/js/website_event_customize_options.js"></script>
|
||||
<script type="text/javascript" src="/website_event_track_online/static/lib/idb-keyval/idb-keyval.js"/>
|
||||
<script type="text/javascript" src="/website_event_track_online/static/src/js/website_event_pwa_widget.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo><data>
|
||||
|
||||
<record id="event_event_view_form" model="ir.ui.view">
|
||||
<field name="name">event.event.view.from.inherit.track.online</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="inherit_id" ref="website_event.event_event_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='website_menu']" position="after">
|
||||
<label for="website_track" string="Showcase Tracks"/>
|
||||
<field name="website_track"/>
|
||||
<label for="website_track_proposal" string="Allow Track Proposals"/>
|
||||
<field name="website_track_proposal"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo><data>
|
||||
|
||||
<menuitem id="event_track_tag_category_menu"
|
||||
name="Track Tag Categories"
|
||||
action="event_track_tag_category_action"
|
||||
parent="event.menu_event_configuration"
|
||||
groups="base.group_no_one"
|
||||
sequence="33"/>
|
||||
|
||||
<menuitem id="event_track_visitor_menu"
|
||||
name="Track Visitors"
|
||||
sequence="38"
|
||||
action="event_track_visitor_action"
|
||||
parent="event.menu_event_configuration"
|
||||
groups="base.group_no_one"/>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="event_sponsor_type_view_tree" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.type.view.tree.inherit.online</field>
|
||||
<field name="model">event.sponsor.type</field>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_type_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='name']" position="after">
|
||||
<field name="display_ribbon_style"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_type_view_form" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.type.view.form.inherit.online</field>
|
||||
<field name="model">event.sponsor.type</field>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_type_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='name']" position="after">
|
||||
<field name="display_ribbon_style"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,68 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="event_sponsor_view_search" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.search.inherit.online</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_view_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<field name="phone"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_view_tree" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.tree.inherit.online</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//tree" position="attributes">
|
||||
<attribute name="multi_edit">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_id']" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<field name="phone"/>
|
||||
<field name="mobile"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_view_form" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.form.inherit.online</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="inherit_id" ref="website_event_track.event_sponsor_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='image_128']" position="replace">
|
||||
<field name="image_512" widget="image" class="oe_avatar"/>
|
||||
</xpath>
|
||||
<xpath expr="//h1//field[@name='partner_id']" position="replace">
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only" string="Sponsor Name"/>
|
||||
<h1><field name="name" placeholder="e.g. : OpenWood Decoration"/></h1>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='event_id']" position="after">
|
||||
<field name="partner_id" string="Partner"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_email']" position="replace">
|
||||
<field name="email" widget="email" string="Email"
|
||||
placeholder="e.g. : open.wood.decoration@example.com"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='url']" position="attributes">
|
||||
<attribute name="placeholder">e.g. : https://www.odoo.com</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_phone']" position="replace">
|
||||
<field name="phone" widget="phone" string="Phone" options="{'enable_sms': True}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_mobile']" position="replace">
|
||||
<field name="mobile" widget="phone" string="Mobile" options="{'enable_sms': True}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo><data>
|
||||
|
||||
<record id="event_track_stage_view_form" model="ir.ui.view">
|
||||
<field name="name">event.track.stage.view.form.inherit.online</field>
|
||||
<field name="model">event.track.stage</field>
|
||||
<field name="inherit_id" ref="website_event_track.event_track_stage_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='is_done']" position="before">
|
||||
<field name="is_accepted"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_stage_view_tree" model="ir.ui.view">
|
||||
<field name="name">event.track.stage.view.tree.inherit.online</field>
|
||||
<field name="model">event.track.stage</field>
|
||||
<field name="inherit_id" ref="website_event_track.event_track_stage_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='name']" position="after">
|
||||
<field name="is_accepted"/>
|
||||
<field name="is_done"/>
|
||||
<field name="is_cancel"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,69 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo><data>
|
||||
<record id="event_track_tag_category_view_form" model="ir.ui.view">
|
||||
<field name="name">event.track.tag.category.view.form</field>
|
||||
<field name="model">event.track.tag.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Track Tag Category">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="tag_ids" context="{'default_category_id': active_id}">
|
||||
<tree string="Tags" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_tag_category_view_list" model="ir.ui.view">
|
||||
<field name="name">event.track.tag.category.view.list</field>
|
||||
<field name="model">event.track.tag.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Track Tags Category">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_tag_category_action" model="ir.actions.act_window">
|
||||
<field name="name">Track Tag Categories</field>
|
||||
<field name="res_model">event.track.tag.category</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_tag_view_form" model="ir.ui.view">
|
||||
<field name="name">event.track.tag.view.form.inherit.online</field>
|
||||
<field name="model">event.track.tag</field>
|
||||
<field name="inherit_id" ref="website_event_track.view_event_track_tag_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='name']" position="after">
|
||||
<field name="color" widget="color_picker"/>
|
||||
<field name="category_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_tag_view_list" model="ir.ui.view">
|
||||
<field name="name">event.track.tag.view.list.inherit.online</field>
|
||||
<field name="model">event.track.tag</field>
|
||||
<field name="inherit_id" ref="website_event_track.view_event_track_tag_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='name']" position="before">
|
||||
<field name="sequence" widget="handle"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='name']" position="after">
|
||||
<field name="color" widget="color_picker"/>
|
||||
<field name="category_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Set original template for tracks / track as tracking visitors -->
|
||||
<record model="ir.ui.view" id="website_event_track.tracks">
|
||||
<field name="track" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="website_event_track.track_view">
|
||||
<field name="track" eval="True"/>
|
||||
</record>
|
||||
|
||||
<!-- 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_online.track_widget_reminder"/>
|
||||
</h3>
|
||||
</xpath>
|
||||
</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_online.track_widget_reminder"/>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Pimp agenda based on accepted / published -->
|
||||
<template id="agenda"
|
||||
name="Track Online: Agenda"
|
||||
inherit_id="website_event_track.agenda">
|
||||
<xpath expr="//t[@name='track_agenda_track_cell']" position="replace">
|
||||
<t t-if="track" name="track_agenda_track_cell">
|
||||
<t t-if="user_event_manager or track.is_published">
|
||||
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
|
||||
<span t-esc="track.name"/>
|
||||
</a>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span t-esc="track.name"/>
|
||||
</t>
|
||||
<div class="d-flex text-muted">
|
||||
<small t-esc="track.partner_name or track.partner_id.name"/>
|
||||
<span t-if="user_event_manager and not track.website_published" class=" ml-auto badge badge-danger">unpublished</span>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Pimp sponsor view -->
|
||||
<template id="event_sponsor"
|
||||
name="Track Online: Sponsors"
|
||||
inherit_id="website_event_track.event_sponsor">
|
||||
<xpath expr="//div[@t-if='event.sponsor_ids']" position="replace">
|
||||
<div class="container mt32 mb16 d-print-none" t-if="event.sponsor_ids">
|
||||
<div t-attf-class="d-flex flex-wrap mb-5 #{'' if (len(event.sponsor_ids) > 10) else 'justify-content-md-center'}">
|
||||
<t t-foreach="event.sponsor_ids" t-as="sponsor">
|
||||
<t t-if="sponsor.url">
|
||||
<a class="o_wevent_sponsor_card" target="_blank" t-att-href="sponsor.url">
|
||||
<div class="h-100 shadow-sm p-2">
|
||||
<span t-field="sponsor.image_128"
|
||||
t-options='{"widget": "image", "class": "img img-fluid"}'/>
|
||||
<div t-if="sponsor.sponsor_type_id.display_ribbon_style and sponsor.sponsor_type_id.display_ribbon_style != 'no_ribbon'" class="ribbon-wrapper">
|
||||
<div t-field="sponsor.sponsor_type_id" t-attf-class="ribbon ribbon_#{sponsor.sponsor_type_id.display_ribbon_style}"/>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</t>
|
||||
<t t-if="not sponsor.url">
|
||||
<div class="o_wevent_sponsor_card">
|
||||
<div class="h-100 shadow-sm p-2">
|
||||
<span t-field="sponsor.image_128"
|
||||
t-options='{"widget": "image", "class": "img img-fluid"}'/>
|
||||
<div t-if="sponsor.sponsor_type_id.display_ribbon_style and sponsor.sponsor_type_id.display_ribbon_style != 'no_ribbon'" class="ribbon-wrapper">
|
||||
<div t-field="sponsor.sponsor_type_id" t-attf-class="ribbon ribbon_#{sponsor.sponsor_type_id.display_ribbon_style}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -1,195 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Revamped agenda : Will need to replace agenda_online from website_event_track in master -->
|
||||
<template id="agenda_online" name="Track Online: Agenda">
|
||||
<t t-call="website_event.layout">
|
||||
<div class="o_wevent_online o_weagenda_index">
|
||||
<!-- Options -->
|
||||
<t t-set="option_track_wishlist" t-value="not event.is_done and request.website.viewref('website_event_track_online.agenda_topbar_wishlist').active"/>
|
||||
<!-- Topbar -->
|
||||
<t t-call="website_event_track_online.agenda_topbar"/>
|
||||
<!-- Drag/Drop Area -->
|
||||
<div class="oe_structure" id="oe_structure_website_event_track_agenda_1"/>
|
||||
<!-- Content -->
|
||||
<div class="container">
|
||||
<div class="row mb-5">
|
||||
<t t-call="website_event_track_online.agenda_main"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Drag/Drop Area -->
|
||||
<div class="oe_structure" id="oe_structure_website_event_track_agenda_2"/>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- TOPBAR: BASE NAVIGATION -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<!-- Main topbar -->
|
||||
<template id="agenda_topbar" name="Agenda 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_weagenda_topbar_filters o_wevent_index_topbar_filters nav">
|
||||
</ul>
|
||||
<div class="form-inline pl-sm-3 pr-0">
|
||||
<label class="invisible text-muted mr-2" id="search_summary"><span id="search_number" class="mr-1">0</span>Results</label>
|
||||
<input type="text" class="form-control" placeholder="Filter Tracks..." id="event_track_search"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<!-- Option: Tracks display: optional wishlist -->
|
||||
<template id="agenda_topbar_wishlist"
|
||||
inherit_id="website_event_track_online.agenda_topbar"
|
||||
name="Allow Wishlists"
|
||||
active="True"
|
||||
customize_show="True">
|
||||
<xpath expr="//ul[hasclass('o_weagenda_topbar_filters')]" position="inside">
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- CONTENT: MAIN TEMPLATES -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<!-- Agenda Main Display -->
|
||||
<template id="agenda_main" name="Tracks: Main Display">
|
||||
<!-- No tracks -->
|
||||
<div class="col-12" t-if="not tracks_by_days">
|
||||
<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>
|
||||
|
||||
<section t-else="" class="col-12" t-foreach="days" t-as="day">
|
||||
<!-- DAY HEADER -->
|
||||
<div class="o_we_track_day_header mt-3 w-100 d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex">
|
||||
<span class="h1 m-0 font-weight-bold" t-esc="day"
|
||||
t-options="{'widget': 'date', 'format': 'EEEE dd'}"/>
|
||||
<div class="d-flex flex-column ml-2">
|
||||
<span class="font-weight-bold" t-esc="day"
|
||||
t-options="{'widget': 'date', 'format': 'MMMM'}"/>
|
||||
<span class="font-weight-bold" t-esc="day"
|
||||
t-options="{'widget': 'date', 'format': 'YYYY'}"/>
|
||||
</div>
|
||||
</div>
|
||||
<small class="float-right text-muted align-self-end"><t t-esc="tracks_by_days[day]"/> tracks</small>
|
||||
</div>
|
||||
<hr class="mt-2 pb-1 mb-1"/>
|
||||
|
||||
<!-- Day Agenda -->
|
||||
<div class="o_we_online_agenda">
|
||||
<table id="table_search" class="table table-sm border-0">
|
||||
<!--Header-->
|
||||
<tr>
|
||||
<th class="border-0 bg-white position-sticky"/>
|
||||
<t t-foreach="locations" t-as="location">
|
||||
<th t-if="location" class="active text-center">
|
||||
<span t-esc="location and location.name or 'Unknown'"/>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
|
||||
<!-- Time Slots -->
|
||||
<t t-set="used_cells" t-value="[]"/>
|
||||
<t t-foreach="time_slots[day]" t-as="time_slot">
|
||||
<t t-set="is_round_hour" t-value="time_slot == time_slot.replace(minute=0)"/>
|
||||
<t t-set="is_half_hour" t-value="time_slot == time_slot.replace(minute=30)"/>
|
||||
|
||||
<tr t-att-class="'%s' % ('active' if is_round_hour else '')">
|
||||
<td class="active">
|
||||
<b t-if="is_round_hour" t-esc="time_slots[day][time_slot]['formatted_time']"/>
|
||||
</td>
|
||||
|
||||
<t t-foreach="locations" t-as="location">
|
||||
<t t-set="tracks" t-value="time_slots[day][time_slot].get(location, {})"/>
|
||||
<t t-if="tracks">
|
||||
<t t-foreach="tracks" t-as="track">
|
||||
<t t-if="track.location_id and track.location_id == location">
|
||||
<td t-att-rowspan="tracks[track]['rowspan']"
|
||||
t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''} o_location_size_#{len(locations)}">
|
||||
<t t-call="website_event_track_online.agenda_main_track"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<td t-att-colspan="len(locations)-1"
|
||||
t-att-rowspan="tracks[track]['rowspan']"
|
||||
t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''} o_location_size_#{len(locations)}">
|
||||
<t t-call="website_event_track_online.agenda_main_track"/>
|
||||
</td>
|
||||
</t>
|
||||
<t t-set="used_cells" t-value="used_cells + tracks[track]['occupied_cells']"/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-elif="location and (time_slot, location) not in used_cells">
|
||||
<td t-att-rowspan="1"
|
||||
t-att-class="'o_location_size_%s %s' % (len(locations),
|
||||
'o_we_agenda_time_slot_half' if is_half_hour else
|
||||
'o_we_agenda_time_slot_main' if is_round_hour else
|
||||
''
|
||||
)"><div/></td>
|
||||
</t>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<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="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>
|
||||
<small t-if="not track.stage_id.is_accepted" title="Not Accepted"
|
||||
class="ml-1 badge badge-danger o_wevent_online_badge_unpublished">Not Accepted</small>
|
||||
<span t-if="option_track_wishlist">
|
||||
<t t-call="website_event_track_online.track_widget_reminder">
|
||||
<t t-set="reminder_light" t-value="True"/>
|
||||
<t t-set="reminder_small" t-value="True"/>
|
||||
<t t-set="light_theme" t-value="False"/>
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="o_we_agenda_card_content d-flex flex-column justify-content-center my-1">
|
||||
<div t-att-class="'text-black' if track.website_published or user_event_manager else 'text-muted'"
|
||||
t-att-onclick="'window.location=\'/event/%s/track/%s\'' % (slug(event), slug(track))
|
||||
if track.website_published or user_event_manager else ''">
|
||||
<span class="o_we_agenda_card_title text-bold" t-esc="track.name"/>
|
||||
</div>
|
||||
<div class="text-muted text-center">
|
||||
<small t-if="track.partner_id or track.partner_name">
|
||||
<t t-esc="track.partner_id.sudo().name or track.partner_name"/></small>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-wrap">
|
||||
<t t-foreach="track.tag_ids" t-as="tag">
|
||||
<span t-if="tag.color" t-att-title="tag.name"
|
||||
t-attf-class="mr-1 mt-1 badge #{'o_tag_color_'+str(tag.color)}" t-esc="tag.name"
|
||||
t-attf-onclick="
|
||||
var value = '#{tag.name}' ;
|
||||
var target = $('#event_track_search');
|
||||
if (target.val() == value) { target.val(''); } else { target.val(value); }
|
||||
target.trigger('input');
|
||||
"
|
||||
/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -1,75 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="website_visitor_action_from_track" model="ir.actions.act_window">
|
||||
<field name="name">Visitors Wishlist</field>
|
||||
<field name="res_model">website.visitor</field>
|
||||
<field name="view_mode">kanban,tree,form,graph</field>
|
||||
<field name="domain">[('event_track_wishlisted_ids', 'in', [active_id])]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Wait for visitors to wishlist your tracks
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_view_search" model="ir.ui.view">
|
||||
<field name="name">event.track.view.search.inherit.event.track.online</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="inherit_id" ref="website_event_track.view_event_track_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='message_needaction']" position="after">
|
||||
<filter string="Always Wishlisted" name="filter_wishlisted_by_default" domain="[('wishlisted_by_default', '=', True)]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_view_tree" model="ir.ui.view" >
|
||||
<field name="name">event.track.view.tree.inherit.event.track.online</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="inherit_id" ref="website_event_track.view_event_track_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='event_id']" position="after">
|
||||
<field name="wishlisted_by_default" optional="hide"/>
|
||||
<field name="wishlist_visitor_count" optional="hide"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_view_form" model="ir.ui.view" >
|
||||
<field name="name">event.track.view.form.inherit.event.track.online</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="inherit_id" ref="website_event_track.view_event_track_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="active" position='after'>
|
||||
<field name="wishlisted_by_default"/>
|
||||
</field>
|
||||
<field name="is_published" position="before">
|
||||
<button name="%(website_event_track_online.website_visitor_action_from_track)d"
|
||||
type="action"
|
||||
class="oe_stat_button"
|
||||
icon="fa-bell">
|
||||
<field name="wishlist_visitor_count" string="Wishlisted By" widget="statinfo"/>
|
||||
</button>
|
||||
</field>
|
||||
<xpath expr="//field[@name='image']" position="replace">
|
||||
<field name="website_image" widget="image" class="oe_avatar"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_biography']" position="after">
|
||||
<field name="image" widget="image" class="oe_avatar float-left"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_action_from_visitor" model="ir.actions.act_window">
|
||||
<field name="name">Wishlisted Tracks</field>
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="domain">[('wishlist_visitor_ids', 'in', [active_id])]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
No track wishlisted by this visitor
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -4,7 +4,7 @@
|
||||
<record id="event_track_visitor_view_search" model="ir.ui.view" >
|
||||
<field name="name">event.track.visitor.view.search.inherit.quiz</field>
|
||||
<field name="model">event.track.visitor</field>
|
||||
<field name="inherit_id" ref="website_event_track_online.event_track_visitor_view_search"/>
|
||||
<field name="inherit_id" ref="website_event_track.event_track_visitor_view_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='is_wishlisted']" position="after">
|
||||
<field name="quiz_completed"/>
|
||||
@@ -15,7 +15,7 @@
|
||||
<record id="event_track_visitor_view_form" model="ir.ui.view">
|
||||
<field name="name">event.track.visitor.view.form.inherit.quiz</field>
|
||||
<field name="model">event.track.visitor</field>
|
||||
<field name="inherit_id" ref="website_event_track_online.event_track_visitor_view_form"/>
|
||||
<field name="inherit_id" ref="website_event_track.event_track_visitor_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='is_wishlisted']" position="after">
|
||||
<field name="quiz_completed"/>
|
||||
@@ -27,7 +27,7 @@
|
||||
<record id="event_track_visitor_view_list" model="ir.ui.view">
|
||||
<field name="name">event.track.visitor.view.list.inherit.quiz</field>
|
||||
<field name="model">event.track.visitor</field>
|
||||
<field name="inherit_id" ref="website_event_track_online.event_track_visitor_view_list"/>
|
||||
<field name="inherit_id" ref="website_event_track.event_track_visitor_view_list"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='is_wishlisted']" position="after">
|
||||
<field name="quiz_completed"/>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
'website': 'https://www.odoo.com/page/events',
|
||||
'description': "",
|
||||
'depends': [
|
||||
'website_event_track_online',
|
||||
'website_event_track',
|
||||
],
|
||||
'data': [
|
||||
'views/assets.xml',
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
|
||||
from ast import literal_eval
|
||||
from pytz import timezone, utc
|
||||
from werkzeug.exceptions import Forbidden, NotFound
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from odoo import fields, http, _
|
||||
from odoo.addons.website_event_track_online.controllers.event_track import EventTrackOnlineController
|
||||
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(EventTrackOnlineController):
|
||||
class WebsiteEventSessionController(EventTrackController):
|
||||
|
||||
def _get_event_tracks_base_domain(self, event):
|
||||
""" Base domain for displaying tracks. Restrict to accepted or published
|
||||
|
||||
@@ -6,7 +6,7 @@ from unittest.mock import patch
|
||||
|
||||
from odoo import fields
|
||||
from odoo.addons.website.models.website_visitor import WebsiteVisitor
|
||||
from odoo.addons.website_event_track_online.tests.common import TestEventTrackOnlineCommon
|
||||
from odoo.addons.website_event_track.tests.common import TestEventTrackOnlineCommon
|
||||
|
||||
|
||||
class TestTrackSuggestions(TestEventTrackOnlineCommon):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
|
||||
<template id="agenda_main_track" name="Track Agenda: Track (Session)"
|
||||
inherit_id="website_event_track_online.agenda_main_track">
|
||||
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
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
t-esc="track.date"
|
||||
t-options="{'widget': 'datetime', 'time_only': True, 'format': 'short'}"/>
|
||||
<t t-if="option_track_wishlist"
|
||||
t-call="website_event_track_online.track_widget_reminder">
|
||||
t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_small" t-value="True"/>
|
||||
</t>
|
||||
</t>
|
||||
@@ -268,7 +268,7 @@
|
||||
<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_online.track_widget_reminder">
|
||||
<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>
|
||||
@@ -277,7 +277,7 @@
|
||||
<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_online.track_widget_reminder">
|
||||
<t t-call="website_event_track.track_widget_reminder">
|
||||
<t t-set="reminder_light" t-value="True"/>
|
||||
</t>
|
||||
</span>
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
<field name="active" eval="False"/>
|
||||
<field name="customize_show" eval="False"/>
|
||||
</record>
|
||||
<record id="website_event_track_online.tracks_wishlist" model="ir.ui.view">
|
||||
<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_online.track_view_wishlist" model="ir.ui.view">
|
||||
<record id="website_event_track.track_view_wishlist" model="ir.ui.view">
|
||||
<field name="active" eval="False"/>
|
||||
<field name="customize_show" eval="False"/>
|
||||
</record>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
<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_online.track_widget_reminder">
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user