From 43b8d2aec1f1867a1b4c01db8d9c2f5cd5b6904f Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 14 Apr 2014 17:36:13 +0200 Subject: [PATCH 1/5] [IMP] fields.date: added date_to_datetime function bzr revid: qdp-launchpad@openerp.com-20140414153613-geu20zacxnf0swol --- openerp/osv/fields.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index f60e83726c4..8273fe09830 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -344,6 +344,29 @@ class date(_column): exc_info=True) return (context_today or today).strftime(tools.DEFAULT_SERVER_DATE_FORMAT) + def date_to_datetime(self, cr, uid, userdate, context=None): + """ Convert date values expressed in user's timezone to + server-side UTC timestamp, assuming a default arbitrary + time of 12:00 AM - because a time is needed. + + :param str userdate: date string in in user time zone + :return: UTC datetime string for server-side use + """ + user_date = datetime.strptime(userdate, DEFAULT_SERVER_DATE_FORMAT) + if context and context.get('tz'): + tz_name = context['tz'] + else: + tz_name = self.pool.get('res.users').read(cr, SUPERUSER_ID, uid, ['tz'])['tz'] + if tz_name: + utc = pytz.timezone('UTC') + context_tz = pytz.timezone(tz_name) + user_datetime = user_date + timedelta(hours=12.0) + local_timestamp = context_tz.localize(user_datetime, is_dst=False) + user_datetime = local_timestamp.astimezone(utc) + return user_datetime.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + return user_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + + class datetime(_column): _type = 'datetime' From 979bb51925b03d7819d4c19b6b70edc4136511e3 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 10 Apr 2014 17:20:39 +0200 Subject: [PATCH 2/5] [IMP] ir.attachment: add method to force all attachments to use selected storage bzr revid: chs@openerp.com-20140410152039-hyf0yaizw8p4weg0 --- openerp/addons/base/ir/ir_attachment.py | 65 +++++++++++++++---------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/openerp/addons/base/ir/ir_attachment.py b/openerp/addons/base/ir/ir_attachment.py index 186c02f00b8..8478682eb7c 100644 --- a/openerp/addons/base/ir/ir_attachment.py +++ b/openerp/addons/base/ir/ir_attachment.py @@ -26,6 +26,8 @@ import os import re from openerp import tools +from openerp.tools.translate import _ +from openerp.exceptions import AccessError from openerp.osv import fields,osv from openerp import SUPERUSER_ID @@ -71,33 +73,49 @@ class ir_attachment(osv.osv): def _filestore(self, cr, uid, context=None): return tools.config.filestore(cr.dbname) + def force_storage(self, cr, uid, context=None): + """Force all attachments to be stored in the currently configured storage""" + if not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'): + raise AccessError(_('Only administrators can execute this action.')) + + location = self._storage(cr, uid, context) + domain = { + 'db': [('store_fname', '!=', False)], + 'file': [('db_datas', '!=', False)], + }[location] + + ids = self.search(cr, uid, domain, context=context) + for attach in self.browse(cr, uid, ids, context=context): + attach.write({'datas': attach.datas}) + return True + # 'data' field implementation - def _full_path(self, cr, uid, location, path): + def _full_path(self, cr, uid, path): # sanitize ath path = re.sub('[.]', '', path) path = path.strip('/\\') return os.path.join(self._filestore(cr, uid), path) - def _get_path(self, cr, uid, location, bin_data): + def _get_path(self, cr, uid, bin_data): sha = hashlib.sha1(bin_data).hexdigest() # retro compatibility fname = sha[:3] + '/' + sha - full_path = self._full_path(cr, uid, location, fname) + full_path = self._full_path(cr, uid, fname) if os.path.isfile(full_path): return fname, full_path # keep existing path # scatter files across 256 dirs # we use '/' in the db (even on windows) fname = sha[:2] + '/' + sha - full_path = self._full_path(cr, uid, location, fname) + full_path = self._full_path(cr, uid, fname) dirname = os.path.dirname(full_path) if not os.path.isdir(dirname): os.makedirs(dirname) return fname, full_path - def _file_read(self, cr, uid, location, fname, bin_size=False): - full_path = self._full_path(cr, uid, location, fname) + def _file_read(self, cr, uid, fname, bin_size=False): + full_path = self._full_path(cr, uid, fname) r = '' try: if bin_size: @@ -108,9 +126,9 @@ class ir_attachment(osv.osv): _logger.error("_read_file reading %s",full_path) return r - def _file_write(self, cr, uid, location, value): + def _file_write(self, cr, uid, value): bin_value = value.decode('base64') - fname, full_path = self._get_path(cr, uid, location, bin_value) + fname, full_path = self._get_path(cr, uid, bin_value) if not os.path.exists(full_path): try: with open(full_path, 'wb') as fp: @@ -119,10 +137,10 @@ class ir_attachment(osv.osv): _logger.error("_file_write writing %s", full_path) return fname - def _file_delete(self, cr, uid, location, fname): + def _file_delete(self, cr, uid, fname): count = self.search(cr, 1, [('store_fname','=',fname)], count=True) - if count <= 1: - full_path = self._full_path(cr, uid, location, fname) + full_path = self._full_path(cr, uid, fname) + if count <= 1 and os.path.exists(full_path): try: os.unlink(full_path) except OSError: @@ -135,11 +153,10 @@ class ir_attachment(osv.osv): if context is None: context = {} result = {} - location = self._storage(cr, uid, context) bin_size = context.get('bin_size') for attach in self.browse(cr, uid, ids, context=context): - if location != 'db' and attach.store_fname: - result[attach.id] = self._file_read(cr, uid, location, attach.store_fname, bin_size) + if attach.store_fname: + result[attach.id] = self._file_read(cr, uid, attach.store_fname, bin_size) else: result[attach.id] = attach.db_datas return result @@ -152,15 +169,15 @@ class ir_attachment(osv.osv): context = {} location = self._storage(cr, uid, context) file_size = len(value.decode('base64')) + attach = self.browse(cr, uid, id, context=context) + if attach.store_fname: + self._file_delete(cr, uid, attach.store_fname) if location != 'db': - attach = self.browse(cr, uid, id, context=context) - if attach.store_fname: - self._file_delete(cr, uid, location, attach.store_fname) - fname = self._file_write(cr, uid, location, value) + fname = self._file_write(cr, uid, value) # SUPERUSER_ID as probably don't have write access, trigger during create - super(ir_attachment, self).write(cr, SUPERUSER_ID, [id], {'store_fname': fname, 'file_size': file_size}, context=context) + super(ir_attachment, self).write(cr, SUPERUSER_ID, [id], {'store_fname': fname, 'file_size': file_size, 'db_datas': False}, context=context) else: - super(ir_attachment, self).write(cr, SUPERUSER_ID, [id], {'db_datas': value, 'file_size': file_size}, context=context) + super(ir_attachment, self).write(cr, SUPERUSER_ID, [id], {'db_datas': value, 'file_size': file_size, 'store_fname': False}, context=context) return True _name = 'ir.attachment' @@ -298,11 +315,9 @@ class ir_attachment(osv.osv): if isinstance(ids, (int, long)): ids = [ids] self.check(cr, uid, ids, 'unlink', context=context) - location = self._storage(cr, uid, context) - if location != 'db': - for attach in self.browse(cr, uid, ids, context=context): - if attach.store_fname: - self._file_delete(cr, uid, location, attach.store_fname) + for attach in self.browse(cr, uid, ids, context=context): + if attach.store_fname: + self._file_delete(cr, uid, attach.store_fname) return super(ir_attachment, self).unlink(cr, uid, ids, context) def create(self, cr, uid, values, context=None): From df55b1eb9d743942b33bbe4081795d8dd3945758 Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 15 Apr 2014 12:08:34 +0200 Subject: [PATCH 3/5] [FIX] Website tour - Click inside the zone before to insert sampleText bzr revid: jke@openerp.com-20140415100834-2pstpw357y9klc89 --- addons/website/static/src/js/website.tour.js | 31 ++++++++++---------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js index b7e55fe166b..622b37e5fcb 100644 --- a/addons/website/static/src/js/website.tour.js +++ b/addons/website/static/src/js/website.tour.js @@ -422,7 +422,22 @@ website.Tour = openerp.Class.extend({ self.autoDragAndDropSnippet($element); - } else if (step.sampleText) { + } else if ($element.is(":visible")) { + + $element.trigger($.Event("mouseenter", { srcElement: $element[0] })); + $element.trigger($.Event("mousedown", { srcElement: $element[0] })); + + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + $element[0].dispatchEvent(evt); + + // trigger after for step like: mouseenter, next step click on button display with mouseenter + setTimeout(function () { + $element.trigger($.Event("mouseup", { srcElement: $element[0] })); + $element.trigger($.Event("mouseleave", { srcElement: $element[0] })); + }, 1000); + } + if (step.sampleText) { $element.trigger($.Event("keydown", { srcElement: $element })); if ($element.is("input") ) { @@ -438,20 +453,6 @@ website.Tour = openerp.Class.extend({ $element.trigger($.Event("change", { srcElement: $element })); }, self.defaultDelay<<1); - } else if ($element.is(":visible")) { - - $element.trigger($.Event("mouseenter", { srcElement: $element[0] })); - $element.trigger($.Event("mousedown", { srcElement: $element[0] })); - - var evt = document.createEvent("MouseEvents"); - evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); - $element[0].dispatchEvent(evt); - - // trigger after for step like: mouseenter, next step click on button display with mouseenter - setTimeout(function () { - $element.trigger($.Event("mouseup", { srcElement: $element[0] })); - $element.trigger($.Event("mouseleave", { srcElement: $element[0] })); - }, 1000); } } self.testtimer = setTimeout(autoStep, 100); From 1e93741081f97aeca42f23f41d31e577be05a927 Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 15 Apr 2014 12:14:06 +0200 Subject: [PATCH 4/5] [FIX] Website banner tour - Fix test according to new banner structure bzr revid: jke@openerp.com-20140415101406-54cdr44xayvyq8xo --- .../website/static/src/js/website.tour.banner.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js index 63ef120d9a1..d401cc40128 100644 --- a/addons/website/static/src/js/website.tour.banner.js +++ b/addons/website/static/src/js/website.tour.banner.js @@ -45,13 +45,23 @@ content: _t("Drag the Banner block and drop it in your page."), popover: { fixed: true }, }, - { + { waitFor: '.oe_overlay_options .oe_options:visible', - element: '#wrap .carousel:first .carousel-caption > div', + element: '#wrap .carousel:first div.carousel-content', placement: 'top', title: _t("Customize banner's text"), content: _t("Click in the text and start editing it."), - popover: { next: _t("Continue") }, + sampleText: 'Here, a customized text', + }, + { + waitNot: '#wrap .carousel:first div.carousel-content:has(h2:'+ + 'containsExact('+_t('Your Banner Title')+')):has(h3:'+ + 'containsExact('+_t('Click to customize this text')+'))', + element: '.oe_snippet_parent:visible', + placement: 'bottom', + title: _t("Get banner properties"), + content: _t("Select the parent container to get the global options of the banner."), + popover: { fixed: true }, }, { element: '.oe_overlay_options .oe_options:visible', From 1c5ed2973e12c602477d583662761d13c5e8070e Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 15 Apr 2014 13:37:51 +0200 Subject: [PATCH 5/5] [FIX] mail template view - Set body_html field as simple text area without cke by default. Else, the mako code are considered as mal formatted and moved. bzr revid: jke@openerp.com-20140415113751-h0a1tg36tht1bys1 --- addons/product_email_template/views/email_template_view.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/product_email_template/views/email_template_view.xml b/addons/product_email_template/views/email_template_view.xml index 5b4600b9719..c1312d31132 100644 --- a/addons/product_email_template/views/email_template_view.xml +++ b/addons/product_email_template/views/email_template_view.xml @@ -12,8 +12,7 @@

Body

- +