mirror of
https://github.com/OCA/web.git
synced 2025-02-22 13:21:25 +02:00
[MIG] Migrate to 9.0
This commit is contained in:
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
# Copyright 2014 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# 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
|
||||
|
||||
@@ -1,299 +0,0 @@
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
import logging
|
||||
import base64
|
||||
import time
|
||||
import copy
|
||||
|
||||
from lxml import etree as ET
|
||||
from openerp import models, fields, api, exceptions
|
||||
from openerp.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
PAGE_PREFIX_PARAMETER = 'help_online_page_prefix'
|
||||
TEMPLATE_PREFIX_PARAMETER = 'help_online_template_prefix'
|
||||
AUTOBACKUP_PARAMETER = 'help_online_autobackup_path'
|
||||
HELP_ONLINE_SNIPPET_IMAGE_PATH = '/help_online/static/src/'\
|
||||
'img/snippet/snippet_thumbs.png'
|
||||
|
||||
|
||||
class ExportHelpWizard(models.TransientModel):
|
||||
_name = "export.help.wizard"
|
||||
_description = 'Export Help Online'
|
||||
|
||||
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):
|
||||
"""
|
||||
- Extract images from page and generate a 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'
|
||||
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
|
||||
|
||||
img_elem.attrib['src'] = new_src
|
||||
img_node = ET.SubElement(data_node,
|
||||
'record',
|
||||
attrib={'id': xml_id,
|
||||
'model': img_model})
|
||||
field_node = ET.SubElement(img_node,
|
||||
'field',
|
||||
attrib={'name': 'datas'})
|
||||
field_node.text = str(image.datas)
|
||||
field_node = ET.SubElement(img_node,
|
||||
'field',
|
||||
attrib={'name': 'datas_fname'})
|
||||
field_node.text = image.datas_fname
|
||||
field_node = ET.SubElement(img_node,
|
||||
'field',
|
||||
attrib={'name': 'name'})
|
||||
field_node.text = image.name
|
||||
field_node = ET.SubElement(img_node,
|
||||
'field',
|
||||
attrib={'name': 'res_model'})
|
||||
field_node.text = image.res_model
|
||||
field_node = ET.SubElement(img_node,
|
||||
'field',
|
||||
attrib={'name': 'mimetype'})
|
||||
field_node.text = image.mimetype
|
||||
data_node.append(img_node)
|
||||
|
||||
def _clean_href_urls(self, page_node, page_prefix, template_prefix):
|
||||
"""
|
||||
Remove host address for href urls
|
||||
"""
|
||||
for a_elem in page_node.iter('a'):
|
||||
if not a_elem.get('href'):
|
||||
continue
|
||||
href = a_elem.get('href')
|
||||
if not href.startswith('http'):
|
||||
continue
|
||||
page_url = '/page/%s' % page_prefix
|
||||
template_url = '/page/%s' % template_prefix
|
||||
if page_url not in href and template_url not in href:
|
||||
continue
|
||||
elif page_url in href and template_url not in href:
|
||||
pass
|
||||
elif page_url not in href and template_url in href:
|
||||
page_url = template_url
|
||||
else:
|
||||
if page_prefix in template_prefix:
|
||||
page_url = template_url
|
||||
else:
|
||||
pass
|
||||
|
||||
if page_url:
|
||||
trail = href.split(page_url, 1)[1]
|
||||
a_elem.attrib['href'] = page_url + trail
|
||||
|
||||
def _generate_snippet_from_template(self, page_node,
|
||||
template_id, template_prefix):
|
||||
"""
|
||||
Generate a website snippet from a template
|
||||
"""
|
||||
page = copy.deepcopy(page_node)
|
||||
snippet = ET.Element('template')
|
||||
snippet.attrib['id'] = template_id + '_snippet'
|
||||
snippet.attrib['inherit_id'] = 'website.snippets'
|
||||
snippet.attrib['name'] = page_node.attrib['name']
|
||||
|
||||
xpath = ET.SubElement(snippet,
|
||||
'xpath',
|
||||
attrib={'expr': "//div[@id='snippet_structure']",
|
||||
'position': 'inside'})
|
||||
main_div = ET.SubElement(xpath,
|
||||
'div')
|
||||
thumbnail = ET.SubElement(main_div,
|
||||
'div',
|
||||
attrib={'class': 'oe_snippet_thumbnail'})
|
||||
ET.SubElement(thumbnail,
|
||||
'img',
|
||||
attrib={'class': 'oe_snippet_thumbnail_img',
|
||||
'src': HELP_ONLINE_SNIPPET_IMAGE_PATH})
|
||||
span = ET.SubElement(thumbnail,
|
||||
'span',
|
||||
attrib={'class': 'oe_snippet_thumbnail_title'})
|
||||
span.text = page_node.attrib['name'].replace(template_prefix, '')
|
||||
body = ET.SubElement(main_div,
|
||||
'section',
|
||||
attrib={'class': 'oe_snippet_body '
|
||||
'mt_simple_snippet'})
|
||||
|
||||
template = page.find(".//div[@id='wrap']")
|
||||
|
||||
for node in template.getchildren():
|
||||
body.append(node)
|
||||
|
||||
return snippet
|
||||
|
||||
def _get_qweb_views_data(self):
|
||||
parameter_model = self.env['ir.config_parameter']
|
||||
page_prefix = parameter_model.get_param(PAGE_PREFIX_PARAMETER,
|
||||
False)
|
||||
template_prefix = parameter_model.get_param(TEMPLATE_PREFIX_PARAMETER,
|
||||
False)
|
||||
|
||||
if not page_prefix or not template_prefix:
|
||||
return False
|
||||
|
||||
domain = [('type', '=', 'qweb'),
|
||||
('page', '=', True),
|
||||
'|',
|
||||
('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')
|
||||
xml_to_export = ET.Element('openerp')
|
||||
data_node = ET.SubElement(xml_to_export, 'data')
|
||||
images_reference = {}
|
||||
for view_data in view_data_list:
|
||||
parser = ET.XMLParser(remove_blank_text=True)
|
||||
root = ET.XML(view_data['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
|
||||
root.attrib['page'] = 'True'
|
||||
|
||||
self._manage_images_on_page(root, data_node, images_reference)
|
||||
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,
|
||||
template_prefix)
|
||||
data_node.append(snippet)
|
||||
|
||||
if len(view_data_list) > 0:
|
||||
return ET.tostring(xml_to_export, encoding='utf-8',
|
||||
xml_declaration=True,
|
||||
pretty_print=True)
|
||||
else:
|
||||
return False
|
||||
|
||||
@api.multi
|
||||
def export_help(self):
|
||||
"""
|
||||
Export all Qweb views related to help online in a Odoo
|
||||
data XML file
|
||||
"""
|
||||
xml_data = self._get_qweb_views_data()
|
||||
if not xml_data:
|
||||
raise exceptions.Warning(_('No data to export !'))
|
||||
out = base64.encodestring(xml_data)
|
||||
|
||||
self.write({'data': out,
|
||||
'export_filename': 'help_online_data.xml'})
|
||||
|
||||
return {
|
||||
'name': _('Export Help'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': self._name,
|
||||
'view_mode': 'form',
|
||||
'view_type': 'form',
|
||||
'res_id': self.id,
|
||||
'views': [(False, 'form')],
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
@api.model
|
||||
def auto_backup(self):
|
||||
"""
|
||||
Export data to a file on home directory of user
|
||||
"""
|
||||
parameter_model = self.env['ir.config_parameter']
|
||||
autobackup_path = parameter_model.get_param(AUTOBACKUP_PARAMETER,
|
||||
False)
|
||||
|
||||
if autobackup_path:
|
||||
xml_data = self._get_qweb_views_data()
|
||||
try:
|
||||
timestr = time.strftime("%Y%m%d-%H%M%S")
|
||||
filename = '%s/help_online_backup-%s.xml' % (autobackup_path,
|
||||
timestr)
|
||||
backup_file = open(filename,
|
||||
'w')
|
||||
backup_file.write(xml_data)
|
||||
backup_file.close()
|
||||
except:
|
||||
_logger.warning(_('Unable to write autobackup file '
|
||||
'in given directory: %s'
|
||||
% autobackup_path))
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
# Copyright 2014 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# 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
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
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)
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
# Copyright 2014 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# 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)
|
||||
|
||||
Reference in New Issue
Block a user