summaryrefslogtreecommitdiff
path: root/addons/website_event
diff options
context:
space:
mode:
authorThibault Delavallée <tde@odoo.com>2020-07-01 13:13:36 +0000
committerThibault Delavallée <tde@odoo.com>2020-07-31 18:05:12 +0000
commit917ad9a9a9f74e36c00ad2bc0d31b588b9afe0c8 (patch)
tree87a2b5f1cadfb26cc9604bb3b898104e258affcd /addons/website_event
parentd5840a90936014d7ec62af936c0fef97505cb669 (diff)
[REF] website_event(_track): better support menu management from frontend
RATIONALE Events are sometimes held online, gathering a community. In this merge we improve Event application to better support full-online events with improved tracks, wishlists, chat rooms, ... PURPOSE New and improved pages are about to land for online event. However current menus and pages management is hard to tweak, especially when dealing with the stable policy of 13.3 . SPECIFICATIONS Refactor and improve code about event menu management. Purpose is to ease inheritance and be able to add menus and pages with less custom code in sub modules. Refactor some code, notably * code dealing with menus to activate and de-activate that is duplicated for each kind of menu; * allow to give a menu_type through inheritance in create_menu notably to support website.event.menu model available in Track app and unfortunately not in website_event; * make a somehow generic way of getting fields dealing with menu items through simple inheritance; * support sequence to allow ordering of menu entries by propagating the sequence to website menus; Behavior in website_event and website_event_track should be the same. Behavior will be tweaked in other modules through inheritance.. Improve behavior when removing frontend menus * correctly fetch views (for Introduction / Location) and try to unlink them to avoid bloating the db; * update boolean menu fields according to website menu management. Removing a menu from frontend should be reflected on boolean fields of event; LINKS PR #55260 Task ID-2310491 (Event Online Preparation 5) Part of Task ID-2252655 (Main Online Event task) Part of Task ID-2283796 (Event B2Basics / Registration Flow) Co-Authored-By: Aurélien Warnon <awa@odoo.com> Co-Authored-By: David Beguin <dbe@odoo.com> Co-Authored-By: Thibault Delavallée <tde@odoo.com>
Diffstat (limited to 'addons/website_event')
-rw-r--r--addons/website_event/i18n/website_event.pot14
-rw-r--r--addons/website_event/models/event_event.py95
-rw-r--r--addons/website_event/tests/common.py34
-rw-r--r--addons/website_event/tests/test_event_internals.py17
4 files changed, 133 insertions, 27 deletions
diff --git a/addons/website_event/i18n/website_event.pot b/addons/website_event/i18n/website_event.pot
index fc88fec0533..6a35067dfc1 100644
--- a/addons/website_event/i18n/website_event.pot
+++ b/addons/website_event/i18n/website_event.pot
@@ -335,11 +335,6 @@ msgid "Date &amp; Time"
msgstr ""
#. module: website_event
-#: model:ir.model.fields,field_description:website_event.field_event_event__website_menu
-msgid "Dedicated Menu"
-msgstr ""
-
-#. module: website_event
#: model:ir.model.fields,field_description:website_event.field_event_type__website_menu
msgid "Display a dedicated menu on Website"
msgstr ""
@@ -471,6 +466,8 @@ msgstr ""
#. module: website_event
#: code:addons/website_event/models/event_event.py:0
+#: code:addons/website_event/models/website_menu.py:0
+#: model_terms:ir.ui.view,arch_db:website_event.template_intro
#, python-format
msgid "Introduction"
msgstr ""
@@ -487,6 +484,7 @@ msgstr ""
#. module: website_event
#: code:addons/website_event/models/event_event.py:0
+#: code:addons/website_event/models/website_menu.py:0
#: model_terms:ir.ui.view,arch_db:website_event.event_description_full
#, python-format
msgid "Location"
@@ -738,6 +736,12 @@ msgid "Website Home"
msgstr ""
#. module: website_event
+#: model:ir.model,name:website_event.model_website_menu
+#: model:ir.model.fields,field_description:website_event.field_event_event__website_menu
+msgid "Website Menu"
+msgstr ""
+
+#. module: website_event
#. openerp-web
#: code:addons/website_event/static/src/js/tours/event_tour.js:0
#, python-format
diff --git a/addons/website_event/models/event_event.py b/addons/website_event/models/event_event.py
index 41b4ff8bd05..c933ec38abf 100644
--- a/addons/website_event/models/event_event.py
+++ b/addons/website_event/models/event_event.py
@@ -33,8 +33,8 @@ class Event(models.Model):
# website
website_published = fields.Boolean(tracking=True)
website_menu = fields.Boolean(
- string='Dedicated Menu',
- compute='_compute_from_event_type', readonly=False, store=True,
+ string='Website Menu',
+ compute='_compute_website_menu', readonly=False, store=True,
help="Creates menus Introduction, Location and Register on the page "
"of the event on the website.")
menu_id = fields.Many2one('website.menu', 'Event Menu', copy=False)
@@ -57,15 +57,14 @@ class Event(models.Model):
event.website_url = '/event/%s' % slug(event)
@api.depends('event_type_id')
- def _compute_from_event_type(self):
+ def _compute_website_menu(self):
""" Also ensure a value for website_menu as it is a trigger notably for
track related menus. """
- super(Event, self)._compute_from_event_type()
for event in self:
- if not event.event_type_id and not event.website_menu:
- event.website_menu = False
- elif event.event_type_id:
+ if event.event_type_id and event.event_type_id != event._origin.event_type_id:
event.website_menu = event.event_type_id.website_menu
+ elif not event.website_menu:
+ event.website_menu = False
@api.model
def create(self, vals):
@@ -74,12 +73,10 @@ class Event(models.Model):
return res
def write(self, vals):
- menu_activated = self.filtered(lambda event: event.website_menu)
- menu_deactivated = self.filtered(lambda event: not event.website_menu)
+ menus_state_by_field = self._split_menus_state_by_field()
res = super(Event, self).write(vals)
- menu_to_deactivate = menu_activated.filtered(lambda event: not event.website_menu)
- menu_to_activate = menu_deactivated.filtered(lambda event: event.website_menu)
- (menu_to_activate | menu_to_deactivate)._update_website_menus()
+ menus_update_by_field = self._get_menus_update_by_field(menus_state_by_field)
+ self._update_website_menus(menus_update_by_field=menus_update_by_field)
return res
# ------------------------------------------------------------
@@ -89,9 +86,58 @@ class Event(models.Model):
def toggle_website_menu(self, val):
self.website_menu = val
+ def _get_menu_update_fields(self):
+ """" Return a list of fields triggering a split of menu to activate /
+ menu to de-activate. Due to saas-13.3 improvement of menu management
+ this is done using side-methods to ease inheritance.
+
+ :return list: list of fields, each of which triggering a menu update
+ like website_menu, website_track, ... """
+ return ['website_menu']
+
+ def _split_menus_state_by_field(self):
+ """ For each field linked to a menu, get the set of events having this
+ menu activated and de-activated. Purpose is to find those whose value
+ changed and update the underlying menus.
+
+ :return dict: key = name of field triggering a website menu update, get {
+ 'activated': subset of self having its menu currently set to True
+ 'deactivated': subset of self having its menu currently set to False
+ } """
+ menus_state_by_field = dict()
+ for fname in self._get_menu_update_fields():
+ activated = self.filtered(lambda event: event[fname])
+ menus_state_by_field[fname] = {
+ 'activated': activated,
+ 'deactivated': self - activated,
+ }
+ return menus_state_by_field
+
+ def _get_menus_update_by_field(self, menus_state_by_field):
+ """ For each field linked to a menu, get the set of events requiring
+ this menu to be activated or de-activated based on previous recorded
+ value.
+
+ :return dict: key = name of field triggering a website menu update, get {
+ 'activated': subset of self having its menu toggled to True
+ 'deactivated': subset of self having its menu toggled to False
+ } """
+ menus_update_by_field = dict()
+ for fname in self._get_menu_update_fields():
+ menus_update_by_field[fname] = self.env['event.event']
+ menus_update_by_field[fname] |= menus_state_by_field[fname]['activated'].filtered(lambda event: not event[fname])
+ menus_update_by_field[fname] |= menus_state_by_field[fname]['deactivated'].filtered(lambda event: event[fname])
+ return menus_update_by_field
+
def _get_menu_entries(self):
""" Method returning menu entries to display on the website view of the
- event, possibly depending on some options in inheriting modules. """
+ event, possibly depending on some options in inheriting modules.
+
+ Each menu entry is a tuple containing :
+ * name: menu item name
+ * url: if set, url to a route (do not use xml_id in that case);
+ * xml_id: template linked to the page (do not use url in that case);
+ """
self.ensure_one()
return [
(_('Introduction'), False, 'website_event.template_intro'),
@@ -99,7 +145,10 @@ class Event(models.Model):
(_('Register'), '/event/%s/register' % slug(self), False),
]
- def _update_website_menus(self):
+ def _update_website_menus(self, menus_update_by_field=None):
+ """ Synchronize event configuration and its menu entries for frontend.
+
+ :param menus_update_by_field: see ``_get_menus_update_by_field``"""
for event in self:
if event.menu_id and not event.website_menu:
event.menu_id.unlink()
@@ -109,19 +158,27 @@ class Event(models.Model):
for sequence, (name, url, xml_id) in enumerate(event._get_menu_entries()):
event._create_menu(sequence, name, url, xml_id)
- def _create_menu(self, sequence, name, url, xml_id):
+ def _create_menu(self, sequence, name, url, xml_id, menu_type=False):
+ """ If url: create a website menu. Menu leads directly to the URL that
+ should be a valid route. If xml_id: create a new page, take its url back
+ thanks to new_page of website, then link it to a menu. Template is
+ duplicated and linked to a new url, meaning each menu will have its own
+ copy of the template.
+
+ :param menu_type: type of menu. Mainly used for inheritance purpose
+ allowing more fine-grain tuning of menus. """
if not url:
self.env['ir.ui.view'].with_context(_force_unlink=True).search([('name', '=', name + ' ' + self.name)]).unlink()
- newpath = self.env['website'].sudo().new_page(name + ' ' + self.name, template=xml_id, ispage=False)['url']
- url = "/event/" + slug(self) + "/page/" + newpath[1:]
- menu = self.env['website.menu'].sudo().create({
+ page_result = self.env['website'].sudo().new_page(name + ' ' + self.name, template=xml_id, ispage=False)
+ url = "/event/" + slug(self) + "/page" + page_result['url'] # url contains starting "/"
+ website_menu = self.env['website.menu'].sudo().create({
'name': name,
'url': url,
'parent_id': self.menu_id.id,
'sequence': sequence,
'website_id': self.website_id.id,
})
- return menu
+ return website_menu
# ------------------------------------------------------------
# TOOLS
diff --git a/addons/website_event/tests/common.py b/addons/website_event/tests/common.py
index b4bd532ab04..333a2ed4789 100644
--- a/addons/website_event/tests/common.py
+++ b/addons/website_event/tests/common.py
@@ -2,16 +2,44 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.event.tests.common import TestEventCommon
+from odoo.addons.mail.tests.common import mail_new_test_user
class TestWebsiteEventCommon(TestEventCommon):
+ @classmethod
+ def setUpClass(cls):
+ super(TestWebsiteEventCommon, cls).setUpClass()
+
+ cls.company_main = cls.env.user.company_id
+ cls.user_event_web_manager = mail_new_test_user(
+ cls.env, login='user_event_web_manager',
+ name='Martin Sales Manager', email='crm_manager@test.example.com',
+ company_id=cls.company_main.id,
+ notification_type='inbox',
+ groups='event.group_event_manager,website.group_website_designer',
+ )
+
def _get_menus(self):
return set(['Introduction', 'Location', 'Register'])
- def _assert_website_menus(self, event):
+ def _assert_website_menus(self, event, menu_entries=None):
self.assertTrue(event.menu_id)
+ if menu_entries is None:
+ menu_entries = self._get_menus()
+
menus = self.env['website.menu'].search([('parent_id', '=', event.menu_id.id)])
- self.assertEqual(len(menus), len(self._get_menus()))
- self.assertEqual(set(menus.mapped('name')), self._get_menus())
+ self.assertEqual(len(menus), len(menu_entries))
+ self.assertEqual(set(menus.mapped('name')), menu_entries)
+
+ for page_specific in ['Introduction', 'Location']:
+ view = self.env['ir.ui.view'].search(
+ [('name', '=', page_specific + ' ' + event.name)]
+ )
+ if page_specific in menu_entries:
+ self.assertTrue(bool(view))
+ # TDE FIXME: page deletion not done in 13.3 for Introduction/Location, difficult to fix
+ # without website.event.menu model (or crappy code based on name)
+ # else:
+ # self.assertFalse(bool(view))
diff --git a/addons/website_event/tests/test_event_internals.py b/addons/website_event/tests/test_event_internals.py
index 83ff4901df8..9e99815fd67 100644
--- a/addons/website_event/tests/test_event_internals.py
+++ b/addons/website_event/tests/test_event_internals.py
@@ -20,6 +20,23 @@ class TestEventWebsite(TestWebsiteEventCommon):
})
self._assert_website_menus(event)
+ @users('user_event_web_manager')
+ def test_menu_management_frontend(self):
+ event = self.env['event.event'].create({
+ 'name': 'TestEvent',
+ 'date_begin': fields.Datetime.to_string(datetime.today() + timedelta(days=1)),
+ 'date_end': fields.Datetime.to_string(datetime.today() + timedelta(days=15)),
+ 'website_menu': True,
+ })
+ self.assertTrue(event.website_menu)
+ self._assert_website_menus(event)
+
+ introduction_menu = event.menu_id.child_id.filtered(lambda menu: menu.name == 'Introduction')
+ introduction_menu.unlink()
+
+ self.assertTrue(event.website_menu)
+ self._assert_website_menus(event, set(['Location', 'Register']))
+
@users('user_eventmanager')
def test_menu_update(self):
event = self.env['event.event'].browse(self.event_0.id)