[MIG] mail_drop_target: Migration to 15.0

pull/1217/head
Jasmin Solanki 2022-04-04 14:25:11 +05:30 committed by chien
parent 4a978873b1
commit 0ff1e8bc0c
9 changed files with 118 additions and 124 deletions

View File

@ -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",
],
},
}

View File

@ -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(

View File

@ -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("")}},{}]},{},[])("/")});

View File

@ -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");
});
},
});

View File

@ -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", {});
});
},
});
});

View File

@ -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>

View File

@ -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
)

View File

@ -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&amp;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&amp;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>

View File

@ -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>