[REF] website_event, *: review event design and features

* event, website_event_questions, website_event_sale,
  website_event_track, base

Part of https://github.com/odoo/odoo/pull/37009
task-2043872

Co-authored-by: qsm-odoo <qsm@odoo.com>
Co-authored-by: Jérémy Kersten <jke@odoo.com>
This commit is contained in:
Cocographique
2019-09-27 13:36:37 +00:00
committed by qsm-odoo
co-authored by qsm-odoo Jérémy Kersten
parent fdd0724636
commit f402afd7b5
28 changed files with 1443 additions and 1058 deletions
+60 -70
View File
@@ -2,10 +2,10 @@
<odoo>
<data>
<record id="base.user_demo" model="res.users">
<field name="groups_id" eval="[(4, ref('event.group_event_user'))]"/>
<field name="groups_id" eval="[(4, ref('event.group_event_user'))]"/>
</record>
<!-- Demo Data for Event Type -->
<!-- Event Type -->
<record id="event_type_0" model="event.type">
<field name="name">Seminar</field>
</record>
@@ -26,7 +26,11 @@
<field name="name">Training</field>
</record>
<!-- event.event -->
<record id="event_type_5" model="event.type">
<field name="name">Sport</field>
</record>
<!-- Event -->
<record id="event_0" model="event.event">
<field name="name">Design Fair Los Angeles</field>
<field name="user_id" ref="base.user_admin"/>
@@ -36,41 +40,16 @@
<field name="seats_max">500</field>
<field name="address_id" ref="base.res_partner_1"/>
<field name="event_type_id" ref="event_type_1"/>
<field name="description"><![CDATA[
<div class="oe_structure">
<center><strong>Join us to our main event of the year: the Design Fair</strong></center>
<p>&nbsp;</p>
<p>Every year we invite our community, partners and end-users to come and meet us! It's the ideal event to get together and present new features, roadmap of future versions, achievements of the software, workshops, training sessions, etc.... This event is also an opportunity to showcase our partners' case studies, methodology or developments. Be there and see directly from the source the features of the version 8!
</p>
<p>This event and all the conferences are in english!</p>
<p>&nbsp;</p>
<p><strong>What's new for this year?</strong></p>
<ul>
<li>The Design Fair is preceded by 2 days of optional training sessions for experts! We propose 3 different training sessions, 2 days each.</li>
<li>The whole event is open to all public! We ask a participation fee of 49.50€ for the costs for the 3 days (morning coffee, coffee breaks, drinks, sandwiches for lunch and the surprising beer party of Wednesday evening) but it's optional. For those who do not want to contribute, there is a free ticket, therefore, catering is not inclued.</li>
<li>The plenary sessions in the morning will be shorter and we will give more time for thematical meetings, conferences, workshops and tutorial sessions in the afternoon.</li>
</ul>
<p>&nbsp;</p>
<p><strong>Program:</strong></p>
<p>Conferences, workshops and trainings will be organized in 6 rooms:</p>
<ul>
<li>2 technical rooms: one dedicated to advanced Odoo developers, one for new developers.</li>
<li>2 technical rooms: one dedicated to advanced Odoo developers, one for new developers.</li>
<li>1 business room: to discuss implementation methodologies, best sales practices, etc.</li>
<li>1 workshop room: mainly for developers.</li>
</ul>
<p><em>If you wish to make a presentation, please send your topic proposal as soon as possible for approval to Mr. Famke Jenssens at ngh (a) yourcompany (dot) com. The presentations should be, for example, a presentation of a community module, a case study, methodology feedback, technical, etc. Each presentation must be in English.</em></p>
<p>&nbsp;</p>
<p><strong>Where to find us:</strong></p>
<p>OpenElec Applications 23 Rockwell Lane, Los Angeles, CA 90001, United States</p>
<p>For any additional information, please contact us at <a href="mailto:events@yourcompany.com">events@yourcompany.com</a>.</p>
<p>&nbsp;</p>
<p>Best regards,</p>
<p>Luigi Roni, Senior Event Manager</p>
<p>&nbsp;</p>
<p align="RIGHT"><em>(OpenElec Applications reserves the right to cancel, re-name or re-locate<br/>the event or change the dates on which it is held.)</em></p>
</div>
]]></field>
</record>
<record id="event.event_1" model="event.event">
<field name="name">Great Reno Ballon Race</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="(DateTime.today()+ timedelta(days=100)).strftime('%Y-%m-%d 20:15:00')" name="date_begin"/>
<field eval="(DateTime.today()+ timedelta(days=101)).strftime('%Y-%m-%d 00:30:00')" name="date_end"/>
<field name="event_type_id" ref="event_type_1"/>
<field name="address_id" ref="base.res_partner_1"/>
<field name="seats_availability">unlimited</field>
</record>
<record id="event_2" model="event.event">
@@ -82,43 +61,54 @@
<field name="address_id" ref="base.res_partner_4"/>
<field name="seats_availability">limited</field>
<field name="seats_max">200</field>
<field name="description"><![CDATA[
<div class="oe_structure">
<center><strong>Conference for Architects</strong></center>
<p>&nbsp;</p>
<p> During this conference, our team will give a detailed overview of our business applications. You’ll know all the benefits of using it.</p>
<p>&nbsp;</p>
<p><strong>Objectives:</strong></p>
<p>Having attended this conference, participants should be able to:</p>
<ul>
<li>Understand the various modules;</li>
<li>Functional flow of the main applications;</li>
</ul>
<p>&nbsp;</p>
<p><strong>Program:</strong></p>
<ul>
<li>Introduction, CRM, Sales Management</li>
<li>Purchase, Sales & Purchase management, Financial accounting.</li>
<li>Project management, Human resources, Contract management.</li>
<li>Warehouse management, Manufacturing (MRP) & Sales, Import/Export.</li>
<li>Point of Sale (POS), Introduction to report customization.</li>
</ul>
<p>&nbsp;</p>
<p><strong>Where to find us:</strong></p>
<p>Chamber Works 60, Rosewood Court Detroit, MI 48212 (United States)</p>
<p>For any additional information, please contact us at <a href="mailto:events@odoo.com">events@odoo.com</a>.</p>
<p>&nbsp;</p>
<p>Best regards,</p>
<p>Luigi Roni, Senior Event Manager</p>
<p>&nbsp;</p>
<p align="RIGHT"><em>(Chamber Works reserves the right to cancel, re-name or re-locate<br/>the event or change the dates on which it is held.)</em></p>
</div>
]]></field>
</record>
<record id="event.event_3" model="event.event">
<field name="name">Live Music Festival</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="(DateTime.today()+ timedelta(days=130)).strftime('%Y-%m-%d 20:15:00')" name="date_begin"/>
<field eval="(DateTime.today()+ timedelta(days=133)).strftime('%Y-%m-%d 00:30:00')" name="date_end"/>
<field name="event_type_id" ref="event_type_3"/>
<field name="address_id" ref="base.res_partner_3"/>
<field name="seats_availability">unlimited</field>
</record>
<record id="event.event_4" model="event.event">
<field name="name">Business workshops</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="(DateTime.today()+ timedelta(days=50)).strftime('%Y-%m-%d 18:00:00')" name="date_begin"/>
<field eval="(DateTime.today()+ timedelta(days=50)).strftime('%Y-%m-%d 22:30:00')" name="date_end"/>
<field name="event_type_id" ref="event_type_4"/>
<field name="address_id" ref="base.res_partner_4"/>
</record>
<record id="event.event_5" model="event.event">
<field name="name">Hockey Tournament</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="(DateTime.today()+ timedelta(days=370)).strftime('%Y-%m-%d 09:00:00')" name="date_begin"/>
<field eval="(DateTime.today()+ timedelta(days=371)).strftime('%Y-%m-%d 17:00:00')" name="date_end"/>
<field name="event_type_id" ref="event_type_5"/>
<field name="address_id" ref="base.res_partner_1"/>
</record>
<record id="event.event_6" model="event.event">
<field name="name">An unpublished event</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="(DateTime.today()+ timedelta(days=30)).strftime('%Y-%m-%d 09:30:00')" name="date_begin"/>
<field eval="(DateTime.today()+ timedelta(days=30)).strftime('%Y-%m-%d 17:30:00')" name="date_end"/>
<field name="event_type_id" ref="event_type_1"/>
<field name="address_id" ref="base.res_partner_1"/>
</record>
<function model="event.event" name="button_confirm" eval="[ref('event_0')]"/>
<function model="event.event" name="button_confirm" eval="[ref('event_1')]"/>
<function model="event.event" name="button_confirm" eval="[ref('event_2')]"/>
<function model="event.event" name="button_confirm" eval="[ref('event_3')]"/>
<function model="event.event" name="button_confirm" eval="[ref('event_4')]"/>
<function model="event.event" name="button_confirm" eval="[ref('event_5')]"/>
<function model="event.event" name="button_confirm" eval="[ref('event_6')]"/>
<!-- Attendee -->
<record id="reg_2_0" model="event.registration">
<field name="name">Camptocamp</field>
<field name="email">odoo@camptocamp.com</field>
+9
View File
@@ -157,6 +157,7 @@ class EventEvent(models.Model):
tracking=True, states={'done': [('readonly', True)]})
date_begin_located = fields.Char(string='Start Date Located', compute='_compute_date_begin_tz')
date_end_located = fields.Char(string='End Date Located', compute='_compute_date_end_tz')
is_one_day = fields.Boolean(compute='_compute_field_is_one_day')
state = fields.Selection([
('draft', 'Unconfirmed'), ('cancel', 'Cancelled'),
@@ -234,6 +235,14 @@ class EventEvent(models.Model):
else:
event.date_end_located = False
@api.depends('date_begin', 'date_end', 'date_tz')
def _compute_field_is_one_day(self):
for event in self:
# Need to localize because it could begin late and finish early in
# another timezone
event = event.with_context(tz=event.date_tz)
event.is_one_day = (event.date_begin.date() == event.date_end.date())
@api.onchange('is_online')
def _onchange_is_online(self):
if self.is_online:
+10 -1
View File
@@ -18,7 +18,16 @@
<field name="price">1500.0</field>
<field name="seats_max">10</field>
</record>
<record id="event_4_ticket_1" model="event.event.ticket">
<field name="name">General Admission</field>
<field name="event_id" ref="event.event_4"/>
<field name="product_id" ref="product_product_event"/>
<field name="deadline" eval="(DateTime.today() + timedelta(30)).strftime('%Y-%m-%d')"/>
<field name="price">99.0</field>
<field name="seats_max">100</field>
</record>
<record id="event_2_ticket_1" model="event.event.ticket">
<field name="name">Standard</field>
<field name="event_id" ref="event.event_2"/>
+11 -11
View File
@@ -292,22 +292,22 @@
</template>
<template id="s_share" name="Share">
<div t-attf-class="s_share #{_classes or ''}">
<div t-attf-class="s_share #{_classes}">
<h4 t-if="not _no_title" class="s_share_title">Share</h4>
<a href="https://www.facebook.com/sharer/sharer.php?u={url}" class="s_share_facebook" target="_blank">
<i class="fa fa-1x fa-facebook rounded shadow-sm"/>
<a href="https://www.facebook.com/sharer/sharer.php?u={url}" t-attf-class="s_share_facebook #{_link_classes}" target="_blank">
<i t-attf-class="fa fa-1x fa-facebook #{not _link_classes and 'rounded shadow-sm'}"/>
</a>
<a href="https://twitter.com/intent/tweet?text={title}&amp;url={url}" class="s_share_twitter" target="_blank">
<i class="fa fa-1x fa-twitter rounded shadow-sm"/>
<a href="https://twitter.com/intent/tweet?text={title}&amp;url={url}" t-attf-class="s_share_twitter #{_link_classes}" target="_blank">
<i t-attf-class="fa fa-1x fa-twitter #{not _link_classes and 'rounded shadow-sm'}"/>
</a>
<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url={url}&amp;title={title}&amp;" class="s_share_linkedin" target="_blank">
<i class="fa fa-1x fa-linkedin rounded shadow-sm"/>
<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url={url}&amp;title={title}&amp;" t-attf-class="s_share_linkedin #{_link_classes}" target="_blank">
<i t-attf-class="fa fa-1x fa-linkedin #{not _link_classes and 'rounded shadow-sm'}"/>
</a>
<a href="https://plus.google.com/share?url={url}" class="s_share_google" target="_blank">
<i class="fa fa-1x fa-google-plus rounded shadow-sm"/>
<a href="https://plus.google.com/share?url={url}" t-attf-class="s_share_google #{_link_classes}" target="_blank">
<i t-attf-class="fa fa-1x fa-google-plus #{not _link_classes and 'rounded shadow-sm'}"/>
</a>
<a href="mailto:?body={url}&amp;subject={title}" class="s_share_email">
<i class="fa fa-1x fa-envelope rounded shadow-sm"/>
<a href="mailto:?body={url}&amp;subject={title}" t-attf-class="s_share_email #{_link_classes}">
<i t-attf-class="fa fa-1x fa-envelope #{not _link_classes and 'rounded shadow-sm'}"/>
</a>
</div>
</template>
+16 -4
View File
@@ -10,6 +10,7 @@ from dateutil.relativedelta import relativedelta
from odoo import fields, http, _
from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.website.controllers.main import QueryURL
from odoo.http import request
@@ -24,6 +25,7 @@ class WebsiteEventController(http.Controller):
Event = request.env['event.event']
EventType = request.env['event.type']
searches.setdefault('search', '')
searches.setdefault('date', 'all')
searches.setdefault('type', 'all')
searches.setdefault('country', 'all')
@@ -65,6 +67,10 @@ class WebsiteEventController(http.Controller):
# search domains
domain_search = {'website_specific': website.website_domain()}
if searches['search']:
domain_search['search'] = [('name', 'ilike', searches['search'])]
current_date = None
current_type = None
current_country = None
@@ -73,6 +79,7 @@ class WebsiteEventController(http.Controller):
domain_search["date"] = date[2]
if date[0] != 'all':
current_date = date[1]
if searches["type"] != 'all':
current_type = EventType.browse(int(searches['type']))
domain_search["type"] = [("event_type_id", "=", int(searches["type"]))]
@@ -113,7 +120,7 @@ class WebsiteEventController(http.Controller):
event_count = Event.search_count(dom_without("none"))
pager = website.pager(
url="/event",
url_args={'date': searches.get('date'), 'type': searches.get('type'), 'country': searches.get('country')},
url_args=searches,
total=event_count,
page=page,
step=step,
@@ -127,6 +134,8 @@ class WebsiteEventController(http.Controller):
order = 'is_published desc, ' + order
events = Event.search(dom_without("none"), limit=step, offset=pager['offset'], order=order)
keep = QueryURL('/event', **{key: value for key, value in searches.items() if (key == 'search' or value != 'all')})
values = {
'current_date': current_date,
'current_country': current_country,
@@ -137,7 +146,7 @@ class WebsiteEventController(http.Controller):
'countries': countries,
'pager': pager,
'searches': searches,
'search_path': "?%s" % werkzeug.url_encode(searches),
'keep': keep,
}
if searches['date'] == 'old':
@@ -188,11 +197,14 @@ class WebsiteEventController(http.Controller):
if not event.can_access_from_current_website():
raise werkzeug.exceptions.NotFound()
urls = event._get_event_resource_urls()
values = {
'event': event,
'main_object': event,
'range': range,
'registrable': event.sudo()._is_event_registrable()
'registrable': event.sudo()._is_event_registrable(),
'google_url': urls.get('google_url'),
'iCal_url': urls.get('iCal_url'),
}
return request.render("website_event.event_description_full", values)
@@ -282,7 +294,7 @@ class WebsiteEventController(http.Controller):
Attendees += Attendees.sudo().create(
Attendees._prepare_attendee_values(registration))
urls = event._get_event_resource_urls(Attendees.ids)
urls = event._get_event_resource_urls()
return request.render("website_event.registration_complete", {
'attendees': Attendees.sudo(),
'event': event,
+127 -171
View File
@@ -1,188 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="base.res_partner_1" model="res.partner">
<field name="is_published">True</field>
</record>
<record id="event.event_0" model="event.event">
<field name="is_published">True</field>
<field name="twitter_hashtag">odoo</field>
<field name="description"><![CDATA[
<section class="s_cover parallax s_parallax_is_fixed pt96 pb96" data-scroll-background-ratio="1">
<span class="s_parallax_bg oe_img_bg oe_custom_bg" style="background-image: url('/web/image/website.s_background_image_02'); background-position: 50% 100%;"/>
<div class="container">
<div class="row s_nb_column_fixed">
<div class="col-lg-12 s_title bg-black-50" data-name="Title">
<h1 class="s_title_thin" style="font-size: 62px; text-align: center;">5 Intensive Days</h1>
<h4 class="text-muted" style="text-align: center;"><font style="color: rgb(255, 255, 255); font-size: 24px;">to learn <i>Odoo Programming</i></font></h4>
<record id="event.event_0" model="event.event">
<field name="is_published">True</field>
<field name="twitter_hashtag">DesignFair</field>
<field name="subtitle">Get Inspired • Stay Connected • Have Fun</field>
<field name="cover_properties">{"background-image": "url('/website_event/static/src/img/event_cover_0.jpg')", "background-color": "oe_black", "resize_class": "o_record_has_cover cover_mid", "opacity": "0.4"}</field>
<field name="description"><![CDATA[
<div class="oe_structure">
<h5>Join us for this 3-day Event</h5>
<p class="lead mb-3">Every year we invite our community, partners and end-users to come and meet us! It's the ideal event to get together and present new features, roadmap of future versions, achievements of the software, workshops, training sessions, etc....</p>
<p class="mb-3">This event is also an opportunity to showcase our partners' case studies, methodology or developments. Be there and see directly from the source the features of the version 12!
</p>
<div class="bg-light rounded-right border-left border-secondary p-3 mb-5" style="border-left-width: 3px !important;">
<p class="mb-0"><i class="fa fa-info-circle mr-2"/>This event and all the conferences are in <b>English</b>!</p>
</div>
<h5 class="mb-2">What's new?</h5>
<ul class="mb-5">
<li class="mb-2"><b>The Design Fair is preceded by 2 days of Training Sessions for experts!</b><br/> We propose 3 different training sessions, 2 days each.</li>
<li class="mb-2"><b>The whole event is open to all public!</b> <br/>We ask a participation fee of 49.50€ for the costs for the 3 days (coffee breaks, catering, drinks and a surprising concert and beer party).<br/> For those who don't want to contribute, there is a free ticket, therefore, catering and access to evening events aren't included.</li>
<li class="mb-2"><b>The plenary sessions in the morning will be shorter</b> and we will give more time for thematical meetings, conferences, workshops and tutorial sessions in the afternoon.</li>
</ul>
<h5 class="mb-2">Program</h5>
<p>Conferences, workshops and trainings will be organized in 6 rooms:</p>
<ul class="mb-5">
<li><b>Technical Rooms</b> - One dedicated to advanced Odoo developers, one for new developers.</li>
<li><b>Technical Rooms</b> - One dedicated to advanced Odoo developers, one for new developers.</li>
<li><b>Business Room</b> - To discuss implementation methodologies, best sales practices, etc.</li>
<li><b>Workshop Room</b> - Mainly for developers.</li>
</ul>
<div class="bg-light rounded-right border-left border-secondary p-3 mb-3" style="border-left-width: 3px !important;">
<p class="mb-0">If you wish to make a presentation, please send your topic proposal as soon as possible for approval to Mr. Famke Jenssens at ngh (a) yourcompany (dot) com. The presentations should be, for example, a presentation of a community module, a case study, methodology feedback, technical, etc. Each presentation must be in English.</em></p>
</div>
<p class="mb-3">For any additional information, please contact us at <a href="mailto:events@yourcompany.com">events@yourcompany.com</a>.</p>
<div class="bg-light rounded-right border-left border-secondary p-3 mb-5" style="border-left-width: 3px !important;">
<p class="mb-0">OpenElec Applications reserves the right to cancel, re-name or re-locate the event or change the dates on which it is held.</p>
</div>
</div>
]]></field>
</record>
<record id="event.event_1" model="event.event">
<field name="website_menu">True</field>
<field name="website_published">True</field>
<field name="subtitle">The Great Reno Balloon Race is the world's largest free hot-air ballooning event.</field>
<field name="twitter_hashtag">RenoRace</field>
<field name="cover_properties">{"background-image": "url('/website_event/static/src/img/event_cover_1.jpg')", "background-color": "oe_black", "resize_class": "o_record_has_cover cover_mid", "opacity": "0.4"}</field>
</record>
<record id="event.event_2" model="event.event">
<field name="website_published">True</field>
<field name="subtitle">Enhance your architectural business and improve professional skills.</field>
<field name="twitter_hashtag">odoo</field>
<field name="cover_properties">{"background-image": "url('/website_event/static/src/img/event_cover_2.jpg')", "background-color": "oe_black", "resize_class": "o_record_has_cover cover_mid", "opacity": "0.4"}</field>
<field name="description"><![CDATA[
<div class="oe_structure">
<h5>Conference for Architects</h5>
<p class="lead">During this conference, our team will give a detailed overview of our business applications. You’ll know all the benefits of using it.</p>
<h6>Objectives</h6>
<p>Having attended this conference, participants should be able to:</p>
<ul class="mb-4">
<li>Understand the various modules;</li>
<li>Functional flow of the main applications;</li>
</ul>
<h6>Program</h6>
<ul class="mb-4">
<li>Introduction, CRM, Sales Management</li>
<li>Purchase, Sales &amp; Purchase management, Financial accounting.</li>
<li>Project management, Human resources, Contract management.</li>
<li>Warehouse management, Manufacturing (MRP) &amp; Sales, Import/Export.</li>
<li>Point of Sale (POS), Introduction to report customization.</li>
</ul>
<p>For any additional information, please contact us at <a href="mailto:events@odoo.com">events@odoo.com</a></p>
<section class="s_we_speaker bg-200 p-3 mb-4" itemscope="itemscope" itemtype="http://schema.org/Person" itemprop="performer">
<span class="badge badge-secondary o_wevent_badge float-right">SPEAKER</span>
<img src="/mail/static/src/img/odoobot.png" width="70" class="img-fluid rounded-circle float-left mr-3" alt=""/>
<div class="overflow-hidden">
<h4 class="mt-3 mb-1" itemprop="name">John DOE</h4>
<h6 class="mb-4">Company</h6>
<p>At just 13 years old, John DOE was already starting to develop his first business applications for customers. After mastering civil engineering, he founded TinyERP. This was the first phase of OpenERP which would later became Odoo, the most installed open-source business software worldwide.</p>
</div>
</section>
<div class="alert alert-info">
<p class="mb-0">Chamber Works reserves the right to cancel, re-name or re-locate the event or change the dates on which it is held.</p>
</div>
</section>
<div class="container">
<div class="text-center mt-5">
<h2>Course Summary</h2>
</div>
]]></field>
</record>
<div class="my-3">
<p><span style="text-align: -webkit-center; ">This course is dedicated to&nbsp;developers who need to grasp knowledge of the <strong>business applications development </strong>process. This course is for new developers or for IT professionals eager to learn more about technical aspects.</span></p>
</div>
</div>
<record id="event.event_3" model="event.event">
<field name="website_published">True</field>
<field name="subtitle">Experience live music, local food and beverages.</field>
<field name="twitter_hashtag">odoo</field>
<field name="cover_properties">{"background-image": "url('/website_event/static/src/img/event_cover_3.jpg')", "background-color": "oe_black", "resize_class": "o_record_has_cover cover_mid", "opacity": "0.4"}</field>
</record>
<div class="container">
<div class="row">
<div class="col-lg-12 text-center mt-5 mb-2">
<h2>What you will learn?</h2>
</div>
<record id="event.event_4" model="event.event">
<field name="website_published">True</field>
<field name="subtitle">Discover how to grow a sustainable business with our experts.</field>
<field name="twitter_hashtag">odoo</field>
<field name="cover_properties">{"background-image": "url('/website_event/static/src/img/event_cover_4.jpg')", "background-color": "oe_black", "resize_class": "o_record_has_cover cover_mid", "opacity": "0.4"}</field>
</record>
<div class="col-lg-4 mb-4">
<div class="card bg-info">
<div class="card-header text-center">
<h2>Day 1</h2>
<record id="event.event_5" model="event.event">
<field name="website_published">True</field>
<field name="subtitle">Bring your outdoor field hockey season to the next level by taking the field at this 9th annual Field Hockey tournament.</field>
<field name="twitter_hashtag">odoo</field>
<field name="cover_properties">{"background-image": "url('/website_event/static/src/img/event_cover_5.jpg')", "background-color": "oe_black", "resize_class": "o_record_has_cover cover_mid", "opacity": "0.4"}</field>
</record>
<p class="text-muted">Introduction to Javascript</p>
</div>
<record id="event.event_6" model="event.event">
<field name="website_published">False</field>
<field name="twitter_hashtag">odoo</field>
<field name="cover_properties">{"background-image": "none", "background-color": "secondary", "opacity": ""}</field>
</record>
<ul class="list-group list-group-flush"><li class="list-group-item">Hello World</li>
<li class="list-group-item">Variables &amp; Operators</li>
<li class="list-group-item">Dive into Strings</li>
<li class="list-group-item">Functions</li>
<li class="list-group-item">Loops</li>
<li class="list-group-item">Arrays</li>
</ul><div class="card-footer text-center">
<p class="text-muted"><i>You will be able to develop simple dynamic components in HTML pages.</i></p>
</div>
</div>
</div>
<record id="base.res_partner_1" model="res.partner">
<field name="is_published">True</field>
</record>
<div class="col-lg-4 mb-4">
<div class="card bg-info">
<div class="card-header text-center">
<h2 style="margin: 0">Day 2</h2>
<record id="base.res_partner_2" model="res.partner">
<field name="is_published">True</field>
</record>
<p class="text-muted" style="margin: 0">Odoo Web Client</p>
</div>
<record id="base.res_partner_3" model="res.partner">
<field name="is_published">True</field>
</record>
<ul class="list-group list-group-flush"><li class="list-group-item">Introduction to JQuery</li>
<li class="list-group-item">Advanced JQuery</li>
<li class="list-group-item">Underscore</li>
<li class="list-group-item">Introduction to QWeb</li>
<li class="list-group-item">Controllers and Views</li>
<li class="list-group-item">Bootstrap CSS</li>
<li class="list-group-item">Calling the ORM</li>
</ul><div class="card-footer text-center">
<p class="text-muted"><i>You will be able to create dynamic page interacting with the ORM.</i></p>
</div>
</div>
</div>
<record id="base.res_partner_4" model="res.partner">
<field name="is_published">True</field>
</record>
<div class="col-lg-4">
<div class="card bg-info">
<div class="card-header text-center">
<h2 style="margin: 0">Day 3</h2>
<record id="event.event_2" model="event.event">
<field name="is_published">True</field>
<field name="twitter_hashtag">odoo</field>
</record>
<p class="text-muted" style="margin: 0">Building a Full Application</p>
</div>
<ul class="list-group list-group-flush"><li class="list-group-item">Modules</li>
<li class="list-group-item">Python Objects</li>
<li class="list-group-item">Report Engine</li>
<li class="list-group-item">Workflows</li>
<li class="list-group-item">Training Center Module</li>
<li class="list-group-item">Integrated Help</li>
<li class="list-group-item">How to Debug</li>
</ul><div class="card-footer text-center">
<p class="text-muted"><i>You will be able to develop a full application with backend and user interface.</i></p>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-12 text-center mb-3 mt-5">
<h2>Requirements</h2>
</div>
<div class="col-lg-12 my-3">
<p><strong>Objectives:</strong></p>
<p><strong>Having attended this course, participants should be able to:</strong></p>
<ul><li>Understand the development concepts and architecture;</li>
<li>Install and administer your own server;</li>
<li>Develop a new module for a particular application.</li>
</ul><p></p>
<p><strong>Our prices include:</strong></p>
<ul><li>drinks and lunch;</li>
<li>training material.</li>
</ul><p></p>
<p><strong>Requirements:</strong></p>
<ul><li>Bring your own laptop.</li>
<li>Participants are expected to have some knowledge in programming.&nbsp;A basic knowledge of the Python programming is recommended.</li>
<li>Participants preferably have a functional knowledge of our software (see Functional Training).</li>
</ul><p></p>
<p>To get more information, visit the <a target="_blank" href="http://odoo.com/">Odoo Official Website</a>.</p>
</div>
</div>
</div>
</div>
<div class="container">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-lg-12">
<h1 class="text-center">Read Great Contents</h1>
<h3 class="text-muted text-center">What do people&nbsp;say about this course?</h3>
</div>
<div class="mt16 col-lg-6">
<blockquote class="border-left pl-3 font-italic mb-0 mt-3">
<i class="fa fa-quote-left"/>
<p class="font-weight-bold">I did not expect such a great learning experience. I feel like I can develop anything now.</p>
<small>John Doe, CEO</small></blockquote>
</div>
<div class="mt16 col-lg-6">
<blockquote class="border-left pl-3 font-italic mb-0 mt-3">
<i class="fa fa-quote-left"/>
<p class="font-weight-bold">This course help me build my first application within a month. Definetly worth its price.</p>
<small>John Doe, CEO</small></blockquote>
</div>
</div>
</div>
</div>
</div>
]]></field> </record>
<record id="base.res_partner_3" model="res.partner">
<field name="is_published">True</field>
</record>
<record id="base.res_partner_4" model="res.partner">
<field name="is_published">True</field>
</record>
<record id="event.event_2" model="event.event">
<field name="is_published">True</field>
<field name="twitter_hashtag">odoo</field>
</record>
<record id="base.res_partner_2" model="res.partner">
<field name="is_published">True</field>
</record>
<record id="base.res_partner_address_4" model="res.partner">
<field name="is_published">True</field>
</record>
<record id="base.res_partner_address_4" model="res.partner">
<field name="is_published">True</field>
</record>
</odoo>
+12 -3
View File
@@ -2,6 +2,7 @@
import pytz
import werkzeug
import json
from odoo import api, fields, models, _
from odoo.addons.http_routing.models.ir_http import slug
@@ -24,8 +25,14 @@ class Event(models.Model):
website_published = fields.Boolean(tracking=True)
subtitle = fields.Char('Event Subtitle', translate=True)
is_participating = fields.Boolean("Is Participating", compute="_compute_is_participating")
cover_properties = fields.Text(
'Cover Properties',
default='{"background-image": "none", "background-color": "oe_blue", "opacity": "0.4", "resize_class": "cover_mid"}')
website_menu = fields.Boolean('Dedicated Menu',
help="Creates menus Introduction, Location and Register on the page "
" of the event on the website.", copy=False)
@@ -129,7 +136,7 @@ class Event(models.Model):
'url': '/report/html/%s/%s?enable_editor' % ('event.event_event_report_template_badge', self.id),
}
def _get_event_resource_urls(self, attendees):
def _get_event_resource_urls(self):
url_date_start = self.date_begin.strftime('%Y%m%dT%H%M%SZ')
url_date_stop = self.date_end.strftime('%Y%m%dT%H%M%SZ')
params = {
@@ -147,8 +154,10 @@ class Event(models.Model):
def _default_website_meta(self):
res = super(Event, self)._default_website_meta()
event_cover_properties = json.loads(self.cover_properties)
res['default_opengraph']['og:image'] = res['default_twitter']['twitter:image'] = event_cover_properties.get('background-image', 'none')[4:-1]
res['default_opengraph']['og:title'] = res['default_twitter']['twitter:title'] = self.name
res['default_opengraph']['og:description'] = res['default_twitter']['twitter:description'] = self.date_begin
res['default_opengraph']['og:description'] = res['default_twitter']['twitter:description'] = self.subtitle
res['default_twitter']['twitter:card'] = 'summary'
res['default_meta_description'] = self.date_begin
res['default_meta_description'] = self.subtitle
return res
Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

@@ -9,6 +9,13 @@ var _t = core._t;
// Catch registration form event, because of JS for attendee details
var EventRegistrationForm = Widget.extend({
events: {
'click .o_wevent_registration_btn': '_onRegistrationBtnClick',
},
/**
* @override
*/
start: function () {
var self = this;
var res = this._super.apply(this.arguments).then(function () {
@@ -21,6 +28,15 @@ var EventRegistrationForm = Widget.extend({
});
return res;
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
* @param {Event} ev
*/
on_click: function (ev) {
ev.preventDefault();
ev.stopPropagation();
@@ -54,6 +70,15 @@ var EventRegistrationForm = Widget.extend({
});
}
},
/**
* @private
* @param {Event} ev
*/
_onRegistrationBtnClick: function (ev) {
var $btn = $(ev.currentTarget);
$btn.toggleClass('btn-primary text-left pl-0');
$btn.siblings().toggleClass('d-none');
},
});
publicWidget.registry.EventRegistrationFormInstance = publicWidget.Widget.extend({
@@ -65,7 +90,7 @@ publicWidget.registry.EventRegistrationFormInstance = publicWidget.Widget.extend
start: function () {
var def = this._super.apply(this, arguments);
var instance = new EventRegistrationForm(this);
return Promise.all([def, instance.appendTo(this.$el)]);
return Promise.all([def, instance.attachTo(this.$el)]);
},
});
@@ -1,13 +1,276 @@
.o_wevent_participating_container {
position: relative;
$o-wevent-event-title-sizes-variants: (
tiny: (
title: $display4-size*0.6,
subtitle: $lead-font-size
),
small: (
title: $display4-size*0.75,
subtitle: $lead-font-size
),
big: (
title: $display3-size,
subtitle: $lead-font-size*1.25
),
huge: (
title: $display2-size,
subtitle: $lead-font-size*1.5
),
hero: (
title: $display1-size,
subtitle: $lead-font-size*1.75
)
) !default;
&::before {
content: "";
@include o-position-absolute(0, auto, 0, 0);
width: 3px;
background-color: theme-color('info');
.o_wevent_event_searchbar_form {
flex: 0 0 100%;
@include media-breakpoint-up(lg) {
flex: 0 0 33%;
}
}
.o_wevent_registration_list_attendees:nth-child(2n) {
background-color: gray('200');
.o_wevent_index_topbar_filters {
.dropdown-toggle {
border: $border-width solid gray('400');
@include o-bg-color(gray('white'), $with-muted: false);
@include border-radius($dropdown-border-radius);
@include hover-focus {
border-color: theme-color('primary');
color: theme-color('primary');
text-decoration: none;
}
&:after {
margin-left: 1.2em;
}
.fa {
margin-right: .4em;
color: theme-color('primary');
}
}
.dropdown-menu {
margin-top: $navbar-padding-y;
min-width: 12rem;
}
.dropdown-item {
&.active .badge { // Invert badge display when the item is active
background-color: color-yiq(theme-color('primary'));
color: theme-color('primary');
}
}
}
.o_wevent_social_link {
$o_link_size: 3em;
display: inline-block;
@include size($o_link_size);
margin: 0 ($spacer * .25) ($spacer * .5) ($spacer * .25);
line-height: $o_link_size;
background-color: gray('100');
border: $border-width solid $border-color;
border-radius: 50%;
text-align: center;
@include hover-focus {
background-color: gray('300');
}
}
.o_wevent_badge {
padding: ($spacer * .5) $spacer;
border-radius: 10rem;
font-weight: $font-weight-normal;
}
// Index
.o_wevent_index {
// Events List
.o_wevent_events_list {
header {
a {
transition: all .25s ease-in-out;
@include hover-focus {
transform: scale(1.05);
}
}
}
&.opt_event_list_cards_bg {
@if (color('body') == #FCFCFC) {
@extend .bg-200;
}
}
.opt_events_list_columns {
header {
height: 200px;
}
}
.opt_events_list_rows {
@include media-breakpoint-down(sm) {
header {
height: 200px;
}
}
}
.o_wevent_badge_event {
@include o-position-absolute($top: 0, $left: 0);
@include border-left-radius(0);
padding: ($spacer * .5) $card-spacer-x;
transform: translateY(-50%);
}
.o_wevent_event_date {
top: $card-spacer-x;
right: $card-spacer-x;
display: flex;
flex-direction: column;
justify-content: center;
@include size(4rem);
border-radius: 50%;
text-align: center;
.o_wevent_event_day {
font-size: 1.125rem;
font-weight: 300;
line-height: 1;
}
.o_wevent_event_month {
font-size: 0.75rem;
font-weight: $font-weight-bold;
text-transform: uppercase;
}
}
.o_wevent_participating,
.o_wevent_unpublished {
position: absolute;
bottom: 0;
width: 100%;
padding: $card-spacer-y $card-spacer-x;
text-align: right;
}
.card-title {
color: $body-color;
}
}
.o_wevent_sidebar_title {
margin: 0 0 ($spacer * 1.5) 0;
border-bottom: $border-width solid $border-color;
padding: 0 0 ($spacer * .5) 0;
font-weight: $font-weight-bold;
text-transform: uppercase;
}
.o_wevent_sidebar_block {
margin: 0 0 ($spacer * 2.5) 0;
}
.o_wevent_sidebar_figure {
position: relative;
.figure-img {
margin-bottom: 0;
}
.figure-caption {
@include o-position-absolute($left: 0, $bottom: 0);
width: 100%;
padding: $spacer;
background-color: rgba($color: #000, $alpha: 0.5);
@include border-bottom-radius($border-radius);
color: #fff;
}
}
}
.o_wevent_event {
.o_wevent_event_title {
margin: 3rem 0;
.o_wevent_event_name {
font-weight: $display4-weight;
line-height: $display-line-height;
@include font-size($display4-size);
}
.o_wevent_event_subtitle {
font-weight: $lead-font-weight;
@include font-size($lead-font-size);
}
}
@each $size, $map in $o-wevent-event-title-sizes-variants {
.o_record_cover_font_#{$size} .o_wevent_event_title {
.o_wevent_event_name {
@include font-size(map-get($map, title));
}
.o_wevent_event_subtitle {
@include font-size(map-get($map, subtitle));
}
}
}
.o_wevent_registration_btn {
flex: 0 0 100%;
&.collapsed {
flex: 0 0 33%;
.close {
display: none;
}
}
.close {
display: block;
}
&:not(.collapsed) {
box-shadow: none;
font-weight: $font-weight-bold;
text-transform: uppercase;
transition: none;
}
}
.o_wevent_sidebar_title {
margin-bottom: $spacer;
opacity: .5;
text-transform: uppercase;
}
.o_wevent_sidebar_block {
padding: $spacer * 3;
border-bottom: $border-width solid $border-color;
&:last-child {
border-bottom: 0;
}
}
}
.o_wevent_event {
.o_record_cover_container {
overflow: hidden;
z-index: 0;
.o_record_cover_component {
display: none;
}
&.o_record_has_cover {
.o_record_cover_image {
background-attachment: fixed;
&::after {
content: "";
display: block;
@include o-position-absolute(0,0,50%,0);
}
}
.o_record_cover_component {
display: block;
z-index: -1;
}
.o_wevent_event_title {
color: white;
}
&.cover_full {
min-height: 600px;
min-height: 100vh;
}
&.cover_mid {
min-height: 400px;
min-height: 55vh;
}
}
}
}
+53 -41
View File
@@ -1,68 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Snippet to display local events -->
<template id="s_country_events" name="Local Events">
<div t-attf-class="oe_country_events #{_classes or 'my-3'}">
<!-- Snippet - Country Events - Placeholder -->
<template id="s_country_events" name="Country Events">
<div t-attf-class="s_country_events_list oe_country_events #{_classes}">
<div class="country_events_list">
<h5>
<i class="fa fa-flag"/> Events from Your Country
</h5>
<h6 class="o_wevent_sidebar_title">
<i class="fa fa-globe mr-2"/>Upcoming Events
</h6>
</div>
</div>
</template>
<!-- Misc templates -->
<template id="country_events_list" name="Country">
<t t-ignore="true">
<!-- Snippet - Country Events - List -->
<template id="country_events_list" name="Country Events List">
<div class="country_events_list">
<t t-if="events">
<div class="country_events_list">
<h6 class="o_wevent_sidebar_title">
<t t-if="country">
<img class="img-fluid" t-att-src="website.image_url(country, 'image')" alt=""></img>
<h4><b>Events: <span t-esc="country.name"></span></b></h4>
<i class="fa fa-flag mr-2"/>Events: <span t-esc="country.name"/>
<img class="img-fluid" t-att-src="website.image_url(country, 'image')" alt=""/>
</t>
<t t-if="not country">
<img class="img-fluid" src="/website_event/static/src/img/world_map.jpg" alt=""></img>
<h4><b>Upcoming Events</b></h4>
<t t-else="">
<i class="fa fa-globe mr-2"/>Upcoming Events
</t>
<div t-foreach="events[:5]" t-as="event_dict" class="oe_website_overflow_ellipsis mb8">
<t t-if="not event_dict['event'].website_published">
<span class="badge badge-danger" role="img" aria-label="Attention: not published" title="Not published"><i class="fa fa-ban"></i></span>
</t>
<t t-if="event_dict['event'].address_id">
<i class="fa fa-map-marker" title="It is a physical event" role="img" aria-label="It is a physical event"></i>
</t>
<t t-if="not event_dict['event'].address_id">
<i class="fa fa-cloud" title="It is an online event" role="img" aria-label="It is an online event"></i>
</t>
<b><span t-esc="event_dict['date']"/>: <span><a t-att-href="event_dict['url']"><t t-esc="event_dict['event'].name"/></a></span></b>
</div>
<t t-if="len(events) &gt; 5">
<div t-if="country">
<b><a t-att-href="'/event?country='+str(country.id)">See all events from <span t-esc="country.name"></span></a></b>
</div>
<div t-if="not country">
<b><a href="/event"> See all upcoming events </a></b>
</div>
</h6>
<ul class="list-group mb-3">
<li t-foreach="events[:5]" t-as="event_dict" class="list-group-item d-flex justify-content-between">
<a t-att-href="event_dict['url']">
<i t-if="not event_dict['event'].website_published" class="fa fa-ban text-danger mr-1" role="img" aria-label="Unpublished" title="Unpublished"/>
<span t-esc="event_dict['event'].name" t-attf-class="#{(not event_dict['event'].website_published) and 'text-danger' or ''}"/>
</a>
<span t-esc="event_dict['date']"/>
</li>
</ul>
<div t-if="len(events) &gt; 5">
<t t-if="country">
<a t-attf-href="/event?country=#{country.id}" class="small"><b>See all events from <span t-esc="country.name"/></b></a>
</t>
<t t-else="">
<a href="/event" class="small"><b>View all</b></a>
</t>
</div>
</t>
</t>
</div>
</template>
<!-- Replace snippet demo with actual snippet and options -->
<template id="remove_external_snippets" inherit_id="website.external_snippets">
<xpath expr="//t[@t-install='website_event']" position="replace"/>
</template>
<template id="country_events" name="Country Events" inherit_id="website.snippets">
<template id="snippets" inherit_id="website.snippets">
<xpath expr="//div[@id='snippet_content']//t[@t-snippet][last()]" position="after">
<t t-snippet="website_event.s_country_events" t-thumbnail="/website_event/static/src/img/world_map.jpg"/>
</xpath>
<xpath expr="//div[@id='snippet_options']" position="inside">
<div data-selector=".oe_country_events"
data-drop-near="p, h1, h2, h3, blockquote, .card"
data-drop-in=".content"/>
<t t-snippet="website_event.s_speaker_bio" t-thumbnail="/website_event/static/src/img/s_country_events.png"/>
</xpath>
</template>
<template id="snippet_options" inherit_id="website.snippet_options">
<xpath expr="//div[@id='so_content_addition']" position="attributes">
<attribute name="data-selector" add=".oe_country_events, .s_speaker_bio" separator=","/>
</xpath>
</template>
<!-- Snippet - Speaker Bio -->
<template id="s_speaker_bio" name="Speaker Bio">
<div class="s_speaker_bio" itemscope="itemscope" itemtype="http://schema.org/Person" itemprop="performer">
<span class="badge badge-secondary text-uppercase o_wevent_badge">Speaker</span>
<img src="/website_event/static/src/img/speaker.png" width="70" class="img-fluid rounded-circle float-left mr-3" alt=""/>
<div class="overflow-hidden">
<h4 class="mt-3 mb-1" itemprop="name">John DOE</h4>
<h6 class="mb-4">Company</h6>
<p>At just 13 years old, John DOE was already starting to develop his first business applications for customers. After mastering civil engineering, he founded TinyERP. This was the first phase of OpenERP which would later became Odoo, the most installed open-source business software worldwide.</p>
</div>
</div>
</template>
</odoo>
File diff suppressed because it is too large Load Diff
@@ -1,16 +0,0 @@
odoo.define('website_event_questions.website_event_questions', function (require) {
'use strict';
var EventRegistrationForm = require('website_event.website_event');
EventRegistrationForm.include({
on_click: function (ev) {
var def = this._super.apply(this, arguments);
def.then(function () {
$("select.o_specific_answer,select.o_general_answer").each(function (index, elem) {
$(elem).select2({ minimumResultsForSearch: -1, width: '100%' });
});
});
},
});
});
@@ -1,55 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="event_question_assets" inherit_id="website.assets_frontend" name="Events Questions">
<xpath expr="/t" position="inside">
<script type="text/javascript" src="/website_event_questions/static/src/js/website_event_questions.js"></script>
<template id="registration_attendee_details_questions" inherit_id="website_event.registration_attendee_details" name="Registration Attendee Details with questions">
<!-- Attendee specific questions -->
<xpath expr="//t[@name='attendee_loop']//*[hasclass('modal-body')]" position="inside">
<t t-if="event.specific_question_ids">
<div t-foreach="event.specific_question_ids" t-as="question" class="row">
<div class="col-lg-6 mt-2">
<label t-esc="question.title"/>
<select t-attf-name="#{counter}-answer_ids-#{question.id}" class="custom-select" required="true">
<t t-foreach="question.answer_ids" t-as="answer">
<option t-esc="answer.name" t-att-value="answer.id"/>
</t>
</select>
</div>
</div>
</t>
</xpath>
<!-- Generic questions -->
<xpath expr="//*[hasclass('modal-footer')]" position="before">
<t t-if="event.general_question_ids">
<div class="modal-body bg-light border-bottom">
<div t-foreach="event.general_question_ids" t-as="question" class="row">
<div class="col-lg-6">
<label class="h5" t-esc="question.title"/>
<select t-attf-name="0-answer_ids-#{question.id}" class="custom-select" required="true">
<t t-foreach="question.answer_ids" t-as="answer">
<option t-esc="answer.name" t-att-value="answer.id"/>
</t>
</select>
</div>
</div>
</div>
</t>
</xpath>
</template>
<template id="registration_attendee_details_questions" inherit_id="website_event.registration_attendee_details" name="Registration Attendee Details with questions">
<data>
<!-- Attendee specific questions -->
<xpath expr="//t[@name='attendee_loop']" position="inside">
<t t-if="event.specific_question_ids">
<div class="mb16 mt16">
<div t-foreach='event.specific_question_ids' t-as='question'>
<div class="row mb4">
<span class="col-lg-7 mt4 text-right"><t t-esc="question.title"/></span>
<div class="col-lg-5">
<select t-attf-name="#{counter}-answer_ids-#{question.id}" class="o_specific_answer" required="true">
<t t-foreach='question.answer_ids' t-as="answer">
<option t-esc='answer.name' t-att-value='answer.id'/>
</t>
</select>
</div>
</div>
</div>
</div>
</t>
</xpath>
<!-- Generic questions -->
<xpath expr="//*[hasclass('modal-body')]/div/t[last()]" position="after">
<t t-if="event.general_question_ids">
<h4 class="o_page_header mt8"><strong>Questions</strong></h4>
<div>
<div t-foreach='event.general_question_ids' t-as='question'>
<div class="row mb4">
<span class="col-lg-7 mt4 text-right"><t t-esc='question.title'/></span>
<div class="col-lg-5">
<select t-attf-name="0-answer_ids-#{question.id}" class="o_general_answer" required="true">
<t t-foreach='question.answer_ids' t-as="answer">
<option t-esc='answer.name' t-att-value='answer.id'/>
</t>
</select>
</div>
</div>
</div>
</div>
</t>
</xpath>
</data>
</template>
</odoo>
@@ -46,7 +46,7 @@ class WebsiteEventSaleController(WebsiteEventController):
attendees = request.env['event.registration'].browse(list(attendee_ids)).sudo()
# clean context and session, then redirect to the confirmation page
request.website.sale_reset()
urls = event._get_event_resource_urls(list(attendee_ids))
urls = event._get_event_resource_urls()
return request.render("website_event.registration_complete", {
'attendees': attendees,
'event': event,
@@ -12,6 +12,10 @@ tour.register('event_buy_tickets', {
content: "Go to the `Events` page",
trigger: 'a[href*="/event"]:contains("Conference for Architects"):first',
},
{
content: "Show available Tickets",
trigger: '.o_wevent_registration_btn',
},
{
content: "Select 1 unit of `Standard` ticket type",
extra_trigger: '#wrap:not(:has(a[href*="/event"]:contains("Conference for Architects")))',
@@ -27,7 +31,7 @@ tour.register('event_buy_tickets', {
{
content: "Click on `Order Now` button",
extra_trigger: 'select:eq(1):has(option:contains(2):propSelected)',
trigger: '.btn-primary:contains("Register Now")',
trigger: '.btn-primary:contains("Register")',
},
{
content: "Fill attendees details",
@@ -7,12 +7,12 @@
</xpath>
</template>
<template id="index" inherit_id="website_event.index" name="Event's Ticket">
<xpath expr="//div[@t-foreach='event_ids']//h4" position="before">
<template id="index" inherit_id="website_event.events_list" name="Event's Ticket">
<xpath expr="//div[@t-foreach='event_ids']//footer" position="inside">
<t t-if="event.state in ['draft', 'confirm'] and event.event_ticket_ids">
<span t-if="event.seats_availability == 'limited' and not event.seats_available" class="badge badge-danger float-right">Sold Out</span>
<span t-if="event.seats_availability == 'limited' and event.seats_available and event.seats_available &lt;= ((event.seats_max or 0) / 4)" class="badge float-right badge-info">
Only <t t-esc="event.seats_available"/> Remaining
<span t-if="event.seats_availability == 'limited' and not event.seats_available" class="text-danger">Sold Out</span>
<span t-if="event.seats_availability == 'limited' and event.seats_available and event.seats_available &lt;= ((event.seats_max or 0) / 4)" class="text-muted">
<em>Only <t t-esc="event.seats_available"/> Remaining</em>
</span>
</t>
</xpath>
@@ -20,59 +20,89 @@
<template id="registration_template" inherit_id="website_event.registration_template">
<xpath expr="//t[@t-id='tickets']" position="replace">
<t t-set="saleable_tickets" t-value="event.event_ticket_ids.filtered(lambda t: not t.is_expired)"/>
<t t-id="tickets" t-foreach="saleable_tickets" t-as="ticket">
<t t-set="tickets" t-value="event.event_ticket_ids.filtered(lambda t: not t.is_expired)"/>
<t t-if="len(event.event_ticket_ids) &gt; 1"> <!-- If some tickets expired and there is only one type left, we keep the same layout -->
<div class="d-flex align-items-center py-2 pl-3 pr-2 border-bottom">
<span t-if="not tickets_available" class="text-danger">
<i class="fa fa-ban mr-2"/>Sold Out
</span>
<div class="ml-auto pr-3">
<span t-if="event.is_participating" class="text-success ml-3">
<i class="fa fa-check mr-2"/>Registered
</span>
</div>
<a href="#" role="button" class="btn btn-primary o_wevent_registration_btn collapsed" data-toggle="collapse" data-target="#o_wevent_tickets_collapse">
Tickets
<span class="close">×</span>
</a>
</div>
<div id="o_wevent_tickets_collapse" class="collapse">
<div t-foreach="tickets" t-as="ticket" class="row mx-0 bg-light border-bottom">
<div class="col-md-8 py-3" itemscope="itemscope" itemtype="http://schema.org/Offer">
<h5 itemprop="name" t-field="ticket.name" class="my-0"/>
<small t-if="ticket.deadline" class="text-muted mr-3" itemprop="availabilityEnds">Sales end on <span itemprop="priceValidUntil" t-field="ticket.deadline"/></small>
</div>
<div class="col-md-4 py-3 pl-md-0">
<div class="d-flex align-items-center">
<t t-if="ticket.price or editable">
<t t-if="(ticket.price-website.get_current_pricelist().currency_id._convert(ticket.price_reduce, event.company_id.sudo().currency_id, event.company_id, datetime.date.today())) &gt; 1 and website.get_current_pricelist().discount_policy == 'without_discount'">
<del class="text-danger mr-1" t-field="ticket.price" t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.get_current_pricelist().currency_id}"/>
</t>
<span t-field="ticket.price_reduce" t-options="{'widget': 'monetary', 'display_currency': website.pricelist_id.currency_id}" groups="account.group_show_line_subtotals_tax_excluded"/>
<span t-field="ticket.price_reduce_taxinc" t-options="{'widget': 'monetary', 'display_currency': website.pricelist_id.currency_id}" groups="account.group_show_line_subtotals_tax_included"/>
<span itemprop="price" class="d-none" t-esc="ticket.price"/>
<span itemprop="priceCurrency" class="d-none" t-esc="website.pricelist_id.currency_id.name"/>
</t>
<span t-if="not ticket.price and not editable" class="font-weight-bold text-uppercase">Free</span>
<select t-attf-name="nb_register-#{ticket.id}" class="w-auto ml-auto custom-select">
<t t-set="seats_max_ticket" t-value="(ticket.seats_availability == 'unlimited' or ticket.seats_available &gt; 9) and 10 or ticket.seats_available + 1"/>
<t t-set="seats_max_event" t-value="(event.seats_availability == 'unlimited' or event.seats_available &gt; 9) and 10 or event.seats_available + 1"/>
<t t-set="seats_max" t-value="min(seats_max_ticket, seats_max_event)"/>
<t t-foreach="range(0, seats_max)" t-as="nb">
<option t-esc="nb" t-att-selected="len(ticket) == 0 and nb == 0 and 'selected'"/>
</t>
</select>
</div>
</div>
<div t-if="tickets.product_id.description_sale" class="col-12">
<p itemprop="description" t-field="tickets.product_id.description_sale" class="small py-2 border-top"/>
</div>
</div>
<div class="row no-gutters">
<div class="col-md-4 offset-md-8 py-2 pl-md-0 pr-md-2">
<button type="submit" class="btn btn-primary btn-block a-submit" t-att-disabled="not tickets_available or None" t-attf-id="#{event.id}">Register</button>
</div>
</div>
</div>
</t>
<t t-else="">
<t t-call="website_event.ticket">
<t t-set="name">
<span itemprop="name" t-field="ticket.name"/>
<t t-set="name"><span t-field="tickets.name"/></t>
<t t-set="price">
<t t-if="tickets.price or editable">
<t t-if="(tickets.price-website.get_current_pricelist().currency_id._convert(tickets.price_reduce, event.company_id.sudo().currency_id, event.company_id, datetime.date.today())) &gt; 1 and website.get_current_pricelist().discount_policy == 'without_discount'">
<del class="text-danger mr-1" t-field="tickets.price" t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.get_current_pricelist().currency_id}"/>
</t>
<span t-field="tickets.price_reduce" t-options="{'widget': 'monetary', 'display_currency': website.pricelist_id.currency_id}" groups="account.group_show_line_subtotals_tax_excluded"/>
<span t-field="tickets.price_reduce_taxinc" t-options="{'widget': 'monetary', 'display_currency': website.pricelist_id.currency_id}" groups="account.group_show_line_subtotals_tax_included"/>
<span itemprop="price" class="d-none" t-esc="tickets.price"/>
<span itemprop="priceCurrency" class="d-none" t-esc="website.pricelist_id.currency_id.name"/>
</t>
<span t-if="not tickets.price and not editable" class="font-weight-bold text-uppercase">Free</span>
</t>
<t t-set="description">
<span itemprop="description" t-field="ticket.product_id.description_sale"/>
<t t-if="tickets.product_id.description_sale" t-set="description">
<span t-field="tickets.product_id.description_sale"/>
</t>
<t t-set="registration_end">
<t t-if="ticket.deadline">
<span itemprop="priceValidUntil" t-field="ticket.deadline"/>
</t>
<t t-if="not ticket.deadline">
<span>Unlimited</span>
</t>
</t>
<t t-set="price">
<t t-if="ticket.price or editable">
<t t-if="(ticket.price-website.get_current_pricelist().currency_id._convert(ticket.price_reduce, event.company_id.sudo().currency_id, event.company_id, datetime.date.today())) &gt; 1
and website.get_current_pricelist().discount_policy == 'without_discount'">
<del class="text-danger mr4" t-field="ticket.price" t-options='{
"widget": "monetary",
"from_currency": event.company_id.sudo().currency_id,
"display_currency": website.get_current_pricelist().currency_id
}'/>
</t>
<span t-field="ticket.price_reduce" t-options='{
"widget": "monetary",
"display_currency": website.pricelist_id.currency_id
}' groups="account.group_show_line_subtotals_tax_excluded"/>
<span t-field="ticket.price_reduce_taxinc" t-options='{
"widget": "monetary",
"display_currency": website.pricelist_id.currency_id
}' groups="account.group_show_line_subtotals_tax_included"/>
<span itemprop="price" style="display:none;" t-esc="ticket.price"/>
<span itemprop="priceCurrency" style="display:none;" t-esc="website.pricelist_id.currency_id.name"/>
</t>
<t t-if="not ticket.price and not editable">
<span>Free</span>
</t>
<span t-if="ticket.seats_max and ((ticket.seats_reserved or 0)*100 / ticket.seats_max)&gt;75" class="badge badge-pill" itemprop="availability" content="http://schema.org/LimitedAvailability">
<t t-esc="ticket.seats_max - ticket.seats_reserved"/>
<span>left</span>
</span>
<t t-if="tickets.deadline">Sales end on <span itemprop="priceValidUntil" t-field="tickets.deadline"/></t>
</t>
<t t-set="quantity">
<select t-attf-name="nb_register-#{ticket.id}" class="form-control">
<t t-set="seats_max_ticket" t-value="(ticket.seats_availability == 'unlimited' or ticket.seats_available &gt; 9) and 10 or ticket.seats_available + 1"/>
<select t-attf-name="nb_register-#{tickets.id}" class="w-auto custom-select">
<t t-set="seats_max_ticket" t-value="(tickets.seats_availability == 'unlimited' or tickets.seats_available &gt; 9) and 10 or tickets.seats_available + 1"/>
<t t-set="seats_max_event" t-value="(event.seats_availability == 'unlimited' or event.seats_available &gt; 9) and 10 or event.seats_available + 1"/>
<t t-set="seats_max" t-value="min(seats_max_ticket, seats_max_event)"/>
<t t-foreach="range(0, seats_max)" t-as="nb">
<option t-esc="nb" t-att-selected="len(saleable_tickets) == 1 and nb == 1 and 'selected'"/>
<option t-esc="nb" t-att-selected="len(tickets) == 1 and nb == 1 and 'selected'"/>
</t>
</select>
</t>
@@ -43,8 +43,8 @@
<template id="agenda">
<t t-call="website_event.layout">
<div class="oe_structure" id="oe_structure_website_event_track_agenda_1"/>
<section class="container">
<h1 class="text-center" t-field="event.name"/>
<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"/>
@@ -112,51 +112,56 @@
</t>
</template>
<template id="tracks">
<t t-call="website_event.event_details">
<div class="oe_structure" id="oe_structure_website_event_track_tracks_1"/>
<div id="left_column">
</div>
<div class="col-lg-9">
<div class="alert alert-warning" t-if="not len(tracks)" role="alert">
No tracks found!
</div>
<div class="row mb-2" t-foreach="tracks" t-as="track">
<div class="col-md-2">
<t t-if="track.image">
<span t-field="track.image"
t-options='{"widget": "image", "class": "rounded-circle"}'/>
</t>
</div>
<div class="col-md-10">
<h3 class="mt0 mb0">
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }" class="text-secondary"><span t-field="track.name"> </span></a>
<small t-if="not track.website_published" class="badge badge-danger">unpublished</small>
</h3>
<ul class="list-inline mb0">
<li t-if="track.partner_id" class="list-inline-item">
<i class="fa fa-user text-primary"/>
<t t-esc="track.partner_id.sudo().name"/>
</li>
<li t-if="track.date" class="list-inline-item"> <i class="fa fa-calendar text-primary"/><span t-field="track.date" t-options='{"hide_seconds":"True"}'/></li>
<li class="list-inline-item" t-if="track.location_id">
<i class="fa fa-map-marker"/>
<span t-field="track.location_id"/>
</li>
</ul>
<ul class="list-inline">
<li t-foreach="track.tag_ids" t-as="tag_id" class="list-inline-item fa fa-tags" t-if="tag_id.color != 0">
<a t-attf-href="/event/#{ slug(event) }/track/tag/#{ slug(tag_id) }">
<i class="fa fa-tags"/>
<span t-field="tag_id.name"/>
</a>
</li>
</ul>
<p class="mt8"><t t-esc="html2plaintext(track.description or '')[0:500]"/><t t-if="track.description">...</t></p>
<t t-call="website_event.layout">
<div class="oe_structure" id="oe_structure_website_event_track_tracks_1"/>
<section class="pt48 pb48">
<div class="container">
<div class="row">
<div id="left_column">
</div>
<div class="col-lg-9">
<div class="alert alert-warning" t-if="not len(tracks)" role="alert">
No tracks found!
</div>
<div class="row mb-2" t-foreach="tracks" t-as="track">
<div class="col-md-2">
<t t-if="track.image">
<span t-field="track.image"
t-options='{"widget": "image", "class": "rounded-circle"}'/>
</t>
</div>
<div class="col-md-10">
<h3 class="mt0 mb0">
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }" class="text-secondary"><span t-field="track.name"> </span></a>
<small t-if="not track.website_published" class="badge badge-danger">unpublished</small>
</h3>
<ul class="list-inline mb0">
<li t-if="track.partner_id" class="list-inline-item">
<i class="fa fa-user text-primary"/>
<t t-esc="track.partner_id.sudo().name"/>
</li>
<li t-if="track.date" class="list-inline-item"> <i class="fa fa-calendar text-primary"/><span t-field="track.date" t-options='{"hide_seconds":"True"}'/></li>
<li class="list-inline-item" t-if="track.location_id">
<i class="fa fa-map-marker"/>
<span t-field="track.location_id"/>
</li>
</ul>
<ul class="list-inline">
<li t-foreach="track.tag_ids" t-as="tag_id" class="list-inline-item fa fa-tags" t-if="tag_id.color != 0">
<a t-attf-href="/event/#{ slug(event) }/track/tag/#{ slug(tag_id) }">
<i class="fa fa-tags"/>
<span t-field="tag_id.name"/>
</a>
</li>
</ul>
<p class="mt8"><t t-esc="html2plaintext(track.description or '')[0:500]"/><t t-if="track.description">...</t></p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<div class="oe_structure" id="oe_structure_website_event_track_tracks_2"/>
</t>
</template>
@@ -186,100 +191,75 @@
</xpath>
</template>
<template id="track_view">
<t t-call="website.layout">
<div id="wrap" class="js_event">
<t t-call="website_event.layout">
<section class="pt48">
<div class="container">
<div class="row mt8">
<div class="col-md-7" id="event_menu">
<ol name="Event Menu" class="breadcrumb" id="event_menu" t-if="event.menu_id" t-att-data-content_menu_id="editable and event.menu_id.id">
<t t-foreach="event.menu_id.child_id" t-as="submenu">
<t t-call="website.submenu">
<t t-set="item_class" t-value="'breadcrumb-item'"/>
<t t-set="link_class" t-value="None"/>
</t>
</t>
</ol>
<div class="row">
<div class="col-12">
<h1 t-field="track.name"/>
<small>Proposed by
<span t-if="track.partner_id" t-field="track.partner_id.sudo().name"/>
<span t-if="not track.partner_id" t-field="track.partner_name"/>
</small>
<ul t-if="track.tag_ids" class="text-center text-muted list-inline">
<li t-foreach="track.tag_ids" t-as="tag_id" class="list-inline-item" t-if="tag_id.color != 0">
<span class="fa fa-tags"></span>
<a t-attf-href="/event/#{ slug(event) }/track/tag/#{ slug(tag_id) }">
<span t-field="tag_id.name"/>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="clearfix"/>
<h2 t-field="track.name" class="text-center"/>
<h3 t-field="event.name" class="text-center text-muted"/>
<ul t-if="track.tag_ids" class="text-center text-muted list-inline">
<li t-foreach="track.tag_ids" t-as="tag_id" class="list-inline-item" t-if="tag_id.color != 0">
<span class="fa fa-tags"></span>
<a t-attf-href="/event/#{ slug(event) }/track/tag/#{ slug(tag_id) }">
<span t-field="tag_id.name"/>
</a>
</li>
</ul>
<section class="row mt32">
<div class="col-lg-8">
<section>
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h2 t-field="track.name"/>
<small>Proposed by
<span t-if="track.partner_id" t-field="track.partner_id.sudo().name"/>
<span t-if="not track.partner_id" t-field="track.partner_name"/>
</small>
</div>
<div class="col-lg-12">
<div t-field="track.description"/>
</div>
<div class="col-lg-12">
<h3>About The Speaker</h3>
<div t-field="track.partner_biography"/>
</div>
</div>
</div>
</section>
<div t-if="track.partner_id" class="mt32">
<div class="row">
</section>
<section class="pt32">
<div class="container">
<div class="row">
<div class="col-lg-8">
<div t-field="track.description"/>
<h3>About The Speaker</h3>
<div t-field="track.partner_biography"/>
<div t-if="track.partner_id" class="row mt32">
<div class="col-md-2">
<span t-field="track.partner_id.sudo().image_128"
t-options='{"widget": "image", "class": "rounded-circle"}'/>
</div><div class="col-md-10">
<h4 t-field="track.partner_id.name" class="mb4"/>
<div class="fa fa-home mb16" t-if="track.partner_id.website">
<a t-att-href="track.partner_id.website"><span t-field="track.partner_id.website"/></a>
</div>
<div t-field="track.partner_id.website_description"/>
<span t-field="track.partner_id.sudo().image_128" t-options='{"widget": "image", "class": "rounded-circle"}'/>
</div>
<div class="col-md-10">
<h4 t-field="track.partner_id.name" class="mb4"/>
<div class="mb16" t-if="track.partner_id.website">
<i class="fa fa-home mr-2"/><a t-att-href="track.partner_id.website"><span t-field="track.partner_id.website"/></a>
</div>
<div t-field="track.partner_id.website_description"/>
</div>
</div>
</div>
<div class="col-lg-4" id="right_column">
<div class="card">
<h4 class="card-header">Practical Info</h4>
<div class="card-body">
<b>Date</b><br/>
<span t-field="track.date" t-options='{"hide_seconds":"True"}'/>
<t t-if="event.date_tz">(<span t-field="event.date_tz"/>)</t>
<br/>
<b>Duration</b><br/>
<span t-field="track.duration" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/><br/>
<b>Location</b><br/>
<span t-field="track.location_id"/><br/>
</div>
</div>
<div class="card" t-if="False">
<h4 class="card-header">Documents</h4>
<div class="card-body">
Put here the list of documents, like slides of
the presentations. Remove the above t-if when
it's implemented.
</div>
</div>
</div>
</div>
<div class="col-lg-4" id="right_column">
<div class="card">
<h4 class="card-header">Practical Info</h4>
<div class="card-body">
<b>Date</b><br/>
<span t-field="track.date" t-options='{"hide_seconds":"True"}'/>
<t t-if="event.date_tz">(<span t-field="event.date_tz"/>)</t>
<br/>
<b>Duration</b><br/>
<span t-field="track.duration" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/><br/>
<b>Location</b><br/>
<span t-field="track.location_id"/><br/>
</div>
</div>
<div class="card" t-if="False">
<h4 class="card-header">Documents</h4>
<div class="card-body">
Put here the list of documents, like slides of
the presentations. Remove the above t-if when
it's implemented.
</div>
</div>
</div>
</section>
</div>
</div>
</section>
</t>
</template>
@@ -308,7 +288,7 @@
<t t-call="website_event.layout">
<div class="oe_structure" id="oe_structure_website_event_track_proposal_1"/>
<div class="container">
<section>
<section class="pt48">
<h1 class="o_page_header">Call for Proposals</h1>
<h2 class="text-center text-secondary font-weight-bold my-4" t-esc="event.name"/>
</section>
+13 -6
View File
@@ -232,30 +232,37 @@ class DateTimeConverter(models.AbstractModel):
def value_to_html(self, value, options):
if not value:
return ''
options = options or {}
lang = self.user_lang()
locale = babel.Locale.parse(lang.code)
format_func = babel.dates.format_datetime
if isinstance(value, str):
value = fields.Datetime.from_string(value)
value = fields.Datetime.context_timestamp(self, value)
if options and 'format' in options:
if 'format' in options:
pattern = options['format']
else:
if options and options.get('time_only'):
if options.get('time_only'):
strftime_pattern = (u"%s" % (lang.time_format))
elif options and options.get('date_only'):
elif options.get('date_only'):
strftime_pattern = (u"%s" % (lang.date_format))
else:
strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))
pattern = posix_to_ldml(strftime_pattern, locale=locale)
if options and options.get('hide_seconds'):
if options.get('hide_seconds'):
pattern = pattern.replace(":ss", "").replace(":s", "")
return pycompat.to_text(babel.dates.format_datetime(value, format=pattern, locale=locale))
if options.get('time_only'):
format_func = babel.dates.format_time
if options.get('date_only'):
format_func = babel.dates.format_date
return pycompat.to_text(format_func(value, format=pattern, locale=locale))
class TextConverter(models.AbstractModel):