Browse Source

[10.0][ADD][web_chatter_paste] (#548)

* Initial commit

* Initial commit

* [ADD] Tests

* [FIX] Dependencies

* [REM] Controller tests

* [FIX] Removed unnecessary incompatibility warning

* [FIX] Hyperlink to issues

* [ADD] Tests

* [FIX] Tests

* [?] Testing test problem

* [?] Testing test problem

* [?] Testing test problem

* [ADD] web_chatter_paste

Initial commit

Initial commit

[ADD] Tests

[FIX] Dependencies

[REM] Controller tests

[FIX] Removed unnecessary incompatibility warning

[FIX] Hyperlink to issues

[ADD] Tests

[FIX] Tests

[?] Testing test problem

[?] Testing test problem

[?] Testing test problem

* Testing problem

* Testing problem

* Testing problem

* [ADD] Mock for http.request

* [FIX] Use patch to mock
pull/589/head
Dennis Sluijk 8 years ago
committed by Dave Lasley
parent
commit
0ac40527cd
  1. 67
      web_chatter_paste/README.rst
  2. 5
      web_chatter_paste/__init__.py
  3. 24
      web_chatter_paste/__manifest__.py
  4. 5
      web_chatter_paste/controllers/__init__.py
  5. 33
      web_chatter_paste/controllers/main.py
  6. 110
      web_chatter_paste/static/src/js/web_chatter_paste.js
  7. 12
      web_chatter_paste/templates/assets.xml
  8. 5
      web_chatter_paste/tests/__init__.py
  9. 43
      web_chatter_paste/tests/test_web_chatter_paste.py

67
web_chatter_paste/README.rst

@ -0,0 +1,67 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
=============
Chatter Paste
=============
Paste images and drop files (while composing a message) into the chatter and upload them directly as attachment.
Configuration
=============
No configuration is needed.
Usage
=====
To paste an image:
#. Copy an image (e.g. a screenshot);
#. paste the image into the chatter's composer.
To drop a file:
#. Drag any file (multiple) from your file system;
#. drop them into the chatter's composer.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/162/10.0
Known issues / Roadmap
======================
* Dropping files only works in Chrome.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/web/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Dennis Sluijk <d.sluijk@onestein.nl>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

5
web_chatter_paste/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import controllers

24
web_chatter_paste/__manifest__.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Chatter Paste',
'summary': """
Paste images and drop files into the chatter and upload them directly
""",
'version': '10.0.1.0.0',
'category': 'Web',
'author': 'Onestein,Odoo Community Association (OCA)',
'website': 'http://www.onestein.eu',
'license': 'AGPL-3',
'depends': [
'base',
'web'
],
'data': [
'templates/assets.xml'
],
'installable': True,
'application': False,
}

5
web_chatter_paste/controllers/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import main

33
web_chatter_paste/controllers/main.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import http
from json import dumps
class ChatterPasteController(http.Controller):
@http.route('/web_chatter_paste/upload_attachment', type='http',
auth="user")
def upload_attachment(self, callback, model, id, filename, mimetype,
content):
request = http.request
model_obj = request.env['ir.attachment']
out = """<script language="javascript" type="text/javascript">
var win = window.top.window;
win.jQuery(win).trigger(%s, %s);
</script>"""
attachment = model_obj.create({
'name': filename,
'datas': content,
'datas_fname': filename,
'res_model': model,
'res_id': int(id)
})
args = {
'filename': filename,
'mimetype': mimetype,
'id': attachment.id
}
return out % (dumps(callback), dumps(args))

110
web_chatter_paste/static/src/js/web_chatter_paste.js

