[IMP] website, *: improve the "edit in backend" button

*: base, mrp_account, product, mail, website_blog, website_event,
   website_forum

This commit improves the button that allows to go to the backend view of
an object when you are on its corresponding page on the website. The
button is more visible and the user can see which object he is going to
edit. Note that this commit also:

- Changes the access key to translate a website page to ALT + T.

- Adds a new access key to edit an object in backend with ALT + E.

- Removes the possibility to duplicate a blog post (but this feature
will be reintroduced later for all models, generically) **.

**: Note that the duplication of blog posts actually had a mistake:

The controller to create a new blog post has been added with [1] where
it has been decided to not be a follower of the blog posts at their
creation. A new controller has been added by [2] to be able to duplicate
a blog post, to be consistent with [1], here also the user does not
become a follower of the new blog post (the copy). So far, so good.
Finally, [3] has changed the blog post creation controller so that the
user who creates the blog post is a follower of the new blog post.
Unfortunately the same change was not made for the duplicate controller,
which is a mistake. There is no reason to be a follower of the newly
created blog posts when you go through the add blog post controller but
not when you go through the duplication controller. The behaviors should
be consistent and there is no reason for there to be a difference.

[1]: https://github.com/odoo/odoo/commit/4c3b516a7b988d758a67ff19242e8ed0837d756c
[2]: https://github.com/odoo/odoo/commit/fe40538aff2b65f7719840c8e2d6e51e858f560f
[3]: https://github.com/odoo/odoo/commit/4bf9dc4078a5ca413539a6fd16400fd5aad46907

task-2889929

closes odoo/odoo#97353

