diff --git a/addons/mail/__manifest__.py b/addons/mail/__manifest__.py index 4a23ef2573c..105d149fa43 100644 --- a/addons/mail/__manifest__.py +++ b/addons/mail/__manifest__.py @@ -38,7 +38,6 @@ ], 'demo': [ 'data/mail_demo.xml', - 'data/mail_activity_demo.xml', 'data/mail_channel_demo.xml', ], 'installable': True, diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index 3445691f601..f0990c7de40 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -230,15 +230,3 @@ class MailController(http.Controller): 'menu_id': request.env['ir.model.data'].xmlid_to_res_id('mail.mail_channel_menu_root_chat'), } return values - - @http.route('/mail/activity/new', type='json', auth='user') - def mail_activity_new(self, note, activity_type_id=None, date_deadline=None): - values = {'note': note} - if date_deadline: - values['date_deadline'] = date_deadline - if not activity_type_id: - activity_type_id = request.env['mail.activity.type'].sudo().search([('category', '=', 'reminder')], limit=1).id - if activity_type_id: - values['activity_type_id'] = activity_type_id - activity = request.env['mail.activity'].create(values) - return activity.id diff --git a/addons/mail/data/mail_activity_data.xml b/addons/mail/data/mail_activity_data.xml index 35a103123ef..950a0794858 100644 --- a/addons/mail/data/mail_activity_data.xml +++ b/addons/mail/data/mail_activity_data.xml @@ -23,12 +23,5 @@ 5 12 - - Reminder - reminder - fa-tasks - 0 - 15 - diff --git a/addons/mail/data/mail_activity_demo.xml b/addons/mail/data/mail_activity_demo.xml deleted file mode 100644 index f15a84331d4..00000000000 --- a/addons/mail/data/mail_activity_demo.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - -

Lunch with colleagues this Sunday.

