diff options
| author | jem-odoo <jem@openerp.com> | 2018-12-06 15:15:57 +0000 |
|---|---|---|
| committer | jem-odoo <jem@openerp.com> | 2019-01-17 13:47:27 +0000 |
| commit | d2b3c9a04b4236c915541cc708a79500ec0c97c0 (patch) | |
| tree | e5811cc2b7f9c163527df4ece58c710a38ed72c3 /addons/mail/static/src | |
| parent | 295b47a4808d9a78bf993c4211ccb5f4eb498818 (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.js | 130 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/activity.xml | 17 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/web_kanban_activity.xml | 36 |
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> |
