From 80cd9e9024e5e3e5f5d0e1e474cb0904033f08a4 Mon Sep 17 00:00:00 2001 From: Laurent Mignon Date: Wed, 22 Jun 2016 11:34:15 +0200 Subject: [PATCH 1/4] [MIG] Migrate to 9.0 --- help_online/README.rst | 69 ++++++ help_online/__init__.py | 23 +- help_online/__manifest__.py | 51 +--- help_online/controllers/__init__.py | 22 +- .../controllers/help_online_controllers.py | 21 +- help_online/models/__init__.py | 24 +- help_online/models/help_online.py | 33 +-- help_online/models/import_help_wizard.py | 49 ---- help_online/models/ir_model.py | 40 +-- help_online/security/help_online_groups.xml | 32 +-- help_online/security/help_online_rules.xml | 60 +++-- help_online/static/src/css/help_online.css | 13 +- help_online/static/src/js/help_online.js | 175 ++++++------- .../src/js/website_help_online.editor.js | 21 -- help_online/static/src/xml/help_online.xml | 43 +++- help_online/tests/__init__.py | 30 +-- help_online/tests/common.py | 100 ++++++++ help_online/tests/data/help_test_data.xml | 2 +- help_online/tests/test_export_help_wizard.py | 121 ++------- help_online/tests/test_help_online.py | 58 +++++ help_online/tests/test_import_help_wizard.py | 59 +++++ help_online/views/export_help_wizard_view.xml | 52 ---- help_online/views/help_online_view.xml | 50 ++-- help_online/views/import_help_wizard_view.xml | 46 ---- help_online/views/ir_ui_view_view.xml | 48 ++-- help_online/views/website_help_online.xml | 12 - help_online/wizards/__init__.py | 6 + .../{models => wizards}/export_help_wizard.py | 231 ++++++++++-------- .../wizards/export_help_wizard_view.xml | 50 ++++ help_online/wizards/import_help_wizard.py | 53 ++++ .../wizards/import_help_wizard_view.xml | 43 ++++ setup/help_online/odoo_addons/__init__.py | 1 + setup/help_online/odoo_addons/help_online | 1 + setup/help_online/setup.py | 6 + 34 files changed, 840 insertions(+), 805 deletions(-) create mode 100644 help_online/README.rst delete mode 100644 help_online/models/import_help_wizard.py delete mode 100644 help_online/static/src/js/website_help_online.editor.js create mode 100644 help_online/tests/common.py create mode 100644 help_online/tests/test_help_online.py create mode 100644 help_online/tests/test_import_help_wizard.py delete mode 100644 help_online/views/export_help_wizard_view.xml delete mode 100644 help_online/views/import_help_wizard_view.xml delete mode 100644 help_online/views/website_help_online.xml create mode 100644 help_online/wizards/__init__.py rename help_online/{models => wizards}/export_help_wizard.py (56%) create mode 100644 help_online/wizards/export_help_wizard_view.xml create mode 100644 help_online/wizards/import_help_wizard.py create mode 100644 help_online/wizards/import_help_wizard_view.xml create mode 100644 setup/help_online/odoo_addons/__init__.py create mode 120000 setup/help_online/odoo_addons/help_online create mode 100644 setup/help_online/setup.py diff --git a/help_online/README.rst b/help_online/README.rst new file mode 100644 index 00000000..375c8514 --- /dev/null +++ b/help_online/README.rst @@ -0,0 +1,69 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=========== +Help Online +=========== + + +This module allows the creation of an online help available from the lists +and forms in Odoo. + +When loading a view, the module generates a button allowing access to an help +page for the related model if the page exists and the user is member of the +group 'Help reader'. If the page doesn't exist and the user is member of +the group 'Help writer', the module generate a button allowing the creation an +help page. + +The help pages are created and managed via the website Module. + +Note: When updating the page prefix parameters, the record rules must be + adapted. + +Usage +===== + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/162/9.0 + + +Known issues / Roadmap +====================== + +Even if the generated urls to the documentation contains an anchor (website/hel-xx#view_type), +it's no more possible to insert/edit anchors elements into the website since this functionnality is not supported +by the new html editor in Odoo 9.0 (summernote). + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Laurent Mignon +* Jonathan Nemry +* Cédric Pigeon + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/help_online/__init__.py b/help_online/__init__.py index ccd23e28..4fc2e537 100644 --- a/help_online/__init__.py +++ b/help_online/__init__.py @@ -1,22 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Nemry Jonathan -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from . import controllers from . import models +from . import wizards diff --git a/help_online/__manifest__.py b/help_online/__manifest__.py index d84efbd7..cf3440fd 100644 --- a/help_online/__manifest__.py +++ b/help_online/__manifest__.py @@ -1,65 +1,30 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Nemry Jonathan -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + { 'name': 'Help Online', - 'version': '8.0.1.0.0', + 'version': '9.0.1.0.0', 'author': "ACSONE SA/NV,Odoo Community Association (OCA)", 'maintainer': 'ACSONE SA/NV', 'website': 'http://www.acsone.eu', + 'license': 'AGPL-3', 'category': 'Documentation', 'depends': [ 'base', 'website', ], - 'description': """ -Help Online -=========== - -This module allows the creation of an online help available from the lists -and forms in Odoo. - -When loading a view, the module generates a button allowing access to an help -page for the related model if the page exists and the user is member of the -group 'Help reader'. If the page doesn't exist and the user is member of -the group 'Help writer', the module generate a button allowing the creation an -help page. - -The help pages are created and managed via the website Module. - -Note: When updating the page prefix parameters, the record rules must be - adapted. - """, 'data': [ 'security/help_online_groups.xml', 'security/help_online_rules.xml', - 'views/export_help_wizard_view.xml', - 'views/import_help_wizard_view.xml', + 'wizards/export_help_wizard_view.xml', + 'wizards/import_help_wizard_view.xml', 'views/ir_ui_view_view.xml', 'views/help_online_view.xml', - 'views/website_help_online.xml', 'data/ir_config_parameter_data.xml', ], 'qweb': [ 'static/src/xml/help_online.xml', ], - 'installable': False, - 'auto_install': False, + 'installable': True, } diff --git a/help_online/controllers/__init__.py b/help_online/controllers/__init__.py index 287fdda2..46333083 100644 --- a/help_online/controllers/__init__.py +++ b/help_online/controllers/__init__.py @@ -1,21 +1,5 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Laurent Mignon -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from .import help_online_controllers diff --git a/help_online/controllers/help_online_controllers.py b/help_online/controllers/help_online_controllers.py index 12339b23..1dc8522e 100644 --- a/help_online/controllers/help_online_controllers.py +++ b/help_online/controllers/help_online_controllers.py @@ -1,23 +1,6 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Laurent Mignon -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import openerp.http as http from openerp.http import request diff --git a/help_online/models/__init__.py b/help_online/models/__init__.py index 615fa9cc..e98044c5 100644 --- a/help_online/models/__init__.py +++ b/help_online/models/__init__.py @@ -1,24 +1,6 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Nemry Jonathan -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from . import help_online -from . import export_help_wizard -from . import import_help_wizard from . import ir_model diff --git a/help_online/models/help_online.py b/help_online/models/help_online.py index 25e34fbb..975cba70 100644 --- a/help_online/models/help_online.py +++ b/help_online/models/help_online.py @@ -1,23 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Laurent Mignon -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from openerp import models, exceptions from openerp.tools.translate import _ @@ -34,9 +18,9 @@ class HelpOnline(models.TransientModel): name = '%s-%s' % (page_prefix, model.replace('.', '-')) return name - def page_exists(self, name): - website_model = self.env['website'] - return website_model.page_exists(name) + def get_existing_pages(self, name, limit=None): + website = self.env['website'] + return website.search_pages(needle=name, limit=limit) def get_page_url(self, model, view_type, domain=None, context=None): user_model = self.env['res.users'] @@ -48,8 +32,9 @@ class HelpOnline(models.TransientModel): if res: description = res[0][1] name = self._get_view_name(model, view_type, domain, context) - if self.page_exists(name): - url = '/page/%s' % name + pages = self.get_existing_pages(name, limit=1) + if pages: + url = pages[0]['loc'] if view_type: url = url + '#' + view_type title = _('Help on %s') % description diff --git a/help_online/models/import_help_wizard.py b/help_online/models/import_help_wizard.py deleted file mode 100644 index bb071784..00000000 --- a/help_online/models/import_help_wizard.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# All Rights Reserved -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsibility of assessing all potential -# consequences resulting from its eventual inadequacies and bugs. -# End users who are looking for a ready-to-use solution with commercial -# guarantees and support are strongly advised to contact a Free Software -# Service Company. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -from openerp import models, fields, api -from openerp.tools import convert - -import base64 -from cStringIO import StringIO - - -class ImportHelpWizard(models.TransientModel): - _name = "import.help.wizard" - - source_file = fields.Binary('Source File') - - @api.one - def import_help(self): - source_file = base64.decodestring(self.source_file) - convert.convert_xml_import(self.env.cr, - self._module, - StringIO(source_file), - idref=None, - mode='init', - noupdate=False, - report=None) diff --git a/help_online/models/ir_model.py b/help_online/models/ir_model.py index fa9df396..fd79f099 100644 --- a/help_online/models/ir_model.py +++ b/help_online/models/ir_model.py @@ -1,29 +1,13 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Cédric Pigeon -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from openerp import models, api from lxml import etree as ET -class ir_model_data(models.Model): +class IrModelData(models.Model): _inherit = 'ir.model.data' @api.model @@ -38,14 +22,14 @@ class ir_model_data(models.Model): xml_str = self.manageImageReferences(values['arch'], module) values['arch'] = xml_str - return super(ir_model_data, self)._update(model, - module, - values, - xml_id=xml_id, - store=store, - noupdate=noupdate, - mode=mode, - res_id=res_id) + return super(IrModelData, self)._update(model, + module, + values, + xml_id=xml_id, + store=store, + noupdate=noupdate, + mode=mode, + res_id=res_id) def manageImageReferences(self, xml_str, module): parser = ET.XMLParser(remove_blank_text=True) diff --git a/help_online/security/help_online_groups.xml b/help_online/security/help_online_groups.xml index fd981bf1..92c5ff72 100644 --- a/help_online/security/help_online_groups.xml +++ b/help_online/security/help_online_groups.xml @@ -1,16 +1,16 @@ - - - - Help reader - - - - Help writer - - - - - \ No newline at end of file + + + + Help reader + + + + Help writer + + + + + diff --git a/help_online/security/help_online_rules.xml b/help_online/security/help_online_rules.xml index 08880d9c..31576c25 100644 --- a/help_online/security/help_online_rules.xml +++ b/help_online/security/help_online_rules.xml @@ -1,32 +1,30 @@ - - - - Online Help Hidden by Default - - [ - '|', - ('type', '!=', 'qweb'), - ('name','not like','help-%'), - ] - - - - - - - Online Help for Help Reader - - [(1, '=', 1)] - - - - - - + + + Online Help Hidden by Default + + [ + '|', + ('type', '!=', 'qweb'), + ('name','not like','help-%'), + ] + + + + + + + Online Help for Help Reader + + [(1, '=', 1)] + + + + + diff --git a/help_online/static/src/css/help_online.css b/help_online/static/src/css/help_online.css index 5878bfe0..638deb76 100644 --- a/help_online/static/src/css/help_online.css +++ b/help_online/static/src/css/help_online.css @@ -1,12 +1,3 @@ -li.oe_help_online_not_found { +a.o_help_online_not_found { background-color: #df3f3f; -} - -.openerp .oe_view_manager .oe_view_manager_switch .oe_list_button_help_online:after { - font-size: 28px; - content: "?"; - text-align: center; - margin: 3px auto 4px; - position: relative; - display: inline-block; -} +} \ No newline at end of file diff --git a/help_online/static/src/js/help_online.js b/help_online/static/src/js/help_online.js index c660a110..c2977dc5 100644 --- a/help_online/static/src/js/help_online.js +++ b/help_online/static/src/js/help_online.js @@ -1,115 +1,86 @@ -openerp.help_online = function (instance) { - var QWeb = instance.web.qweb; - var _t = instance.web._t; - var _lt = instance.web._lt; +odoo.define('oca.HelpOnline', function (require) { + "use strict"; - instance.web.ListView.include({ - load_list: function () { - var self = this; - var add_button = false; - if (!this.$buttons) { - add_button = true; - } + var core = require('web.core'); + var QWeb = core.qweb; + var _t = core._t; + var ViewManager = require('web.ViewManager'); + var ControlPanel = require('web.ControlPanel'); + var Dialog = require('web.Dialog'); + + ControlPanel.include({ + start: function(){ this._super.apply(this, arguments); - this.$buttons.on('click', '.oe_list_button_help_online', function() { - self.do_action({ - type: 'ir.actions.act_url', - url: '/partner_mobile', - target: 'self', - }); - }); - }, - }); - - openerp.web.TreeView.include({ - view_loading: function(r) { - var ret = this._super(r); - if(! _.isUndefined(this.ViewManager.load_help_buttons)){ - this.ViewManager.load_help_buttons(); - } - return ret - }, - }); - - openerp.web.ListView.include({ - view_loading: function(r) { - var ret = this._super(r); - if(! _.isUndefined(this.ViewManager.load_help_buttons)){ - this.ViewManager.load_help_buttons(); - } - return ret + this._toggle_visibility(true); + this.nodes = _.extend( + this.nodes, + {$help_online_buttons: this.$('.o_help_online_buttons')}); + this._toggle_visibility(false); }, }); - - openerp.web.FormView.include({ - view_loading: function(r) { - var ret = this._super(r); - if(!_.isUndefined(this.ViewManager.clean_help_buttons)){ - this.ViewManager.clean_help_buttons(); - } - return ret - }, - - do_show: function (options){ - var ret = this._super(options); - if(! _.isUndefined(this.ViewManager.load_help_buttons)){ - this.ViewManager.load_help_buttons(); + + ViewManager.include({ + + /** + * This function render the help button with the informations received + * from the call to the method build_url from the help_online controller + */ + render_help_button: function(url_info){ + var $helpButton = $(QWeb.render("HelpOnline.Button", {'view_manager':this, 'url_info': url_info})); + $helpButton.tooltip(); + if (url_info.exists === false) { + $helpButton.on('click', function (event) { + var evt = event; + evt.preventDefault(); + Dialog.confirm( + self, + _t('Page does not exist. Do you want to create?'), + {confirm_callback: function() { + var form = $("
"); + form.attr({ + id : "formform", + // The location given in the link itself + action : evt.target.href, + method : "GET", + // Open in new window/tab + target : evt.target.target + }); + $("body").append(form); + $("#formform").submit(); + $("#formform").remove(); + return false; + } + }); + }); } - return ret + return $helpButton; }, - }); - openerp.web.ViewManager.include({ - clean_help_buttons:function() { - this.$el.find("div.oe_help_online_buttons").first().remove(); - }, - - load_help_buttons:function() { - var self = this; - this.rpc('/help_online/build_url', {model: this.dataset.model, view_type: this.active_view}).then(function(result) { - self.clean_help_buttons(); + /** + * This function render the help buttons container on the view. + * It should be called after start() by render_view_control_elements. + * @param {control_elements} the list of control elements to display into the ControlPanel + */ + render_help_buttons: function(control_elements){ + if (! control_elements.$help_online_buttons){ + control_elements.$help_online_buttons = $('
'); + } + var self = this; + this.rpc('/help_online/build_url', {model: this.dataset.model, view_type: this.active_view.type}).then(function(result) { if (result && ! _.isEmpty(result)) { - self.$helpButtonsEl = $(QWeb.render("HelpOnline.Buttons", {'view_manager':self, 'url_info': result})); - self.$el.find("ul.oe_view_manager_switch.oe_button_group.oe_right").first().before(self.$helpButtonsEl); - self.$helpButtonsEl.find('a.oe_list_button_help_online').tooltip(); - if (result.exists === false) { - self.$helpButtonsEl.find('li').addClass('oe_help_online_not_found') - self.$helpButtonsEl.find('a.oe_list_button_help_online').on('click', function (event) { - var evt = event; - evt.preventDefault(); - var dialog = new instance.web.Dialog(this, { - title: _t('Confirm'), - buttons: [ - {text: _t("Cancel"), click: function() { - this.parents('.modal').modal('hide'); - return false; - } - }, - {text: _t("Ok"), click: function() { - this.parents('.modal').modal('hide'); - var form = $("
"); - form.attr( - { - id : "formform", - // The location given in the link itself - action : evt.target.href, - method : "GET", - // Open in new window/tab - target : evt.target.target - }); - $("body").append(form); - $("#formform").submit(); - $("#formform").remove(); - return false; - } - } - ], - }, $('
').text(_t('Page does not exist. Do you want to create?'))).open(); - }); - } + var $helpButton = self.render_help_button(result); + control_elements.$help_online_buttons = $helpButton; + // update the control panel with the new help button + self.update_control_panel({cp_content: _.extend({}, self.searchview_elements, control_elements)}, {clear: false}); } }); }, + render_view_control_elements: function() { + var control_elements = this._super.apply(this, arguments); + this.render_help_buttons(control_elements); + return control_elements; + }, + }); -} +}); diff --git a/help_online/static/src/js/website_help_online.editor.js b/help_online/static/src/js/website_help_online.editor.js deleted file mode 100644 index 0dc2f3d1..00000000 --- a/help_online/static/src/js/website_help_online.editor.js +++ /dev/null @@ -1,21 +0,0 @@ -(function () { - 'use strict'; - - var website = openerp.website; - var _t = openerp._t; - website.RTE.include({ - _config: function () { - // add anchor button - var config = this._super(); - config.plugins = config.plugins.concat(',link'); - _.each(config.toolbar, function (tb) { - if (tb.name === 'span'){ - tb.items.unshift('Anchor'); - } - }); - return config; - }, - }); -})(); - - diff --git a/help_online/static/src/xml/help_online.xml b/help_online/static/src/xml/help_online.xml index fb55b85b..bc987ef8 100644 --- a/help_online/static/src/xml/help_online.xml +++ b/help_online/static/src/xml/help_online.xml @@ -1,13 +1,36 @@ + - -
-
    -
  • - -
  • -
