mirror of https://github.com/OCA/social.git
[MIG] mail_drop_target: Migration to 15.0
parent
4a978873b1
commit
0ff1e8bc0c
|
@ -2,13 +2,23 @@
|
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
{
|
||||
"name": "Drag & drop emails to Odoo",
|
||||
"version": "14.0.1.0.1",
|
||||
"version": "15.0.1.0.0",
|
||||
"author": "Therp BV,Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"category": "Discuss",
|
||||
"website": "https://github.com/OCA/social",
|
||||
"summary": "Attach emails to Odoo by dragging them from your desktop",
|
||||
"depends": ["mail", "web_drop_target"],
|
||||
"depends": ["mail"],
|
||||
"external_dependencies": {"python": ["extract_msg"]},
|
||||
"data": ["views/templates.xml", "views/res_config_settings_views.xml"],
|
||||
"data": ["views/res_config_settings_views.xml"],
|
||||
"assets": {
|
||||
"web.assets_backend": [
|
||||
"mail_drop_target/static/lib/base64js.min.js",
|
||||
"mail_drop_target/static/src/js/mail_drop_target.esm.js",
|
||||
"mail_drop_target/static/src/css/mail_drop_target.css",
|
||||
],
|
||||
"web.assets_qweb": [
|
||||
"mail_drop_target/static/src/xml/*.xml",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class MailThread(models.AbstractModel):
|
|||
thread_id=None,
|
||||
):
|
||||
message = _("This message is already imported.")
|
||||
raise exceptions.Warning(message)
|
||||
raise exceptions.UserError(message)
|
||||
|
||||
@api.model
|
||||
def message_process_msg(
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
(function(r){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=r()}else if(typeof define==="function"&&define.amd){define([],r)}else{var e;if(typeof window!=="undefined"){e=window}else if(typeof global!=="undefined"){e=global}else if(typeof self!=="undefined"){e=self}else{e=this}e.base64js=r()}})(function(){var r,e,n;return function(){function r(e,n,t){function o(i,a){if(!n[i]){if(!e[i]){var u=typeof require=="function"&&require;if(!a&&u)return u(i,!0);if(f)return f(i,!0);var d=new Error("Cannot find module '"+i+"'");throw d.code="MODULE_NOT_FOUND",d}var c=n[i]={exports:{}};e[i][0].call(c.exports,function(r){var n=e[i][1][r];return o(n?n:r)},c,c.exports,r,e,n,t)}return n[i].exports}var f=typeof require=="function"&&require;for(var i=0;i<t.length;i++)o(t[i]);return o}return r}()({"/":[function(r,e,n){"use strict";n.byteLength=c;n.toByteArray=v;n.fromByteArray=s;var t=[];var o=[];var f=typeof Uint8Array!=="undefined"?Uint8Array:Array;var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(var a=0,u=i.length;a<u;++a){t[a]=i[a];o[i.charCodeAt(a)]=a}o["-".charCodeAt(0)]=62;o["_".charCodeAt(0)]=63;function d(r){var e=r.length;if(e%4>0){throw new Error("Invalid string. Length must be a multiple of 4")}return r[e-2]==="="?2:r[e-1]==="="?1:0}function c(r){return r.length*3/4-d(r)}function v(r){var e,n,t,i,a;var u=r.length;i=d(r);a=new f(u*3/4-i);n=i>0?u-4:u;var c=0;for(e=0;e<n;e+=4){t=o[r.charCodeAt(e)]<<18|o[r.charCodeAt(e+1)]<<12|o[r.charCodeAt(e+2)]<<6|o[r.charCodeAt(e+3)];a[c++]=t>>16&255;a[c++]=t>>8&255;a[c++]=t&255}if(i===2){t=o[r.charCodeAt(e)]<<2|o[r.charCodeAt(e+1)]>>4;a[c++]=t&255}else if(i===1){t=o[r.charCodeAt(e)]<<10|o[r.charCodeAt(e+1)]<<4|o[r.charCodeAt(e+2)]>>2;a[c++]=t>>8&255;a[c++]=t&255}return a}function l(r){return t[r>>18&63]+t[r>>12&63]+t[r>>6&63]+t[r&63]}function h(r,e,n){var t;var o=[];for(var f=e;f<n;f+=3){t=(r[f]<<16&16711680)+(r[f+1]<<8&65280)+(r[f+2]&255);o.push(l(t))}return o.join("")}function s(r){var e;var n=r.length;var o=n%3;var f="";var i=[];var a=16383;for(var u=0,d=n-o;u<d;u+=a){i.push(h(r,u,u+a>d?d:u+a))}if(o===1){e=r[n-1];f+=t[e>>2];f+=t[e<<4&63];f+="=="}else if(o===2){e=(r[n-2]<<8)+r[n-1];f+=t[e>>10];f+=t[e>>4&63];f+=t[e<<2&63];f+="="}i.push(f);return i.join("")}},{}]},{},[])("/")});
|
|
@ -0,0 +1,58 @@
|
|||
/** @odoo-module **/
|
||||
/* global base64js:false, Uint8Array:false */
|
||||
// Copyright 2018 Therp BV <https://therp.nl>
|
||||
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
import {MessageList} from "@mail/components/message_list/message_list";
|
||||
import {patch} from "web.utils";
|
||||
import {useDragVisibleDropZone} from "@mail/component_hooks/use_drag_visible_dropzone/use_drag_visible_dropzone";
|
||||
|
||||
patch(MessageList.prototype, "mail_drop_target.mail_drop", {
|
||||
setup() {
|
||||
this._super();
|
||||
this.isDropZoneVisible = useDragVisibleDropZone();
|
||||
},
|
||||
async _onDropZoneFilesDropped(ev) {
|
||||
ev.stopPropagation();
|
||||
this.isDropZoneVisible.value = false;
|
||||
var self = this;
|
||||
Promise.all(
|
||||
Array.from(ev.detail.files).map((drop_file) => {
|
||||
var reader = new FileReader();
|
||||
var mail_processor = "";
|
||||
if (drop_file.name.endsWith(".msg")) {
|
||||
mail_processor = "message_process_msg";
|
||||
} else {
|
||||
mail_processor = "message_drop";
|
||||
}
|
||||
reader.readAsArrayBuffer(drop_file);
|
||||
reader.onload = function (event) {
|
||||
var data = "";
|
||||
// TODO: read some config parameter if this should set
|
||||
// some of the context keys to suppress mail.thread's behavior
|
||||
if (mail_processor == "message_process_msg") {
|
||||
data = base64js.fromByteArray(
|
||||
new Uint8Array(event.target.result)
|
||||
);
|
||||
} else {
|
||||
var reader_array = new Uint8Array(event.target.result);
|
||||
data = "";
|
||||
for (var i = 0; i < reader_array.length; i++) {
|
||||
data += String.fromCharCode(parseInt(reader_array[i]));
|
||||
}
|
||||
}
|
||||
self.env.services.rpc({
|
||||
model: "mail.thread",
|
||||
method: mail_processor,
|
||||
args: [self.threadView.thread.model, data],
|
||||
kwargs: {
|
||||
thread_id: self.threadView.thread.id,
|
||||
},
|
||||
});
|
||||
};
|
||||
})
|
||||
).then(function () {
|
||||
return self.trigger("reload");
|
||||
});
|
||||
},
|
||||
});
|
|
@ -1,66 +0,0 @@
|
|||
/* global base64js:false, Uint8Array:false */
|
||||
// Copyright 2018 Therp BV <https://therp.nl>
|
||||
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
odoo.define("mail_drop_target", function (require) {
|
||||
"use strict";
|
||||
var Chatter = require("mail.Chatter");
|
||||
var web_drop_target = require("web_drop_target");
|
||||
|
||||
Chatter.include(web_drop_target.DropTargetMixin);
|
||||
|
||||
Chatter.include({
|
||||
_drop_allowed_types: ["message/rfc822"],
|
||||
_get_record_id: function () {
|
||||
return this.record.res_id;
|
||||
},
|
||||
|
||||
_handle_drop_items: function (drop_items) {
|
||||
var self = this;
|
||||
_.each(drop_items, function (item, e) {
|
||||
return self._handle_file_drop_proxy(item, e);
|
||||
});
|
||||
},
|
||||
_handle_file_drop_proxy: function (item, e) {
|
||||
var self = this;
|
||||
var file = item;
|
||||
if (!file || !(file instanceof Blob)) {
|
||||
return;
|
||||
}
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = self.proxy(
|
||||
_.partial(self._handle_file_drop, file, reader, e)
|
||||
);
|
||||
reader.onerror = self.proxy("_file_reader_error_handler");
|
||||
reader.readAsArrayBuffer(file);
|
||||
},
|
||||
_handle_file_drop: function (drop_file, reader) {
|
||||
var self = this,
|
||||
mail_processor = "",
|
||||
data = "";
|
||||
if (drop_file.name.endsWith(".msg")) {
|
||||
mail_processor = "message_process_msg";
|
||||
data = base64js.fromByteArray(new Uint8Array(reader.result));
|
||||
} else {
|
||||
mail_processor = "message_drop";
|
||||
var reader_array = new Uint8Array(reader.result);
|
||||
data = "";
|
||||
for (var i = 0; i < reader_array.length; i++) {
|
||||
data += String.fromCharCode(parseInt(reader_array[i]));
|
||||
}
|
||||
}
|
||||
// TODO: read some config parameter if this should set
|
||||
// some of the context keys to suppress mail.thread's behavior
|
||||
return this._rpc({
|
||||
model: "mail.thread",
|
||||
method: mail_processor,
|
||||
args: [this.record.model, data],
|
||||
kwargs: {
|
||||
thread_id: this.record.data.id,
|
||||
},
|
||||
}).then(function () {
|
||||
self.trigger_up("reload", {});
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-inherit="mail.MessageList" t-inherit-mode="extension">
|
||||
<xpath expr="//div[1]" position="inside">
|
||||
<t t-if="isDropZoneVisible.value">
|
||||
<DropZone
|
||||
class="o_MailBox_dropZone"
|
||||
t-on-o-dropzone-files-dropped="_onDropZoneFilesDropped"
|
||||
t-ref="dropzone"
|
||||
/>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
|
@ -3,10 +3,10 @@ import base64
|
|||
from mock import patch
|
||||
|
||||
from odoo import exceptions, tools
|
||||
from odoo.tests.common import SavepointCase
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestMailDropTarget(SavepointCase):
|
||||
class TestMailDropTarget(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
@ -15,16 +15,14 @@ class TestMailDropTarget(SavepointCase):
|
|||
cls.partner.message_subscribe(partner_ids=cls.partner.ids)
|
||||
|
||||
def test_eml(self):
|
||||
message = tools.file_open(
|
||||
"sample.eml", subdir="addons/mail_drop_target/tests"
|
||||
).read()
|
||||
message = tools.file_open("addons/mail_drop_target/tests/sample.eml").read()
|
||||
comments = len(self.partner.message_ids)
|
||||
self.partner.message_process(
|
||||
self.partner._name, message, thread_id=self.partner.id
|
||||
)
|
||||
self.partner.refresh()
|
||||
self.assertEqual(comments + 1, len(self.partner.message_ids))
|
||||
with self.assertRaises(exceptions.Warning):
|
||||
with self.assertRaises(exceptions.UserError):
|
||||
self.partner.message_drop(
|
||||
self.partner._name, message, thread_id=self.partner.id
|
||||
)
|
||||
|
@ -32,7 +30,7 @@ class TestMailDropTarget(SavepointCase):
|
|||
def test_msg(self):
|
||||
message = base64.b64encode(
|
||||
tools.file_open(
|
||||
"sample.msg", mode="rb", subdir="addons/mail_drop_target/tests"
|
||||
"addons/mail_drop_target/tests/sample.msg", mode="rb"
|
||||
).read()
|
||||
)
|
||||
comments = len(self.partner.message_ids)
|
||||
|
@ -43,7 +41,7 @@ class TestMailDropTarget(SavepointCase):
|
|||
self.assertEqual(comments + 1, len(self.partner.message_ids))
|
||||
msg = self.partner.message_ids.filtered(lambda m: m.subject == "Test")
|
||||
self.assertIsNotNone(msg.notified_partner_ids)
|
||||
with self.assertRaises(exceptions.Warning):
|
||||
with self.assertRaises(exceptions.UserError):
|
||||
self.partner.message_process_msg(
|
||||
self.partner._name, message, thread_id=self.partner.id
|
||||
)
|
||||
|
@ -57,7 +55,7 @@ class TestMailDropTarget(SavepointCase):
|
|||
def test_msg_no_notification(self):
|
||||
message = base64.b64encode(
|
||||
tools.file_open(
|
||||
"sample.msg", mode="rb", subdir="addons/mail_drop_target/tests"
|
||||
"addons/mail_drop_target/tests/sample.msg", mode="rb"
|
||||
).read()
|
||||
)
|
||||
settings = self.env["res.config.settings"].create({})
|
||||
|
@ -71,7 +69,7 @@ class TestMailDropTarget(SavepointCase):
|
|||
self.assertEqual(comments + 1, len(self.partner.message_ids))
|
||||
msg = self.partner.message_ids.filtered(lambda m: m.subject == "Test")
|
||||
self.assertEqual(len(msg.notified_partner_ids), 0)
|
||||
with self.assertRaises(exceptions.Warning):
|
||||
with self.assertRaises(exceptions.UserError):
|
||||
self.partner.message_process_msg(
|
||||
self.partner._name, message, thread_id=self.partner.id
|
||||
)
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.mail</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="mail.res_config_settings_view_form" />
|
||||
<field name="arch" type="xml">
|
||||
<div id="emails" position="inside">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="disable_notify_mail_drop_target" />
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label
|
||||
string="Disable Mail Drag&Drop Notification"
|
||||
for="disable_notify_mail_drop_target"
|
||||
/>
|
||||
<div class="text-muted">
|
||||
When a user drops an email into an existing thread
|
||||
the followers of the thread will not be notified.
|
||||
</div>
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.mail</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="mail.res_config_settings_view_form" />
|
||||
<field name="arch" type="xml">
|
||||
<div id="emails" position="inside">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="disable_notify_mail_drop_target" />
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label
|
||||
string="Disable Mail Drag&Drop Notification"
|
||||
for="disable_notify_mail_drop_target"
|
||||
/>
|
||||
<div class="text-muted">
|
||||
When a user drops an email into an existing thread
|
||||
the followers of the thread will not be notified.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<openerp>
|
||||
<data>
|
||||
<template
|
||||
id="assets_backend"
|
||||
name="mail_drop_target assets"
|
||||
inherit_id="web.assets_backend"
|
||||
>
|
||||
<xpath expr="." position="inside">
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="/mail_drop_target/static/src/js/mail_drop_target.js"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/mail_drop_target/static/src/css/mail_drop_target.css"
|
||||
/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
Loading…
Reference in New Issue