[IMP] document_page: Use html_diff for checking differences

This commit is contained in:
Enric Tobella
2025-12-15 09:59:54 +01:00
parent 90a8ed45f6
commit e92017023c
12 changed files with 162 additions and 70 deletions

View File

@@ -1,7 +1,3 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association
============= =============
Document Page Document Page
============= =============
@@ -17,7 +13,7 @@ Document Page
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status :target: https://odoo-community.org/page/development-status
:alt: Beta :alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github
@@ -61,6 +57,12 @@ To use this module, you need to:
- Click on Pages to create pages and select the previous category to use - Click on Pages to create pages and select the previous category to use
the template the template
Improve diff of history
-----------------------
If you want to improve how history is shown, you can install html_diff
python library. A new comparison method will be installed.
Bug Tracker Bug Tracker
=========== ===========
@@ -83,23 +85,34 @@ Contributors
------------ ------------
- Gervais Naoussi <gervaisnaoussi@gmail.com> - Gervais Naoussi <gervaisnaoussi@gmail.com>
- Maxime Chambreuil <mchambreuil@ursainfosystems.com> - Maxime Chambreuil <mchambreuil@ursainfosystems.com>
- Iván Todorovich <ivan.todorovich@gmail.com> - Iván Todorovich <ivan.todorovich@gmail.com>
- Jose Maria Alzaga <jose.alzaga@aselcis.com> - Jose Maria Alzaga <jose.alzaga@aselcis.com>
- Lois Rilo <lois.rilo@forgeflow.com> - Lois Rilo <lois.rilo@forgeflow.com>
- Simone Orsi <simone.orsi@camptocamp.com> - Simone Orsi <simone.orsi@camptocamp.com>
- `Tecnativa <https://www.tecnativa.com>`__: - `Tecnativa <https://www.tecnativa.com>`__:
- Ernesto Tejeda - Ernesto Tejeda
- Víctor Martínez - Víctor Martínez
Trobz - Trobz
- Dung Tran <dungtd@trobz.com>
- Dung Tran <dungtd@trobz.com>
- `Sygel <https://www.sygel.es>`__: - `Sygel <https://www.sygel.es>`__:
- Ángel García de la Chica Herrera - Ángel García de la Chica Herrera
- `Dixmit <https://www.dixmit.com>`__:
- Enric Tobella
Other credits Other credits
------------- -------------

View File