+ + + + + + + + - + + + + + + + + + + + + + + + + +
+ +
+
+
+ diff --git a/help_online/tests/__init__.py b/help_online/tests/__init__.py index cc5a18f0..24fd5c2e 100644 --- a/help_online/tests/__init__.py +++ b/help_online/tests/__init__.py @@ -1,27 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -from . import test_export_help_wizard - -fast_suite = [ -] +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -checks = [ - test_export_help_wizard, -] +from . import test_help_online +from . import test_export_help_wizard +from . import test_import_help_wizard diff --git a/help_online/tests/common.py b/help_online/tests/common.py new file mode 100644 index 00000000..51fc02ae --- /dev/null +++ b/help_online/tests/common.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import os +import sys +from lxml import etree as ET + +from openerp.tools.convert import convert_xml_import + + +class TestWizardCommon(object): + _data_files = ('data/help_test_data.xml',) + + _module_ns = 'help_online' + + def createPage(self, pageName, imgXmlId=False): + imgId = False + if imgXmlId: + imgId = self.ref(imgXmlId) + + rootNode = ET.Element('t') + rootNode.attrib['name'] = pageName + rootNode.attrib['t-name'] = "website.%s" % pageName + tNode = ET.SubElement(rootNode, + 't', + attrib={'t-call': 'website.layout'}) + structDivNode = ET.SubElement(tNode, + 'div', + attrib={'class': 'oe_structure oe_empty', + 'id': 'wrap'}) + sectionNode = ET.SubElement(structDivNode, + 'section', + attrib={'class': 'mt16 mb16'}) + containerNode = ET.SubElement(sectionNode, + 'div', + attrib={'class': 'container'}) + rowNode = ET.SubElement(containerNode, + 'div', + attrib={'class': 'row'}) + bodyDivNode = ET.SubElement(rowNode, + 'div', + attrib={'class': 'col-md-12 ' + 'text-center mt16 mb32'}) + style = "font-family: 'Helvetica Neue', Helvetica,"\ + " Arial, sans-serif; color: rgb(51, 51, 51);"\ + " text-align: left;" + h2Node = ET.SubElement(bodyDivNode, + 'h2', + attrib={'style': style}) + h2Node.text = "Test Sample Title" + if imgId: + imgDivNode = ET.SubElement(bodyDivNode, + 'div', + attrib={'style': 'text-align: left;'}) + src = "/website/image?field=datas&"\ + "model=ir.attachment&id=%s" % str(imgId) + ET.SubElement(imgDivNode, + 'img', + attrib={'class': 'img-thumbnail', + 'src': src}) + imgDivNode = ET.SubElement(bodyDivNode, + 'div', + attrib={'style': 'text-align: left;'}) + src = "/website/image/ir.attachment/%s_ccc838d/datas" % str(imgId) + ET.SubElement(imgDivNode, + 'img', + attrib={'class': 'img-thumbnail', + 'src': src}) + imgDivNode = ET.SubElement(bodyDivNode, + 'div', + attrib={'style': 'text-align: left;'}) + src = "/web/image/%s" % str(imgId) + ET.SubElement(imgDivNode, + 'img', + attrib={'class': 'img-thumbnail', + 'src': src}) + arch = ET.tostring(rootNode, encoding='utf-8', xml_declaration=False) + vals = { + 'name': pageName, + 'type': 'qweb', + 'arch': arch, + 'page': True, + } + view_id = self.env['ir.ui.view'].create(vals) + return view_id.id + + def setUp(self): + super(TestWizardCommon, self).setUp() + self.pageName = False + self.imgXmlId = False + self.pageTemplate = False + # Loads the data file before + module = sys.modules[self.__class__.__module__] + base_path = os.path.dirname(module.__file__) + for path in self._data_files: + path = path.split('/') + path.insert(0, base_path) + path = os.path.join(*path) + convert_xml_import(self.cr, self._module_ns, path) diff --git a/help_online/tests/data/help_test_data.xml b/help_online/tests/data/help_test_data.xml index 3d939d21..55723379 100644 --- a/help_online/tests/data/help_test_data.xml +++ b/help_online/tests/data/help_test_data.xml @@ -75,4 +75,4 @@ YFBaQ6YYbTbt679Y0nIRIfKXS1d/8J7oqRWRGxO2b92S+NyzK2n3aAwoCf/7jpEfsQAoxU3nESI/ image/png - \ No newline at end of file + diff --git a/help_online/tests/test_export_help_wizard.py b/help_online/tests/test_export_help_wizard.py index 097e03b2..b9fcdc2e 100644 --- a/help_online/tests/test_export_help_wizard.py +++ b/help_online/tests/test_export_help_wizard.py @@ -1,105 +1,17 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Cédric Pigeon -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -import logging +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + import base64 from lxml import etree as ET -from anybox.testing.openerp import SharedSetupTransactionCase - -_logger = logging.getLogger(__name__) - - -class test_export_help_wizard(object): - _data_files = ('data/help_test_data.xml',) +import openerp.tests.common as common +from .common import TestWizardCommon - _module_ns = 'help_online' - def createPage(self, pageName, imgXmlId=False): - imgId = False - if imgXmlId: - imgId = self.ref('%s.%s' % (self._module_ns, imgXmlId)) - - rootNode = ET.Element('t') - rootNode.attrib['name'] = pageName - rootNode.attrib['t-name'] = "website.%s" % pageName - tNode = ET.SubElement(rootNode, - 't', - attrib={'t-call': 'website.layout'}) - structDivNode = ET.SubElement(tNode, - 'div', - attrib={'class': 'oe_structure oe_empty', - 'id': 'wrap'}) - sectionNode = ET.SubElement(structDivNode, - 'section', - attrib={'class': 'mt16 mb16'}) - containerNode = ET.SubElement(sectionNode, - 'div', - attrib={'class': 'container'}) - rowNode = ET.SubElement(containerNode, - 'div', - attrib={'class': 'row'}) - bodyDivNode = ET.SubElement(rowNode, - 'div', - attrib={'class': 'col-md-12 ' - 'text-center mt16 mb32'}) - style = "font-family: 'Helvetica Neue', Helvetica,"\ - " Arial, sans-serif; color: rgb(51, 51, 51);"\ - " text-align: left;" - h2Node = ET.SubElement(bodyDivNode, - 'h2', - attrib={'style': style}) - h2Node.text = "Test Sample Title" - if imgId: - imgDivNode = ET.SubElement(bodyDivNode, - 'div', - attrib={'style': 'text-align: left;'}) - src = "/website/image?field=datas&"\ - "model=ir.attachment&id=%s" % str(imgId) - ET.SubElement(imgDivNode, - 'img', - attrib={'class': 'img-thumbnail', - 'src': src}) - imgDivNode = ET.SubElement(bodyDivNode, - 'div', - attrib={'style': 'text-align: left;'}) - src = "/website/image/ir.attachment/%s_ccc838d/datas" % str(imgId) - ET.SubElement(imgDivNode, - 'img', - attrib={'class': 'img-thumbnail', - 'src': src}) - arch = ET.tostring(rootNode, encoding='utf-8', xml_declaration=False) - vals = { - 'name': pageName, - 'type': 'qweb', - 'arch': arch, - 'page': True, - } - view_id = self.env['ir.ui.view'].create(vals) - return view_id.id - - def setUp(self): - super(test_export_help_wizard, self).setUp() - self.pageName = False - self.imgXmlId = False - self.pageTemplate = False +class TestExportHelpWizard(TestWizardCommon): + pageName = None + imgXmlId = None def test_export_help(self): """ @@ -123,7 +35,8 @@ class test_export_help_wizard(object): if self.imgXmlId: xPath = ".//record[@id='%s']" % self.imgXmlId imgNodeList = rootXml.findall(xPath) - self.assertEqual(len(imgNodeList), 2) + self.assertEqual(len(imgNodeList), 1, + 'The same image should be exported only once') for imgElem in templateNodeList[0].iter('img'): imgSrc = imgElem.get('src') @@ -131,7 +44,7 @@ class test_export_help_wizard(object): self.assertIn("/ir.attachment/%s|" % self.imgXmlId, imgSrc) else: - self.assertIn("id=%s" % self.imgXmlId, imgSrc) + self.assertIn("/web/image/%s" % self.imgXmlId, imgSrc) if self.pageTemplate: xPath = ".//template[@id='website.%s_snippet']" % self.pageName @@ -140,20 +53,18 @@ class test_export_help_wizard(object): self.assertNotIn("website.", templateNodeList[0].attrib['name']) -class test_export_help_with_image(test_export_help_wizard, - SharedSetupTransactionCase): +class TestExportHelpWithImage(TestExportHelpWizard, common.TransactionCase): def setUp(self): - super(test_export_help_with_image, self).setUp() + super(TestExportHelpWithImage, self).setUp() parameter_model = self.env['ir.config_parameter'] page_prefix = parameter_model.get_param('help_online_page_prefix') self.pageName = '%stest-page' % page_prefix - self.imgXmlId = 'test_img_1' + self.imgXmlId = '%s.test_img_1' % self._module_ns -class test_export_help_template(test_export_help_wizard, - SharedSetupTransactionCase): +class TestExportHelpTemplate(TestExportHelpWizard, common.TransactionCase): def setUp(self): - super(test_export_help_template, self).setUp() + super(TestExportHelpTemplate, self).setUp() parameter_model = self.env['ir.config_parameter'] param = 'help_online_template_prefix' template_prefix = parameter_model.get_param(param) diff --git a/help_online/tests/test_help_online.py b/help_online/tests/test_help_online.py new file mode 100644 index 00000000..e1f5815c --- /dev/null +++ b/help_online/tests/test_help_online.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import mock + +import openerp.tests.common as common +from .common import TestWizardCommon + + +class TestHelpOnline(TestWizardCommon, common.TransactionCase): + + def test_get_page_url(self): + model = 'res.partner' + help_online = self.env['help.online'] + user = self.env.user + group_writer = self.env.ref('help_online.help_online_group_writer') + group_reader = self.env.ref('help_online.help_online_group_reader') + self.assertTrue(user.has_group('help_online.help_online_group_writer')) + with mock.patch('openerp.addons.website.models.website' + '.website.search_pages') as search_pages: + # The expected page dosn't exist + search_pages.return_value = [] + info = help_online.get_page_url(model, 'form') + self.assertDictEqual( + {'exists': False, + 'title': 'Create Help page for Partner', + 'url': 'website/add/help-res-partner'}, info, + "If the user is member of help_online_group_writer " + "and the page doesn't exist, the module should return an url " + "to create the page") + # remove user of group writer. + group_writer.write({'users': [(3, self.env.user.id)]}) + info = help_online.get_page_url(model, 'form') + self.assertDictEqual( + {}, info, + "If the user is not member of help_online_group_writer " + "and the page doesn't exist, the module should return an " + "empty dict") + # The expected page exists + search_pages.return_value = [{'loc': 'pages/help-res-partner'}] + self.assertTrue( + user.has_group('help_online.help_online_group_reader')) + info = help_online.get_page_url(model, 'form') + self.assertDictEqual( + {'exists': True, + 'title': 'Help on Partner', + 'url': 'pages/help-res-partner#form'}, info, + "If the user is member of help_online_group_reader " + "and the page exists, the module should return an url " + "to the page") + # remove user from group reader + group_reader.write({'users': [(3, self.env.user.id)]}) + info = help_online.get_page_url(model, 'form') + self.assertDictEqual( + {}, info, + "If the user is not member of help_online_group_reader " + "and the page exists, the module should return an empty dict") diff --git a/help_online/tests/test_import_help_wizard.py b/help_online/tests/test_import_help_wizard.py new file mode 100644 index 00000000..818a9284 --- /dev/null +++ b/help_online/tests/test_import_help_wizard.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import base64 + +import openerp.tests.common as common +from .common import TestWizardCommon + + +class TestImportHelpWizard(TestWizardCommon, common.TransactionCase): + + def setUp(self): + super(TestImportHelpWizard, self).setUp() + self.page_name = "export_import_help" + self.img_xml_id = '%s.test_img_1' % self._module_ns + self.img_name = self.env.ref(self.img_xml_id).name + self.ir_attchement = self.env['ir.attachment'] + self.ir_ui_view = self.env['ir.ui.view'] + self.export_help_wizard = self.env['export.help.wizard'] + self.import_help_wizard = self.env['import.help.wizard'] + + def _do_check_resources(self, expected=1): + pages = self.ir_ui_view.search([('name', '=', self.page_name)]) + self.assertEqual(expected, len(pages)) + attachments = self.ir_attchement.search( + [('name', '=', self.img_name)]) + self.assertEqual(expected, len(attachments)) + + def test_import_help(self): + self.createPage(pageName=self.page_name, imgXmlId=self.img_xml_id) + self._do_check_resources() + wizard = self.export_help_wizard.create({}) + wizard.export_help() + xmlData = base64.decodestring(wizard.data) + self.env.ref(self.img_xml_id).unlink() + self.ir_ui_view.search([('name', '=', self.page_name)]).unlink() + self._do_check_resources(0) + wizard = self.import_help_wizard.create({ + 'source_file': base64.encodestring(xmlData) + }) + wizard.import_help() + self._do_check_resources() + + def test_import_export_help(self): + """Check that exported data are not ducplicated by export / import + """ + self.createPage(pageName=self.page_name, imgXmlId=self.img_xml_id) + self._do_check_resources() + # export + wizard = self.export_help_wizard.create({}) + wizard.export_help() + xmlData = base64.decodestring(wizard.data) + self._do_check_resources() + wizard = self.import_help_wizard.create({ + 'source_file': base64.encodestring(xmlData) + }) + wizard.import_help() + self._do_check_resources() diff --git a/help_online/views/export_help_wizard_view.xml b/help_online/views/export_help_wizard_view.xml deleted file mode 100644 index a9788438..00000000 --- a/help_online/views/export_help_wizard_view.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - export.help.wizard.view - export.help.wizard - form - -
- - - - -

