diff --git a/addons/event/__manifest__.py b/addons/event/__manifest__.py
index e49f260e24a..2c1e03c7d1c 100644
--- a/addons/event/__manifest__.py
+++ b/addons/event/__manifest__.py
@@ -32,6 +32,7 @@ Key Features
'views/res_config_settings_views.xml',
'views/event_templates.xml',
'views/res_partner_views.xml',
+ 'views/event_tag_views.xml'
],
'demo': [
'data/res_users_demo.xml',
diff --git a/addons/event/data/event_demo.xml b/addons/event/data/event_demo.xml
index 91651959471..01022610b7e 100644
--- a/addons/event/data/event_demo.xml
+++ b/addons/event/data/event_demo.xml
@@ -25,6 +25,50 @@
Europe/Brussels
+
+
+ Age
+
+
+
+ Activity
+
+
+
+ 5-10
+
+
+
+
+ 10-14
+
+
+
+
+ 15-18
+
+
+
+
+ 18+
+
+
+
+
+ Culture
+
+
+
+
+ Music
+
+
+
+
+ Sport
+
+
+
Design Fair Los Angeles
@@ -37,6 +81,7 @@
US/Pacific
+
Free
@@ -72,6 +117,7 @@
blocked
+
@@ -125,6 +171,7 @@
limited
200
+
Standard
@@ -160,6 +207,7 @@
+
Standard
@@ -200,6 +248,7 @@
done
+
General Admission
@@ -224,6 +273,7 @@
+
diff --git a/addons/event/models/__init__.py b/addons/event/models/__init__.py
index 943b57206f9..4aefa5d6068 100644
--- a/addons/event/models/__init__.py
+++ b/addons/event/models/__init__.py
@@ -5,6 +5,7 @@ from . import event_event
from . import event_mail
from . import event_registration
from . import event_stage
+from . import event_tag
from . import event_ticket
from . import res_config_settings
from . import res_partner
diff --git a/addons/event/models/event_event.py b/addons/event/models/event_event.py
index 301cfb99266..a091da8ff6b 100644
--- a/addons/event/models/event_event.py
+++ b/addons/event/models/event_event.py
@@ -21,10 +21,10 @@ except ImportError:
class EventType(models.Model):
_name = 'event.type'
- _description = 'Event Category'
+ _description = 'Event Template'
_order = 'sequence, id'
- name = fields.Char('Event Category', required=True, translate=True)
+ name = fields.Char('Event Template', required=True, translate=True)
sequence = fields.Integer()
# tickets
use_ticket = fields.Boolean('Ticketing')
@@ -32,6 +32,7 @@ class EventType(models.Model):
'event.type.ticket', 'event_type_id',
string='Tickets', compute='_compute_event_type_ticket_ids',
readonly=False, store=True)
+ tag_ids = fields.Many2many('event.tag', string="Tags", copy=True)
# registration
has_seats_limitation = fields.Boolean('Limited Seats')
seats_max = fields.Integer(
@@ -91,7 +92,6 @@ class EventType(models.Model):
if not template.has_seats_limitation:
template.seats_max = 0
-
class EventEvent(models.Model):
"""Event"""
_name = 'event.event'
@@ -118,11 +118,13 @@ class EventEvent(models.Model):
'res.partner', string='Organizer', tracking=True,
default=lambda self: self.env.company.partner_id,
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
- event_type_id = fields.Many2one('event.type', string='Category', ondelete='set null')
+ event_type_id = fields.Many2one('event.type', string='Template', ondelete='set null')
color = fields.Integer('Kanban Color Index')
event_mail_ids = fields.One2many(
'event.mail', 'event_id', string='Mail Schedule', copy=True,
compute='_compute_from_event_type', readonly=False, store=True)
+ tag_ids = fields.Many2many('event.tag', string="Tags", readonly=False,
+ copy=True, store=True, compute="_compute_from_event_type")
# Kanban fields
kanban_state = fields.Selection([('normal', 'In Progress'), ('done', 'Done'), ('blocked', 'Blocked')], default='normal')
kanban_state_label = fields.Char(
@@ -379,6 +381,9 @@ class EventEvent(models.Model):
})
for line in event.event_type_id.event_type_ticket_ids]
+ if event.event_type_id.tag_ids:
+ event.tag_ids = event.event_type_id.tag_ids
+
@api.constrains('seats_max', 'seats_available', 'seats_availability')
def _check_seats_limit(self):
if any(event.seats_availability == 'limited' and event.seats_max and event.seats_available < 0 for event in self):
diff --git a/addons/event/models/event_tag.py b/addons/event/models/event_tag.py
new file mode 100644
index 00000000000..fc5f733386a
--- /dev/null
+++ b/addons/event/models/event_tag.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import _, api, fields, models
+
+
+class EventTagCategory(models.Model):
+ _name = "event.tag.category"
+ _description = "Event Tag Category"
+ _order = "sequence"
+
+ name = fields.Char("Name", required=True, translate=True)
+ sequence = fields.Integer('Sequence', default=0)
+ tag_ids = fields.One2many('event.tag', 'category_id', string="Tags")
+
+class EventTag(models.Model):
+ _name = "event.tag"
+ _description = "Event Tag"
+ _order = "sequence"
+
+ name = fields.Char("Name", required=True, translate=True)
+ sequence = fields.Integer('Sequence', default=0)
+ category_id = fields.Many2one("event.tag.category", string="Category", required=True, ondelete='cascade')
+
+ def name_get(self):
+ return [(tag.id, _("%s: %s" % (tag.category_id.name, tag.name))) for tag in self]
diff --git a/addons/event/security/ir.model.access.csv b/addons/event/security/ir.model.access.csv
index 9d680924f5d..909f21e4b80 100644
--- a/addons/event/security/ir.model.access.csv
+++ b/addons/event/security/ir.model.access.csv
@@ -19,3 +19,7 @@ access_event_type_mail_event_user,event.type.mail.event.user,model_event_type_ma
access_event_type_mail_event_manager,event.type.mail.event.manager,model_event_type_mail,event.group_event_manager,1,1,1,1
access_event_stage_user,event.stage.user,model_event_stage,event.group_event_user,1,1,1,1
access_event_stage_manager,event.stage.manager,model_event_stage,event.group_event_manager,1,1,1,1
+access_event_category,event.tag.category,model_event_tag_category,event.group_event_user,1,0,0,0
+access_event_category_manager,event.tag.category manager,model_event_tag_category,event.group_event_manager,1,1,1,1
+access_event_tag,event.tag,model_event_tag,event.group_event_user,1,0,0,0
+access_event_tag_manager,event.tag manager,model_event_tag,event.group_event_manager,1,1,1,1
diff --git a/addons/event/views/event_menu_views.xml b/addons/event/views/event_menu_views.xml
index 3f42322e9b3..ffb58639d61 100644
--- a/addons/event/views/event_menu_views.xml
+++ b/addons/event/views/event_menu_views.xml
@@ -28,7 +28,7 @@
sequence="99"
parent="event_main_menu"
groups="event.group_event_user"/>
-
@@ -37,5 +37,9 @@
sequence="10"
parent="menu_event_configuration"
groups="base.group_no_one"/>
+
diff --git a/addons/event/views/event_tag_views.xml b/addons/event/views/event_tag_views.xml
new file mode 100644
index 00000000000..6d2ae530bb9
--- /dev/null
+++ b/addons/event/views/event_tag_views.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+ event.tag.category.view.tree
+ event.tag.category
+
+
+
+
+
+
+
+
+
+
+ event.tag.category.view.form
+ event.tag.category
+
+
+
+
+
+
+ Event Tags Categories
+ event.tag.category
+ tree,form
+
+
+
+
+ event.tag.view.tree
+ event.tag
+
+
+
+
+
+
+
+
+
+
+ event.tag.view.form
+ event.tag
+
+
+
+
+
+
+
+
+
diff --git a/addons/event/views/event_views.xml b/addons/event/views/event_views.xml
index 43f778f9a5e..7a9842507f2 100644
--- a/addons/event/views/event_views.xml
+++ b/addons/event/views/event_views.xml
@@ -86,6 +86,10 @@
+
+
+
+
Attendees
@@ -131,7 +135,7 @@
event.type.tree
event.type
-
+
@@ -142,7 +146,7 @@
event.type.search
event.type
-
+
@@ -150,7 +154,7 @@
- Event Categories
+ Event Templates
event.type
@@ -227,6 +231,7 @@
+
@@ -446,7 +451,7 @@
domain="[('activity_ids.date_deadline', '>', context_today().strftime('%Y-%m-%d'))]"/>
-
+
diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py
index 570074d7b4b..8691222101d 100644
--- a/addons/website_event/controllers/main.py
+++ b/addons/website_event/controllers/main.py
@@ -5,6 +5,8 @@ import re
import werkzeug
from werkzeug.datastructures import OrderedMultiDict
+from ast import literal_eval
+from collections import defaultdict
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
@@ -12,6 +14,7 @@ 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
+from odoo.osv import expression
from odoo.tools.misc import get_lang, format_date
@@ -28,6 +31,7 @@ class WebsiteEventController(http.Controller):
searches.setdefault('search', '')
searches.setdefault('date', 'all')
+ searches.setdefault('tags', '')
searches.setdefault('type', 'all')
searches.setdefault('country', 'all')
@@ -70,6 +74,19 @@ class WebsiteEventController(http.Controller):
if searches['search']:
domain_search['search'] = [('name', 'ilike', searches['search'])]
+ search_tags = self._extract_searched_event_tags(searches)
+ if search_tags:
+ # Example: You filter on age: 10-12 and activity: football.
+ # Doing it this way allows to only get events who are tagged "age: 10-12" AND "activity: football".
+ # Add another tag "age: 12-15" to the search and it would fetch the ones who are tagged:
+ # ("age: 10-12" OR "age: 12-15") AND "activity: football
+ grouped_tags = defaultdict(list)
+ for tag in search_tags:
+ grouped_tags[tag.category_id].append(tag)
+ domain_search['tags'] = []
+ for group in grouped_tags:
+ domain_search['tags'] = expression.AND([domain_search['tags'], [('tag_ids', 'in', [tag.id for tag in grouped_tags[group]])]])
+
current_date = None
current_type = None
current_country = None
@@ -102,11 +119,6 @@ class WebsiteEventController(http.Controller):
date[3] = Event.search_count(dom_without('date') + date[2])
domain = dom_without('type')
- types = Event.read_group(domain, ["id", "event_type_id"], groupby=["event_type_id"], orderby="event_type_id")
- types.insert(0, {
- 'event_type_id_count': sum([int(type['event_type_id_count']) for type in types]),
- 'event_type_id': ("all", _("All Categories"))
- })
domain = dom_without('country')
countries = Event.read_group(domain, ["id", "country_id"], groupby="country_id", orderby="country_id")
@@ -141,10 +153,11 @@ class WebsiteEventController(http.Controller):
'current_type': current_type,
'event_ids': events, # event_ids used in website_event_track so we keep name as it is
'dates': dates,
- 'types': types,
+ 'categories': request.env['event.tag.category'].search([]),
'countries': countries,
'pager': pager,
'searches': searches,
+ 'search_tags': search_tags,
'keep': keep,
}
@@ -342,3 +355,15 @@ class WebsiteEventController(http.Controller):
'google_url': urls.get('google_url'),
'iCal_url': urls.get('iCal_url')
})
+
+ def _extract_searched_event_tags(self, searches):
+ tags = request.env['event.tag']
+ if searches.get('tags'):
+ try:
+ tag_ids = literal_eval(searches['tags'])
+ except:
+ pass
+ else:
+ # perform a search to filter on existing / valid tags implicitely
+ tags = request.env['event.tag'].search([('id', 'in', tag_ids)])
+ return tags
diff --git a/addons/website_event/security/ir.model.access.csv b/addons/website_event/security/ir.model.access.csv
index 1024bdc8213..e55cfc58bbf 100644
--- a/addons/website_event/security/ir.model.access.csv
+++ b/addons/website_event/security/ir.model.access.csv
@@ -4,3 +4,5 @@ access_event_event_portal,event.event.portal,event.model_event_event,base.group_
access_event_type_public,event.type.public,event.model_event_type,,1,0,0,0
access_event_event_ticket_public,event.event.ticket.public,event.model_event_event_ticket,base.group_public,1,0,0,0
access_event_event_ticket_portal,event.event.ticket.portal,event.model_event_event_ticket,base.group_portal,1,0,0,0
+access_event_category_public,event.tag.category.public,event.model_event_tag_category,,1,0,0,0
+access_event_tag_public,event.tag.public,event.model_event_tag,,1,0,0,0
diff --git a/addons/website_event/static/src/scss/website_event.scss b/addons/website_event/static/src/scss/website_event.scss
index 4be4eeacba2..127874736f7 100644
--- a/addons/website_event/static/src/scss/website_event.scss
+++ b/addons/website_event/static/src/scss/website_event.scss
@@ -1,11 +1,3 @@
-.o_wevent_event_searchbar_form {
- flex: 0 0 100%;
-
- @include media-breakpoint-up(lg) {
- flex: 0 0 33%;
- }
-}
-
.o_wevent_index_topbar_filters {
.dropdown-toggle {
border: $border-width solid gray('400');
diff --git a/addons/website_event/views/event_templates.xml b/addons/website_event/views/event_templates.xml
index 3bd32369a92..35592fed462 100644
--- a/addons/website_event/views/event_templates.xml
+++ b/addons/website_event/views/event_templates.xml
@@ -15,6 +15,9 @@
+
+
+
@@ -231,7 +265,7 @@
-
+
@@ -290,20 +324,6 @@
-
-
-