[IMP] mail,portal,project: add preview to portal link

Before this commit, when the user shares a portal link, the receiver
has to click on the link to understand what it is about.

This commit uses new key called `preview_object` inside
`portal.frontend_layout` template.
When it is defined, it will add some useful information for the
preview link.
This commit also defines `preview_object` in portal view of project
and task to be able to have the preview link to prevent the user
from having to click on the link to understand what it is about.

task-3186692

closes odoo/odoo#113622

Related: odoo/enterprise#37514
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
This commit is contained in:
kais-odoo
2023-10-10 11:07:44 +00:00
committed by Xavier Bol (xbo)
parent 7f35c48ef5
commit ed268f81f4
8 changed files with 57 additions and 0 deletions
+2
View File
@@ -19,6 +19,7 @@ class LinkPreview(models.Model):
source_url = fields.Char('URL', required=True)
og_type = fields.Char('Type')
og_title = fields.Char('Title')
og_site_name = fields.Char('Site name')
og_image = fields.Char('Image')
og_description = fields.Text('Description')
og_mimetype = fields.Char('MIME type')
@@ -97,5 +98,6 @@ class LinkPreview(models.Model):
'og_mimetype': preview.og_mimetype,
'og_title': preview.og_title,
'og_type': preview.og_type,
'og_site_name': preview.og_site_name,
'source_url': preview.source_url,
} for preview in self]
@@ -21,6 +21,7 @@
<h6 class="card-title mb-0 me-2" t-attf-class="{{ props.linkPreview.og_description ? 'text-truncate' : 'overflow-hidden' }}">
<a t-att-href="props.linkPreview.source_url" target="_blank" t-out="props.linkPreview.og_title"/>
</h6>
<span t-if="props.linkPreview.og_site_name" t-out="props.linkPreview.og_site_name"/>
<p t-if="props.linkPreview.og_description" class="o-mail-LinkPreviewCard-description card-text mb-0 mt-2 text-muted small overflow-hidden" t-out="props.linkPreview.og_description"/>
</div>
</div>
@@ -39,6 +39,8 @@ export class LinkPreview extends Record {
/** @type {string} */
og_type;
/** @type {string} */
og_site_name;
/** @type {string} */
source_url;
get imageUrl() {
@@ -56,6 +58,7 @@ export class LinkPreview extends Record {
get isCard() {
return !this.isImage && !this.isVideo;
}
}
LinkPreview.register();
+3
View File
@@ -115,6 +115,7 @@ class TestLinkPreview(MailCommon):
'og_mimetype': False,
'og_title': self.og_title,
'og_type': False,
'og_site_name': False,
'source_url': self.source_url,
}] for link_preview in message.link_preview_ids
}
@@ -134,6 +135,7 @@ class TestLinkPreview(MailCommon):
'og_mimetype': None,
'og_title': self.og_title,
'og_type': None,
'og_site_name': None,
'source_url': self.source_url,
},
{
@@ -142,6 +144,7 @@ class TestLinkPreview(MailCommon):
'og_mimetype': None,
'og_title': self.title,
'og_type': None,
'og_site_name': None,
'source_url': self.source_url,
},
{
+2
View File
@@ -73,6 +73,7 @@ def get_link_preview_from_html(url, response):
return False
og_description = tree.xpath('//meta[@property="og:description"]/@content')
og_type = tree.xpath('//meta[@property="og:type"]/@content')
og_site_name = tree.xpath('//meta[@property="og:site_name"]/@content')
og_image = tree.xpath('//meta[@property="og:image"]/@content')
og_mimetype = tree.xpath('//meta[@property="og:image:type"]/@content')
return {
@@ -81,5 +82,6 @@ def get_link_preview_from_html(url, response):
'og_mimetype': og_mimetype[0] if og_mimetype else None,
'og_title': og_title,
'og_type': og_type[0] if og_type else None,
'og_site_name': og_site_name[0] if og_site_name else None,
'source_url': url,
}
+22
View File
@@ -35,6 +35,28 @@
</div>
</div>
</xpath>
<xpath expr="//head/meta" position="after">
<t t-if="preview_object">
<!-- Remove seo_object to not define og and twitter tags twice when wesbite is installed -->
<t t-set="seo_object" t-value="False"/>
<t t-set="company" t-value="preview_object.company_id or request.env.company"/>
<t t-set="not_uses_default_logo" t-value="company and not company.uses_default_logo"/>
<meta property="og:title" t-att-content="preview_object.name"/>
<meta property="og:description" t-att-content="preview_object.description.striptags() if preview_object.description else ''"/>
<meta property="og:site_name" t-att-content="company.name if company else ''"/>
<t t-if="not_uses_default_logo">
<meta property="og:image" t-attf-content="/web/binary/company_logo?company={{ company.id }}"/>
</t>
<meta property="og:image:width" content="300"/>
<meta property="og:image:height" content="200"/>
<meta name="twitter:card" content="summary_large_image"/>
<meta property="twitter:title" t-att-content="preview_object.name"/>
<meta property="twitter:description" t-att-content="preview_object.description.striptags() if preview_object.description else ''"/>
<t t-if="not_uses_default_logo">
<meta property="twitter:image" t-attf-content="/web/binary/company_logo?company={{ company.id }}"/>
</t>
</t>
</xpath>
</template>
<!-- Added by another template so that it can be disabled if needed -->
+2
View File
@@ -46,6 +46,7 @@ class ProjectCustomerPortal(CustomerPortal):
pager=pager,
project=project,
task_url=f'projects/{project.id}/task',
preview_object=project,
)
if not groupby:
@@ -255,6 +256,7 @@ class ProjectCustomerPortal(CustomerPortal):
'user': request.env.user,
'project_accessible': project_accessible,
'task_link_section': [],
'preview_object': task,
}
values = self._get_page_view_values(task, access_token, values, history, False, **kwargs)
@@ -120,7 +120,29 @@
</t>
</template>
<template id="task_link_preview_front_end" inherit_id="portal.frontend_layout" primary="True">
<xpath expr="//t[@t-if='not_uses_default_logo'][1]" position="before">
<t t-if="preview_object.displayed_image_id">
<meta property="og:image" t-attf-content="/web/image/{{ preview_object.displayed_image_id.id }}/300x200?access_token={{ preview_object.displayed_image_id.generate_access_token()[0] }}"/>
</t>
</xpath>
<xpath expr="//t[@t-if='not_uses_default_logo'][2]" position="before">
<t t-if="preview_object.displayed_image_id">
<meta property="twitter:image" t-attf-content="/web/image/{{ preview_object.displayed_image_id.id }}/300x200?access_token={{ preview_object.displayed_image_id.generate_access_token()[0] }}"/>
</t>
</xpath>
</template>
<template id="task_link_preview_portal_layout" inherit_id="portal.portal_layout" primary="True">
<xpath expr="//t[@t-call='portal.frontend_layout']" position="attributes">
<attribute name="t-call">project.task_link_preview_front_end</attribute>
</xpath>
</template>
<template id="portal_my_task" name="My Task" inherit_id="portal.portal_sidebar" primary="True">
<xpath expr="//t[@t-call='portal.portal_layout']" position="attributes">
<attribute name="t-call">project.task_link_preview_portal_layout</attribute>
</xpath>
<xpath expr="//div[hasclass('o_portal_sidebar')]" position="inside">
<t t-set="title" t-value="task.name"/>
<t t-set="o_portal_fullwidth_alert" groups="project.group_project_user">