- This wizard allow you to export all QWeb views - related to help online. The result will be an Odoo - data xml file. -

-
- - - -
- -
-
-
-
- - - Export Help - export.help.wizard - - form - form - new - ir.actions.act_window - -
-
\ No newline at end of file diff --git a/help_online/views/help_online_view.xml b/help_online/views/help_online_view.xml index b4c9137a..8e3877b4 100644 --- a/help_online/views/help_online_view.xml +++ b/help_online/views/help_online_view.xml @@ -1,28 +1,24 @@ - - - - - - - Website Pages - ir.ui.view - - form - tree,form - {"search_default_website":1} - - - - - - - - - + + + + + Website Pages + ir.ui.view + + form + tree,form + {"search_default_website":1} + + + + + + + + diff --git a/help_online/views/import_help_wizard_view.xml b/help_online/views/import_help_wizard_view.xml deleted file mode 100644 index 15aa93c3..00000000 --- a/help_online/views/import_help_wizard_view.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - import.help.wizard.view - import.help.wizard - form - -
- -

- This wizard allow you to import QWeb views - related to help online. The required file format is an Odoo - data xml file. -

-
- - - -
- -
-
-
-
- - - Import Help - import.help.wizard - - form - form - new - ir.actions.act_window - - -
-
\ No newline at end of file diff --git a/help_online/views/ir_ui_view_view.xml b/help_online/views/ir_ui_view_view.xml index de42f9ca..fa1ae16d 100644 --- a/help_online/views/ir_ui_view_view.xml +++ b/help_online/views/ir_ui_view_view.xml @@ -1,28 +1,24 @@ - - + + + ir.ui.view search (help_online) + + ir.ui.view + + + + + + - - ir.ui.view search (help_online) - - ir.ui.view - - - - - - - - - ir.ui.view form (help_online) - - ir.ui.view - - - - - - - - - + + ir.ui.view form (help_online) + + ir.ui.view + + + + + + + diff --git a/help_online/views/website_help_online.xml b/help_online/views/website_help_online.xml deleted file mode 100644 index ae504364..00000000 --- a/help_online/views/website_help_online.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/help_online/wizards/__init__.py b/help_online/wizards/__init__.py new file mode 100644 index 00000000..d3b6f547 --- /dev/null +++ b/help_online/wizards/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import export_help_wizard +from . import import_help_wizard diff --git a/help_online/models/export_help_wizard.py b/help_online/wizards/export_help_wizard.py similarity index 56% rename from help_online/models/export_help_wizard.py rename to help_online/wizards/export_help_wizard.py index 81063184..3f62621e 100644 --- a/help_online/models/export_help_wizard.py +++ b/help_online/wizards/export_help_wizard.py @@ -1,31 +1,18 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Cédric Pigeon -# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + import logging import base64 import time import copy - +import urlparse +from werkzeug.routing import Map, Rule from lxml import etree as ET from openerp import models, fields, api, exceptions from openerp.tools.translate import _ +from openerp.addons.web.controllers.main import Binary +from openerp.addons.website.controllers.main import WebsiteBinary _logger = logging.getLogger(__name__) @@ -43,94 +30,114 @@ class ExportHelpWizard(models.TransientModel): data = fields.Binary('XML', readonly=True) export_filename = fields.Char('Export XML Filename', size=128) - def _manage_images_on_page(self, page_node, data_node, images_reference): + binary = Binary() + websiteBinary = WebsiteBinary() + + img_url_map = Map([ + Rule('/web/image'), + Rule('/web/image/'), + Rule('/web/image//'), + Rule('/web/image//x'), + Rule('/web/image//x/' + ''), + Rule('/web/image///'), + Rule('/web/image////' + ''), + Rule('/web/image////' + 'x'), + Rule('/web/image////' + 'x/'), + Rule('/web/image/'), + Rule('/web/image//'), + Rule('/web/image//x'), + Rule('/web/image//x/'), + Rule('/web/image/-'), + Rule('/web/image/-/'), + Rule('/web/image/-/x'), + Rule('/web/image/-/x' + '/'), + Rule('/website/image'), + Rule('/website/image/'), + Rule('/website/image//x'), + Rule('/website/image//'), + Rule('/website/image///x'), + Rule('/website/image///'), + Rule('/website/image////x') + ]) + + def _manage_images_on_page(self, page_node, data_node, exported_resources): """ - - Extract images from page and generate a xml node + - Extract images from page and generate an xml node - Replace db id in url with xml id """ - - def get_attach_id(images_reference, - img_model, img_src, generated_xml_id=False): - attach_id = False - if 'id=' in img_src: - id_pos = img_src.index('id=') + 3 - attach_id = img_src[id_pos:] - else: - fragments = img_src.split('ir.attachment/') - attach_id, _ = fragments[1].split('_', 1) - - if attach_id in images_reference: - xml_id = images_reference[attach_id] - else: - ir_data = self.env['ir.model.data'].search( - [('model', '=', img_model), - ('res_id', '=', attach_id)]) - xml_id = generated_xml_id - if ir_data: - xml_id = ir_data[0].name - images_reference[attach_id] = xml_id - - return attach_id, xml_id - - def substitute_id_by_xml_id(img_src, attach_id, xml_id): - new_src = False - if 'id=' in img_src: - new_src = img_src.replace(attach_id, xml_id) - else: - fragments = img_src.split('ir.attachment/') - _, trail = fragments[1].split('_', 1) - new_src = "/website/image/ir.attachment/%s|%s" % \ - (xml_id, trail) - return new_src - - i_img = 0 img_model = 'ir.attachment' + urls = self.img_url_map.bind("dummy.org", "/") for img_elem in page_node.iter('img'): img_src = img_elem.get('src') - if img_model in img_src: - i_img += 1 - generated_xml_id = "%s_img_%s" % \ - (page_node.attrib['name'], str(i_img).rjust(2, '0')) - attach_id, xml_id = get_attach_id(images_reference, - img_model, - img_src, - generated_xml_id) - - new_src = substitute_id_by_xml_id(img_src, attach_id, xml_id) - - if not attach_id: - continue - - image = self.env[img_model].browse(int(attach_id)) - if not image: - continue - + parse_result = urlparse.urlparse(img_src) + path = parse_result.path + query_args = parse_result.query + if urls.test(parse_result.path, "GET"): + endpoint, kwargs = urls.match(path, "GET", + query_args=query_args) + kwargs.update(dict(urlparse.parse_qsl(query_args))) + image = None + # get the binary object + xml_id = kwargs.get('xmlid') + if xml_id: + image = self.env.ref(xml_id, False) + else: + _id = kwargs.get('id') + model = kwargs.get('model', 'ir.attachment') + if _id and model: + _id, _, unique = str(_id).partition('_') + image = self.env[model].browse(int(_id)) + if (not image or + not image.exists() or + image._name != img_model): + raise exceptions.UserError( + _('Only images from ir.attachment are supported when ' + 'exporting help pages')) + exported_data = image.export_data( + ['id', + 'datas', + 'datas_fname', + 'name', + 'res_model', + 'mimetype'], + raw_data=False)['datas'][0] + xml_id = exported_data[0] + new_src = '/web/image/%s' % xml_id img_elem.attrib['src'] = new_src - img_node = ET.SubElement(data_node, - 'record', - attrib={'id': xml_id, - 'model': img_model}) + if xml_id in exported_resources: + continue + img_node = ET.SubElement( + data_node, + 'record', + attrib={'id': xml_id, + 'model': image._name}) field_node = ET.SubElement(img_node, 'field', attrib={'name': 'datas'}) - field_node.text = str(image.datas) + field_node.text = str(exported_data[1]) field_node = ET.SubElement(img_node, 'field', attrib={'name': 'datas_fname'}) - field_node.text = image.datas_fname + field_node.text = exported_data[2] field_node = ET.SubElement(img_node, 'field', attrib={'name': 'name'}) - field_node.text = image.name + field_node.text = exported_data[3] field_node = ET.SubElement(img_node, 'field', attrib={'name': 'res_model'}) - field_node.text = image.res_model + field_node.text = exported_data[4] field_node = ET.SubElement(img_node, 'field', attrib={'name': 'mimetype'}) - field_node.text = image.mimetype + field_node.text = exported_data[5] data_node.append(img_node) + exported_resources.add(xml_id) def _clean_href_urls(self, page_node, page_prefix, template_prefix): """ @@ -216,39 +223,67 @@ class ExportHelpWizard(models.TransientModel): ('name', 'like', '%s%%' % page_prefix), ('name', 'like', '%s%%' % template_prefix)] - view_data_list = self.env['ir.ui.view'].search_read(domain, - ['arch', 'name'], - order='name') + ir_ui_views = self.env['ir.ui.view'].search(domain, order='name') xml_to_export = ET.Element('openerp') data_node = ET.SubElement(xml_to_export, 'data') - images_reference = {} - for view_data in view_data_list: + exported_resources = set() + for ir_ui_view in ir_ui_views: parser = ET.XMLParser(remove_blank_text=True) - root = ET.XML(view_data['arch'], parser=parser) - + root = ET.XML(ir_ui_view.arch, parser=parser) root.tag = 'template' - template_id = root.attrib.pop('t-name') - root.attrib['name'] = view_data['name'].replace('website.', '') - root.attrib['id'] = template_id + xml_id = self._get_ir_ui_view_xml_id( + ir_ui_view, root.attrib.pop('t-name')) + root.attrib['name'] = ir_ui_view.name.replace('website.', '') + root.attrib['id'] = xml_id root.attrib['page'] = 'True' - self._manage_images_on_page(root, data_node, images_reference) + self._manage_images_on_page(root, data_node, exported_resources) self._clean_href_urls(root, page_prefix, template_prefix) data_node.append(root) if root.attrib['name'].startswith(template_prefix): snippet = self._generate_snippet_from_template(root, - template_id, + xml_id, template_prefix) data_node.append(snippet) - if len(view_data_list) > 0: + if len(ir_ui_views) > 0: return ET.tostring(xml_to_export, encoding='utf-8', xml_declaration=True, pretty_print=True) else: return False + @api.model + def _get_ir_ui_view_xml_id(self, ir_ui_view, template_name): + """This method check if an xml_id exists for the given ir.ui.view + If no xml_id exists, a new one is created with template name as + value to ensure that the import of the generated file will update + the existing view in place of creating new copies. + """ + ir_model_data = self.sudo().env['ir.model.data'] + data = ir_model_data.search([('model', '=', ir_ui_view._name), + ('res_id', '=', ir_ui_view.id)]) + if data: + if data[0].module: + return '%s.%s' % (data[0].module, data[0].name) + else: + return data[0].name + else: + module, name = template_name.split('.') + postfix = ir_model_data.search_count( + [('module', '=', module), + ('name', 'like', name)]) + if postfix: + name = '%s_%s' % (name, postfix) + ir_model_data.create({ + 'model': ir_ui_view._name, + 'res_id': ir_ui_view.id, + 'module': module, + 'name': name, + }) + return module + '.' + name + @api.multi def export_help(self): """ diff --git a/help_online/wizards/export_help_wizard_view.xml b/help_online/wizards/export_help_wizard_view.xml new file mode 100644 index 00000000..3b281200 --- /dev/null +++ b/help_online/wizards/export_help_wizard_view.xml @@ -0,0 +1,50 @@ + + + + export.help.wizard.view + export.help.wizard + form + +
+ + + + +

