[FIX] website, *: redirect to the WebsitePreview using ir.actions.client
*: website_forum, website_hr_recruitment, website_sale Before this commit, most of the backend redirections to the WebsitePreview, introduced in [1], were using ir.actions.url with the get_client_action_url util, which was not optimal. This commit changes that to use a new get_client_action method, which returns the ir.actions.client record. It will execute the action directly, avoid to redirect the router before, and improve performances. Also, it allows to solve bugs, as: - The back navigation from the WebsitePreview to the ListViews. Going through the /web controller would add an entry in the history, and going back on it would reload the client action. [1]: https://github.com/odoo/odoo/commit/31cc10b91dc7762e23b4bde9b945be0c4ce3fe3b task-2687506 closes odoo/odoo#102991 X-original-commit: 30fb11e479fb7b3db3649e55fcbdb06bfcdb398c Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -399,8 +399,8 @@ class IrModuleModule(models.Model):
|
||||
result = active_todo.action_launch()
|
||||
else:
|
||||
result = website.button_go_website(mode_edit=True)
|
||||
if result.get('url') and 'enable_editor' in result['url']:
|
||||
result['url'] = result['url'].replace('enable_editor', 'with_loader=1&enable_editor')
|
||||
if result.get('tag') == 'website_preview' and result.get('context', {}).get('params', {}).get('enable_editor'):
|
||||
result['context']['params']['with_loader'] = True
|
||||
return result
|
||||
|
||||
def button_remove_theme(self):
|
||||
|
||||
@@ -200,12 +200,7 @@ class WebsitePublishedMixin(models.AbstractModel):
|
||||
return self.write({'website_published': not self.website_published})
|
||||
|
||||
def open_website_url(self):
|
||||
url = self.env['website'].get_client_action_url(self.website_url)
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': url,
|
||||
'target': 'self',
|
||||
}
|
||||
return self.env['website'].get_client_action(self.website_url)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
@@ -283,16 +278,18 @@ class WebsitePublishedMultiMixin(WebsitePublishedMixin):
|
||||
return is_published
|
||||
|
||||
def open_website_url(self):
|
||||
client_action_url = self.env['website'].get_client_action_url(self.website_url)
|
||||
website_id = False
|
||||
if self.website_id:
|
||||
client_action_url = f'{client_action_url}&website_id={self.website_id.id}'
|
||||
website_id = self.website_id.id
|
||||
if self.website_id.domain:
|
||||
client_action_url = url_join(self.website_id.domain, client_action_url)
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': client_action_url,
|
||||
'target': 'self',
|
||||
}
|
||||
client_action_url = self.env['website'].get_client_action_url(self.website_url)
|
||||
client_action_url = f'{client_action_url}&website_id={website_id}'
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': url_join(self.website_id.domain, client_action_url),
|
||||
'target': 'self',
|
||||
}
|
||||
return self.env['website'].get_client_action(self.website_url, False, website_id)
|
||||
|
||||
|
||||
class WebsiteSearchableMixin(models.AbstractModel):
|
||||
|
||||
@@ -1301,18 +1301,24 @@ class Website(models.Model):
|
||||
action_params["enable_editor"] = 1
|
||||
return "/web#" + urls.url_encode(action_params)
|
||||
|
||||
def get_client_action(self, url, mode_edit=False, website_id=False):
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("website.website_preview")
|
||||
action['context'] = {
|
||||
'params': {
|
||||
'path': url,
|
||||
'enable_editor': mode_edit,
|
||||
'website_id': website_id,
|
||||
}
|
||||
}
|
||||
return action
|
||||
|
||||
def button_go_website(self, path='/', mode_edit=False):
|
||||
self._force()
|
||||
if mode_edit:
|
||||
# If the user gets on a translated page (e.g /fr) the editor will
|
||||
# never start. Forcing the default language fixes this issue.
|
||||
path = url_for(path, self.default_lang_id.url_code)
|
||||
path = self.get_client_action_url(path, True)
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': path,
|
||||
'target': 'self',
|
||||
}
|
||||
return self.get_client_action(path, mode_edit)
|
||||
|
||||
def _get_canonical_url_localized(self, lang, canonical_params):
|
||||
"""Returns the canonical URL for the current request with translatable
|
||||
|
||||
@@ -127,6 +127,7 @@ export class WebsitePreview extends Component {
|
||||
}, () => []);
|
||||
|
||||
useEffect(() => {
|
||||
let leftOnBackNavigation = false;
|
||||
// When reaching a "regular" url of the webclient's router, an
|
||||
// hashchange event should be dispatched to properly display the
|
||||
// content of the previous URL before reaching the client action,
|
||||
@@ -136,12 +137,18 @@ export class WebsitePreview extends Component {
|
||||
window.dispatchEvent(new HashChangeEvent('hashchange', {
|
||||
newURL: window.location.href.toString()
|
||||
}));
|
||||
leftOnBackNavigation = true;
|
||||
}
|
||||
};
|
||||
window.addEventListener('popstate', handleBackNavigation);
|
||||
return () => {
|
||||
history.pushState({}, null, this.backendUrl);
|
||||
window.removeEventListener('popstate', handleBackNavigation);
|
||||
// When leaving the client action, its original url is pushed
|
||||
// so that the router can replay the action on back navigation
|
||||
// from other screens.
|
||||
if (!leftOnBackNavigation) {
|
||||
history.pushState({}, null, this.backendUrl);
|
||||
}
|
||||
};
|
||||
}, () => []);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ export const PageControllerMixin = (component) => class extends component {
|
||||
super.setup();
|
||||
this.website = useService('website');
|
||||
this.dialog = useService('dialog');
|
||||
this.rpc = useService('rpc');
|
||||
|
||||
this.websiteSelection = [{id: 0, name: this.env._t("All Websites")}];
|
||||
|
||||
@@ -37,14 +38,15 @@ export const PageControllerMixin = (component) => class extends component {
|
||||
* Adds the new 'website content' record depending on the targeted model and
|
||||
* 'create_action' passed in context.
|
||||
*/
|
||||
createWebsiteContent() {
|
||||
async createWebsiteContent() {
|
||||
if (this.props.resModel === 'website.page') {
|
||||
return this.dialog.add(AddPageDialog, {selectWebsite: true});
|
||||
}
|
||||
const action = this.props.context.create_action;
|
||||
if (action) {
|
||||
if (/^\//.test(action)) {
|
||||
window.location.replace(action);
|
||||
const url = await this.rpc(action);
|
||||
this.website.goToWebsite({ path: url, edition: true });
|
||||
return;
|
||||
}
|
||||
this.actionService.doAction(action, {
|
||||
|
||||
@@ -28,10 +28,17 @@ export function useLoaderOnClick() {
|
||||
try {
|
||||
const resParams = params.getResParams();
|
||||
const callback = await orm.silent.call(resParams.resModel, name, [[resParams.resId]]);
|
||||
let keepLoader = false;
|
||||
if (callback) {
|
||||
callback.target = 'main';
|
||||
await action.doAction(callback);
|
||||
if (callback.tag === 'website_preview' && callback.context.params.with_loader) {
|
||||
keepLoader = true;
|
||||
}
|
||||
}
|
||||
if (!keepLoader) {
|
||||
website.hideLoader();
|
||||
}
|
||||
website.hideLoader();
|
||||
} catch (error) {
|
||||
website.hideLoader();
|
||||
throw error;
|
||||
|
||||
@@ -27,9 +27,5 @@ class BaseLanguageInstall(models.TransientModel):
|
||||
params = self._context.get('params', {})
|
||||
if 'url_return' in params:
|
||||
url = params['url_return'].replace('[lang]', self.first_lang_id.code)
|
||||
return {
|
||||
'url': self.env['website'].get_client_action_url(url),
|
||||
'type': 'ir.actions.act_url',
|
||||
'target': 'self'
|
||||
}
|
||||
return self.env['website'].get_client_action(url)
|
||||
return action
|
||||
|
||||
@@ -252,11 +252,7 @@ class Forum(models.Model):
|
||||
|
||||
def go_to_website(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'target': 'self',
|
||||
'url': self.env['website'].get_client_action_url(self._compute_website_url()),
|
||||
}
|
||||
return self.env['website'].get_client_action(self._compute_website_url())
|
||||
|
||||
@api.model
|
||||
def _update_website_count(self):
|
||||
@@ -974,11 +970,7 @@ class Post(models.Model):
|
||||
|
||||
def go_to_website(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'target': 'self',
|
||||
'url': self.env['website'].get_client_action_url(self.website_url),
|
||||
}
|
||||
return self.env['website'].get_client_action(self.website_url)
|
||||
|
||||
@api.model
|
||||
def _search_get_detail(self, website, order, options):
|
||||
|
||||
@@ -85,13 +85,13 @@ class WebsiteHrRecruitment(http.Controller):
|
||||
'contract_type_id': contract_type_id,
|
||||
})
|
||||
|
||||
@http.route('/jobs/add', type='http', auth="user", website=True)
|
||||
@http.route('/jobs/add', type='json', auth="user", website=True)
|
||||
def jobs_add(self, **kwargs):
|
||||
# avoid branding of website_description by setting rendering_bundle in context
|
||||
job = request.env['hr.job'].with_context(rendering_bundle=True).create({
|
||||
'name': _('Job Title'),
|
||||
})
|
||||
return request.redirect(request.env["website"].get_client_action_url(f"/jobs/detail/{slug(job)}", True))
|
||||
return f"/jobs/detail/{slug(job)}"
|
||||
|
||||
@http.route('''/jobs/detail/<model("hr.job"):job>''', type='http', auth="public", website=True, sitemap=True)
|
||||
def jobs_detail(self, job, **kwargs):
|
||||
|
||||
@@ -12,7 +12,9 @@ patch(NewContentModal.prototype, 'website_hr_recruitment_new_content', {
|
||||
newJobElement.status = MODULE_STATUS.INSTALLED;
|
||||
},
|
||||
|
||||
createNewJob() {
|
||||
window.location.replace('/jobs/add');
|
||||
async createNewJob() {
|
||||
const url = await this.rpc('/jobs/add');
|
||||
this.website.goToWebsite({ path: url, edition: true });
|
||||
this.websiteContext.showNewContentModal = false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -125,19 +125,11 @@ class ResConfigSettings(models.TransientModel):
|
||||
|
||||
def action_update_terms(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': self.env["website"].get_client_action_url('/terms', True),
|
||||
'target': 'self',
|
||||
}
|
||||
return self.env["website"].get_client_action('/terms', True)
|
||||
|
||||
def action_open_extra_info(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': self.env["website"].get_client_action_url('/shop/extra_info', True),
|
||||
'target': 'self',
|
||||
}
|
||||
return self.env["website"].get_client_action('/shop/extra_info', True)
|
||||
|
||||
def action_open_sale_mail_templates(self):
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user