diff options
| author | Sébastien Theys <seb@odoo.com> | 2019-06-04 15:11:08 +0200 |
|---|---|---|
| committer | Sébastien Theys <seb@odoo.com> | 2019-06-04 22:14:13 +0200 |
| commit | 76cf2ae82a45b9ffcf63b524944a42b7f5192b0c (patch) | |
| tree | 89540178c9e62def90377eb50ea8f7e1c089aff6 /addons/web_editor/controllers/main.py | |
| parent | 191c556d6b50b35178ea5bb91fb998bcffb86367 (diff) | |
[IMP] web_editor, *: improve media dialog attachment upload
* = web_unsplash, website
Remove iframe upload and replace it with a proper RPC. The route is now only
accepting one file at a time, which makes it easier to maintain, and allows to
process the first file as soon as it is ready, instead of having to wait on
everything.
Also fix a bug where a document could not be uploaded because it would try to
parse it as an image.
Remove filter after search result from the JS and add the corresponding
conditions in the domain to avoid processing and returning unnecessary records.
If multiple attachments exist with the same URL, now display them all to avoid
confusion.
Compute all the necessary values in the python model instead of in the JS.
Allow SVG in the widget (the server already accepted them before).
Disable multiple image upload when not in multiImages mode.
task-1930726
PR: #31208
Diffstat (limited to 'addons/web_editor/controllers/main.py')
| -rw-r--r-- | addons/web_editor/controllers/main.py | 134 |
1 files changed, 51 insertions, 83 deletions
diff --git a/addons/web_editor/controllers/main.py b/addons/web_editor/controllers/main.py index 41bb7fceb54..85797ba2e23 100644 --- a/addons/web_editor/controllers/main.py +++ b/addons/web_editor/controllers/main.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import base64 import io -import json import logging import re import time @@ -11,7 +9,8 @@ from PIL import Image, ImageFont, ImageDraw from lxml import etree from odoo.http import request -from odoo import http, tools +from odoo import http, tools, _ +from odoo.exceptions import UserError logger = logging.getLogger(__name__) @@ -153,86 +152,21 @@ class Web_Editor(http.Controller): return True - #------------------------------------------------------ - # upload an image as base64 - #------------------------------------------------------ - @http.route('/web_editor/add_image_base64', type='json', auth='user', methods=['POST'], website=True) - def add_image_base64(self, res_model, res_id, image_base64, filename, disable_optimization=None, **kwargs): - attachment = self._image_to_attachment(res_model, res_id, image_base64, filename, filename, disable_optimization=disable_optimization) - return attachment.read(['name', 'mimetype', 'checksum', 'url', 'type', 'res_id', 'res_model', 'access_token'])[0] - - def _image_to_attachment(self, res_model, res_id, image_base64, name, datas_fname, disable_optimization=None): - Attachments = request.env['ir.attachment'] + @http.route('/web_editor/attachment/add_data', type='json', auth='user', methods=['POST'], website=True) + def add_data(self, name, data, disable_optimization=False, res_id=False, res_model='ir.ui.view', filters=False, **kwargs): if not disable_optimization: - image_base64 = tools.image_process(image_base64, verify_resolution=True) - attachment = Attachments.create({ - 'name': name, - 'datas_fname': datas_fname, - 'datas': image_base64, - 'public': res_model == 'ir.ui.view', - 'res_id': res_id, - 'res_model': res_model, - }) - attachment.generate_access_token() - return attachment - - #------------------------------------------------------ - # add attachment (images or link) - #------------------------------------------------------ - @http.route('/web_editor/attachment/add', type='http', auth='user', methods=['POST'], website=True) - def attach(self, upload=None, url=None, disable_optimization=None, filters=None, **kwargs): - # the upload argument doesn't allow us to access the files if more than - # one file is uploaded, as upload references the first file - # therefore we have to recover the files from the request object - Attachments = request.env['ir.attachment'] # registry for the attachment table - - res_model = kwargs.get('res_model', 'ir.ui.view') - if res_model != 'ir.ui.view' and kwargs.get('res_id'): - res_id = int(kwargs['res_id']) - else: - res_id = None - - uploads = [] - message = None - if not upload: # no image provided, storing the link and the image name - name = url.split("/").pop() # recover filename - datas_fname = name - if filters: - datas_fname = filters + '_' + datas_fname - attachment = Attachments.create({ - 'name': name, - 'datas_fname': datas_fname, - 'type': 'url', - 'url': url, - 'public': res_model == 'ir.ui.view', - 'res_id': res_id, - 'res_model': res_model, - }) - attachment.generate_access_token() - uploads += attachment.read(['name', 'mimetype', 'checksum', 'url', 'type', 'res_id', 'res_model', 'access_token']) - else: # images provided try: - attachments = request.env['ir.attachment'] - for c_file in request.httprequest.files.getlist('upload'): - image_base64 = base64.b64encode(c_file.read()) - name = c_file.filename - datas_fname = name - if filters: - datas_fname = filters + '_' + datas_fname - attachments += self._image_to_attachment(res_model, res_id, image_base64, name, datas_fname, disable_optimization=disable_optimization) - uploads += attachments.read(['name', 'mimetype', 'checksum', 'url', 'type', 'res_id', 'res_model', 'access_token']) - except Exception as e: - logger.exception("Failed to upload image to attachment") - message = str(e) - - return """<script type='text/javascript'> - window.attachments = %s; - window.error = %s; - </script>""" % (json.dumps(uploads), json.dumps(message)) + data = tools.image_process(data, verify_resolution=True) + except OSError: + pass # not an image + attachment = self._attachment_create(name=name, data=data, res_id=res_id, res_model=res_model, filters=filters) + return attachment._get_media_info() + + @http.route('/web_editor/attachment/add_url', type='json', auth='user', methods=['POST'], website=True) + def add_url(self, url, res_id=False, res_model='ir.ui.view', filters=False, **kwargs): + attachment = self._attachment_create(url=url, res_id=res_id, res_model=res_model, filters=filters) + return attachment._get_media_info() - #------------------------------------------------------ - # remove attachment (images or link) - #------------------------------------------------------ @http.route('/web_editor/attachment/remove', type='json', auth='user', website=True) def remove(self, ids, **kwargs): """ Removes a web-based image attachment if it is used by no view (template) @@ -264,11 +198,12 @@ class Web_Editor(http.Controller): attachments_to_remove.unlink() return removal_blocked_by - ## This route is used from CropImageDialog to get image info. - ## It is used to display the original image when we crop a previously - ## cropped image @http.route('/web_editor/get_image_info', type='json', auth='user', website=True) def get_image_info(self, image_id=None, xml_id=None): + """This route is used from CropImageDialog to get image info. + It is used to display the original image when we crop a previously + cropped image. + """ if xml_id: record = request.env['ir.attachment'].get_attachment_by_key(xml_id) elif image_id: @@ -284,6 +219,39 @@ class Web_Editor(http.Controller): result['originalSrc'] = record.url return result + def _attachment_create(self, name='', data=False, url=False, res_id=False, res_model='ir.ui.view', filters=None): + """Create and return a new attachment.""" + if not name and url: + name = url.split("/").pop() + + if res_model != 'ir.ui.view' and res_id: + res_id = int(res_id) + else: + res_id = False + + if filters: + name = filters + '_' + name + + attachment_data = { + 'name': name, + 'public': res_model == 'ir.ui.view', + 'res_id': res_id, + 'res_model': res_model, + } + + if data: + attachment_data['datas'] = data + elif url: + attachment_data.update({ + 'type': 'url', + 'url': url, + }) + else: + raise UserError(_("You need to specify either data or url to create an attachment.")) + + attachment = request.env['ir.attachment'].create(attachment_data) + return attachment + @http.route("/web_editor/get_assets_editor_resources", type="json", auth="user", website=True) def get_assets_editor_resources(self, key, get_views=True, get_scss=True, get_js=True, bundles=False, bundles_restriction=[], only_user_custom_files=True): """ |