+ This wizard allow you to export all QWeb views + related to help online. The result will be an Odoo + data xml file. +

+
+ + + +
+ +
+
+
+
+ + + Export Help + export.help.wizard + + form + form + new + ir.actions.act_window + +
diff --git a/help_online/wizards/import_help_wizard.py b/help_online/wizards/import_help_wizard.py new file mode 100644 index 00000000..77694d20 --- /dev/null +++ b/help_online/wizards/import_help_wizard.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2014 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import base64 +from cStringIO import StringIO +from lxml import etree +import logging +import os + +from openerp import api, fields, models +from openerp.tools import convert, misc +from openerp.tools.config import config + +_logger = logging.getLogger(__name__) + + +class XmlImport(convert.xml_import): + """Override base xml_import to be able to import record with an exported + xml_id ('__export__.XXX-XXX') + """ + + def _test_xml_id(self, xml_id): + if '.' in xml_id: + module, _id = xml_id.split('.') + if module == '__export__': + return True + super(XmlImport, self)._test_xml_id(xml_id) + + +class ImportHelpWizard(models.TransientModel): + _name = "import.help.wizard" + + source_file = fields.Binary('Source File') + + @api.multi + def import_help(self): + for this in self: + xmlfile = StringIO(base64.decodestring(this.source_file)) + doc = etree.parse(xmlfile) + relaxng = etree.RelaxNG( + etree.parse( + os.path.join(config['root_path'], 'import_xml.rng'))) + try: + relaxng.assert_(doc) + except Exception: + _logger.info('The XML file does not fit the required schema !', + exc_info=True) + _logger.info(misc.ustr(relaxng.error_log.last_error)) + raise + obj = XmlImport(self.env.cr, self._module, idref={}, mode='init', + report=None, noupdate=False, xml_filename=None) + obj.parse(doc.getroot(), mode='init') diff --git a/help_online/wizards/import_help_wizard_view.xml b/help_online/wizards/import_help_wizard_view.xml new file mode 100644 index 00000000..75f4b601 --- /dev/null +++ b/help_online/wizards/import_help_wizard_view.xml @@ -0,0 +1,43 @@ + + + + import.help.wizard.view + import.help.wizard + form + +
+ +

