diff --git a/mail_tracking/models/mail_message.py b/mail_tracking/models/mail_message.py index fc6cc67..5925a49 100644 --- a/mail_tracking/models/mail_message.py +++ b/mail_tracking/models/mail_message.py @@ -242,6 +242,8 @@ class MailMessage(models.Model): failed_trackings = self.mail_tracking_ids.filtered( lambda x: x.state in self.get_failed_states() ) + if not failed_trackings or not self.mail_tracking_needs_action: + return failed_partners = failed_trackings.mapped("partner_id") failed_recipients = failed_partners.name_get() if self.author_id: @@ -305,3 +307,9 @@ class MailMessage(models.Model): ) return ids + + @api.model + def get_failed_messsage_info(self, ids, model): + msg_ids = self.search([('res_id', '=', ids), ('model', '=', model)]) + res = [msg._prepare_dict_failed_message() for msg in msg_ids.sorted("date", reverse=True) if msg._prepare_dict_failed_message()] + return res diff --git a/mail_tracking/static/src/js/chatter.js b/mail_tracking/static/src/js/chatter.js new file mode 100644 index 0000000..bceb3ed --- /dev/null +++ b/mail_tracking/static/src/js/chatter.js @@ -0,0 +1,30 @@ +odoo.define('mail_tracking/static/src/js/chatter.js', function (require) { +'use strict'; + +const ChatterContainer = require('mail/static/src/components/chatter_container/chatter_container.js'); +const { attr } = require('mail/static/src/model/model_field.js'); +const { registerInstancePatchModel,registerFieldPatchModel, registerClassPatchModel, + } = require('mail/static/src/model/model_core.js'); + +registerInstancePatchModel('mail.chatter', 'mail/static/src/models/chatter/chatter.js', { + async refresh() { + this._super(...arguments); + this.thread.refreshMessagefailed() + }, + toggleMessageFailedBoxVisibility() { + this.update({ isMessageFailedBoxVisible: !this.isMessageFailedBoxVisible }) + }, + _onThreadIdOrThreadModelChanged() { + this._super(...arguments); + this.thread.refreshMessagefailed() + } + +}); +registerFieldPatchModel('mail.chatter', 'mail/static/src/models/chatter/chatter.js', { + isMessageFailedBoxVisible: attr({ + default: true, + }), +}); + + +}); \ No newline at end of file diff --git a/mail_tracking/static/src/js/discuss/discuss.js b/mail_tracking/static/src/js/discuss/discuss.js new file mode 100644 index 0000000..5fbb251 --- /dev/null +++ b/mail_tracking/static/src/js/discuss/discuss.js @@ -0,0 +1,139 @@ +odoo.define('mail_tracking/static/src/js/discuss/discuss.js', function(require) { + 'use strict'; + + const { + attr + } = require('mail/static/src/model/model_field.js'); + const { + registerInstancePatchModel, + registerFieldPatchModel, + registerClassPatchModel + } = require('mail/static/src/model/model_core.js'); + const { + one2one, + many2one + } = require('mail/static/src/model/model_field.js'); + + registerInstancePatchModel('mail.messaging_initializer', 'mail/static/src/models/messaging_initializer/messaging_initializer.js', { + async start() { + this._super(...arguments); + this.messaging.update({ + failedmsg: [ + ['create', { + id: 'failedmsg', + isServerPinned: true, + model: 'mail.box', + name: this.env._t("Failed"), + }] + ], + }); + + }, + async _init({ + channel_slots, + commands = [], + current_partner, + current_user_id, + mail_failures = {}, + mention_partner_suggestions = [], + menu_id, + moderation_channel_ids = [], + moderation_counter = 0, + needaction_inbox_counter = 0, + partner_root, + public_partner, + public_partners, + shortcodes = [], + starred_counter = 0, + failed_counter = 0 + }) { + const discuss = this.messaging.discuss; + // partners first because the rest of the code relies on them + this._initPartners({ + current_partner, + current_user_id, + moderation_channel_ids, + partner_root, + public_partner, + public_partners, + }); + // mailboxes after partners and before other initializers that might + // manipulate threads or messages + this._initMailboxes({ + moderation_channel_ids, + moderation_counter, + needaction_inbox_counter, + starred_counter, + failed_counter, + }); + // various suggestions in no particular order + this._initCannedResponses(shortcodes); + this._initCommands(commands); + this._initMentionPartnerSuggestions(mention_partner_suggestions); + // channels when the rest of messaging is ready + await this.async(() => this._initChannels(channel_slots)); + // failures after channels + this._initMailFailures(mail_failures); + discuss.update({ menu_id }); + }, + + _initMailboxes({ + moderation_channel_ids, + moderation_counter, + needaction_inbox_counter, + starred_counter, + failed_counter, + }) { + this.env.messaging.inbox.update({ counter: needaction_inbox_counter }); + this.env.messaging.starred.update({ counter: starred_counter }); + this.env.messaging.failedmsg.update({ counter: failed_counter }); + if (moderation_channel_ids.length > 0) { + this.messaging.moderation.update({ + counter: moderation_counter, + isServerPinned: true, + }); + } + } + + }); + + registerFieldPatchModel('mail.messaging', 'mail/static/src/models/messaging/messaging.js', { + failedmsg: one2one('mail.thread'), + + }); + + registerInstancePatchModel('mail.thread_cache', 'mail/static/src/models/thread_cache/thread_cache.js', { + _extendMessageDomain(domain) { + const thread = this.thread; + if (thread === this.env.messaging.failedmsg) { + return domain.concat([ + ['is_failed_message', '=', true] + ]); + } else { + return this._super(...arguments); + } + } + + }); + + registerFieldPatchModel('mail.message', 'mail/static/src/models/message/message.js', { + messagingFailedmsg: many2one('mail.thread', { + related: 'messaging.failedmsg', + }), + isFailed: attr({ + default: false, + }), + + }); + + registerClassPatchModel('mail.message', 'mail/static/src/models/message/message.js', { + convertData(data) { + const data2 = this._super(data); + if ('is_failed_message' in data) { + data2.isFailed = data.is_failed_message; + } + return data2; + }, + }); + +}); \ No newline at end of file diff --git a/mail_tracking/static/src/js/failed_message/mail_failed_box.js b/mail_tracking/static/src/js/failed_message/mail_failed_box.js new file mode 100644 index 0000000..30b3e1e --- /dev/null +++ b/mail_tracking/static/src/js/failed_message/mail_failed_box.js @@ -0,0 +1,95 @@ +odoo.define('mail_tracking/static/src/js/failed_message/mail_failed_box.js', function(require) { + 'use strict'; + + const components = { + Message: require('mail/static/src/components/message/message.js'), + }; + + const useShouldUpdateBasedOnProps = require('mail/static/src/component_hooks/use_should_update_based_on_props/use_should_update_based_on_props.js'); + const useStore = require('mail/static/src/component_hooks/use_store/use_store.js'); + + const chatter = require('mail/static/src/components/chatter/chatter.js'); + + const { + Component, + useState + } = owl; + + + class MessageFailedBox extends Component { + + constructor(...args) { + super(...args); + useStore(props => { + const chatter = this.env.models['mail.chatter'].get(props.chatterLocalId); + const thread = chatter && chatter.thread; + return { + chatter: chatter ? chatter.__state : undefined, + thread: thread && thread.__state, + }; + + }); + + + } + + get chatter() { + return this.env.models['mail.chatter'].get(this.props.chatterLocalId); + } + + _onClickTitle() { + this.chatter.toggleMessageFailedBoxVisibility(); + } + _markFailedMessageReviewed(id) { + return this.env.services.rpc({ + model: "mail.message", + method: "set_need_action_done", + args: [ + [id] + ], + }); + } + _onRetryFailedMessage(event) { + event.preventDefault(); + var messageID = $(event.currentTarget).data("message-id"); + const thread = this.chatter.thread; + var self = this; + this.env.bus.trigger('do-action', { + action: 'mail.mail_resend_message_action', + options: { + additional_context: { + mail_message_to_resend: messageID, + }, + on_close: () => { + self.trigger('reload', { keepChanges: true }); + thread.refresh(); + }, + }, + }); + } + _onMarkFailedMessageReviewed(event) { + event.preventDefault(); + var messageID = $(event.currentTarget).data("message-id"); + this._markFailedMessageReviewed(messageID) + this.trigger('reload', { keepChanges: true }); + this.chatter.thread.refreshMessagefailed(); + this.chatter.thread.refresh(); + } + + + + + } + MessageFailedBox.template = "mail_tracking.MessageFailedBox"; + MessageFailedBox.props = { + chatterLocalId: String, + }; + chatter.components = Object.assign({}, chatter.components, { + MessageFailedBox + }); + return MessageFailedBox; + + + + +}); \ No newline at end of file diff --git a/mail_tracking/static/src/js/failed_message/thread.js b/mail_tracking/static/src/js/failed_message/thread.js index 1a35f52..e1cfcab 100644 --- a/mail_tracking/static/src/js/failed_message/thread.js +++ b/mail_tracking/static/src/js/failed_message/thread.js @@ -1,322 +1,60 @@ -/* Copyright 2019 Alexandre Díaz - License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */ -odoo.define("mail_tracking.FailedMessageThread", function (require) { - "use strict"; +odoo.define('mail_tracking/static/src/js/failed_message/thread.js', function(require) { + 'use strict'; - var AbstractField = require("web.AbstractField"); - var BasicModel = require("web.BasicModel"); - var BasicView = require("web.BasicView"); - var Chatter = require("mail.Chatter"); - var MailThread = require("mail.widget.Thread"); - var utils = require("mail.utils"); - var core = require("web.core"); - var field_registry = require("web.field_registry"); - var time = require("web.time"); + const components = { + Message: require('mail/static/src/components/message/message.js'), + }; - var QWeb = core.qweb; + const useShouldUpdateBasedOnProps = require('mail/static/src/component_hooks/use_should_update_based_on_props/use_should_update_based_on_props.js'); + const useStore = require('mail/static/src/component_hooks/use_store/use_store.js'); - /** - * Helper method to fetch failed messages - * - * @private - * @param {Object} widget - * @param {Array} ids - * @returns {Array} - */ - function _readMessages(widget, ids) { - if (!ids.length) { - return $.when([]); + const chatter = require('mail/static/src/components/chatter/chatter.js'); + + const { + Component, + useState + } = owl; + + const { + registerInstancePatchModel, + registerFieldPatchModel, + } = require('mail/static/src/model/model_core.js'); + const { + one2many + } = require('mail/static/src/model/model_field.js'); + + + + + registerInstancePatchModel('mail.thread', 'mail_tracking/static/src/js/failed_message/thread.js', { + + async refreshMessagefailed() { + var id = this.__values.id + var model = this.__values.model + const messagefailedData = await this.async(() => this.env.services.rpc({ + model: 'mail.message', + method: 'get_failed_messsage_info', + args: [id, model], + }, { + shadow: true + })); + const messagefailed = this.env.models['mail.message.failed'].insert(messagefailedData.map( + messageData => this.env.models['mail.message.failed'].convertData(messageData) + )); + this.update({ + messagefailed: [ + ['replace', messagefailed] + ] + }); } - var context = widget.record && widget.record.getContext(); - return widget - ._rpc({ - model: "mail.message", - method: "get_failed_messages", - args: [ids], - context: context || widget.getSession().user_context, - }) - .then(function (messages) { - // Convert date to moment - _.each(messages, function (msg) { - msg.date = moment(time.auto_str_to_date(msg.date)); - msg.hour = utils.timeFromNow(msg.date); - }); - return messages; - }); - } - BasicModel.include({ - /** - * Fetch data for the 'mail_failed_message' field widget in form views. - * - * @private - * @param {Object} record - * @param {String} fieldName - * @returns {Array} - */ - _fetchSpecialFailedMessages: function (record, fieldName) { - var localID = - record._changes && fieldName in record._changes - ? record._changes[fieldName] - : record.data[fieldName]; - return _readMessages(this, this.localData[localID].res_ids); - }, }); - var FailedMessage = AbstractField.extend({ - className: "o_mail_failed_message", - events: { - "click .o_failed_message_retry": "_onRetryFailedMessage", - "click .o_failed_message_reviewed": "_onMarkFailedMessageReviewed", - }, - specialData: "_fetchSpecialFailedMessages", + registerFieldPatchModel('mail.thread', 'mail_tracking/static/src/js/failed_message/thread.js', { + messagefailed: one2many('mail.message.failed', { + inverse: 'thread', + }), - /** - * Overrides to reference failed messages in a easy way - * - * @override - */ - init: function () { - this._super.apply(this, arguments); - this.failed_messages = this.record.specialData[this.name] || []; - }, - - /** - * Overrides to listen bus notifications - * - * @override - */ - start: function () { - this._super.apply(this, arguments); - this.call("bus_service", "onNotification", this, this._onNotification); - }, - - /** - * Paremeters used to render widget - * - * @private - * @returns {Object} - */ - _failedItemsQWebParams: function () { - return { - failed_messages: this.failed_messages, - nbFailedMessages: this.failed_messages.length, - date_format: time.getLangDateFormat(), - datetime_format: time.getLangDatetimeFormat(), - }; - }, - - /** - * @private - */ - _render: function () { - if (this.failed_messages.length) { - this.$el.html( - QWeb.render( - "mail_tracking.failed_message_items", - this._failedItemsQWebParams() - ) - ); - } else { - this.$el.empty(); - } - }, - - /** - * Reset widget data using selected record - * - * @private - * @param {Object} record - */ - _reset: function (record) { - this._super.apply(this, arguments); - this.failed_messages = this.record.specialData[this.name] || []; - this.res_id = record.res_id; - }, - - /** - * Trigger event to reload mail widgets - * - * @private - * @param {Array} fieldsToReload - */ - _reload: function (fieldsToReload) { - this.trigger_up("reload_mail_fields", fieldsToReload); - }, - - /** - * Mark failed message as reviewed - * - * @private - * @param {Int} id - * @returns {Promise} - */ - _markFailedMessageReviewed: function (id) { - return this._rpc({ - model: "mail.message", - method: "set_need_action_done", - args: [[id]], - context: this.record.getContext(), - }); - }, - - // Handlers - /** - * Listen bus notification to launch reload process. - * This bus notification is received when the user uses - * 'mail.resend.message' wizard. - * - * @private - * @param {Array} notifs - */ - _onNotification: function (notifs) { - var self = this; - _.each(notifs, function (notif) { - var model = notif[0][1]; - if (model === "res.partner") { - var data = notif[1]; - if (data.type === "toggle_tracking_status") { - // Reload 'mail_failed_message' widget - self._reload({failed_message: true}); - } - } - }); - }, - - /** - * Handle retry failed message event to open the mail.resend.message - * wizard. - * - * @private - * @param {Event} event - */ - _onRetryFailedMessage: function (event) { - event.preventDefault(); - var messageID = $(event.currentTarget).data("message-id"); - this.do_action("mail.mail_resend_message_action", { - additional_context: { - mail_message_to_resend: messageID, - }, - }); - }, - - /** - * Handle mark message as reviewed event - * - * @private - * @param {Event} event - */ - _onMarkFailedMessageReviewed: function (event) { - event.preventDefault(); - var messageID = $(event.currentTarget).data("message-id"); - this._markFailedMessageReviewed(messageID).then( - $.proxy(this, "_reload", {failed_message: true}) - ); - }, }); - field_registry.add("mail_failed_message", FailedMessage); - - var mailWidgets = ["mail_failed_message"]; - BasicView.include({ - /** - * Overrides to add 'mail_failed_message' widget as "mail widget" used - * in Chatter. - * - * @override - */ - init: function () { - this._super.apply(this, arguments); - var fieldsInfo = this.fieldsInfo[this.viewType]; - for (var fieldName in fieldsInfo) { - var fieldInfo = fieldsInfo[fieldName]; - // Search fields using 'mail_failed_messsage' widget. - // Only one field can exists using the widget, the last - // found wins. - if (_.contains(mailWidgets, fieldInfo.widget)) { - // Add field as "mail field" shared with Chatter - this.mailFields[fieldInfo.widget] = fieldName; - // Avoid fetch x2many data, this will be done by widget - fieldInfo.__no_fetch = true; - } - } - // Update renderParmans mailFields to include the found field - // using 'mail_failed_messsage' widget. This info is used by the - // renderers [In Odoo vanilla by the form renderer to initialize - // Chatter widget]. - _.extend(this.rendererParams.mailFields, this.mailFields); - }, - }); - - Chatter.include({ - /** - * Overrides to initialize 'mail_failed_message' widget. - * - * @override - */ - init: function (parent, record, mailFields, options) { - this._super.apply(this, arguments); - // Initialize mail_failed_message widget - if (mailFields.mail_failed_message) { - this.fields.failed_message = new FailedMessage( - this, - mailFields.mail_failed_message, - record, - options - ); - } - }, - - /** - * Injects failed messages widget before the chatter - * - * @private - * @returns {Promise} - */ - _render: function () { - var self = this; - return this._super.apply(this, arguments).then(function () { - if (self.fields.failed_message) { - self.fields.failed_message.$el.insertBefore( - self.$el.find(".o_mail_thread") - ); - } - }); - }, - - /** - * Overrides to reload 'mail_failed_message' widget - * - * @override - */ - _onReloadMailFields: function (event) { - if (this.fields.failed_message && event.data.failed_message) { - this.trigger_up("reload", { - fieldNames: [this.fields.failed_message.name], - keepChanges: true, - }); - } else { - // Workaround to avoid trigger reload event twice (once for - // mail_failed_message and again with empty 'fieldNames'. - this._super.apply(this, arguments); - } - }, - }); - - MailThread.include({ - /** - * Show 'retry' & 'Set as reviewed' buttons in the Chatter - * - * @override - */ - init: function () { - this._super.apply(this, arguments); - this._enabledOptions.displayRetryButton = true; - this._enabledOptions.displayReviewedButton = true; - this._disabledOptions.displayRetryButton = false; - this._disabledOptions.displayReviewedButton = false; - }, - }); - - return FailedMessage; -}); +}); \ No newline at end of file diff --git a/mail_tracking/static/src/js/mail_tracking.js b/mail_tracking/static/src/js/mail_tracking.js index 7263ba3..c37a843 100644 --- a/mail_tracking/static/src/js/mail_tracking.js +++ b/mail_tracking/static/src/js/mail_tracking.js @@ -1,167 +1,48 @@ -/* Copyright 2016 Antonio Espinosa - - Copyright 2018 David Vidal - - License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */ +odoo.define('mail_tracking/static/src/js/mail_tracking.js', function(require) { + 'use strict'; -odoo.define("mail_tracking.partner_tracking", function (require) { - "use strict"; + const { + registerClassPatchModel, + registerFieldPatchModel, + registerInstancePatchModel, + } = require('mail/static/src/model/model_core.js'); + const { + attr + } = require('mail/static/src/model/model_field.js'); - var core = require("web.core"); - var ActionManager = require("web.ActionManager"); - var AbstractMessage = require("mail.model.AbstractMessage"); - var Message = require("mail.model.Message"); - var ThreadWidget = require("mail.widget.Thread"); - - var _t = core._t; - - AbstractMessage.include({ - /** - * Messages do not have any PartnerTrackings. - * - * @returns {Boolean} - */ - hasPartnerTrackings: function () { - return false; - }, - - /** - * Messages do not have any email Cc values. - * - * @returns {Boolean} - */ - hasEmailCc: function () { - return false; + registerClassPatchModel('mail.message', 'mail_tracking/static/src/js/mail_tracking.js', { + convertData(data) { + const data2 = this._super(data); + if ('partner_trackings' in data) { + data2.partner_trackings = data.partner_trackings; + } + return data2; }, }); - Message.include({ - init: function (parent, data) { - this._super.apply(this, arguments); - this._partnerTrackings = data.partner_trackings || []; - this._emailCc = data.email_cc || []; - this._trackNeedsAction = data.track_needs_action || false; + registerFieldPatchModel('mail.message', 'mail_tracking/static/src/js/mail_tracking.js', { + partner_trackings: attr(), + }); + + + registerInstancePatchModel('mail.model', 'mail_tracking/static/src/js/mail_tracking.js', { + + + hasPartnerTrackings() { + return _.some(this.__values.partner_trackings); }, - /** - * State whether this message contains some PartnerTrackings values - * - * @override - * @returns {Boolean} - */ - hasPartnerTrackings: function () { - return _.some(this._partnerTrackings); - }, - - /** - * State whether this message contains some email Cc values - * - * @returns {Boolean} - */ - hasEmailCc: function () { + hasEmailCc() { return _.some(this._emailCc); }, - /** - * Get the PartnerTrackings values of this message - * If this message has no PartnerTrackings values, returns [] - * - * @override - * @returns {Object[]} - */ - getPartnerTrackings: function () { + getPartnerTrackings: function() { if (!this.hasPartnerTrackings()) { return []; } - return this._partnerTrackings; + return this.__values.partner_trackings; }, - /** - * Get the email Cc values of this message - * If this message has no email Cc values, returns [] - * - * @returns {Array} - */ - getEmailCc: function () { - if (!this.hasEmailCc()) { - return []; - } - return this._emailCc; - }, + }) - /** - * Check if the email is an Cc - * If this message has no email Cc values, returns false - * - * @param {String} email - * @returns {Boolean} - */ - isEmailCc: function (email) { - if (!this.hasEmailCc()) { - return false; - } - return _.some(this._emailCc, function (item) { - return item[0] === email; - }); - }, - - toggleTrackingStatus: function () { - return this._rpc({ - model: "mail.message", - method: "toggle_tracking_status", - args: [[this.id]], - }); - }, - }); - - ThreadWidget.include({ - events: _.extend(ThreadWidget.prototype.events, { - "click .o_mail_action_tracking_partner": "on_tracking_partner_click", - "click .o_mail_action_tracking_status": "on_tracking_status_click", - }), - on_tracking_partner_click: function (event) { - var partner_id = this.$el.find(event.currentTarget).data("partner"); - var state = { - model: "res.partner", - id: partner_id, - title: _t("Tracking partner"), - }; - event.preventDefault(); - this.action_manager.do_push_state(state); - var action = { - type: "ir.actions.act_window", - view_type: "form", - view_mode: "form", - res_model: "res.partner", - views: [[false, "form"]], - target: "current", - res_id: partner_id, - }; - this.do_action(action); - }, - on_tracking_status_click: function (event) { - var tracking_email_id = $(event.currentTarget).data("tracking"); - var state = { - model: "mail.tracking.email", - id: tracking_email_id, - title: _t("Message tracking"), - }; - event.preventDefault(); - this.action_manager.do_push_state(state); - var action = { - type: "ir.actions.act_window", - view_type: "form", - view_mode: "form", - res_model: "mail.tracking.email", - views: [[false, "form"]], - target: "new", - res_id: tracking_email_id, - }; - this.do_action(action); - }, - init: function () { - this._super.apply(this, arguments); - this.action_manager = this.findAncestor(function (ancestor) { - return ancestor instanceof ActionManager; - }); - }, - }); -}); +}); \ No newline at end of file diff --git a/mail_tracking/static/src/js/message.js b/mail_tracking/static/src/js/message.js new file mode 100644 index 0000000..268187c --- /dev/null +++ b/mail_tracking/static/src/js/message.js @@ -0,0 +1,67 @@ +odoo.define('mail_tracking/static/src/js/message.js', function(require) { + 'use strict'; + + const Message = require('mail/static/src/components/message/message.js'); + const MessageList = require('mail/static/src/components/message_list/message_list.js'); + var core = require('web.core'); + var _t = core._t; + + + class MessageTracking extends Message { + constructor(parent, props) { + super(parent, props); + } + _onTrackingStatusClick(event) { + var tracking_email_id = $(event.currentTarget).data("tracking"); + event.preventDefault(); + return this.env.bus.trigger('do-action', { + action: { + type: "ir.actions.act_window", + view_type: "form", + view_mode: "form", + res_model: "mail.tracking.email", + views: [ + [false, "form"] + ], + target: "new", + res_id: tracking_email_id, + } + }); + } + +// for discuss + _onMarkFailedMessageReviewed(event) { + event.preventDefault(); + var messageID = $(event.currentTarget).data("message-id"); + this._markFailedMessageReviewed(messageID) + window.location.reload(); + } + _onRetryFailedMessage(event) { + event.preventDefault(); + var messageID = $(event.currentTarget).data("message-id"); + this.env.bus.trigger('do-action', { + action: 'mail.mail_resend_message_action', + options: { + additional_context: { + mail_message_to_resend: messageID, + }, + on_close: () => { + window.location.reload(); + }, + }, + }); + } + _markFailedMessageReviewed(id) { + return this.env.services.rpc({ + model: "mail.message", + method: "set_need_action_done", + args: [ + [id] + ], + }); + } + + }; + MessageList.components.Message = MessageTracking; + +}); \ No newline at end of file diff --git a/mail_tracking/static/src/js/models/thread.js b/mail_tracking/static/src/js/models/thread.js new file mode 100644 index 0000000..49d4f2f --- /dev/null +++ b/mail_tracking/static/src/js/models/thread.js @@ -0,0 +1,67 @@ +odoo.define('mail_tracking/static/src/js/models/thread.js', function(require) { + 'use strict'; + + const { + registerNewModel + } = require('mail/static/src/model/model_core.js'); + const { + attr, + many2many, + many2one + } = require('mail/static/src/model/model_field.js'); + const { + clear + } = require('mail/static/src/model/model_field_command.js'); + + function factory(dependencies) { + + class MessageFailed extends dependencies['mail.model'] { + static convertData(data) { + const data2 = {}; + if ('author' in data) { + if (!data.author) { + data2.author = [ + ['unlink-all'] + ]; + } else { + data2.author = data.author[1]; + data2.author_id = data.author[0]; + } + } + if ('body' in data) { + data2.body = data.body; + } + if ('date' in data) { + data2.date = data.date; + } + if ('failed_recipients' in data) { + data2.failed_recipients = data.failed_recipients; + } + if ('id' in data) { + data2.id = data.id; + } + return data2; + } + + } + + MessageFailed.fields = { + thread: many2one('mail.thread', { + inverse: 'messagefailed', + }), + body: attr(), + author: attr(), + author_id: attr(), + date: attr(), + failed_recipients: attr(), + id: attr(), + }; + + MessageFailed.modelName = 'mail.message.failed'; + + return MessageFailed; + } + + registerNewModel('mail.message.failed', factory); + +}); \ No newline at end of file diff --git a/mail_tracking/static/src/xml/failed_message/discuss.xml b/mail_tracking/static/src/xml/failed_message/discuss.xml index 9e426b2..bec5ffe 100644 --- a/mail_tracking/static/src/xml/failed_message/discuss.xml +++ b/mail_tracking/static/src/xml/failed_message/discuss.xml @@ -1,44 +1,38 @@ - - - - - - - - -
- Failed - - -
-
- - - - -
Congratulations, you don't have any failed messages
-
Failed messages appear here.
+ + + +
- + - - - - - + + + + + + + Set as Reviewed + + + + Retry + + + + - - + \ No newline at end of file diff --git a/mail_tracking/static/src/xml/failed_message/thread.xml b/mail_tracking/static/src/xml/failed_message/thread.xml index 280615c..8c52beb 100644 --- a/mail_tracking/static/src/xml/failed_message/thread.xml +++ b/mail_tracking/static/src/xml/failed_message/thread.xml @@ -1,86 +1,107 @@ - - - + + + + + + + + + \ No newline at end of file diff --git a/mail_tracking/static/src/xml/mail_tracking.xml b/mail_tracking/static/src/xml/mail_tracking.xml index ebfaf46..0bbbeb6 100644 --- a/mail_tracking/static/src/xml/mail_tracking.xml +++ b/mail_tracking/static/src/xml/mail_tracking.xml @@ -4,7 +4,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> diff --git a/mail_tracking/views/assets.xml b/mail_tracking/views/assets.xml index 9fa8b7a..19375d4 100644 --- a/mail_tracking/views/assets.xml +++ b/mail_tracking/views/assets.xml @@ -22,12 +22,28 @@ />