From 71f2c8ee4b14e33cdf8a54a28a5b3f8b55a1594b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 21 Aug 2013 11:45:50 +0200 Subject: [PATCH 1/6] [IMP] simplify CKEditor's image dialog, implement very basic attachment picker TODO: image picker which isn't just a crappy select, using widget type html (?) bzr revid: xmo@openerp.com-20130821094550-u3k5aaqna7zyl8ek --- addons/website/controllers/main.py | 23 ++++-- addons/website/static/src/js/website.js | 94 ++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 8 deletions(-) diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index bd3f7285126..04b801715bf 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -27,6 +27,10 @@ def auth_method_public(): http.auth_methods['public'] = auth_method_public +# PIL images have a type flag, but no MIME. Reverse type flag to MIME. +PIL_MIME_MAPPING = {'PNG': 'image/png', 'JPEG': 'image/jpeg', 'GIF': 'image/gif', } +# Completely arbitrary limits +MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT = IMAGE_LIMITS = (1024, 768) class Website(openerp.addons.web.controllers.main.Home): @http.route('/', type='http', auth="admin") def index(self, **kw): @@ -145,15 +149,20 @@ class Website(openerp.addons.web.controllers.main.Home): buf = cStringIO.StringIO(base64.decodestring(attachment.datas)) image = Image.open(buf) - image.thumbnail((1024, 768), Image.ANTIALIAS) + mime = PIL_MIME_MAPPING[image.format] - response = werkzeug.wrappers.Response(status=200, mimetype={ - 'PNG': 'image/png', - 'JPEG': 'image/jpeg', - 'GIF': 'image/gif', - }[image.format]) + w, h = image.size + resized = w > MAX_IMAGE_WIDTH or h > MAX_IMAGE_HEIGHT + + # If saving unnecessary, just send the image buffer, don't go through + # Image.save() (especially as it breaks animated gifs) + if not resized: + buf.seek(0) + return werkzeug.wrappers.Response(buf, status=200, mimetype=mime) + + image.thumbnail(IMAGE_LIMITS, Image.ANTIALIAS) + response = werkzeug.wrappers.Response(status=200, mimetype=mime) image.save(response.stream, image.format) - return response @http.route('/website/image', type='http', auth="public") diff --git a/addons/website/static/src/js/website.js b/addons/website/static/src/js/website.js index eb224c7905c..afe7cc53448 100644 --- a/addons/website/static/src/js/website.js +++ b/addons/website/static/src/js/website.js @@ -273,7 +273,7 @@ $(function(){ ]},{ name: 'span', items: [ "Link", "Unlink", "Blockquote", "BulletedList", - "NumberedList", "Indent", "Outdent", + "NumberedList", "Indent", "Outdent" ]},{ name: 'justify', items: [ "JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock" @@ -380,5 +380,97 @@ $(function(){ }, }); + function noop() {} + var alter_dialog = { + image: function (definition) { + definition.removeContents('Link'); + definition.removeContents('advanced'); + + var upload = definition.getContents('Upload'); + upload.add({ + type: 'select', + label: 'Existing attachments', + id: 'ir_attachment', + items: [['']], + /** + * On dialog load, fetch all attachments (on ir.ui.view => + * previously uploaded images) and add them to the select's + * options (items array & add method) + */ + onLoad: function () { + var field = this; + + // FIXME: fuck this garbage, also fuck openerp.Model + return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + model: 'ir.attachment', + method: 'search_read', + args: [], + kwargs: { + fields: ['name'], + domain: [['res_model', '=', 'ir.ui.view']], + order: 'name', + } + }).then(function (results) { + _(results).each(function (result) { + field.add(result.name, result.id); + }); + }); + }, + /** + * The image widgets uses "txtUrl" to do most of its stuff. + * Synchronize select & txtUrl by generating the correct URL + * and setting it there + */ + onChange: function () { + var id = this.getValue(); + var url = this.getDialog().getContentElement('info', 'txtUrl'); + if (!id) { + url.setValue(''); + return; + } + + url.setValue('/website/attachment/' + id); + }, + }); + // Override uploadButton to send its information to the select + // created above instead of directly to txtUrl. The select will + // propagate to txtUrl + upload.get('uploadButton').filebrowser = { + onSelect: function (url) { + var id = url.split('/').pop(); + var attachments = this.getDialog().getContentElement('Upload', 'ir_attachment'); + // TODO: return supplementary info to get image/attachment name? + attachments.add(id, id); + attachments.setValue(id); + } + }; + + var old_show = definition.onShow; + definition.onShow = function () { + // CKEDITOR does not *override* onShow, is smashes the existing + // one instead, so override "by hand" + if (old_show) { + old_show.call(this); + } + // Assloads of code in the image plugin just go and tear into + // the info tab without a care, so can't just remove the tab or + // its content. Hide the tab instead, the effect is roughly the + // same. + this.hidePage('info'); + // Force the dialog to always and only display the Upload tab + this.selectPage('Upload'); + this.on('selectPage', function (e) { + setTimeout(function () { + if (e.data.page !== 'Upload') { + this.selectPage('Upload'); + } + }.bind(this), 0); + }); + } + } + }; + CKEDITOR.on('dialogDefinition', function (ev) { + (alter_dialog[ev.data.name] || noop)(ev.data.definition); + }) }); From 2731bc014c859c63417bdc0e15ae1b38e8953733 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 21 Aug 2013 14:13:58 +0200 Subject: [PATCH 2/6] [IMP] mark a bunch of templates as pages, mark all new pages as pages on creation bzr revid: xmo@openerp.com-20130821121358-b6y5d1b8wgz8iyo0 --- addons/website/controllers/main.py | 3 ++- addons/website/views/views.xml | 6 +++--- addons/website_crm/views/website_crm.xml | 2 +- addons/website_event/views/website_event.xml | 4 ++-- addons/website_hr/views/website_hr.xml | 2 +- addons/website_mail/views/website_mail.xml | 2 +- addons/website_sale/views/website_sale.xml | 10 +++++----- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 04b801715bf..2d977287560 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -49,7 +49,8 @@ class Website(openerp.addons.web.controllers.main.Home): newview = view.browse(request.cr, request.uid, newview_id, context={}) newview.write({ 'arch': newview.arch.replace("website.default_page", path), - 'name': "page/%s" % path + 'name': "page/%s" % path, + 'page': True, }) if '.' in path: module, idname = path.split('.') diff --git a/addons/website/views/views.xml b/addons/website/views/views.xml index 7d75ecde6ba..9db549d334e 100644 --- a/addons/website/views/views.xml +++ b/addons/website/views/views.xml @@ -131,7 +131,7 @@ -