Related: odoo/enterprise#30075
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Co-authored-by: qsm-odoo <qsm@odoo.com>
This commit is contained in:
Guillaume (gdi)
2022-09-04 18:29:37 +02:00
committed by qsm-odoo
co-authored by qsm-odoo
parent 14408d6af5
commit c2f394253e
17 changed files with 60 additions and 81 deletions
-1
View File
@@ -16,7 +16,6 @@ class Users(models.Model):
"""
_name = 'res.users'
_inherit = ['res.users']
_description = 'Users'
notification_type = fields.Selection([
('email', 'Handle by Emails'),
-1
View File
@@ -23,7 +23,6 @@ class ProductTemplate(models.Model):
class ProductProduct(models.Model):
_name = 'product.product'
_inherit = 'product.product'
_description = 'Product'
def button_bom_cost(self):
self.ensure_one()
+1 -1
View File
@@ -12,7 +12,7 @@ from odoo.tools import float_compare
class ProductProduct(models.Model):
_name = "product.product"
_description = "Product"
_description = "Product Variant"
_inherits = {'product.template': 'product_tmpl_id'}
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'priority desc, default_code, name, id'
+1 -1
View File
@@ -15,7 +15,7 @@ _logger = logging.getLogger(__name__)
class ProductTemplate(models.Model):
_name = "product.template"
_inherit = ['mail.thread', 'mail.activity.mixin', 'image.mixin']
_description = "Product Template"
_description = "Product"
_order = "priority desc, name"
@tools.ormcache()
@@ -42,6 +42,9 @@ export const websiteService = {
let hasMultiWebsites;
let actionJsId;
let blockingProcesses = [];
let modelNamesProm = null;
const modelNames = {};
const context = reactive({
showNewContentModal: false,
showAceEditor: false,
@@ -222,6 +225,34 @@ export const websiteService = {
hideLoader() {
bus.trigger('HIDE-WEBSITE-LOADER');
},
/**
* Returns the (translated) "functional" name of a model
* (_description) given its "technical" name (_name).
*
* @param {string} [model]
* @returns {string}
*/
async getUserModelName(model = this.currentWebsite.metadata.mainObject.model) {
if (!modelNamesProm) {
// FIXME the `get_available_models` is to be removed/changed
// in a near future. This code is to be adapted, probably
// with another helper to map a model functional name from
// its technical map without the need of the right access
// rights (which is why I cannot use search_read here).
modelNamesProm = orm.call("ir.model", "get_available_models")
.then(modelsData => {
for (const modelData of modelsData) {
modelNames[modelData['model']] = modelData['display_name'];
}
})
// Precaution in case the util is simply removed without
// adapting this method: not critical, we can restore
// later and use the fallback until the fix is made.
.catch(() => {});
}
await modelNamesProm;
return modelNames[model] || env._t("Data");
},
};
},
};
@@ -1,29 +1,25 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { useService, useBus } from "@web/core/utils/hooks";
const { Component, onMounted } = owl;
const { Component, onWillStart, onMounted } = owl;
const websiteSystrayRegistry = registry.category('website_systray');
export class EditInBackendSystray extends Component {
setup() {
this.websiteService = useService('website');
this.actionService = useService('action');
onWillStart(this._updateMainObjectName);
useBus(websiteSystrayRegistry, 'CONTENT-UPDATED', this._updateMainObjectName);
onMounted(() => {
this.websiteService.editedObjectPath = null;
});
}
getElements() {
return [{
title: this.env._t("Settings"),
callback: () => this.editInBackend(),
}];
}
editInBackend() {
const { metadata: { mainObject } } = this.websiteService.currentWebsite;
this.websiteService.editedObjectPath = this.websiteService.contentWindow.location.pathname;
@@ -35,16 +31,16 @@ export class EditInBackendSystray extends Component {
view_mode: "form",
});
}
async _updateMainObjectName() {
this.mainObjectName = await this.websiteService.getUserModelName();
}
}
EditInBackendSystray.template = "website.EditInBackendSystray";
EditInBackendSystray.components = {
Dropdown,
DropdownItem
};
export const systrayItem = {
Component: EditInBackendSystray,
isDisplayed: env => env.services.website.currentWebsite && env.services.website.currentWebsite.metadata.editableInBackend,
};
registry.category("website_systray").add("EditInBackend", systrayItem, { sequence: 7 });
registry.category("website_systray").add("EditInBackend", systrayItem, { sequence: 9 });
@@ -1,14 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="website.EditInBackendSystray" owl="1">
<Dropdown class="'o_menu_systray_item o_website_edit_in_backend'" togglerClass="'p-2'">
<t t-set-slot="toggler"><i class="fa fa-caret-down"/></t>
<t t-foreach="getElements()" t-as="element" t-key="element_index">
<DropdownItem
t-esc="element.title"
onSelected="element.callback"
/>
</t>
</Dropdown>
<div class="o_website_edit_in_backend">
<a href="#" accesskey="e" t-on-click="editInBackend">
<span class="fa fa-cog me-2"/>
<t t-esc="mainObjectName"/>
</a>
</div>
</t>
</templates>
@@ -62,4 +62,4 @@ export const systrayItem = {
isDisplayed: (env) => env.services.website.currentWebsite.metadata.editable,
};
registry.category("website_systray").add("EditWebsite", systrayItem, { sequence: 8 });
registry.category("website_systray").add("EditWebsite", systrayItem, { sequence: 7 });
@@ -96,7 +96,7 @@ export class NewContentModal extends Component {
moduleXmlId: 'base.module_website_hr_recruitment',
status: MODULE_STATUS.NOT_INSTALLED,
icon: xml`<i class="fa fa-briefcase"/>`,
title: this.env._t('Job Offer'),
title: this.env._t('Job Position'),
},
{
moduleXmlId: 'base.module_website_sale',
@@ -32,4 +32,4 @@ export const systrayItem = {
isDisplayed: env => env.services.website.currentWebsite && env.services.website.currentWebsite.metadata.translatable,
};
registry.category("website_systray").add("TranslateWebsiteSystray", systrayItem, { sequence: 9 });
registry.category("website_systray").add("TranslateWebsiteSystray", systrayItem, { sequence: 8 });
@@ -3,7 +3,7 @@
<t t-name="website.TranslateWebsiteSystray" owl="1">
<div class="o_translate_website_container">
<a href="#" accesskey="a" t-on-click="startTranslate">
<a href="#" accesskey="t" t-on-click="startTranslate">
<span t-if="websiteContext.translation" class="fa fa-refresh fa-spin me-2"/>
TRANSLATE
</a>
-13
View File
@@ -205,7 +205,6 @@ class WebsiteBlog(http.Controller):
if blog:
values['main_object'] = blog
values['edit_in_backend'] = True
values['blog_url'] = QueryURL('', ['blog', 'tag'], blog=blog, tag=tag, date_begin=date_begin, date_end=date_end, search=search)
else:
values['blog_url'] = QueryURL('/blog', ['tag'], date_begin=date_begin, date_end=date_end, search=search)
@@ -301,15 +300,3 @@ class WebsiteBlog(http.Controller):
request.session['posts_viewed'].append(blog_post.id)
request.session.modified = True
return response
@http.route('/blog/post_duplicate', type='http', auth="user", website=True, methods=['POST'])
def blog_post_copy(self, blog_post_id, **post):
""" Duplicate a blog.
:param blog_post_id: id of the blog post currently browsed.
:return redirect to the new blog created
"""
new_blog_post = request.env['blog.post'].with_context(mail_create_nosubscribe=True).browse(int(blog_post_id)).copy()
client_action_url = request.env["website"].get_client_action_url(f"/blog/{slug(new_blog_post.blog_id)}/{slug(new_blog_post)}", True)
return request.redirect(client_action_url)
@@ -1,27 +0,0 @@
/** @odoo-module **/
import { EditInBackendSystray } from '@website/systray_items/edit_in_backend';
import { patch } from 'web.utils';
import wUtils from 'website.utils';
patch(EditInBackendSystray.prototype, 'website_blog_edit_in_backend', {
/**
* @override
*/
getElements() {
const elements = this._super();
const { metadata: { mainObject } } = this.websiteService.currentWebsite;
if (mainObject.model === 'blog.post') {
return [...elements, {
title: this.env._t("Duplicate"),
callback: () => this.duplicate(),
}];
}
return elements;
},
async duplicate() {
const { metadata: { mainObject } } = this.websiteService.currentWebsite;
wUtils.sendRequest('/blog/post_duplicate', { blog_post_id: mainObject.id });
}
});
@@ -40,11 +40,7 @@ EventAdditionalTourSteps.include({
content: Markup(_t("Looking great! Let's now <b>publish</b> this page so that it becomes <b>visible</b> on your website!")),
position: 'bottom',
}, {
trigger: '.o_menu_systray_item.o_website_edit_in_backend .dropdown-toggle',
content: _t("Want to change your event configuration? Let's go back to the event form."),
position: 'bottom',
}, {
trigger: '.o_menu_systray_item.o_website_edit_in_backend .dropdown-menu .dropdown-item',
trigger: '.o_website_edit_in_backend > a',
extra_trigger: 'iframe .o_wevent_event',
content: _t("This shortcut will bring you right back to the event form."),
position: 'bottom'
@@ -62,7 +62,7 @@ odoo.define("website_event.tour", function (require) {
content: _t("Click to publish your event."),
position: "top",
}, {
trigger: ".o_menu_systray_item.o_website_edit_in_backend",
trigger: ".o_website_edit_in_backend > a",
content: _t("Click here to customize your event further."),
position: "bottom",
}]);
+2 -1
View File
@@ -155,7 +155,7 @@ class WebsiteForum(WebsiteProfile):
values = self._prepare_user_values(forum=forum, searches=post, header={'ask_hide': not forum.active})
values.update({
'main_object': tag or forum,
'edit_in_backend': not tag,
'edit_in_backend': True,
'question_ids': question_ids,
'question_count': question_count,
'search_count': question_count,
@@ -258,6 +258,7 @@ class WebsiteForum(WebsiteProfile):
values = self._prepare_user_values(forum=forum, searches=post)
values.update({
'main_object': question,
'edit_in_backend': True,
'question': question,
'can_bump': (question.forum_id.allow_bump and not question.child_count and (datetime.today() - question.write_date).days > 9),
'header': {'question_data': True},
+1 -1
View File
@@ -244,7 +244,7 @@ class Users(models.Model):
avatar, ... The user model is now dedicated to technical data.
"""
_name = "res.users"
_description = 'Users'
_description = 'User'
_inherits = {'res.partner': 'partner_id'}
_order = 'name, login'