diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index 52d5f8e711f..c4e0e20675a 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -225,6 +225,45 @@ class Website(Home):
raise werkzeug.exceptions.NotFound()
return request.redirect(url)
+ @http.route('/website/get_suggested_links', type='json', auth="user", website=True)
+ def get_suggested_link(self, needle, limit=10):
+ current_website = request.website
+
+ matching_pages = []
+ for page in current_website.search_pages(needle, limit=int(limit)):
+ matching_pages.append({
+ 'value': page['loc'],
+ 'label': 'name' in page and '%s (%s)' % (page['loc'], page['name']) or page['loc'],
+ })
+ matching_urls = set(map(lambda match: match['value'], matching_pages))
+
+ matching_last_modified = []
+ last_modified_pages = current_website.get_website_pages(order='write_date desc', limit=5)
+ for url, name in last_modified_pages.mapped(lambda p: (p.url, p.name)):
+ if needle.lower() in name.lower() or needle.lower() in url.lower() and url not in matching_urls:
+ matching_last_modified.append({
+ 'value': url,
+ 'label': '%s (%s)' % (url, name),
+ })
+
+ suggested_controllers = []
+ for name, url, mod in current_website.get_suggested_controllers():
+ if needle.lower() in name.lower() or needle.lower() in url.lower():
+ module = mod and request.env.ref('base.module_%s' % mod, False)
+ icon = mod and "
" % (module and module.icon or mod) or ''
+ suggested_controllers.append({
+ 'value': url,
+ 'label': '%s%s (%s)' % (icon, url, name),
+ })
+
+ return {
+ 'matching_pages': sorted(matching_pages, key=lambda o: o['label']),
+ 'others': [
+ dict(title=_('Last modified pages'), values=matching_last_modified),
+ dict(title=_('Apps url'), values=suggested_controllers),
+ ]
+ }
+
# ------------------------------------------------------
# Edit
# ------------------------------------------------------
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 9eeb0a98589..d230000c23f 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -13,7 +13,7 @@ from werkzeug.datastructures import OrderedMultiDict
from werkzeug.exceptions import NotFound
from odoo import api, fields, models, tools
-from odoo.addons.http_routing.models.ir_http import slugify, _guess_mimetype
+from odoo.addons.http_routing.models.ir_http import slugify, _guess_mimetype, url_for
from odoo.addons.website.models.ir_http import sitemap_qs2dom
from odoo.addons.portal.controllers.portal import pager
from odoo.http import request
@@ -862,7 +862,7 @@ class Website(models.Model):
def get_website_pages(self, domain=[], order='name', limit=None):
domain += self.get_current_website().website_domain()
- pages = self.env['website.page'].search(domain, order='name', limit=limit)
+ pages = self.env['website.page'].search(domain, order=order, limit=limit)
return pages
def search_pages(self, needle=None, limit=None):
@@ -874,6 +874,14 @@ class Website(models.Model):
break
return res
+ def get_suggested_controllers(self):
+ """
+ Returns a tuple (name, url, icon).
+ Where icon can be a module name, or a path
+ """
+ suggested_controllers = [(_('Homepage'), url_for('/'), 'website')]
+ return suggested_controllers
+
@api.model
def image_url(self, record, field, size=None):
""" Returns a local url that points to the image field of a given browse record. """
diff --git a/addons/website/static/src/js/utils.js b/addons/website/static/src/js/utils.js
index d8e69e3eba4..7947eb6f93c 100644
--- a/addons/website/static/src/js/utils.js
+++ b/addons/website/static/src/js/utils.js
@@ -33,7 +33,35 @@ function loadAnchors(url) {
* @param {jQuery} $input
*/
function autocompleteWithPages(self, $input) {
- $input.autocomplete({
+ $.widget("website.urlcomplete", $.ui.autocomplete, {
+ _create: function () {
+ this._super();
+ this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
+ },
+ _renderMenu: function (ul, items) {
+ const self = this;
+ items.forEach(item => {
+ if (item.separator) {
+ self._renderSeparator(ul, item);
+ }
+ else {
+ self._renderItem(ul, item);
+ }
+ });
+ },
+ _renderSeparator: function (ul, item) {
+ return $("
")
+ .append(`${item.separator}
`)
+ .appendTo(ul);
+ },
+ _renderItem: function (ul, item) {
+ return $("")
+ .data('ui-autocomplete-item', item)
+ .append(`${item.label}
`)
+ .appendTo(ul);
+ },
+ });
+ $input.urlcomplete({
source: function (request, response) {
if (request.term[0] === '#') {
loadAnchors(request.term).then(function (anchors) {
@@ -41,17 +69,22 @@ function autocompleteWithPages(self, $input) {
});
} else {
return self._rpc({
- model: 'website',
- method: 'search_pages',
- args: [null, request.term],
- kwargs: {
+ route: '/website/get_suggested_links',
+ params: {
+ needle: request.term,
limit: 15,
- },
- }).then(function (exists) {
- var rs = _.map(exists, function (r) {
- return r.loc;
+ }
+ }).then(function (res) {
+ let choices = res.matching_pages;
+ res.others.forEach(other => {
+ if (other.values.length) {
+ choices = choices.concat(
+ [{separator: other.title}],
+ other.values,
+ );
+ }
});
- response(rs.sort());
+ response(choices);
});
}
},
diff --git a/addons/website/tests/__init__.py b/addons/website/tests/__init__.py
index 99ac6f1bc57..a9fac1e745b 100644
--- a/addons/website/tests/__init__.py
+++ b/addons/website/tests/__init__.py
@@ -17,3 +17,4 @@ from . import test_views
from . import test_website_favicon
from . import test_website_reset_password
from . import test_website_visitor
+from . import test_controllers
diff --git a/addons/website/tests/test_controllers.py b/addons/website/tests/test_controllers.py
new file mode 100644
index 00000000000..edfb65feeb0
--- /dev/null
+++ b/addons/website/tests/test_controllers.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import json
+
+from odoo import tests
+from odoo.tools import mute_logger
+
+
+@tests.tagged('post_install', '-at_install')
+class TestControllers(tests.HttpCase):
+
+ @mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
+ def test_last_created_pages_autocompletion(self):
+ self.authenticate("admin", "admin")
+ Page = self.env['website.page']
+ last_5_url_edited = []
+ base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ suggested_links_url = base_url + '/website/get_suggested_links'
+
+ for i in range(0, 10):
+ new_page = Page.create({
+ 'name': 'Generic',
+ 'type': 'qweb',
+ 'arch': '''
+ content
+ ''',
+ 'key': "test.generic_view-%d" % i,
+ 'url': "/generic-%d" % i,
+ 'is_published': True,
+ })
+ if i % 2 == 0:
+ # mark as old
+ new_page._write({'write_date': '2020-01-01'})
+ else:
+ last_5_url_edited.append(new_page.url)
+
+ res = self.opener.post(url=suggested_links_url, json={'params': {'needle': '/'}})
+ resp = json.loads(res.content)
+ assert 'result' in resp
+ suggested_links = resp['result']
+ last_modified_history = next(o for o in suggested_links['others'] if o["title"] == "Last modified pages")
+ last_modified_values = map(lambda o: o['value'], last_modified_history['values'])
+ self.assertTrue(set(last_modified_values) == set(last_5_url_edited))
diff --git a/addons/website_blog/models/website.py b/addons/website_blog/models/website.py
index 17478434aa9..a647326c340 100644
--- a/addons/website_blog/models/website.py
+++ b/addons/website_blog/models/website.py
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models, _
+from odoo.addons.http_routing.models.ir_http import url_for
class Website(models.Model):
@@ -56,3 +57,8 @@ class Website(models.Model):
})
return dep
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Blog'), url_for('/blog'), 'website_blog'))
+ return suggested_controllers
diff --git a/addons/website_crm_partner_assign/data/crm_partner_assign_data.xml b/addons/website_crm_partner_assign/data/crm_partner_assign_data.xml
index f88fc4a7231..5ca6dee5ea0 100644
--- a/addons/website_crm_partner_assign/data/crm_partner_assign_data.xml
+++ b/addons/website_crm_partner_assign/data/crm_partner_assign_data.xml
@@ -120,14 +120,4 @@
-
-
-
-
-
diff --git a/addons/website_crm_partner_assign/models/__init__.py b/addons/website_crm_partner_assign/models/__init__.py
index 7021ef01854..f5fb173f8f5 100644
--- a/addons/website_crm_partner_assign/models/__init__.py
+++ b/addons/website_crm_partner_assign/models/__init__.py
@@ -3,3 +3,4 @@
from . import crm_lead
from . import res_partner
+from . import website
diff --git a/addons/website_crm_partner_assign/models/website.py b/addons/website_crm_partner_assign/models/website.py
new file mode 100644
index 00000000000..5910fb511d3
--- /dev/null
+++ b/addons/website_crm_partner_assign/models/website.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+from odoo.addons.http_routing.models.ir_http import url_for
+
+
+class Website(models.Model):
+ _inherit = "website"
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Resellers'), url_for('/partners'), 'website_crm_partner_assign'))
+ return suggested_controllers
diff --git a/addons/website_customer/__manifest__.py b/addons/website_customer/__manifest__.py
index 3dde2763480..ab0d19a695d 100644
--- a/addons/website_customer/__manifest__.py
+++ b/addons/website_customer/__manifest__.py
@@ -18,7 +18,6 @@ Publish your customers as business references on your website to attract new pot
'data/res_partner_demo.xml',
],
'data': [
- 'data/website_customer_data.xml',
'views/website_customer_templates.xml',
'views/res_partner_views.xml',
'security/ir.model.access.csv',
diff --git a/addons/website_customer/data/website_customer_data.xml b/addons/website_customer/data/website_customer_data.xml
deleted file mode 100644
index 46d3e781292..00000000000
--- a/addons/website_customer/data/website_customer_data.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/addons/website_customer/models/__init__.py b/addons/website_customer/models/__init__.py
index 9ec15f238e2..79be1c95b6d 100644
--- a/addons/website_customer/models/__init__.py
+++ b/addons/website_customer/models/__init__.py
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import res_partner
+from . import website
diff --git a/addons/website_customer/models/website.py b/addons/website_customer/models/website.py
new file mode 100644
index 00000000000..fe812512cc5
--- /dev/null
+++ b/addons/website_customer/models/website.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+from odoo.addons.http_routing.models.ir_http import url_for
+
+
+class Website(models.Model):
+ _inherit = "website"
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('References'), url_for('/customers'), 'website_customer'))
+ return suggested_controllers
diff --git a/addons/website_event/models/__init__.py b/addons/website_event/models/__init__.py
index e972cdb2a6f..67661173e03 100644
--- a/addons/website_event/models/__init__.py
+++ b/addons/website_event/models/__init__.py
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from . import event_event
+from . import website
diff --git a/addons/website_event/models/website.py b/addons/website_event/models/website.py
new file mode 100644
index 00000000000..bb34800aa26
--- /dev/null
+++ b/addons/website_event/models/website.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+from odoo.addons.http_routing.models.ir_http import url_for
+
+
+class Website(models.Model):
+ _inherit = "website"
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Events'), url_for('/event'), 'website_event'))
+ return suggested_controllers
diff --git a/addons/website_forum/models/website.py b/addons/website_forum/models/website.py
index 29a42fd8850..dcd937bf835 100644
--- a/addons/website_forum/models/website.py
+++ b/addons/website_forum/models/website.py
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import models, fields
+from odoo import models, fields, _
+from odoo.addons.http_routing.models.ir_http import url_for
class Website(models.Model):
@@ -13,3 +14,8 @@ class Website(models.Model):
website.forums_count = Forum.search_count(website.website_domain())
forums_count = fields.Integer(compute=_compute_field_forums_count)
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Forum'), url_for('/forum'), 'website_forum'))
+ return suggested_controllers
diff --git a/addons/website_hr_recruitment/data/config_data.xml b/addons/website_hr_recruitment/data/config_data.xml
index 46ecb179e0b..5cac1bc871b 100644
--- a/addons/website_hr_recruitment/data/config_data.xml
+++ b/addons/website_hr_recruitment/data/config_data.xml
@@ -1,12 +1,6 @@
-
Website Recruitment Form
self
diff --git a/addons/website_hr_recruitment/models/__init__.py b/addons/website_hr_recruitment/models/__init__.py
index 7e9137491c9..dad12c939ce 100644
--- a/addons/website_hr_recruitment/models/__init__.py
+++ b/addons/website_hr_recruitment/models/__init__.py
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import hr_recruitment
+from . import website
diff --git a/addons/website_hr_recruitment/models/website.py b/addons/website_hr_recruitment/models/website.py
new file mode 100644
index 00000000000..5a2cd5d37d5
--- /dev/null
+++ b/addons/website_hr_recruitment/models/website.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+from odoo.addons.http_routing.models.ir_http import url_for
+
+
+class Website(models.Model):
+ _inherit = "website"
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Jobs'), url_for('/jobs'), 'website_hr_recruitment'))
+ return suggested_controllers
diff --git a/addons/website_livechat/controllers/main.py b/addons/website_livechat/controllers/main.py
index 242d78857f9..340604cca80 100644
--- a/addons/website_livechat/controllers/main.py
+++ b/addons/website_livechat/controllers/main.py
@@ -49,6 +49,7 @@ class WebsiteLivechat(LivechatController):
# the value dict to render the template
values = {
+ 'main_object': channel,
'channel': channel,
'ratings': ratings,
'team': channel.sudo().user_ids,
diff --git a/addons/website_livechat/data/website_livechat_data.xml b/addons/website_livechat/data/website_livechat_data.xml
index 554ff7694dd..556079a5970 100644
--- a/addons/website_livechat/data/website_livechat_data.xml
+++ b/addons/website_livechat/data/website_livechat_data.xml
@@ -5,13 +5,6 @@
-
-
diff --git a/addons/website_livechat/models/website.py b/addons/website_livechat/models/website.py
index 31458961b73..a4bd8b1513e 100644
--- a/addons/website_livechat/models/website.py
+++ b/addons/website_livechat/models/website.py
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import api, fields, models
+from odoo import fields, models, _
+from odoo.addons.http_routing.models.ir_http import url_for
class Website(models.Model):
@@ -55,3 +56,8 @@ class Website(models.Model):
"type": "chat_request"
}
return {}
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Live Support'), url_for('/livechat'), 'website_livechat'))
+ return suggested_controllers
diff --git a/addons/website_livechat/views/website_livechat.xml b/addons/website_livechat/views/website_livechat.xml
index 28860638f79..23c27eadb10 100644
--- a/addons/website_livechat/views/website_livechat.xml
+++ b/addons/website_livechat/views/website_livechat.xml
@@ -68,12 +68,6 @@
-
-
-
-
-
-
Livechat Channel
@@ -83,7 +77,7 @@
Statistics
-
+

@@ -98,7 +92,7 @@
-
+

@@ -113,7 +107,7 @@
-
+

@@ -134,7 +128,7 @@
The last feedbacks
-
+
@@ -200,7 +194,7 @@
-
Livechat Support Channels
+
Livechat Support Channels
@@ -208,13 +202,13 @@
-
+
-
diff --git a/addons/website_mail_channel/data/mail_template_data.xml b/addons/website_mail_channel/data/mail_template_data.xml
index 0f3056ea2c4..52859d08aae 100644
--- a/addons/website_mail_channel/data/mail_template_data.xml
+++ b/addons/website_mail_channel/data/mail_template_data.xml
@@ -175,13 +175,4 @@
-
-
-
-
diff --git a/addons/website_mail_channel/models/__init__.py b/addons/website_mail_channel/models/__init__.py
index 5280d256a09..f5c2bbb5e3c 100644
--- a/addons/website_mail_channel/models/__init__.py
+++ b/addons/website_mail_channel/models/__init__.py
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import mail_channel
from . import mail_mail
+from . import website
diff --git a/addons/website_mail_channel/models/website.py b/addons/website_mail_channel/models/website.py
new file mode 100644
index 00000000000..854e99bdbe8
--- /dev/null
+++ b/addons/website_mail_channel/models/website.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+from odoo.addons.http_routing.models.ir_http import url_for
+
+
+class Website(models.Model):
+ _inherit = "website"
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Mailing Lists'), url_for('/groups'), 'website_mail_channel'))
+ return suggested_controllers
diff --git a/addons/website_membership/__manifest__.py b/addons/website_membership/__manifest__.py
index 7246cc2ced2..3b87b94f5b1 100644
--- a/addons/website_membership/__manifest__.py
+++ b/addons/website_membership/__manifest__.py
@@ -11,7 +11,6 @@ Publish your members/association directory publicly.
""",
'depends': ['website_partner', 'website_google_map', 'association', 'website_sale'],
'data': [
- 'data/membership_data.xml',
'views/product_template_views.xml',
'views/website_membership_templates.xml',
'security/ir.model.access.csv',
diff --git a/addons/website_membership/data/membership_data.xml b/addons/website_membership/data/membership_data.xml
deleted file mode 100644
index b542857e5ec..00000000000
--- a/addons/website_membership/data/membership_data.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/addons/website_membership/models/__init__.py b/addons/website_membership/models/__init__.py
index cda92309290..6627227f59c 100644
--- a/addons/website_membership/models/__init__.py
+++ b/addons/website_membership/models/__init__.py
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import membership
+from . import website
diff --git a/addons/website_membership/models/website.py b/addons/website_membership/models/website.py
new file mode 100644
index 00000000000..71540ac32b1
--- /dev/null
+++ b/addons/website_membership/models/website.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+from odoo.addons.http_routing.models.ir_http import url_for
+
+
+class Website(models.Model):
+ _inherit = "website"
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Members'), url_for('/members'), 'website_membership'))
+ return suggested_controllers
diff --git a/addons/website_sale/models/website.py b/addons/website_sale/models/website.py
index 9177367a4a2..deb6e746828 100644
--- a/addons/website_sale/models/website.py
+++ b/addons/website_sale/models/website.py
@@ -3,10 +3,11 @@
import logging
-from odoo import api, fields, models, tools, SUPERUSER_ID
+from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.http import request
from odoo.addons.website.models import ir_http
+from odoo.addons.http_routing.models.ir_http import url_for
_logger = logging.getLogger(__name__)
@@ -364,3 +365,8 @@ class Website(models.Model):
if self.env.user.has_group('sales_team.group_sale_salesman'):
return self.env.ref('website.backend_dashboard').read()[0]
return super(Website, self).action_dashboard_redirect()
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('eCommerce'), url_for('/shop'), 'website_sale'))
+ return suggested_controllers
diff --git a/addons/website_slides/models/website.py b/addons/website_slides/models/website.py
index 1896243fa8f..7b559895b1c 100644
--- a/addons/website_slides/models/website.py
+++ b/addons/website_slides/models/website.py
@@ -1,10 +1,16 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import api, fields, models
+from odoo import fields, models, _
+from odoo.addons.http_routing.models.ir_http import url_for
class Website(models.Model):
_inherit = "website"
website_slide_google_app_key = fields.Char('Google Doc Key')
+
+ def get_suggested_controllers(self):
+ suggested_controllers = super(Website, self).get_suggested_controllers()
+ suggested_controllers.append((_('Courses'), url_for('/slides'), 'website_slides'))
+ return suggested_controllers