@@ -30,6 +30,9 @@
], ],
"demo": ["demo/document_page.xml"], "demo": ["demo/document_page.xml"],
"assets": { "assets": {
"web._assets_primary_variables": [
"document_page/static/src/**/document_page_variables.scss",
],
"web.assets_backend": [ "web.assets_backend": [
"document_page/static/src/scss/document_page.scss", "document_page/static/src/scss/document_page.scss",
"document_page/static/src/js/document_page_kanban_controller.esm.js", "document_page/static/src/js/document_page_kanban_controller.esm.js",

View File

@@ -3,8 +3,16 @@
import difflib import difflib
try:
import html_diff
except ImportError:
html_diff = None
import logging
from odoo import api, fields, models from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class DocumentPageHistory(models.Model): class DocumentPageHistory(models.Model):
"""This model is necessary to manage a document history.""" """This model is necessary to manage a document history."""
@@ -43,11 +51,16 @@ class DocumentPageHistory(models.Model):
) )
rec.diff = self._get_diff(prev.id, rec.id) rec.diff = self._get_diff(prev.id, rec.id)
@api.model
def _get_diff(self, v1, v2): def _get_diff(self, v1, v2):
"""Return the difference between two version of document version."""
text1 = v1 and self.browse(v1).content or "" text1 = v1 and self.browse(v1).content or ""
text2 = v2 and self.browse(v2).content or "" text2 = v2 and self.browse(v2).content or ""
if html_diff:
return html_diff.diff(text1, text2)
# Keeping old logic. to be removed in 19 or 18.abs
_logger.warning(
"_get_diff: using fallback logic, please install 'html_diff' library "
"for better diff rendering"
)
# Include line breaks to make it more readable # Include line breaks to make it more readable
# TODO: consider using a beautify library directly on the content # TODO: consider using a beautify library directly on the content
text1 = text1.replace("</p><p>", "</p>\r\n<p>") text1 = text1.replace("</p><p>", "</p>\r\n<p>")

View File

@@ -8,8 +8,11 @@
- Ernesto Tejeda - Ernesto Tejeda
- Víctor Martínez - Víctor Martínez
Trobz - Trobz
- Dung Tran \<<dungtd@trobz.com>\>
- Dung Tran \<<dungtd@trobz.com>\>
- [Sygel](https://www.sygel.es): - [Sygel](https://www.sygel.es):
- Ángel García de la Chica Herrera - Ángel García de la Chica Herrera
- [Dixmit](https://www.dixmit.com):
- Enric Tobella

View File

@@ -5,3 +5,8 @@ To use this module, you need to:
the template the template
- Click on Pages to create pages and select the previous category to use - Click on Pages to create pages and select the previous category to use
the template the template
## Improve diff of history
If you want to improve how history is shown, you can install html_diff python library.
A new comparison method will be installed.

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" /> <meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title> <title>Document Page</title>
<style type="text/css"> <style type="text/css">
/* /*
@@ -360,49 +360,47 @@ ul.auto-toc {
</style> </style>
</head> </head>
<body> <body>
<div class="document"> <div class="document" id="document-page">
<h1 class="title">Document Page</h1>
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="document-page">
<h1>Document Page</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !! !! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !! !! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:029a3933b3eea6e056988a1f6fb36f83a4539b5a7d32e7bef7b60dfc3f871c98 !! source digest: sha256:029a3933b3eea6e056988a1f6fb36f83a4539b5a7d32e7bef7b60dfc3f871c98
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/knowledge/tree/18.0/document_page"><img alt="OCA/knowledge" src="https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/knowledge-18-0/knowledge-18-0-document_page"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/knowledge&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p> <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/knowledge/tree/18.0/document_page"><img alt="OCA/knowledge" src="https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/knowledge-18-0/knowledge-18-0-document_page"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/knowledge&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows you to write web pages for internal documentation.</p> <p>This module allows you to write web pages for internal documentation.</p>
<p><strong>Table of contents</strong></p> <p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents"> <div class="contents local topic" id="contents">
<ul class="simple"> <ul class="simple">
<li><a class="reference internal" href="#installation" id="toc-entry-1">Installation</a></li> <li><a class="reference internal" href="#installation" id="toc-entry-1">Installation</a></li>
<li><a class="reference internal" href="#configuration" id="toc-entry-2">Configuration</a></li> <li><a class="reference internal" href="#configuration" id="toc-entry-2">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-3">Usage</a></li> <li><a class="reference internal" href="#usage" id="toc-entry-3">Usage</a><ul>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-4">Bug Tracker</a></li> <li><a class="reference internal" href="#improve-diff-of-history" id="toc-entry-4">Improve diff of history</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-5">Credits</a><ul> </ul>
<li><a class="reference internal" href="#authors" id="toc-entry-6">Authors</a></li> </li>
<li><a class="reference internal" href="#contributors" id="toc-entry-7">Contributors</a></li> <li><a class="reference internal" href="#bug-tracker" id="toc-entry-5">Bug Tracker</a></li>
<li><a class="reference internal" href="#other-credits" id="toc-entry-8">Other credits</a></li> <li><a class="reference internal" href="#credits" id="toc-entry-6">Credits</a><ul>
<li><a class="reference internal" href="#maintainers" id="toc-entry-9">Maintainers</a></li> <li><a class="reference internal" href="#authors" id="toc-entry-7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-8">Contributors</a></li>
<li><a class="reference internal" href="#other-credits" id="toc-entry-9">Other credits</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-10">Maintainers</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
<div class="section" id="installation"> <div class="section" id="installation">
<h2><a class="toc-backref" href="#toc-entry-1">Installation</a></h2> <h1><a class="toc-backref" href="#toc-entry-1">Installation</a></h1>
<p>This module depends on module knowledge. So make sure to have it in your <p>This module depends on module knowledge. So make sure to have it in your
addons list.</p> addons list.</p>
</div> </div>
<div class="section" id="configuration"> <div class="section" id="configuration">
<h2><a class="toc-backref" href="#toc-entry-2">Configuration</a></h2> <h1><a class="toc-backref" href="#toc-entry-2">Configuration</a></h1>
<p>No configuration required.</p> <p>No configuration required.</p>
</div> </div>
<div class="section" id="usage"> <div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-3">Usage</a></h2> <h1><a class="toc-backref" href="#toc-entry-3">Usage</a></h1>
<p>To use this module, you need to:</p> <p>To use this module, you need to:</p>
<ul class="simple"> <ul class="simple">
<li>Go to Knowledge menu</li> <li>Go to Knowledge menu</li>
@@ -411,9 +409,14 @@ the template</li>
<li>Click on Pages to create pages and select the previous category to use <li>Click on Pages to create pages and select the previous category to use
the template</li> the template</li>
</ul> </ul>
<div class="section" id="improve-diff-of-history">
<h2><a class="toc-backref" href="#toc-entry-4">Improve diff of history</a></h2>
<p>If you want to improve how history is shown, you can install html_diff
python library. A new comparison method will be installed.</p>
</div>
</div> </div>
<div class="section" id="bug-tracker"> <div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-4">Bug Tracker</a></h2> <h1><a class="toc-backref" href="#toc-entry-5">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/knowledge/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/knowledge/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed If you spotted it first, help us to smash it by providing a detailed and welcomed
@@ -421,15 +424,15 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-5">Credits</a></h2> <h1><a class="toc-backref" href="#toc-entry-6">Credits</a></h1>
<div class="section" id="authors"> <div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-6">Authors</a></h3> <h2><a class="toc-backref" href="#toc-entry-7">Authors</a></h2>
<ul class="simple"> <ul class="simple">
<li>OpenERP SA</li> <li>OpenERP SA</li>
</ul> </ul>
</div> </div>
<div class="section" id="contributors"> <div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-7">Contributors</a></h3> <h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
<ul class="simple"> <ul class="simple">
<li>Gervais Naoussi &lt;<a class="reference external" href="mailto:gervaisnaoussi&#64;gmail.com">gervaisnaoussi&#64;gmail.com</a>&gt;</li> <li>Gervais Naoussi &lt;<a class="reference external" href="mailto:gervaisnaoussi&#64;gmail.com">gervaisnaoussi&#64;gmail.com</a>&gt;</li>
<li>Maxime Chambreuil &lt;<a class="reference external" href="mailto:mchambreuil&#64;ursainfosystems.com">mchambreuil&#64;ursainfosystems.com</a>&gt;</li> <li>Maxime Chambreuil &lt;<a class="reference external" href="mailto:mchambreuil&#64;ursainfosystems.com">mchambreuil&#64;ursainfosystems.com</a>&gt;</li>
@@ -442,18 +445,22 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
<li>Víctor Martínez</li> <li>Víctor Martínez</li>
</ul> </ul>
</li> </li>
</ul> <li>Trobz<ul>
<p>Trobz</p>
<ul class="simple">
<li>Dung Tran &lt;<a class="reference external" href="mailto:dungtd&#64;trobz.com">dungtd&#64;trobz.com</a>&gt;</li> <li>Dung Tran &lt;<a class="reference external" href="mailto:dungtd&#64;trobz.com">dungtd&#64;trobz.com</a>&gt;</li>
</ul>
</li>
<li><a class="reference external" href="https://www.sygel.es">Sygel</a>:<ul> <li><a class="reference external" href="https://www.sygel.es">Sygel</a>:<ul>
<li>Ángel García de la Chica Herrera</li> <li>Ángel García de la Chica Herrera</li>
</ul> </ul>
</li> </li>
<li><a class="reference external" href="https://www.dixmit.com">Dixmit</a>:<ul>
<li>Enric Tobella</li>
</ul>
</li>
</ul> </ul>
</div> </div>
<div class="section" id="other-credits"> <div class="section" id="other-credits">
<h3><a class="toc-backref" href="#toc-entry-8">Other credits</a></h3> <h2><a class="toc-backref" href="#toc-entry-9">Other credits</a></h2>
<p>The development of this module has been financially supported by:</p> <p>The development of this module has been financially supported by:</p>
<ul class="simple"> <ul class="simple">
<li>Odoo SA &lt;<a class="reference external" href="http://www.odoo.com">http://www.odoo.com</a>&gt;</li> <li>Odoo SA &lt;<a class="reference external" href="http://www.odoo.com">http://www.odoo.com</a>&gt;</li>
@@ -462,7 +469,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
</ul> </ul>
</div> </div>
<div class="section" id="maintainers"> <div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-9">Maintainers</a></h3> <h2><a class="toc-backref" href="#toc-entry-10">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p> <p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"> <a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /> <img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
@@ -475,6 +482,5 @@ promote its widespread use.</p>
</div> </div>
</div> </div>
</div> </div>
</div>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,36 @@
table.diff { .o_document_page_diff {
font-family: Courier; table.diff {
border: medium; font-family: Courier;
border: medium;
.diff_header { .diff_header {
background-color: #e0e0e0; background-color: $o_document_page_diff_header_background;
}
td.diff_header {
text-align: right;
}
.diff_next {
background-color: $o_document_page_diff_next_background;
}
.diff_add {
background-color: $o_document_page_diff_add_background;
}
.diff_chg {
background-color: $o_document_page_diff_change_background;
}
.diff_sub {
background-color: $o_document_page_diff_subtract_background;
}
} }
del {
td.diff_header { background-color: $o_document_page_diff_subtract_background;
text-align: right;
} }
ins {
.diff_next { background-color: $o_document_page_diff_add_background;
background-color: #c0c0c0;
}
.diff_add {
background-color: #aaffaa;
}
.diff_chg {
background-color: #ffff77;
}
.diff_sub {
background-color: #ffaaaa;
} }
} }

View File

@@ -0,0 +1,5 @@
$o_document_page_diff_header_background: #e0e0e0;
$o_document_page_diff_next_background: #c0c0c0;
$o_document_page_diff_add_background: #aaffaa;
$o_document_page_diff_change_background: #ffff77;
$o_document_page_diff_subtract_background: #ffaaaa;

View File

@@ -1,19 +1,48 @@
from unittest.mock import patch
from odoo.tests import common from odoo.tests import common
from odoo.tools import mute_logger
class TestDocumentPageHistory(common.TransactionCase): class TestDocumentPageHistory(common.TransactionCase):
"""document_page_history test class.""" """document_page_history test class."""
def test_page_history_demo_page1(self): def test_old_page_history_demo_page1(self):
"""Test page history demo page1.""" """Test page history demo page1."""
page = self.env.ref("document_page.demo_page1") page = self.env["document.page"].create(
{
"name": "Test Page",
"content": "Initial content",
}
)
page.content = "Test content updated" page.content = "Test content updated"
history_document = self.env["document.page.history"] history_document = self.env["document.page.history"]
history_pages = history_document.search([("page_id", "=", page.id)]) history_pages = history_document.search([("page_id", "=", page.id)])
active_ids = [i.id for i in history_pages] active_ids = [i.id for i in history_pages]
result = history_document._get_diff(active_ids[0], active_ids[0]) with (
self.assertEqual(result, "There are no changes in revisions.") patch(
"odoo.addons.document_page.models.document_page_history.html_diff", None
),
mute_logger("odoo.addons.document_page.models.document_page_history"),
):
result = history_document._get_diff(active_ids[0], active_ids[0])
self.assertEqual(result, "There are no changes in revisions.")
result = history_document._get_diff(active_ids[0], active_ids[1]) result = history_document._get_diff(active_ids[0], active_ids[1])
self.assertNotEqual(result, "There are no changes in revisions.") self.assertNotEqual(result, "There are no changes in revisions.")
def test_new_page_history_demo_page1(self):
"""Test page history demo page1."""
page = self.env["document.page"].create(
{
"name": "Test Page",
"content": "Initial content",
}
)
page.content = "Test content updated"
history_document = self.env["document.page.history"]
history_pages = history_document.search([("page_id", "=", page.id)])
active_ids = [i.id for i in history_pages]
result = history_document._get_diff(active_ids[0], active_ids[0])
self.assertEqual(result, page.content)

View File

@@ -8,7 +8,12 @@ class TestDocumentPageShowDiff(common.TransactionCase):
def test_show_demo_page1_diff(self): def test_show_demo_page1_diff(self):
"""Show test page history difference.""" """Show test page history difference."""
page = self.env.ref("document_page.demo_page1") page = self.env["document.page"].create(
{
"name": "Test Page",
"content": "Initial content",
}
)
show_diff_object = self.env["wizard.document.page.history.show_diff"] show_diff_object = self.env["wizard.document.page.history.show_diff"]

View File

@@ -69,6 +69,7 @@
<field <field
name="diff" name="diff"
widget="html" widget="html"
class="o_document_page_diff"
style="overflow-x: scroll" style="overflow-x: scroll"
/> />
</page> </page>

View File

@@ -1 +1,2 @@
odoo_test_helper odoo_test_helper
html_diff