summaryrefslogtreecommitdiff
path: root/addons/mail/static/src
diff options
context:
space:
mode:
authorjem-odoo <jem@openerp.com>2018-12-06 15:15:57 +0000
committerjem-odoo <jem@openerp.com>2019-01-17 13:47:27 +0000
commitd2b3c9a04b4236c915541cc708a79500ec0c97c0 (patch)
treee5811cc2b7f9c163527df4ece58c710a38ed72c3 /addons/mail/static/src
parent295b47a4808d9a78bf993c4211ccb5f4eb498818 (diff)
[IMP] mail: upload a file to mark activity as done
This commit introduces the "upload file" activity type category. For an activity of that time, uploading a file will mark the activity as done (and maybe create the forced next activities). This activity type is seen as a shortcut to upload a file with a reminder. Task-1915004 closes odoo/odoo#29861
Diffstat (limited to 'addons/mail/static/src')
-rw-r--r--addons/mail/static/src/js/activity.js130
-rw-r--r--addons/mail/static/src/xml/activity.xml17
-rw-r--r--addons/mail/static/src/xml/web_kanban_activity.xml36
3 files changed, 161 insertions, 22 deletions
diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js
index db9366f2795..9543a7ebff2 100644
--- a/addons/mail/static/src/js/activity.js
+++ b/addons/mail/static/src/js/activity.js
@@ -8,6 +8,7 @@ var BasicModel = require('web.BasicModel');
var core = require('web.core');
var field_registry = require('web.field_registry');
var session = require('web.session');
+var framework = require('web.framework');
var time = require('web.time');
var QWeb = core.qweb;
@@ -102,10 +103,27 @@ var setDelayLabel = function (activities){
return activities;
};
+/**
+ * Set the file upload identifier for 'upload_file' type activities
+ *
+ * @param {Array} activities list of activity Object
+ * @return {Array} : list of modified activity Object
+ */
+var setFileUploadID = function (activities) {
+ _.each(activities, function (activity) {
+ if (activity.activity_category === 'upload_file') {
+ activity.fileuploadID = _.uniqueId('o_fileupload');
+ }
+ });
+ return activities;
+};
+
var BasicActivity = AbstractField.extend({
events: {
'click .o_edit_activity': '_onEditActivity',
+ 'change input.o_input_file': '_onFileChanged',
'click .o_mark_as_done': '_onMarkActivityDone',
+ 'click .o_mark_as_done_upload_file': '_onMarkActivityDoneUploadFile',
'click .o_activity_template_preview': '_onPreviewMailTemplate',
'click .o_schedule_activity': '_onScheduleActivity',
'click .o_activity_template_send': '_onSendMailTemplate',
@@ -139,13 +157,17 @@ var BasicActivity = AbstractField.extend({
* @private
* @param {Object} params
* @param {integer} params.activityID
+ * @param {integer[]} params.attachmentIds
* @param {string} params.feedback
+ *
+ * @return {$.Promise}
*/
_markActivityDone: function (params) {
var activityID = params.activityID;
- var feedback = params.feedback;
+ var feedback = params.feedback || false;
+ var attachmentIds = params.attachmentIds || [];
- this._sendActivityFeedback(activityID, feedback)
+ return this._sendActivityFeedback(activityID, feedback, attachmentIds)
.then(this._reload.bind(this, { activity: true, thread: true }));
},
/**
@@ -209,14 +231,18 @@ var BasicActivity = AbstractField.extend({
* @private
* @param {integer} activityID
* @param {string} feedback
+ * @param {integer[]} attachmentIds
* @return {$.Promise}
*/
- _sendActivityFeedback: function (activityID, feedback) {
+ _sendActivityFeedback: function (activityID, feedback, attachmentIds) {
return this._rpc({
model: 'mail.activity',
method: 'action_feedback',
args: [[activityID]],
- kwargs: {feedback: feedback},
+ kwargs: {
+ feedback: feedback,
+ attachment_ids: attachmentIds || [],
+ },
context: this.record.getContext(),
});
},
@@ -225,6 +251,28 @@ var BasicActivity = AbstractField.extend({
// Handlers
//------------------------------------------------------------
+ /**
+ * @private
+ * @param {Object[]} activities
+ */
+ _bindOnUploadAction: function (activities) {
+ var self = this;
+ _.each(activities, function (activity) {
+ if (activity.fileuploadID) {
+ $(window).on(activity.fileuploadID, function() {
+ framework.unblockUI();
+ // find the button clicked and display the feedback popup on it
+ var files = Array.prototype.slice.call(arguments, 1);
+ self._markActivityDone({
+ activityID: activity.id,
+ attachmentIds: _.pluck(files, 'id')
+ }).then(function () {
+ self.trigger_up('reload');
+ });
+ });
+ }
+ });
+ },
/** Binds a focusout handler on a bootstrap popover
* Useful to do some operations on the popover's HTML,
* like keeping the user's input for the feedback
@@ -257,7 +305,18 @@ var BasicActivity = AbstractField.extend({
var activityID = $(ev.currentTarget).data('activity-id');
return this._openActivityForm(activityID, this._reload.bind(this, { activity: true, thread: true }));
},
- /**
+ /**
+ * @private
+ * @param {FormEvent} ev
+ */
+ _onFileChanged: function (ev) {
+ ev.stopPropagation();
+ ev.preventDefault();
+ var $form = $(ev.currentTarget).closest('form');
+ $form.submit();
+ framework.blockUI();
+ },
+ /**
* Called when marking an activity as done
*
* It lets the current user write a feedback in a popup menu.
@@ -282,7 +341,10 @@ var BasicActivity = AbstractField.extend({
var $panel = self.$('#o_activity_form_' + activityID);
if (!$panel.data('bs.collapse')) {
- var $form = $(QWeb.render('mail.activity_feedback_form', { previous_activity_type_id: previousActivityTypeID, force_next: forceNextActivity}));
+ var $form = $(QWeb.render('mail.activity_feedback_form', {
+ previous_activity_type_id: previousActivityTypeID,
+ force_next: forceNextActivity
+ }));
$panel.append($form);
self._onMarkActivityDoneActions($markDoneBtn, $form, activityID);
@@ -319,7 +381,10 @@ var BasicActivity = AbstractField.extend({
trigger:'click',
placement: 'right', // FIXME: this should work, maybe a bug in the popper lib
content : function () {
- var $popover = $(QWeb.render('mail.activity_feedback_form', { previous_activity_type_id: previousActivityTypeID, force_next: forceNextActivity}));
+ var $popover = $(QWeb.render('mail.activity_feedback_form', {
+ previous_activity_type_id: previousActivityTypeID,
+ force_next: forceNextActivity
+ }));
self._onMarkActivityDoneActions($markDoneBtn, $popover, activityID);
return $popover;
},
@@ -368,6 +433,17 @@ var BasicActivity = AbstractField.extend({
/**
* @private
* @param {MouseEvent} ev
+ */
+ _onMarkActivityDoneUploadFile: function (ev) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ var fileuploadID = $(ev.currentTarget).data('fileupload-id');
+ var $input = this.$("[target='" + fileuploadID + "'] > input.o_input_file");
+ $input.click();
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
* @returns {$.Deferred}
*/
_onPreviewMailTemplate: function (ev) {
@@ -439,6 +515,19 @@ var BasicActivity = AbstractField.extend({
})
.then(this._reload.bind(this, {activity: true}));
},
+ /**
+ * Unbind event triggered when a file is uploaded.
+ *
+ * @private
+ * @param {Array} activities: list of activity to unbind
+ */
+ _unbindOnUploadAction: function (activities) {
+ _.each(activities, function (activity) {
+ if (activity.fileuploadID) {
+ $(window).off(activity.fileuploadID);
+ }
+ });
+ },
});
// -----------------------------------------------------------------------------
@@ -457,11 +546,17 @@ var Activity = BasicActivity.extend({
this._super.apply(this, arguments);
this._activities = this.record.specialData[this.name];
},
+ /**
+ * @override
+ */
+ destroy: function () {
+ this._unbindOnUploadAction();
+ return this._super.apply(this, arguments);
+ },
//------------------------------------------------------------
// Private
//------------------------------------------------------------
-
/**
* @private
* @param {Object} fieldsToReload
@@ -483,7 +578,7 @@ var Activity = BasicActivity.extend({
activity.note = '';
}
});
- var activities = setDelayLabel(this._activities);
+ var activities = setFileUploadID(setDelayLabel(this._activities));
if (activities.length) {
var nbActivities = _.countBy(activities, 'state');
this.$el.html(QWeb.render('mail.activity_items', {
@@ -494,8 +589,12 @@ var Activity = BasicActivity.extend({
nbOverdueActivities: nbActivities.overdue,
dateFormat: time.getLangDateFormat(),
datetimeFormat: time.getLangDatetimeFormat(),
+ session: session,
+ widget: this,
}));
+ this._bindOnUploadAction(this._activities);
} else {
+ this._unbindOnUploadAction(this._activities);
this.$el.empty();
}
},
@@ -555,7 +654,13 @@ var KanbanActivity = BasicActivity.extend({
this.selection = selection;
this._setState(record);
},
-
+ /**
+ * @override
+ */
+ destroy: function () {
+ this._unbindOnUploadAction();
+ return this._super.apply(this, arguments);
+ },
//------------------------------------------------------------
// Private
//------------------------------------------------------------
@@ -590,11 +695,14 @@ var KanbanActivity = BasicActivity.extend({
var self = this;
this.$('.o_activity').html(QWeb.render('mail.KanbanActivityLoading'));
return _readActivities(this, this.value.res_ids).then(function (activities) {
+ activities = setFileUploadID(activities);
self.$('.o_activity').html(QWeb.render('mail.KanbanActivityDropdown', {
selection: self.selection,
records: _.groupBy(setDelayLabel(activities), 'state'),
- uid: session.uid,
+ session: session,
+ widget: self,
}));
+ self._bindOnUploadAction(activities);
});
},
/**
diff --git a/addons/mail/static/src/xml/activity.xml b/addons/mail/static/src/xml/activity.xml
index d38afb5c799..dafad00b008 100644
--- a/addons/mail/static/src/xml/activity.xml
+++ b/addons/mail/static/src/xml/activity.xml
@@ -83,11 +83,24 @@
</div>
</t>
<t t-name="mail.activity_thread_message_tools">
- <div t-if="activity.can_write">
- <span class="o_mark_as_done" data-toggle="popover" t-att-data-activity-id="activity.id" t-att-data-force-next-activity="activity.force_next" t-att-data-previous-activity-type-id="activity.activity_type_id[0]">
+ <div t-if="activity.can_write" class="o_thread_message_tools btn-group">
+ <span t-if="activity.activity_category !== 'upload_file'" class="o_mark_as_done" data-toggle="popover" t-att-data-activity-id="activity.id" t-att-data-force-next-activity="activity.force_next" t-att-data-previous-activity-type-id="activity.activity_type_id[0]">
<a role="button" href="#" class="btn btn-link btn-success text-muted o_activity_link mr8">
<i class="fa fa-check"/> Mark Done </a>
</span>
+ <span t-if="activity.activity_category === 'upload_file'" class="o_mark_as_done_upload_file" t-att-data-activity-id="activity.id" t-att-data-force-next-activity="activity.force_next" t-att-data-previous-activity-type-id="activity.activity_type_id[0]" t-att-data-fileupload-id="activity.fileuploadID">
+ <a role="button" href="#" class="btn btn-link btn-success text-muted o_activity_link mr8">
+ <i class="fa fa-upload"/> Upload Document </a>
+ </span>
+ <span t-if="activity.activity_category === 'upload_file'" class="d-none">
+ <t t-call="HiddenInputFile">
+ <t t-set="fileupload_id" t-value="activity.fileuploadID"/>
+ <t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
+ <input type="hidden" name="model" t-att-value="activity.res_model"/>
+ <input type="hidden" name="id" t-att-value="activity.res_id"/>
+ <input type="hidden" name="session_id" t-att-value="session.session_id"/>
+ </t>
+ </span>
<a role="button" href="#" class="btn btn-link btn-secondary text-muted o_edit_activity o_activity_link" t-att-data-activity-id="activity.id">
<i class="fa fa-pencil"/> Edit
</a>
diff --git a/addons/mail/static/src/xml/web_kanban_activity.xml b/addons/mail/static/src/xml/web_kanban_activity.xml
index e7cf7be1daf..698091e9875 100644
--- a/addons/mail/static/src/xml/web_kanban_activity.xml
+++ b/addons/mail/static/src/xml/web_kanban_activity.xml
@@ -52,8 +52,8 @@
</t>
<t t-name="mail.activities-list-group-item">
- <li t-att-data-activity-id="log.id" t-attf-class="list-group-item o_log_activity d-flex #{edit_class} #{log_last ? 'border-bottom' : ''}" role="menuitem">
- <div class="o_activity_title">
+ <li t-attf-class="list-group-item o_log_activity d-flex #{log_last ? 'border-bottom' : ''}" role="menuitem">
+ <div t-attf-class="o_activity_title o_log_activity #{edit_class}" t-att-data-activity-id="log.id">
<div t-attf-class="o_activity_title_entry {{! log.force_next ? 'align-items-center' : 'mb-1'}}">
<span t-attf-class="fa #{log.icon ? log.icon : 'fa-bell' } fa-fw mr-2 text-center text-muted" role="img" aria-label="Log" title="Log"/>
<strong class="text-dark"><t t-esc="log.title_action or log.activity_type_id[1]"/></strong>
@@ -74,18 +74,36 @@
</small>
</div>
</t>
- <div t-if="log.user_id[0] != uid and log.mail_template_ids" class="o_activity_title_entry">
+ <div t-if="log.user_id[0] != session.uid and log.mail_template_ids" class="o_activity_title_entry">
<span class="fa fa-user fa-fw mr-2 text-center text-muted" role="img" aria-label="User" title="User"/>
<span><t t-esc="log.user_id[1]" /></span>
</div>
</div>
<div t-if="log.can_write" class="flex-grow-1 text-right">
- <a t-att-data-force-next-activity="log.force_next"
- t-att-data-previous-activity-type-id="log.activity_type_id[0]"
- t-att-data-activity-id="log.id"
- t-attf-href="#o_mark_done_form{{log.id}}"
- class="o_mark_as_done o_activity_link o_activity_link_kanban fa fa-check-circle"
- data-toggle="collapse" title="Mark as done" role="img" aria-label="Mark as done"/>
+ <t t-if="log.activity_category === 'upload_file'">
+ <a t-att-data-force-next-activity="log.force_next"
+ t-att-data-previous-activity-type-id="log.activity_type_id[0]"
+ t-att-data-activity-id="log.id"
+ class="o_mark_as_done_upload_file o_activity_link o_activity_link_kanban fa fa-upload"
+ title="Upload file" role="img" t-att-data-fileupload-id="log.fileuploadID"/>
+ <span class="d-none">
+ <t t-call="HiddenInputFile">
+ <t t-set="fileupload_id" t-value="log.fileuploadID"/>
+ <t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
+ <input type="hidden" name="model" t-att-value="log.res_model"/>
+ <input type="hidden" name="id" t-att-value="log.res_id"/>
+ <input type="hidden" name="session_id" t-att-value="session.session_id"/>
+ </t>
+ </span>
+ </t>
+ <t t-else="">
+ <a t-att-data-force-next-activity="log.force_next"
+ t-att-data-previous-activity-type-id="log.activity_type_id[0]"
+ t-att-data-activity-id="log.id"
+ t-attf-href="#o_mark_done_form{{log.id}}"
+ class="o_mark_as_done o_activity_link o_activity_link_kanban fa fa-check-circle"
+ data-toggle="collapse" title="Mark as done" role="img" aria-label="Mark as done"/>
+ </t>
</div>
</li>
</t>