Skip to content
Permalink
Browse files

[IMP] web,web_editor,website,website_blog: add image preview dialog

  • Loading branch information...
seb-odoo committed May 15, 2019
1 parent a4e5797 commit e748b66d98b8d647e55a1d7b232da9bfc4ddf640
@@ -1031,11 +1031,12 @@ def content_image(self, xmlid=None, model='ir.attachment', id=None, field='datas
# other kwargs are ignored on purpose
return self._content_image(xmlid=xmlid, model=model, id=id, field=field,
filename_field=filename_field, unique=unique, filename=filename, mimetype=mimetype,
download=download, width=width, height=height, crop=crop, access_token=access_token)
download=download, width=width, height=height, crop=crop,
quality=int(kwargs.get('quality', 0)), access_token=access_token)

def _content_image(self, xmlid=None, model='ir.attachment', id=None, field='datas',
filename_field='datas_fname', unique=None, filename=None, mimetype=None,
download=None, width=0, height=0, crop=False, access_token=None,
download=None, width=0, height=0, crop=False, quality=0, access_token=None,
placeholder='placeholder.png', **kwargs):
status, headers, image_base64 = request.env['ir.http'].binary_content(
xmlid=xmlid, model=model, id=id, field=field, unique=unique, filename=filename,
@@ -1049,7 +1050,7 @@ def _content_image(self, xmlid=None, model='ir.attachment', id=None, field='data
if not (width or height):
width, height = odoo.tools.image_guess_size_from_field_name(field)

image_base64 = image_process(image_base64, (width, height), crop=crop)
image_base64 = image_process(image_base64, size=(int(width), int(height)), crop=crop, quality=quality)

content = base64.b64decode(image_base64)
headers = http.set_safe_image_headers(headers, content)
@@ -153,20 +153,35 @@ def _update_checklist_recursive (self, li, checked, children=False, ancestors=Fa
return True

@http.route('/web_editor/attachment/add_datas', type='json', auth='user', methods=['POST'], website=True)
def add_datas(self, filename, datas, disable_optimization=False, res_id=False, res_model='ir.ui.view', filters=False, **kwargs):
if not disable_optimization:
def add_datas(self, filename, datas, quality=0, width=0, height=0, res_id=False, res_model='ir.ui.view', filters=False, **kwargs):
if width or height or quality:
try:
datas = tools.image_process(datas, verify_resolution=True)
datas = tools.image_process(datas, size=(width, height), quality=quality, verify_resolution=True)
except OSError:
pass # not an image
attachment = self._attachment_create(name=filename, datas=datas, 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_document_url(self, url, res_id=False, res_model='ir.ui.view', filters=False, **kwargs):
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()

@http.route('/web_editor/attachment/<model("ir.attachment"):attachment>/update', type='json', auth='user', methods=['POST'], website=True)
def attachment_update(self, attachment, filename=None, width=0, height=0, quality=0):
if attachment.type == 'url':
raise UserError(_("You cannot change the quality, the width or the filename of an URL attachment."))
data = {}
if filename:
data['datas_fname'] = filename
if width or height or quality:
try:
data['datas'] = tools.image_process(attachment.datas, size=(width, height), quality=quality)
except OSError:
pass # not an image
attachment.write(data)
return attachment._get_media_info()

@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)
@@ -61,7 +61,12 @@ var MediaPlugin = AbstractPlugin.extend({
media = $mediaParent[0];
$mediaParent = $mediaParent.parent();
}

// if the image is for a field, the model should handle the resize
var mediaWidth = $(media).parent().data('oeField') ? 1920 : $(media).width();

var mediaDialog = new weWidgets.MediaDialog(this.options.parent, {
mediaWidth: mediaWidth,
onlyImages: $mediaParent.data('oeField') === 'image' || $mediaParent.data('oeType') === 'image',
},
$(media).clone()[0]
@@ -0,0 +1,161 @@
odoo.define('wysiwyg.widgets.image_optimize_dialog', function (require) {
'use strict';

var core = require('web.core');
var Dialog = require('web.Dialog');

var _t = core._t;

var ImagePreviewDialog = Dialog.extend({
template: 'wysiwyg.widgets.image.preview',
xmlDependencies: ['/web_editor/static/src/xml/wysiwyg.xml'],

events: _.extend({}, Dialog.prototype.events, {
'click .o_we_width_preset': '_onClickWidthPreset',
'input #o_we_quality_input': '_onInputQuality',
'input #o_we_width': '_updatePreview',
'input .js_quality_range': '_updatePreview',
}),
/**
* @constructor
*/
init: function (parent, options, attachment, promise, optimizedWidth, isExisting) {
this._super(parent, _.extend({}, {
title: _t("Improve your Image"),
size: 'large',
buttons: [
{text: _t("Optimize"), classes: 'btn-primary', close: false, click: this._onOptimize.bind(this)},
{text: _t("Keep Original"), close: true}
],
}, options));
this.on('closed', this, this._onClosed);

this.isExisting = isExisting;
this.attachment = attachment;
this.promise = promise;
this.optimizedWidth = Math.min(optimizedWidth || attachment.image_width, attachment.image_width);
this.defaultQuality = this.isExisting ? 100 : 80;
this.defaultWidth = this.isExisting ? attachment.image_width : this.optimizedWidth;

this.suggestedWidths = [];
this._addSuggestedWidth(64, '64');
this._addSuggestedWidth(128, '128');
this._addSuggestedWidth(256, '256');
this._addSuggestedWidth(512, '512');
this._addSuggestedWidth(1024, '1024');
this._addSuggestedWidth(this.optimizedWidth,
_.str.sprintf(_t("%d (Suggested)"), this.optimizedWidth));
this.suggestedWidths.push({
'width': this.attachment.image_width,
'text': _.str.sprintf(_t("%d (Original)"), this.attachment.image_width),
});
this.suggestedWidths = _.sortBy(this.suggestedWidths, 'width');
// TODO SEB check with SBU for how to handle quality setting for png, svg, ...
this._updatePreview = _.debounce(this._updatePreview.bind(this), 300);
},
/**
* @override
*/
start: function () {
var self = this;
var promise = this._super.apply(this, arguments);
this.$previewImage = this.$('.js_preview_image');
this.$qualityRange = this.$('.js_quality_range');
this.$qualityInput = this.$('#o_we_quality_input');
this.$filename = this.$('#o_we_filename');
this.$widthInput = this.$('#o_we_width');
this.$configColumn = this.$('#o_we_config_column');
this.$previewColumn = this.$('#o_we_preview_column');
this.$previewError = this.$('#o_we_preview_error');
this.$widthPresets = this.$('.o_we_width_preset');
this._updatePreview();
this.opened().then(function () {
self.$filename.focus();
});
return promise;
},
_addSuggestedWidth: function (size, text) {
if (size < this.attachment.image_width) {
this.suggestedWidths.push({
width: size,
text: text,
});
}
},
/**
* Requests a preview for the current settings and displays it.
*
* @private
* @returns {Promise}
*/
_updatePreview: function () {
var quality = parseInt(this.$qualityRange.val());
this.$qualityInput.val(quality);
var width = parseInt(this.$widthInput.val());
this.$previewImage.attr('src', _.str.sprintf('/web/image/%d/%dx0?quality=%d',
this.attachment.id, width, quality));
this.$widthPresets.removeClass('active');
this.$widthPresets.each(function () {
var $button = $(this);
if (parseInt($button.data('width')) === width) {
$button.addClass('active');
}
});
},
_onInputQuality: function () {
var quality = parseInt(this.$qualityInput.val());
this.$qualityRange.val(quality);
this._updatePreview();
},
/**
* Handles clicking on the save button, which is resolving the promise with
* the current settings.
*/
_onOptimize: function (ev) {
var self = this;
var filename = this.$filename.val();
if (!filename || this.$widthInput.val() > this.attachment.image_width || this.$widthInput.val() < 0) {
return Promise.reject();
}
var params = {
'filename': filename,
};
params['quality'] = parseInt(this.$qualityRange.val());
params['width'] = parseInt(this.$widthInput.val());
// avoid reducing quality when trying to just rename an existing image
if (this.isExisting) {
if (params['quality'] === this.defaultQuality) {
params['quality'] = 0;
}
if (params['width'] === this.defaultWidth) {
params['width'] = 0;
}
}

return this._rpc({
route: _.str.sprintf('/web_editor/attachment/%d/update', this.attachment.id),
params: params,
}).then(function (attachment) {
self.promise.resolve(attachment);
self.close();
});
},
/**
* Does nothing if called after save, otherwise resolves with the original
* attachment.
*/
_onClosed: function () {
this.promise.resolve(this.attachment);
},
_onClickWidthPreset: function (ev) {
ev.preventDefault();
this.$widthInput.val(parseInt($(ev.target).data('width')));
this._updatePreview();
},

});

return {
ImagePreviewDialog: ImagePreviewDialog,
};
});
Oops, something went wrong.

0 comments on commit e748b66

Please sign in to comment.
You can’t perform that action at this time.