From f3e405fbe174d737f0a945295a28d9480b0cc4c1 Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 8 Apr 2014 13:54:24 +0200 Subject: [PATCH 1/9] [FIX] Website snippet - Update carousel to use bootstrap position and size without CSS. Fix bug with slide-to which doesn't work. bzr revid: jke@openerp.com-20140408115424-irsmuhibasonhv7p --- addons/website/static/src/css/website.css | 74 +++---------------- addons/website/static/src/css/website.sass | 61 ++------------- .../static/src/js/website.snippets.editor.js | 2 +- addons/website/views/snippets.xml | 30 +++----- 4 files changed, 30 insertions(+), 137 deletions(-) diff --git a/addons/website/static/src/css/website.css b/addons/website/static/src/css/website.css index 354796a053e..ee732d0495f 100644 --- a/addons/website/static/src/css/website.css +++ b/addons/website/static/src/css/website.css @@ -1,3 +1,4 @@ +@charset "utf-8"; /* THIS CSS FILE IS FOR WEBSITE THEMING CUSTOMIZATION ONLY * * css for editor buttons, openerp widget included in the website and other @@ -305,69 +306,6 @@ section, .carousel, .parallax, .row, .hr, .blockquote { background-size: cover; } -.carousel .carousel-caption { - position: absolute; - right: 50%; - left: 50%; - bottom: 20px; -} -.carousel .carousel-caption > div { - position: absolute; - text-align: left; - padding: 20px; - background: rgba(0, 0, 0, 0.4); - bottom: 20px; -} -.carousel .carousel-caption h1, .carousel .carousel-caption h2, .carousel .carousel-caption h3 { - margin-top: 10px; - margin-bottom: 10px; -} -.carousel .carousel-image { - top: 5%; - bottom: 5%; - position: absolute; - max-height: 90%; - margin: 0 auto; -} -.carousel .item.text_only .carousel-image { - display: none !important; -} -.carousel .item.text_only .carousel-caption { - left: 10%; - right: 10%; - top: 10%; - bottom: auto; -} -.carousel .item.text_only .carousel-caption > div { - text-align: center; - background: transparent; - bottom: auto; - width: 100%; -} -.carousel .item.text_image .carousel-caption { - left: 10%; -} -.carousel .item.text_image .carousel-caption > div { - right: 50%; - margin-right: -20%; - max-width: 550px; -} -.carousel .item.text_image .carousel-image { - right: 10%; - left: 50%; -} -.carousel .item.image_text .carousel-caption { - right: 10%; -} -.carousel .item.image_text .carousel-caption > div { - left: 50%; - margin-left: -20%; - max-width: 550px; -} -.carousel .item.image_text .carousel-image { - right: 50%; - left: 10%; -} .carousel .carousel-control { cursor: pointer; } @@ -394,6 +332,16 @@ div.carousel .carousel-indicators li { div.carousel .carousel-indicators .active { background-color: grey; } +div.carousel span.carousel-img img, div.carousel div.carousel-content { + max-height: 95%; + padding: 10px; +} +div.carousel div.carousel-content { + background-color: black; + color: white; + background: rgba(0, 0, 0, 0.3); + margin-top: 75px; +} .parallax { background-size: cover; diff --git a/addons/website/static/src/css/website.sass b/addons/website/static/src/css/website.sass index 77da53c2958..ff50fb3dd18 100644 --- a/addons/website/static/src/css/website.sass +++ b/addons/website/static/src/css/website.sass @@ -249,59 +249,6 @@ section, .carousel, .parallax, .row, .hr, .blockquote height: 100% background-size: cover .carousel - .carousel-caption - position: absolute - right: 50% - left: 50% - bottom: 20px - > div - position: absolute - text-align: left - padding: 20px - background: rgba(0, 0, 0, 0.4) - bottom: 20px - h1, h2, h3 - margin-top: 10px - margin-bottom: 10px - .carousel-image - top: 5% - bottom: 5% - position: absolute - max-height: 90% - margin: 0 auto - .item.text_only - .carousel-image - display: none !important - .carousel-caption - left: 10% - right: 10% - top: 10% - bottom: auto - > div - text-align: center - background: transparent - bottom: auto - width: 100% - .item.text_image - .carousel-caption - left: 10% - > div - right: 50% - margin-right: -20% - max-width: 550px - .carousel-image - right: 10% - left: 50% - .item.image_text - .carousel-caption - right: 10% - > div - left: 50% - margin-left: -20% - max-width: 550px - .carousel-image - right: 50% - left: 10% .carousel-control cursor: pointer span @@ -324,6 +271,14 @@ div.carousel border: 1px solid grey .active background-color: grey + span.carousel-img img, div.carousel-content + max-height: 95% + padding: 10px + div.carousel-content + background-color: black + color: white + background: rgba(0, 0, 0, 0.3) + margin-top: 75px .parallax background-size: cover diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index 52deeabf5e6..c5a085f209d 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -927,7 +927,7 @@ drop_and_build_snippet: function() { this.id = this.unique_id(); this.$target.attr("id", this.id); - this.$target.find("[data-slide]").attr("href", "#" + this.id); + this.$target.find("[data-slide]").attr("data-cke-saved-href", "#" + this.id); this.$target.find("[data-slide-to]").attr("data-target", "#" + this.id); this.rebind_event(); diff --git a/addons/website/views/snippets.xml b/addons/website/views/snippets.xml index 3e27ffb227f..7ee96aa1162 100644 --- a/addons/website/views/snippets.xml +++ b/addons/website/views/snippets.xml @@ -26,16 +26,18 @@ From 14be89970611e344026883e9f1e6d0a918f62876 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 14 Apr 2014 16:47:54 +0200 Subject: [PATCH 4/9] [FIX] calendar: fix string quoting mess in email template bzr revid: rco@openerp.com-20140414144754-08fgs7xnzax5uzht --- addons/calendar/calendar_data.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/calendar/calendar_data.xml b/addons/calendar/calendar_data.xml index ef413ee3bb5..7179566989c 100644 --- a/addons/calendar/calendar_data.xml +++ b/addons/calendar/calendar_data.xml @@ -212,7 +212,7 @@ : % for attendee in object.event_id.attendee_ids: -
+
% if attendee.cn != object.cn: ${attendee.cn} % else: @@ -345,7 +345,7 @@ : % for attendee in object.event_id.attendee_ids: -
+
% if attendee.cn != object.cn: ${attendee.cn} % else: @@ -477,7 +477,7 @@ : % for attendee in object.event_id.attendee_ids: -
+
% if attendee.cn != object.cn: ${attendee.cn} % else: From 43b8d2aec1f1867a1b4c01db8d9c2f5cd5b6904f Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 14 Apr 2014 17:36:13 +0200 Subject: [PATCH 5/9] [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 6/9] [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 7/9] [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 8/9] [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 9/9] [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

- +