- - -
-
-
\ No newline at end of file diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index 2d252f911c4..5da155e61ce 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -5,7 +5,6 @@ from datetime import date, datetime, timedelta from odoo import api, exceptions, fields, models, _ from odoo.osv import expression -from odoo.tools import html2plaintext class MailActivityType(models.Model): @@ -46,7 +45,7 @@ class MailActivityType(models.Model): 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id', string='Preceding Activities') category = fields.Selection([ - ('default', 'Other'), ('reminder', 'Reminder')], default='default', + ('default', 'Other')], default='default', string='Category', help='Categories may trigger specific behavior like opening calendar view') @@ -70,10 +69,10 @@ class MailActivity(models.Model): return res # owner - res_id = fields.Integer('Related Document ID', index=True) + res_id = fields.Integer('Related Document ID', index=True, required=True) res_model_id = fields.Many2one( 'ir.model', 'Document Model', - index=True, ondelete='cascade') + index=True, ondelete='cascade', required=True) res_model = fields.Char( 'Related Document Model', index=True, related='res_model_id.model', store=True, readonly=True) @@ -90,9 +89,6 @@ class MailActivity(models.Model): note = fields.Html('Note') feedback = fields.Html('Feedback') date_deadline = fields.Date('Due Date', index=True, required=True, default=fields.Date.today) - active = fields.Boolean( - 'Open', default=True, - help='Done reminders should be archived instead of marked as done.') automated = fields.Boolean( 'Automated activity', readonly=True, help='Indicates this activity has been created automatically and not by any user.') @@ -122,8 +118,7 @@ class MailActivity(models.Model): @api.depends('res_model', 'res_id') def _compute_res_name(self): for activity in self: - if activity.res_model and activity.res_id: - activity.res_name = self.env[activity.res_model].browse(activity.res_id).name_get()[0][1] + activity.res_name = self.env[activity.res_model].browse(activity.res_id).name_get()[0][1] @api.depends('date_deadline') def _compute_state(self): @@ -173,14 +168,7 @@ class MailActivity(models.Model): doc_operation = 'read' if operation == 'read' else 'write' activity_to_documents = dict() for activity in self.sudo(): - if activity.res_model and activity.res_id: - activity_to_documents.setdefault(activity.res_model, list()).append(activity.res_id) - else: - if (operation != 'create' and self.env.user.id != activity.user_id.id): - raise exceptions.AccessError(_("You can only access your own records.")) - elif operation == 'create' and not self.env.user.has_group('base.group_user'): - raise exceptions.AccessError(_("Only employee can create reminder.")) - + activity_to_documents.setdefault(activity.res_model, list()).append(activity.res_id) for model, res_ids in activity_to_documents.items(): self.env[model].check_access_rights(doc_operation, raise_exception=True) try: @@ -196,19 +184,11 @@ class MailActivity(models.Model): values_w_defaults = self.default_get(self._fields.keys()) values_w_defaults.update(values) - # Reminder have no summary (for display name) It will add first line of note to summary. - if 'res_model_id' not in values and 'summary' not in values: - values_w_defaults['summary'] = self._compute_summary_from_note(values.get('note', _('Reminder'))) - # continue as sudo because activities are somewhat protected activity = super(MailActivity, self.sudo()).create(values_w_defaults) activity_user = activity.sudo(self.env.user) activity_user._check_access('create') - - # subscribe to document if any - if activity.res_id and activity.res_model: - self.env[activity_user.res_model].browse(activity_user.res_id).message_subscribe(partner_ids=[activity_user.user_id.partner_id.id]) - + self.env[activity_user.res_model].browse(activity_user.res_id).message_subscribe(partner_ids=[activity_user.user_id.partner_id.id]) if activity.date_deadline <= fields.Date.today(): self.env['bus.bus'].sendone( (self._cr.dbname, 'res.partner', activity.user_id.partner_id.id), @@ -218,28 +198,13 @@ class MailActivity(models.Model): @api.multi def write(self, values): self._check_access('write') - if not self.env.user._is_admin() and any(field in values.keys() for field in ['res_model', 'res_id', 'res_model_id']): - raise exceptions.AccessError(_("You cannot re-attach a reminder to another record.")) - if values.get('user_id'): pre_responsibles = self.mapped('user_id.partner_id') - - reminders = self.filtered(lambda a: not a.res_id and not a.res_model) if 'note' in values and 'summary' not in values else self.env['mail.activity'] - activities = self - reminders - res = True - if activities: - res &= super(MailActivity, activities.sudo()).write(values) - if reminders: # if we have reminder, note is set and summary is not set. We need to update summary - upd_values = dict( - values, - summary=self._compute_summary_from_note(values['note']) - ) - res &= super(MailActivity, reminders.sudo()).write(upd_values) + res = super(MailActivity, self.sudo()).write(values) if values.get('user_id'): for activity in self: - if activity.res_id and activity.res_model: # subscribe to document if any - self.env[activity.res_model].browse(activity.res_id).message_subscribe(partner_ids=[activity.user_id.partner_id.id]) + self.env[activity.res_model].browse(activity.res_id).message_subscribe(partner_ids=[activity.user_id.partner_id.id]) if activity.date_deadline <= fields.Date.today(): self.env['bus.bus'].sendone( (self._cr.dbname, 'res.partner', activity.user_id.partner_id.id), @@ -262,29 +227,6 @@ class MailActivity(models.Model): {'type': 'activity_updated', 'activity_deleted': True}) return super(MailActivity, self.sudo()).unlink() - @api.multi - def toggle_active(self): - """ Override model-method to send bus notification about (un)archived reminders """ - res = super(MailActivity, self).toggle_active() - for activity in self: - if activity.active: - self.env['bus.bus'].sendone( - (self._cr.dbname, 'res.partner', activity.user_id.partner_id.id), - {'type': 'activity_updated', 'activity_created': True}) - else: - self.env['bus.bus'].sendone( - (self._cr.dbname, 'res.partner', activity.user_id.partner_id.id), - {'type': 'activity_updated', 'activity_deleted': True}) - return res - - def _compute_summary_from_note(self, note): - """ Returns the first line of html note """ - if note: - summary = html2plaintext(note).strip().replace('*', '').split("\n")[0] - else: - summary = _('Reminder') - return summary or _('Reminder') - @api.multi def action_done(self): """ Wrapper without feedback because web button add context as diff --git a/addons/mail/models/res_users.py b/addons/mail/models/res_users.py index 5b7c82d6725..40032cac40f 100644 --- a/addons/mail/models/res_users.py +++ b/addons/mail/models/res_users.py @@ -70,35 +70,23 @@ class Users(models.Model): @api.model def activity_user_count(self): - # Reminders don't having any model so here we assign 'mail.activity' as reminder's model. - query = """SELECT m.id, count(*), act.res_model AS model, + query = """SELECT m.id, count(*), act.res_model as model, CASE WHEN now()::date - act.date_deadline::date = 0 Then 'today' WHEN now()::date - act.date_deadline::date > 0 Then 'overdue' WHEN now()::date - act.date_deadline::date < 0 Then 'planned' END AS states FROM mail_activity AS act - LEFT OUTER JOIN ir_model AS m ON act.res_model_id = m.id - WHERE user_id = %s AND active = TRUE + JOIN ir_model AS m ON act.res_model_id = m.id + WHERE user_id = %s GROUP BY m.id, states, act.res_model; """ self.env.cr.execute(query, [self.env.uid]) activity_data = self.env.cr.dictfetchall() model_ids = [a['id'] for a in activity_data] - model_names = {n[0]:n[1] for n in self.env['ir.model'].browse(model_ids).name_get()} + model_names = {n[0]: n[1] for n in self.env['ir.model'].browse(model_ids).name_get()} - # always add default entry for reminders - user_activities = { - None: { - 'name': _("Reminder"), - 'model': None, - 'icon': '/mail/static/src/img/reminder.png', - 'total_count': 0, - 'today_count': 0, - 'overdue_count': 0, - 'planned_count': 0 - } - } + user_activities = {} for activity in activity_data: if not user_activities.get(activity['model']): user_activities[activity['model']] = { diff --git a/addons/mail/static/src/img/reminder.png b/addons/mail/static/src/img/reminder.png deleted file mode 100644 index a585b8d6e09..00000000000 Binary files a/addons/mail/static/src/img/reminder.png and /dev/null differ diff --git a/addons/mail/static/src/js/systray.js b/addons/mail/static/src/js/systray.js index d382745df29..5a4c8ea4675 100644 --- a/addons/mail/static/src/js/systray.js +++ b/addons/mail/static/src/js/systray.js @@ -3,13 +3,11 @@ odoo.define('mail.systray', function (require) { var config = require('web.config'); var core = require('web.core'); -var datepicker = require('web.datepicker'); var session = require('web.session'); var SystrayMenu = require('web.SystrayMenu'); var Widget = require('web.Widget'); var QWeb = core.qweb; -var _t = core._t; /** * Menu item appended in the systray part of the navbar @@ -159,13 +157,8 @@ var MessagingMenu = Widget.extend({ var ActivityMenu = Widget.extend({ template:'mail.chat.ActivityMenu', events: { - 'click': '_onActivityMenuClick', - 'click .o_mail_channel_preview:not(.o_reminder)': '_onActivityFilterClick', - 'click .o_reminder_show': '_onAddReminderClick', - 'click .o_reminder_save': '_onReminderSaveClick', - 'click .o_reminder_set_datetime': '_onReminderDateTimeSetClick', - 'keydown input.o_reminder_input': '_onReminderInputKeyDown', - 'click .o_reminder': '_onNewReminderClick', + "click": "_onActivityMenuClick", + "click .o_mail_channel_preview": "_onActivityFilterClick", }, start: function () { this.$activities_preview = this.$('.o_mail_navbar_dropdown_channels'); @@ -191,21 +184,8 @@ var ActivityMenu = Widget.extend({ context: session.user_context, }, }).then(function (data) { - // We required reminder to be first always. Moving its position from n-th to zero if not at zero - var reminderIndex = _.findIndex(data, function (val) { return val.model == null; }); - if (reminderIndex > 0) { - data.splice(0, 0, data.splice(reminderIndex, 1)[0]); - } self.activities = data; - - //we want to add count in reminders title - var reminders = _.findWhere(data, {'model': null}); - if (reminders) { - var totalReminders = reminders.overdue_count + reminders.planned_count + reminders.today_count; - //manualy count total reminders since reminders.total_count only sum today and overdue - reminders.name = _.str.sprintf(_t('Reminders (%s)'), totalReminders); - } - self.activityCounter = _.reduce(self.activities, function (total_count, p_data) { return total_count + p_data.total_count; }, 0); + self.activityCounter = _.reduce(data, function (total_count, p_data) { return total_count + p_data.total_count; }, 0); self.$('.o_notification_counter').text(self.activityCounter); self.$el.toggleClass('o_no_notification', !self.activityCounter); }); @@ -261,27 +241,6 @@ var ActivityMenu = Widget.extend({ this.$el.toggleClass('o_no_notification', !this.activityCounter); } }, - /** - * Save the reminder to database using datepicker date and field as note - * @private - */ - _saveReminder: function () { - var note = this.$('.o_reminder_input').val().trim(); - if (! note) { - return; - } - var params = {'note': note}; - var reminderDateTime = this.reminderDateTimeWidget.getValue(); - if (reminderDateTime) { - params = _.extend(params, {'date_deadline': reminderDateTime}); - } - this.$('.o_reminder_show').removeClass('hidden'); - this.$('.o_reminder').addClass('hidden'); - this._rpc({ - route: '/mail/activity/new', - params: params, - }).then(this._updateActivityPreview.bind(this)); - }, //------------------------------------------------------------ // Handlers //----------------------------------------------------------- @@ -300,20 +259,15 @@ var ActivityMenu = Widget.extend({ } else { context['search_default_activities_' + data.filter] = 1; } - if (data.res_model == null) { - // Opening Reminder custom kanban view with action. - this.do_action('mail.mail_activity_action_reminders', {additional_context: context}); - } else { - this.do_action({ - type: 'ir.actions.act_window', - name: data.model_name, - res_model: data.res_model, - views: [[false, 'kanban'], [false, 'form']], - search_view_id: [false], - domain: [['activity_user_id', '=', session.uid]], - context:context, - }); - } + this.do_action({ + type: 'ir.actions.act_window', + name: data.model_name, + res_model: data.res_model, + views: [[false, 'kanban'], [false, 'form']], + search_view_id: [false], + domain: [['activity_user_id', '=', session.uid]], + context:context, + }); }, /** * When menu clicked update activity preview if counter updated @@ -325,65 +279,6 @@ var ActivityMenu = Widget.extend({ this._updateActivityPreview(); } }, - /** - * When add new reminder button clicked, toggling quick reminder create view inside - * Systray activity view - * - * @private - * @param {MouseEvent} event - */ - _onAddReminderClick: function (event) { - event.stopPropagation(); - if (!this.reminderDateTimeWidget){ - this.reminderDateTimeWidget = new datepicker.DateWidget(this, {useCurrent: true}); - } - this.reminderDateTimeWidget.appendTo(this.$('.o_reminder_datetime')); - this.$('.o_reminder_show, .o_reminder').toggleClass('hidden'); - this.$('.o_reminder_input').val('').focus(); - - }, - /** - * When focusing on input for new quick reminder systerm tray must be open. - * Preventing to close - * - * @private - * @param {MouseEvent} event - */ - _onNewReminderClick: function (event) { - event.stopPropagation(); - }, - /** - * Opens datetime picker for reminder. - * Quick FIX due to no option for set custom icon instead of caret in datepicker. - * - * @private - * @param {MouseEvent} event - */ - _onReminderDateTimeSetClick: function (event) { - event.preventDefault(); - event.stopPropagation(); - this.reminderDateTimeWidget.$input.click(); - }, - /** - * Saving reminder (quick create) and updating activity preview - * - * @private - * @param {MouseEvent} event - */ - _onReminderSaveClick: function (event) { - this._saveReminder(); - }, - /** - * Handling Enter key for quick create reminder. - * - * @private - * @param {KeyboardEvent} event - */ - _onReminderInputKeyDown: function (event) { - if (event.which === $.ui.keyCode.ENTER) { - this._saveReminder(); - } - }, }); SystrayMenu.Items.push(MessagingMenu); diff --git a/addons/mail/static/src/less/discuss.less b/addons/mail/static/src/less/discuss.less index b2bfc6236c8..4e0ae26dccc 100644 --- a/addons/mail/static/src/less/discuss.less +++ b/addons/mail/static/src/less/discuss.less @@ -391,7 +391,7 @@ .o_channel_title { .o-flex-display(); .o_channel_name { - .o-flex(1, 1, auto); + .o-flex(0, 1, auto); .o-text-overflow(); } .o_channel_counter { @@ -428,27 +428,6 @@ } } -.o_reminder.o_mail_channel_preview { - background-color: white; - .o_reminder_input { - border: none; - } - .o_reminder_datetime { - .o_datepicker { - .o_datepicker_input { - float: right; - text-align: right; - border: none; - font-size: 11px; - width: 50%; - } - .o_datepicker_button { - display: none; - } - } - } -} - @media (max-width: @screen-xs-max) { @o-mail-chatter-mobile-gap: 2%; diff --git a/addons/mail/static/src/less/mail_activity.less b/addons/mail/static/src/less/mail_activity.less index f98e0974b7b..5f1320ce402 100644 --- a/addons/mail/static/src/less/mail_activity.less +++ b/addons/mail/static/src/less/mail_activity.less @@ -132,15 +132,6 @@ .o_kanban_inline_block { display: inline-block; } - .o_text_line_through { - text-decoration: line-through; - } - .o_reminder_title { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - padding-bottom: 10px; - } .o_mail_activity { .o_activity_btn { span.fa { diff --git a/addons/mail/static/src/xml/systray.xml b/addons/mail/static/src/xml/systray.xml index e70d36ed4c1..dd61c486b9b 100644 --- a/addons/mail/static/src/xml/systray.xml +++ b/addons/mail/static/src/xml/systray.xml @@ -80,29 +80,6 @@ -
- Add new reminder -
-