+ This wizard allow you to import QWeb views + related to help online. The required file format is an Odoo + data xml file. +

+
+ + + +
+ +
+
+
+
+ + + Import Help + import.help.wizard + + form + form + new + ir.actions.act_window + +
diff --git a/setup/help_online/odoo_addons/__init__.py b/setup/help_online/odoo_addons/__init__.py new file mode 100644 index 00000000..de40ea7c --- /dev/null +++ b/setup/help_online/odoo_addons/__init__.py @@ -0,0 +1 @@ +__import__('pkg_resources').declare_namespace(__name__) diff --git a/setup/help_online/odoo_addons/help_online b/setup/help_online/odoo_addons/help_online new file mode 120000 index 00000000..1f1bc8e3 --- /dev/null +++ b/setup/help_online/odoo_addons/help_online @@ -0,0 +1 @@ +../../../help_online \ No newline at end of file diff --git a/setup/help_online/setup.py b/setup/help_online/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/help_online/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 49c738a4c40e4fb6a3bd396041f120e5e836225e Mon Sep 17 00:00:00 2001 From: Laurent Mignon Date: Fri, 13 Jan 2017 11:33:49 +0100 Subject: [PATCH 2/4] [MIG] Migrate to 10.0 --- help_online/README.rst | 4 ++-- help_online/__manifest__.py | 3 +-- help_online/controllers/help_online_controllers.py | 4 ++-- help_online/data/ir_config_parameter_data.xml | 4 ++-- help_online/models/help_online.py | 4 ++-- help_online/models/ir_model.py | 2 +- help_online/security/help_online_groups.xml | 2 +- help_online/tests/common.py | 2 +- help_online/tests/data/help_test_data.xml | 4 ++-- help_online/tests/test_export_help_wizard.py | 2 +- help_online/tests/test_help_online.py | 7 ++++--- help_online/tests/test_import_help_wizard.py | 2 +- help_online/wizards/export_help_wizard.py | 10 +++++----- help_online/wizards/import_help_wizard.py | 6 +++--- setup/help_online/{odoo_addons => odoo}/__init__.py | 0 setup/help_online/odoo/addons/__init__.py | 1 + setup/help_online/odoo/addons/help_online | 1 + setup/help_online/odoo_addons/help_online | 1 - 18 files changed, 30 insertions(+), 29 deletions(-) rename setup/help_online/{odoo_addons => odoo}/__init__.py (100%) create mode 100644 setup/help_online/odoo/addons/__init__.py create mode 120000 setup/help_online/odoo/addons/help_online delete mode 120000 setup/help_online/odoo_addons/help_online diff --git a/help_online/README.rst b/help_online/README.rst index 375c8514..8e1a0ff7 100644 --- a/help_online/README.rst +++ b/help_online/README.rst @@ -26,7 +26,7 @@ Usage .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/162/9.0 + :target: https://runbot.odoo-community.org/runbot/162/10.0 Known issues / Roadmap @@ -34,7 +34,7 @@ Known issues / Roadmap Even if the generated urls to the documentation contains an anchor (website/hel-xx#view_type), it's no more possible to insert/edit anchors elements into the website since this functionnality is not supported -by the new html editor in Odoo 9.0 (summernote). +by the new html editor in Odoo 10.0 (summernote). Bug Tracker diff --git a/help_online/__manifest__.py b/help_online/__manifest__.py index cf3440fd..aa0db85d 100644 --- a/help_online/__manifest__.py +++ b/help_online/__manifest__.py @@ -4,14 +4,13 @@ { 'name': 'Help Online', - 'version': '9.0.1.0.0', + 'version': '10.0.1.0.0', 'author': "ACSONE SA/NV,Odoo Community Association (OCA)", 'maintainer': 'ACSONE SA/NV', 'website': 'http://www.acsone.eu', 'license': 'AGPL-3', 'category': 'Documentation', 'depends': [ - 'base', 'website', ], 'data': [ diff --git a/help_online/controllers/help_online_controllers.py b/help_online/controllers/help_online_controllers.py index 1dc8522e..e0ed5919 100644 --- a/help_online/controllers/help_online_controllers.py +++ b/help_online/controllers/help_online_controllers.py @@ -2,8 +2,8 @@ # Copyright 2014 ACSONE SA/NV () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -import openerp.http as http -from openerp.http import request +import odoo.http as http +from odoo.http import request class HelpOnlineController(http.Controller): diff --git a/help_online/data/ir_config_parameter_data.xml b/help_online/data/ir_config_parameter_data.xml index 3f3cf68f..213c3d5e 100644 --- a/help_online/data/ir_config_parameter_data.xml +++ b/help_online/data/ir_config_parameter_data.xml @@ -1,5 +1,5 @@ - + @@ -22,4 +22,4 @@ - + diff --git a/help_online/models/help_online.py b/help_online/models/help_online.py index 975cba70..4eb4fd86 100644 --- a/help_online/models/help_online.py +++ b/help_online/models/help_online.py @@ -2,8 +2,8 @@ # Copyright 2014 ACSONE SA/NV () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import models, exceptions -from openerp.tools.translate import _ +from odoo import models, exceptions +from odoo.tools.translate import _ class HelpOnline(models.TransientModel): diff --git a/help_online/models/ir_model.py b/help_online/models/ir_model.py index fd79f099..8a136c12 100644 --- a/help_online/models/ir_model.py +++ b/help_online/models/ir_model.py @@ -2,7 +2,7 @@ # Copyright 2014 ACSONE SA/NV () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import models, api +from odoo import models, api from lxml import etree as ET diff --git a/help_online/security/help_online_groups.xml b/help_online/security/help_online_groups.xml index 92c5ff72..971582ce 100644 --- a/help_online/security/help_online_groups.xml +++ b/help_online/security/help_online_groups.xml @@ -9,7 +9,7 @@ diff --git a/help_online/tests/common.py b/help_online/tests/common.py index 51fc02ae..a2d5e842 100644 --- a/help_online/tests/common.py +++ b/help_online/tests/common.py @@ -6,7 +6,7 @@ import os import sys from lxml import etree as ET -from openerp.tools.convert import convert_xml_import +from odoo.tools.convert import convert_xml_import class TestWizardCommon(object): diff --git a/help_online/tests/data/help_test_data.xml b/help_online/tests/data/help_test_data.xml index 55723379..cfc8b038 100644 --- a/help_online/tests/data/help_test_data.xml +++ b/help_online/tests/data/help_test_data.xml @@ -1,5 +1,5 @@ - + iVBORw0KGgoAAAANSUhEUgAAANwAAAAzCAIAAABzKvGBAAAOOUlEQVR42u1beVRU5xWfYcZh3wao @@ -75,4 +75,4 @@ YFBaQ6YYbTbt679Y0nIRIfKXS1d/8J7oqRWRGxO2b92S+NyzK2n3aAwoCf/7jpEfsQAoxU3nESI/ image/png - + diff --git a/help_online/tests/test_export_help_wizard.py b/help_online/tests/test_export_help_wizard.py index b9fcdc2e..fb0ec1f2 100644 --- a/help_online/tests/test_export_help_wizard.py +++ b/help_online/tests/test_export_help_wizard.py @@ -5,7 +5,7 @@ import base64 from lxml import etree as ET -import openerp.tests.common as common +import odoo.tests.common as common from .common import TestWizardCommon diff --git a/help_online/tests/test_help_online.py b/help_online/tests/test_help_online.py index e1f5815c..8c963576 100644 --- a/help_online/tests/test_help_online.py +++ b/help_online/tests/test_help_online.py @@ -4,7 +4,7 @@ import mock -import openerp.tests.common as common +import odoo.tests.common as common from .common import TestWizardCommon @@ -17,8 +17,9 @@ class TestHelpOnline(TestWizardCommon, common.TransactionCase): group_writer = self.env.ref('help_online.help_online_group_writer') group_reader = self.env.ref('help_online.help_online_group_reader') self.assertTrue(user.has_group('help_online.help_online_group_writer')) - with mock.patch('openerp.addons.website.models.website' - '.website.search_pages') as search_pages: + website = self.env['website'] + with mock.patch.object(website.__class__, + 'search_pages') as search_pages: # The expected page dosn't exist search_pages.return_value = [] info = help_online.get_page_url(model, 'form') diff --git a/help_online/tests/test_import_help_wizard.py b/help_online/tests/test_import_help_wizard.py index 818a9284..d9b64e86 100644 --- a/help_online/tests/test_import_help_wizard.py +++ b/help_online/tests/test_import_help_wizard.py @@ -4,7 +4,7 @@ import base64 -import openerp.tests.common as common +import odoo.tests.common as common from .common import TestWizardCommon diff --git a/help_online/wizards/export_help_wizard.py b/help_online/wizards/export_help_wizard.py index 3f62621e..aad0f08d 100644 --- a/help_online/wizards/export_help_wizard.py +++ b/help_online/wizards/export_help_wizard.py @@ -9,10 +9,10 @@ import copy import urlparse from werkzeug.routing import Map, Rule from lxml import etree as ET -from openerp import models, fields, api, exceptions -from openerp.tools.translate import _ -from openerp.addons.web.controllers.main import Binary -from openerp.addons.website.controllers.main import WebsiteBinary +from odoo import models, fields, api, exceptions +from odoo.tools.translate import _ +from odoo.addons.web.controllers.main import Binary +from odoo.addons.website.controllers.main import WebsiteBinary _logger = logging.getLogger(__name__) @@ -224,7 +224,7 @@ class ExportHelpWizard(models.TransientModel): ('name', 'like', '%s%%' % template_prefix)] ir_ui_views = self.env['ir.ui.view'].search(domain, order='name') - xml_to_export = ET.Element('openerp') + xml_to_export = ET.Element('odoo') data_node = ET.SubElement(xml_to_export, 'data') exported_resources = set() for ir_ui_view in ir_ui_views: diff --git a/help_online/wizards/import_help_wizard.py b/help_online/wizards/import_help_wizard.py index 77694d20..07517d50 100644 --- a/help_online/wizards/import_help_wizard.py +++ b/help_online/wizards/import_help_wizard.py @@ -8,9 +8,9 @@ from lxml import etree import logging import os -from openerp import api, fields, models -from openerp.tools import convert, misc -from openerp.tools.config import config +from odoo import api, fields, models +from odoo.tools import convert, misc +from odoo.tools.config import config _logger = logging.getLogger(__name__) diff --git a/setup/help_online/odoo_addons/__init__.py b/setup/help_online/odoo/__init__.py similarity index 100% rename from setup/help_online/odoo_addons/__init__.py rename to setup/help_online/odoo/__init__.py diff --git a/setup/help_online/odoo/addons/__init__.py b/setup/help_online/odoo/addons/__init__.py new file mode 100644 index 00000000..de40ea7c --- /dev/null +++ b/setup/help_online/odoo/addons/__init__.py @@ -0,0 +1 @@ +__import__('pkg_resources').declare_namespace(__name__) diff --git a/setup/help_online/odoo/addons/help_online b/setup/help_online/odoo/addons/help_online new file mode 120000 index 00000000..7b389642 --- /dev/null +++ b/setup/help_online/odoo/addons/help_online @@ -0,0 +1 @@ +../../../../help_online \ No newline at end of file diff --git a/setup/help_online/odoo_addons/help_online b/setup/help_online/odoo_addons/help_online deleted file mode 120000 index 1f1bc8e3..00000000 --- a/setup/help_online/odoo_addons/help_online +++ /dev/null @@ -1 +0,0 @@ -../../../help_online \ No newline at end of file From 1a5b413d43bc3ba0359079ba880f57da35b6a1e1 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 8 Mar 2017 09:38:16 +0100 Subject: [PATCH 3/4] [IMP] help_online: new application icon --- help_online/static/description/icon.png | Bin 80511 -> 2933 bytes help_online/views/help_online_view.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/help_online/static/description/icon.png b/help_online/static/description/icon.png index ab8d478d6a88fbdce713c25f88e2d692105b7d7c..92efa71b0c0b9ad9731809041238552c6a11c144 100644 GIT binary patch literal 2933 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 literal 80511 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 jQoLiQd=dOFZovN^4?QL4{"search_default_website":1} - + From 4f6c1ff67139aad6c9936038c22886e0c31b42fe Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 8 Mar 2017 10:58:24 +0100 Subject: [PATCH 4/4] [FIX] help_online: avoid removal of exported pages Always use the '__export__' prefix when generating the xmlid of pages exported by the export wizard to avoid autmomatic removal of these pages by Odoo on system update (-u) --- help_online/tests/test_export_help_wizard.py | 4 ++-- help_online/wizards/export_help_wizard.py | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/help_online/tests/test_export_help_wizard.py b/help_online/tests/test_export_help_wizard.py index fb0ec1f2..933ca3cb 100644 --- a/help_online/tests/test_export_help_wizard.py +++ b/help_online/tests/test_export_help_wizard.py @@ -27,7 +27,7 @@ class TestExportHelpWizard(TestWizardCommon): parser = ET.XMLParser(remove_blank_text=True) rootXml = ET.XML(xmlData, parser=parser) - xPath = ".//template[@id='website.%s']" % self.pageName + xPath = ".//template[@id='__export__.%s']" % self.pageName templateNodeList = rootXml.findall(xPath) self.assertEqual(len(templateNodeList), 1) self.assertNotIn("website.", templateNodeList[0].attrib['name']) @@ -47,7 +47,7 @@ class TestExportHelpWizard(TestWizardCommon): self.assertIn("/web/image/%s" % self.imgXmlId, imgSrc) if self.pageTemplate: - xPath = ".//template[@id='website.%s_snippet']" % self.pageName + xPath = ".//template[@id='__export__.%s_snippet']" % self.pageName templateNodeList = rootXml.findall(xPath) self.assertEqual(len(templateNodeList), 1) self.assertNotIn("website.", templateNodeList[0].attrib['name']) diff --git a/help_online/wizards/export_help_wizard.py b/help_online/wizards/export_help_wizard.py index aad0f08d..e7c7da91 100644 --- a/help_online/wizards/export_help_wizard.py +++ b/help_online/wizards/export_help_wizard.py @@ -271,6 +271,10 @@ class ExportHelpWizard(models.TransientModel): return data[0].name else: module, name = template_name.split('.') + # always use __export__ as module by convention to + # avoid the removal by odoo of the exported pages on system + # update (-u ) + module = "__export__" postfix = ir_model_data.search_count( [('module', '=', module), ('name', 'like', name)])