diff --git a/document_page/README.rst b/document_page/README.rst index da347ffa..1b1a76de 100644 --- a/document_page/README.rst +++ b/document_page/README.rst @@ -55,6 +55,7 @@ Contributors * Gervais Naoussi * Maxime Chambreuil +* Iván Todorovich Funders ------- diff --git a/document_page/__manifest__.py b/document_page/__manifest__.py index 0f5646ec..38e3b19b 100644 --- a/document_page/__manifest__.py +++ b/document_page/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Document Page', - 'version': '10.0.1.0.0', + 'version': '10.0.2.0.0', 'category': 'Knowledge Management', 'author': 'OpenERP SA, Odoo Community Association (OCA)', 'images': [ @@ -26,9 +26,12 @@ 'wizard/document_page_create_menu.xml', 'wizard/document_page_show_diff.xml', 'views/document_page.xml', + 'views/document_page_category.xml', + 'views/document_page_history.xml', + 'views/document_page_assets.xml', + 'views/report_document_page.xml', 'security/document_page_security.xml', 'security/ir.model.access.csv', - 'data/document_page.xml', ], 'demo': [ 'demo/document_page.xml' diff --git a/document_page/data/document_page.xml b/document_page/data/document_page.xml deleted file mode 100644 index af054bea..00000000 --- a/document_page/data/document_page.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/document_page/demo/document_page.xml b/document_page/demo/document_page.xml index 7fb2fe85..799dfbee 100644 --- a/document_page/demo/document_page.xml +++ b/document_page/demo/document_page.xml @@ -9,7 +9,7 @@ OpenERP Features category - + Summary of the feature Long explanation diff --git a/document_page/migrations/10.0.2.0.0/post-migration.py b/document_page/migrations/10.0.2.0.0/post-migration.py new file mode 100644 index 00000000..5c40d42b --- /dev/null +++ b/document_page/migrations/10.0.2.0.0/post-migration.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Ivan Todorovich +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + + +def migrate(cr, version): # pragma: no cover + # Set all pre-existing categories template to its content + cr.execute(""" + UPDATE document_page + SET template = content + WHERE type = 'category' + """) diff --git a/document_page/models/document_page.py b/document_page/models/document_page.py index 1c58ce72..3824dc5d 100644 --- a/document_page/models/document_page.py +++ b/document_page/models/document_page.py @@ -2,11 +2,8 @@ # Copyright (C) 2004-2010 Tiny SPRL (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import logging from odoo import api, fields, models -_logger = logging.getLogger(__name__) - class DocumentPage(models.Model): """This class is use to manage Document.""" @@ -37,17 +34,48 @@ class DocumentPage(models.Model): 'Children' ) - content = fields.Text("Content") + content = fields.Text( + "Content", + compute='_compute_content', + inverse='_inverse_content', + search='_search_content', + required=True, + ) + # no-op computed field + summary = fields.Char( + help='Describe the changes made', + compute=lambda x: x, + inverse=lambda x: x, + ) + + template = fields.Html( + "Template", + help="Template that will be used as a content template " + "for all new page of this category.", + ) + + # deprecated - should be removed on 11.0 + # left here because some modules might still need it display_content = fields.Text( string='Displayed Content', - compute='_get_display_content' + compute='_compute_display_content' + ) + + history_head = fields.Many2one( + 'document.page.history', + 'HEAD', + compute='_compute_history_head', + store=True, + auto_join=True, ) history_ids = fields.One2many( 'document.page.history', 'page_id', - 'History' + 'History', + order='create_date DESC', + readonly=True, ) menu_id = fields.Many2one( @@ -56,82 +84,88 @@ class DocumentPage(models.Model): readonly=True ) - create_date = fields.Datetime( - "Created on", - readonly=True + content_date = fields.Datetime( + 'Last Contribution Date', + related='history_head.create_date', + store=True, + index=True, + readonly=True, ) - create_uid = fields.Many2one( + content_uid = fields.Many2one( 'res.users', - 'Author', - readonly=True + 'Last Contributor', + related='history_head.create_uid', + store=True, + index=True, + readonly=True, ) - write_date = fields.Datetime( - "Modification Date", - readonly=True - ) - - write_uid = fields.Many2one( - 'res.users', - "Last Contributor", - readonly=True - ) - - def _get_page_index(self, page, link=True): + @api.multi + def _get_page_index(self, link=True): """Return the index of a document.""" + self.ensure_one() index = [] - for subpage in page.child_ids: - index += ["
  • " + self._get_page_index(subpage) + - "
  • "] + for subpage in self.child_ids: + index += ["
  • " + subpage._get_page_index() + "
  • "] r = '' if link: - r = '%s' % (page.id, page.name) + r = '%s' % (self.id, self.name) if index: r += "
      " + "".join(index) + "
    " return r - def _get_display_content(self): - """Return the content of a document.""" - for page in self: - if page.type == "category": - display_content = self._get_page_index(page, link=False) - else: - display_content = page.content - page.display_content = display_content - - @api.onchange("parent_id") - def do_set_content(self): - """We Set it the right content to the new parent.""" - if self.parent_id and not self.content: - if self.parent_id.type == "category": - self.content = self.parent_id.content - - def create_history(self, page_id, content): - """Create the first history of a newly created document.""" - history = self.env['document.page.history'] - return history.create({ - "content": content, - "page_id": page_id - }) + @api.multi + @api.depends('content') + def _compute_display_content(self): + # @deprecated, simply use content + for rec in self: + rec.display_content = rec.content @api.multi - def write(self, vals): - """Write the content and set the history.""" - result = super(DocumentPage, self).write(vals) - content = vals.get('content') - if content: - for page in self: - self.create_history(page.id, content) - return result + @api.depends('history_head', 'history_ids') + def _compute_content(self): + for rec in self: + if rec.type == 'category': + rec.content = rec._get_page_index(link=False) + else: + if rec.history_head: + rec.content = rec.history_head.content + else: + # html widget's default, so it doesn't trigger ghost save + rec.content = '


    ' - @api.model - @api.returns('self', lambda value: value.id) - def create(self, vals): - """Create the first history of a document.""" - page_id = super(DocumentPage, self).create(vals) - content = vals.get('content') - if content: - self.create_history(page_id.id, content) - return page_id + @api.multi + def _inverse_content(self): + for rec in self: + if rec.type == 'content': + rec._create_history({ + 'content': rec.content, + 'summary': rec.summary, + }) + + @api.multi + def _search_content(self, operator, value): + return [('history_head.content', operator, value)] + + @api.multi + @api.depends('history_ids') + def _compute_history_head(self): + for rec in self: + if rec.history_ids: + rec.history_head = rec.history_ids[0] + + @api.multi + def _create_history(self, vals): + self.ensure_one() + history = self.env['document.page.history'] + vals['page_id'] = self.id + return history.create(vals) + + @api.onchange("parent_id") + def _onchange_parent_id(self): + """We Set it the right content to the new parent.""" + if not self.content or self.content == '


    ': + if self.parent_id and self.parent_id.type == "category": + self.content = self.parent_id.template diff --git a/document_page/models/document_page_history.py b/document_page/models/document_page_history.py index 4124a9f8..8334d6ab 100644 --- a/document_page/models/document_page_history.py +++ b/document_page/models/document_page_history.py @@ -2,13 +2,10 @@ # Copyright (C) 2004-2010 Tiny SPRL (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import logging import difflib -from odoo import fields, models +from odoo import api, fields, models from odoo.tools.translate import _ -_logger = logging.getLogger(__name__) - class DocumentPageHistory(models.Model): """This model is necessary to manage a document history.""" @@ -16,24 +13,40 @@ class DocumentPageHistory(models.Model): _name = "document.page.history" _description = "Document Page History" _order = 'id DESC' - _rec_name = "create_date" - page_id = fields.Many2one('document.page', 'Page') + page_id = fields.Many2one('document.page', 'Page', ondelete='cascade') summary = fields.Char('Summary', index=True) content = fields.Text("Content") - create_date = fields.Datetime("Date") - create_uid = fields.Many2one('res.users', "Modified By") + diff = fields.Text(compute='_compute_diff') + @api.multi + @api.depends('content', 'page_id.history_ids') + def _compute_diff(self): + """Shows a diff between this version and the previous version""" + history = self.env['document.page.history'] + for rec in self: + prev = history.search([ + ('page_id', '=', rec.page_id.id), + ('create_date', '<', rec.create_date)], + limit=1, + order='create_date DESC') + if prev: + rec.diff = self.getDiff(prev.id, rec.id) + else: + rec.diff = self.getDiff(False, rec.id) + + @api.model def getDiff(self, v1, v2): """Return the difference between two version of document version.""" - text1 = self.browse(v1).content - text2 = self.browse(v2).content - line1 = line2 = '' - if text1: - line1 = text1.splitlines(1) - if text2: - line2 = text2.splitlines(1) - if (not line1 and not line2) or (line1 == line2): + text1 = v1 and self.browse(v1).content or '' + text2 = v2 and self.browse(v2).content or '' + # Include line breaks to make it more readable + # TODO: consider using a beautify library directly on the content + text1 = text1.replace('

    ', '

    \r\n

    ') + text2 = text2.replace('

    ', '

    \r\n

    ') + line1 = text1.splitlines(1) + line2 = text2.splitlines(1) + if line1 == line2: return _('There are no changes in revisions.') else: diff = difflib.HtmlDiff() @@ -43,3 +56,11 @@ class DocumentPageHistory(models.Model): "Revision-{}".format(v2), context=True ) + + @api.multi + def name_get(self): + result = [] + for rec in self: + name = "%s #%i" % (rec.page_id.name, rec.id) + result.append((rec.id, name)) + return result diff --git a/document_page/security/document_page_security.xml b/document_page/security/document_page_security.xml index 14308202..57495106 100644 --- a/document_page/security/document_page_security.xml +++ b/document_page/security/document_page_security.xml @@ -1,7 +1,16 @@ - + + Editor + + + + + + Manager + + diff --git a/document_page/security/ir.model.access.csv b/document_page/security/ir.model.access.csv index 2b2fd18c..a61ea1d4 100644 --- a/document_page/security/ir.model.access.csv +++ b/document_page/security/ir.model.access.csv @@ -1,4 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -document_page_all,document.page,model_document_page,,1,0,0,0 -document_page,document.page,model_document_page,base.group_user,1,1,1,1 -document_page_history,document.page.history,model_document_page_history,base.group_user,1,0,1,0 +document_page_user,document.page user,model_document_page,knowledge.group_document_user,1,0,0,0 +document_page_history_user,document.page.history user,model_document_page_history,knowledge.group_document_user,1,0,0,0 +document_page_editor,document.page editor,model_document_page,group_document_editor,1,1,1,0 +document_page_history_editor,document.page.history editor,model_document_page_history,group_document_editor,1,1,1,0 +document_page_manager,document.page manager,model_document_page,group_document_manager,1,1,1,1 +document_page_history_manager,document.page.history manager,model_document_page_history,group_document_manager,1,1,1,0 diff --git a/document_page/static/src/css/document_page.css b/document_page/static/src/css/document_page.css index ddbbcffd..00a6336c 100644 --- a/document_page/static/src/css/document_page.css +++ b/document_page/static/src/css/document_page.css @@ -1,12 +1,29 @@ -.oe_form_editable .oe_document_page { - display: none; +table.diff { + font-family: Courier; + border: medium; } -table.diff {font-family:Courier; border:medium;} -.diff_header {background-color:#e0e0e0} -td.diff_header {text-align:right} -.diff_next {background-color:#c0c0c0} -.diff_add {background-color:#aaffaa} -.diff_chg {background-color:#ffff77} -.diff_sub {background-color:#ffaaaa} +table.diff .diff_header { + background-color: #e0e0e0 +} + +table.diff td.diff_header { + text-align: right +} + +table.diff .diff_next { + background-color:#c0c0c0 +} + +table.diff .diff_add { + background-color:#aaffaa +} + +table.diff .diff_chg { + background-color:#ffff77 +} + +table.diff .diff_sub { + background-color:#ffaaaa +} diff --git a/document_page/tests/__init__.py b/document_page/tests/__init__.py index 4c507a03..14e2fa0b 100644 --- a/document_page/tests/__init__.py +++ b/document_page/tests/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from . import test_document_page, test_document_page_history +from . import test_document_page from . import test_document_page_create_menu from . import test_document_page_show_diff diff --git a/document_page/tests/test_document_page.py b/document_page/tests/test_document_page.py index a0fb1b4d..32da79e2 100644 --- a/document_page/tests/test_document_page.py +++ b/document_page/tests/test_document_page.py @@ -4,34 +4,37 @@ from odoo.tests import common class TestDocumentPage(common.TransactionCase): - """document_page test class.""" + + def setUp(self): + super(TestDocumentPage, self).setUp() + self.page_obj = self.env['document.page'] + self.history_obj = self.env['document.page.history'] + self.category1 = self.env.ref('document_page.demo_category1') + self.page1 = self.env.ref('document_page.demo_page1') def test_page_creation(self): - """Test page creation.""" - parent_page = self.env.ref('document_page.demo_category1') - - self.assertEqual(parent_page.name, 'OpenERP Features') - - record = self.env['document.page'].create({ - 'name': 'Test Page1', - 'parent_id': parent_page.id, + page = self.page_obj.create({ + 'name': 'Test Page 1', + 'parent_id': self.category1.id, 'content': 'Test content' }) - self.assertEqual(record.name, 'Test Page1') + self.assertEqual(page.content, 'Test content') + self.assertEqual(len(page.history_ids), 1) + page.content = 'New content for Demo Page' + self.assertEqual(len(page.history_ids), 2) - def test_category_display_content(self): - """Test category display content.""" - page = self.env.ref('document_page.demo_category1') - self.assertTrue(page.display_content.find('Demo') > 1) + def test_category_template(self): + page = self.page_obj.create({ + 'name': 'Test Page 2', + 'parent_id': self.category1.id, + }) + page._onchange_parent_id() + self.assertEqual(page.content, self.category1.template) - def test_page_display_content(self): - """Test page display content.""" - page = self.env.ref('document_page.demo_page1') - self.assertTrue(page.display_content.find('Demo') > 1) - - def test_page_do_set_content(self): - """Test page set content.""" - page = self.env.ref('document_page.demo_page1') - page.content = None - page.do_set_content() - self.assertTrue(page.display_content.find('Summary') == 1) + def test_page_history_diff(self): + page = self.page_obj.create({ + 'name': 'Test Page 3', + 'content': 'Test content' + }) + page.content = 'New content' + self.assertIsNotNone(page.history_ids[0].diff) diff --git a/document_page/tests/test_document_page_create_menu.py b/document_page/tests/test_document_page_create_menu.py index 2a34ec1f..2484d008 100644 --- a/document_page/tests/test_document_page_create_menu.py +++ b/document_page/tests/test_document_page_create_menu.py @@ -8,7 +8,7 @@ class TestDocumentPageCreateMenu(common.TransactionCase): def test_page_menu_creation(self): """Test page menu creation.""" - menu_parent = self.env.ref('knowledge.menu_document_root') + menu_parent = self.env.ref('knowledge.menu_document') menu_created = self.env['document.page.create.menu'].create( {'menu_name': 'Wiki Test menu', 'menu_parent_id': menu_parent.id} diff --git a/document_page/tests/test_document_page_show_diff.py b/document_page/tests/test_document_page_show_diff.py index 8f897065..5befd18d 100644 --- a/document_page/tests/test_document_page_show_diff.py +++ b/document_page/tests/test_document_page_show_diff.py @@ -19,7 +19,7 @@ class TestDocumentPageShowDiff(common.TransactionCase): self.assertTrue( show_diff_object.with_context( active_ids=[i.id for i in history_pages] - ).get_diff() + )._get_diff() ) page.write({'content': 'Text content updated'}) @@ -30,7 +30,7 @@ class TestDocumentPageShowDiff(common.TransactionCase): with self.assertRaises(Exception) as context: show_diff_object.with_context( active_ids=[i.id for i in history_pages] - ).get_diff() + )._get_diff() self.assertTrue(_("Select one or maximum two history revisions!") in context.exception) diff --git a/document_page/views/document_page.xml b/document_page/views/document_page.xml index ee5b136c..78b8f1b3 100644 --- a/document_page/views/document_page.xml +++ b/document_page/views/document_page.xml @@ -1,11 +1,6 @@ - - document.page.tree @@ -15,8 +10,8 @@ - - + + @@ -30,8 +25,8 @@ - - + + @@ -47,31 +42,32 @@

    - + - - - + + + - - - -
    - -
    + + + + + + + + + + + + + +
    @@ -88,12 +84,7 @@

    -
    - -
    + @@ -104,90 +95,19 @@ document.page - - + + + - - - + + + - - - document.page.category.form - document.page - -
    - - -

    - - - - - - - - - - - - -
    -
    - -
    - -
    - -
    -
    -
    -
    -
    - - -
    -
    -
    -
    - - - document.page.category.tree - document.page - - - - - - - - - - @@ -200,116 +120,48 @@ -

    - Click to create a new web page. -

    +

    + Click to create a new web page. +

    + tree + form + + + + + + + name="Pages" + parent="menu_wiki" + action="action_page" + sequence="10" /> - - Category - document.page - [('type','=','category')] - {'default_type': 'category'} - form - tree,form - - - - - - tree - - - - - - form - - - - - - - - document.page.history.tree - document.page.history - - - - - - - - - - - document.page.history.form - document.page.history - -
    -
    - - - - Page history - document.page.history - form - tree,form - - - - - + id="action_related_page_create_menu" + name="Create Menu" + res_model="document.page.create.menu" + target="new" + view_type="form" + view_mode="form" + src_model="document.page"/> diff --git a/document_page/views/document_page_assets.xml b/document_page/views/document_page_assets.xml new file mode 100644 index 00000000..b85b0e06 --- /dev/null +++ b/document_page/views/document_page_assets.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/document_page/views/document_page_category.xml b/document_page/views/document_page_category.xml new file mode 100755 index 00000000..4725954e --- /dev/null +++ b/document_page/views/document_page_category.xml @@ -0,0 +1,88 @@ + + + + + + document.page.category.form + document.page + +
    + + +

    + + + + + + + + + + + + + + + + + + +
    +
    + + +
    +
    +
    +
    + + + document.page.category.tree + document.page + + + + + + + + + + + + + + + Category + document.page + [('type','=','category')] + {'default_type': 'category'} + form + tree,form + + + + + + + tree + + + + + + + form + + + + + + + +
    diff --git a/document_page/views/document_page_history.xml b/document_page/views/document_page_history.xml new file mode 100755 index 00000000..b0b49faf --- /dev/null +++ b/document_page/views/document_page_history.xml @@ -0,0 +1,88 @@ + + + + + + document.page.history.tree + document.page.history + + + + + + + + + + + + + + document.page.history.search + document.page.history + + + + + + + + + + + + + + + document.page.history.form + document.page.history + +
    + +

    + + + + + + + + + + + + + +
    +
    +
    +
    + + + + Page history + document.page.history + form + tree,form + + + + + + + +
    diff --git a/document_page/views/report_document_page.xml b/document_page/views/report_document_page.xml new file mode 100755 index 00000000..56419a9c --- /dev/null +++ b/document_page/views/report_document_page.xml @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/document_page/wizard/document_page_show_diff.py b/document_page/wizard/document_page_show_diff.py index 0ebf4df8..6757ddb2 100644 --- a/document_page/wizard/document_page_show_diff.py +++ b/document_page/wizard/document_page_show_diff.py @@ -2,7 +2,8 @@ # Copyright (C) 2004-2010 Tiny SPRL (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import exceptions, fields, models +from odoo import fields, models +from odoo.exceptions import UserError from odoo.tools.translate import _ @@ -11,33 +12,24 @@ class DocumentPageShowDiff(models.TransientModel): _name = 'wizard.document.page.history.show_diff' - def get_diff(self): + def _get_diff(self): """Return the Difference between two document.""" history = self.env["document.page.history"] ids = self.env.context.get('active_ids', []) - - diff = "" + diff = False if len(ids) == 2: if ids[0] > ids[1]: diff = history.getDiff(ids[1], ids[0]) else: diff = history.getDiff(ids[0], ids[1]) elif len(ids) == 1: - old = history.browse(ids[0]) - nids = history.search( - [('page_id', '=', old.page_id.id)], - order='id DESC', - limit=1 - ) - diff = history.getDiff(ids[0], nids.id) + diff = history.browse(ids[0]).diff else: - raise exceptions.Warning( - _("Select one or maximum two history revisions!") - ) + raise UserError( + _("Select one or maximum two history revisions!")) return diff diff = fields.Text( - 'Diff', readonly=True, - default=get_diff + default=_get_diff, ) diff --git a/document_page/wizard/document_page_show_diff.xml b/document_page/wizard/document_page_show_diff.xml index 93dd7278..c933ac64 100644 --- a/document_page/wizard/document_page_show_diff.xml +++ b/document_page/wizard/document_page_show_diff.xml @@ -6,14 +6,10 @@ Show Difference wizard.document.page.history.show_diff -
    - + +