@ -0,0 +1,110 @@
/* Copyright 2017 Onestein
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
odoo.define('web_chatter_paste', function (require) {
"use strict";
var core = require('web.core'),
composer = require('mail.composer');
composer.BasicComposer.include({
start: function() {
var self = this;
var res = this._super.apply(this, arguments);
this.$('.o_composer_text_field').bind('drop', function(e) {
e.stopPropagation();
e.preventDefault();
var files = e.originalEvent.dataTransfer.files;
var i = 0;
var next = function() {
$(window).off(self.fileupload_id, next);
i++;
upload();
}
var upload = function() {
if (files.length <= i) return;
var reader = new FileReader();
reader.onload = function() {
$(window).on(self.fileupload_id, next);
self.add_as_attachment(reader.result, files[i].name);
}
reader.readAsDataURL(files[i]);
}
upload();
});
this.$('.o_composer_text_field').bind('paste', function(e) {
if (!e.originalEvent.clipboardData.items) return;
var items = e.originalEvent.clipboardData.items;
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item.type != 'image/png') continue;
var reader = new FileReader();
reader.onload = function() {
self.add_as_attachment(reader.result, _.uniqueId('pasted_file') + '.png');
}
reader.readAsDataURL(item.getAsFile());
}
});
return res;
},
add_as_attachment: function(data, filename, cb) {
//Fetch mimetype and base64
var mimetype = data.substring(5, data.indexOf(';'));
var base64_data = data.substr(data.indexOf(',') + 1, data.length);
//Change and submit form
this.prepare_form();
this.$('form.o_form_binary_form input.filename').val(filename);
this.$('form.o_form_binary_form input.content').val(base64_data);
this.$('form.o_form_binary_form input.mimetype').val(mimetype);
this.$('form.o_form_binary_form').submit();
this.reverse_form();
var attachments = this.get('attachment_ids');
this.$attachment_button.prop('disabled', true);
attachments.push({
'id': 0,
'name': _.uniqueId('attachment_name'),
'filename': filename,
'url': filename,
'upload': true,
'mimetype': '',
});
},
prepare_form: function() {
//Change action
this.$('form.o_form_binary_form').attr('action', '/web_chatter_paste/upload_attachment');
//Remove ufile
this.$('form.o_form_binary_form input.o_form_input_file').remove();
//Add hidden input content
var $content = $('<input type="hidden" name="content" class="content" />');
this.$('form.o_form_binary_form').append($content);
//Add hidden input filename
var $filename = $('<input type="hidden" name="filename" class="filename" />');
this.$('form.o_form_binary_form').append($filename);
//Add hidden input filename
var $mimetype = $('<input type="hidden" name="mimetype" class="mimetype" />');
this.$('form.o_form_binary_form').append($mimetype);
},
reverse_form: function() {
//Change action
this.$('form.o_form_binary_form').attr('action', '/web/binary/upload_attachment');
//Remove new input
this.$('form.o_form_binary_form input.content').remove();
this.$('form.o_form_binary_form input.filename').remove();
this.$('form.o_form_binary_form input.mimetype').remove();
//Restore old input
var $ufile = $('<input class="o_form_input_file" name="ufile" type="file" />');
this.$('form.o_form_binary_form').append($ufile);
}
});
});

12
web_chatter_paste/templates/assets.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2017 Onestein
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<template id="assets_backend" inherit_id="web.assets_backend">
<xpath expr=".">
<script type="text/javascript"
src="/web_chatter_paste/static/src/js/web_chatter_paste.js"/>
</xpath>
</template>
</odoo>

5
web_chatter_paste/tests/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_web_chatter_paste

43
web_chatter_paste/tests/test_web_chatter_paste.py

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from mock import patch
from odoo import http
from odoo.tests.common import HttpCase
from odoo.addons.web_chatter_paste.controllers.main \
import ChatterPasteController
class TestWebChatterPaste(HttpCase):
def test_controller(self):
partner_id = self.ref('base.main_partner')
attachment_obj = self.env['ir.attachment']
attachment_count = attachment_obj.search_count([
('res_model', '=', 'res.partner'),
('res_id', '=', partner_id)
])
f = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6' \
'QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFN' \
'vZnR3YXJlAHBhaW50Lm5ldCA0LjAuOWwzfk4AAAAMSURBVBhXY/j//z8ABf4C/q' \
'c1gYQAAAAASUVORK5CYII='
with patch.object(http, 'request') as request:
request.env = self.env
controller = ChatterPasteController()
controller.upload_attachment(
'_',
'res.partner',
partner_id,
'test.png',
'image/png',
f
)
new_attachment_count = attachment_obj.search_count([
('res_model', '=', 'res.partner'),
('res_id', '=', partner_id)
])
self.assertEqual(attachment_count + 1, new_attachment_count)
Loading…
Cancel
Save