[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
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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);
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user