From 807c4c3f5e729d8b2f463d93e73b0dbbc008492b Mon Sep 17 00:00:00 2001
From: Dharmang Soni <dpr@openerp.com>
Date: Wed, 4 Apr 2018 15:34:43 +0530
Subject: [PATCH] [REF] mail, note: move reminder feature from mail to note
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This commit refactors f488dc58c37fdc7fd49df759165de641e213444b that added reminder feature in activities.
After merging it was suggested specifications were not correct and it has
been decided to move the whole reminder feature in note.

Reminders are now notes instead of activities. Now when having note appµ
systray proposes to create a note / reminder. A note.note record is created
with info given by the user. If a date is given in the systray quick create
then an activity is scheduled on this note.

This means user can create records in activity systray that are not
activities but notes used as reminders. Those will use the first availableµ
note column for the user.

As reminders are now notes the support of activities not linked to any
document is removed, as well as archiving activities and tests linked to
that behavior.

This commit has been not carefully tested nor in-depth reviewied. It is
considered as too important for the upcoming freeze. This closes task ID
1833628. Closes #24129 . Many thanks to @dpr-odoo for its quick development
and good work on this task.
---
 addons/mail/__manifest__.py                   |   1 -
 addons/mail/controllers/main.py               |  12 --
 addons/mail/data/mail_activity_data.xml       |   7 -
 addons/mail/data/mail_activity_demo.xml       |  10 --
 addons/mail/models/mail_activity.py           |  74 +---------
 addons/mail/models/res_users.py               |  22 +--
 addons/mail/static/src/img/reminder.png       | Bin 4953 -> 0 bytes
 addons/mail/static/src/js/systray.js          | 129 ++--------------
 addons/mail/static/src/less/discuss.less      |  23 +--
 .../mail/static/src/less/mail_activity.less   |   9 --
 addons/mail/static/src/xml/systray.xml        |  23 ---
 addons/mail/static/tests/systray_tests.js     |  38 +----
 addons/mail/views/mail_activity_views.xml     |  99 -------------
 addons/note/__init__.py                       |   3 +-
 addons/note/__manifest__.py                   |   5 +
 addons/note/controllers/__init__.py           |   4 +
 addons/note/controllers/note.py               |  27 ++++
 addons/note/data/mail_activity_data.xml       |  12 ++
 addons/note/models/__init__.py                |   1 +
 addons/note/models/mail_activity.py           |  16 ++
 addons/note/models/res_users.py               |  27 +++-
 addons/note/static/src/js/systray.js          | 138 ++++++++++++++++++
 addons/note/static/src/less/note.less         |  38 +++++
 addons/note/static/src/xml/systray.xml        |  32 ++++
 addons/note/static/tests/systray_tests.js     |  66 +++++++++
 addons/note/views/mail_activity_views.xml     |  14 ++
 addons/note/views/note_templates.xml          |   7 +
 addons/test_mail/tests/test_mail_activity.py  |  44 ------
 28 files changed, 417 insertions(+), 464 deletions(-)
 delete mode 100644 addons/mail/data/mail_activity_demo.xml
 delete mode 100644 addons/mail/static/src/img/reminder.png
 create mode 100644 addons/note/controllers/__init__.py
 create mode 100644 addons/note/controllers/note.py
 create mode 100644 addons/note/data/mail_activity_data.xml
 create mode 100644 addons/note/models/mail_activity.py
 create mode 100644 addons/note/static/src/js/systray.js
 create mode 100644 addons/note/static/src/xml/systray.xml
 create mode 100644 addons/note/static/tests/systray_tests.js
 create mode 100644 addons/note/views/mail_activity_views.xml

diff --git a/addons/mail/__manifest__.py b/addons/mail/__manifest__.py
index 4a23ef2573c6..105d149fa435 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 3445691f6019..f0990c7de40b 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 35a103123efb..950a07948586 100644
--- a/addons/mail/data/mail_activity_data.xml
+++ b/addons/mail/data/mail_activity_data.xml
@@ -23,12 +23,5 @@
             <field name="days">5</field>
             <field name="sequence">12</field>
         </record>
-        <record id="mail_activity_data_reminder" model="mail.activity.type">
-            <field name="name">Reminder</field>
-            <field name="category">reminder</field>
-            <field name="icon">fa-tasks</field>
-            <field name="days">0</field>
-            <field name="sequence">15</field>
-        </record>
     </data>
 </odoo>
diff --git a/addons/mail/data/mail_activity_demo.xml b/addons/mail/data/mail_activity_demo.xml
deleted file mode 100644
index f15a84331d41..000000000000
--- a/addons/mail/data/mail_activity_demo.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0"?>
-<odoo>
-    <data noupdate="1">
-        <record id="mail_activity_reminder_0" model="mail.activity">
-            <field name="note" type="html"><p>Lunch with colleagues this Sunday.</p></field>
-            <field name="user_id" ref="base.user_root"/>
-            <field name="active" eval="True"/>
-        </record>
-	</data>
-</odoo>
\ No newline at end of file
diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py
index 2d252f911c47..5da155e61ce2 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 5b7c82d67255..40032cac40fa 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 a585b8d6e09421ec098d88df187ba0ecd67fc6cd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4953
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
Xb9CCT0<2gz00000NkvXXu0mjf?bi@w

diff --git a/addons/mail/static/src/js/systray.js b/addons/mail/static/src/js/systray.js
index d382745df291..5a4c8ea4675e 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 b2bfc6236c88..4e0ae26dccc9 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 f98e0974b7b0..5f1320ce4023 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 e70d36ed4c17..dd61c486b9b9 100644
--- a/addons/mail/static/src/xml/systray.xml
+++ b/addons/mail/static/src/xml/systray.xml
@@ -80,29 +80,6 @@
                 </div>
             </div>
         </t>
-        <div class="o_reminder_show">
-            <a class="btn btn-block text-center">Add new reminder</a>
-        </div>
-        <div class="o_reminder o_mail_channel_preview hidden">
-            <div class="o_mail_channel_image o_mail_channel_app">
-                <img src="/mail/static/src/img/reminder.png"/>
-            </div>
-            <div class="o_channel_info">
-                <div class="o_channel_title">
-                    <span class="o_channel_name"><strong>Set a reminder</strong></span>
-                    <div class="o_reminder_datetime"/>
-                    <span class="ml4">
-                        <a class="o_reminder_set_datetime text-muted">
-                            <span class="fa fa-clock-o"/>
-                        </a>
-                    </span>
-                    <span class="ml8 mr4">
-                        <a class="o_reminder_save">SAVE</a>
-                    </span>
-                </div>
-                <p><input class="o_reminder_input" type="text" placeholder="Remember..." /></p>
-            </div>
-        </div>
     </t>
 
     <t t-name="mail.chat.ActivityMenu">
diff --git a/addons/mail/static/tests/systray_tests.js b/addons/mail/static/tests/systray_tests.js
index 7ad26493cb2b..f8585d376994 100644
--- a/addons/mail/static/tests/systray_tests.js
+++ b/addons/mail/static/tests/systray_tests.js
@@ -23,7 +23,6 @@ QUnit.module('ActivityMenu', {
                     today_count: { type: "integer"},
                     overdue_count: { type: "integer"},
                     total_count: { type: "integer"},
-                    active: { type: "boolean"}
                 },
                 records: [{
                         name: "Contact",
@@ -48,13 +47,6 @@ QUnit.module('ActivityMenu', {
                         today_count: 1,
                         overdue_count: 1,
                         total_count: 3,
-                    },
-                    {
-                        model: null,
-                        planned_count: 1,
-                        today_count: 1,
-                        overdue_count: 0,
-                        total_count: 2,
                     }],
                 },
             };
@@ -79,8 +71,8 @@ QUnit.test('activity menu widget: menu with no records', function (assert) {
     activityMenu.destroy();
 });
 
-QUnit.test('activity menu widget: activity menu with 4 records', function (assert) {
-    assert.expect(17);
+QUnit.test('activity menu widget: activity menu with 3 records', function (assert) {
+    assert.expect(10);
     var self = this;
     var activityMenu = new systray.ActivityMenu();
     testUtils.addMockEnvironment(activityMenu, {
@@ -89,16 +81,6 @@ QUnit.test('activity menu widget: activity menu with 4 records', function (asser
             if (args.method === 'activity_user_count') {
                 return $.when(self.data['mail.activity.menu']['records']);
             }
-            if (route === '/mail/activity/new') {
-                assert.deepEqual(args, {'note': 'New Reminder'}, 'Create reminder should get proper value');
-                _.each(self.data['mail.activity.menu'].records, function (record) {
-                    if (record.model == null) {
-                        record.today_count += 1;
-                        record.total_count += 1;
-                    }
-                });
-                return $.when();
-            }
             return this._super(route, args);
         },
     });
@@ -106,7 +88,7 @@ QUnit.test('activity menu widget: activity menu with 4 records', function (asser
     assert.ok(activityMenu.$el.hasClass('o_mail_navbar_item'), 'should be the instance of widget');
     assert.ok(activityMenu.$('.o_mail_channel_preview').hasClass('o_mail_channel_preview'), "should instance of widget");
     assert.ok(activityMenu.$('.o_notification_counter').hasClass('o_notification_counter'), "widget should have notification counter");
-    assert.strictEqual(parseInt(activityMenu.el.innerText), 7, "widget should have 7 notification counter");
+    assert.strictEqual(parseInt(activityMenu.el.innerText), 5, "widget should have 5 notification counter");
 
     var context = {};
     testUtils.intercept(activityMenu, 'do_action', function(event) {
@@ -141,20 +123,6 @@ QUnit.test('activity menu widget: activity menu with 4 records', function (asser
     activityMenu.$('.dropdown-toggle').click();
     activityMenu.$(".o_mail_navbar_dropdown_channels > div[data-model_name='Issue']").click();
 
-    // toggle quick create for reminder
-    activityMenu.$('.dropdown-toggle').click();
-    assert.strictEqual(activityMenu.$('.o_reminder_show').hasClass("hidden"), false, 'ActivityMenu should have Add new reminder CTA');
-    activityMenu.$('.o_reminder_show').click();
-    assert.strictEqual(activityMenu.$('.o_reminder_show').hasClass("hidden"), true, 'ActivityMenu should hide CTA when entering a new reminder');
-    assert.strictEqual(activityMenu.$('.o_reminder').hasClass("hidden"), false, 'ActivityMenu should display input for new reminder');
-
-    // creating quick reminder
-    activityMenu.$("input.o_reminder_input").val("New Reminder");
-    activityMenu.$(".o_reminder_save").click();
-    assert.strictEqual(parseInt(activityMenu.el.innerText), 8, "widget should have 9 notifications (8 base + 1 new reminder)");
-    assert.strictEqual(activityMenu.$('.o_reminder_show').hasClass("hidden"), false, 'ActivityMenu add reminder button should be displayed');
-    assert.strictEqual(activityMenu.$('.o_reminder').hasClass("hidden"), true, 'ActivityMenu add reminder input should be hidden');
-
     activityMenu.destroy();
 });
 });
diff --git a/addons/mail/views/mail_activity_views.xml b/addons/mail/views/mail_activity_views.xml
index c04f8c821052..1d09f8baedff 100644
--- a/addons/mail/views/mail_activity_views.xml
+++ b/addons/mail/views/mail_activity_views.xml
@@ -182,103 +182,4 @@
         </field>
     </record>
 
-    <record id="mail_activity_view_form_reminder" model="ir.ui.view">
-        <field name="name">mail.activity.view.form</field>
-        <field name="model">mail.activity</field>
-        <field name="priority">21</field>
-        <field name="arch" type="xml">
-            <form string="Reminders">
-                <sheet>
-                    <field name="active" invisible="1"/>
-                    <div class="oe_button_box" name="button_box">
-                        <button class="oe_stat_button" type="object" name="toggle_active" icon="fa-archive">
-                            <field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
-                        </button>
-                    </div>
-                    <group>
-                        <field name="date_deadline" string="Reminder Date"/>
-                    </group>
-                    <field name="note"/>
-                </sheet>
-            </form>
-        </field>
-    </record>
-
-    <record id="mail_activity_view_kanban" model="ir.ui.view">
-        <field name="name">mail.activity.view.kanban</field>
-        <field name="model">mail.activity</field>
-        <field name="arch" type="xml">
-            <kanban class="o_kanban_small_column">
-                <field name="summary"/>
-                <field name="note"/>
-                <field name="active"/>
-                <field name="res_id"/>
-                <field name="res_model"/>
-                <templates>
-                    <t t-name="kanban-box">
-                        <div t-attf-class="oe_kanban_global_click">
-                            <div class="o_dropdown_kanban dropdown">
-                                <a class="dropdown-toggle btn" data-toggle="dropdown" href="#">
-                                    <span class="fa fa-ellipsis-v"/>
-                                </a>
-                                <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
-                                    <li><a type="delete">Delete</a></li>
-                                </ul>
-                            </div>
-                            <div class="oe_kanban_content">
-                                <div>
-                                    <div t-attf-class="#{record.active.raw_value ? '' : 'o_text_line_through'} o_reminder_title">
-                                        <strong><field name="summary"/></strong>
-                                    </div>
-                                    <div class="row">
-                                        <div class="col-xs-10">
-                                            <span class="text-muted"><span class="fa fa-clock-o"/> <field name="date_deadline"/></span>
-                                        </div>
-                                        <div class="col-xs-2">
-                                            <a name="toggle_active" type="object" t-if="record.active.raw_value" title="Mark as done" class="pull-right"><i class="fa fa-check"/></a>
-                                            <a name="toggle_active" type="object" t-if="!record.active.raw_value" title="Re-open reminder" class="pull-right"><i class="fa fa-undo"/></a>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                    </t>
-                </templates>
-            </kanban>
-        </field>
-    </record>
-
-    <record id="mail_activity_view_search_reminder" model="ir.ui.view">
-        <field name="name">mail.activity.reminder.view.search</field>
-        <field name="model">mail.activity</field>
-        <field name="arch" type="xml">
-            <search string="Activity">
-                <field name="active"/>
-                <field name="note"/>
-                <separator/>
-                <filter string="Active" name="filter_open_reminders"
-                        domain="[('active', '=', True)]"/>
-                <filter string="Archived" name="filter_closed_reminders"
-                        domain="[('active', '=', False)]"/>
-                <separator/>
-                <filter string="Late Reminders" name="activities_overdue" domain="[('date_deadline', '&lt;', context_today().strftime('%Y-%m-%d'))]" help="Show all reminders for which the next action date is before today"/>
-                <filter string="Today Reminders" name="activities_today" domain="[('date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
-                <filter string="Future Reminders" name="activities_upcoming_all" domain="[('date_deadline', '&gt;', context_today().strftime('%Y-%m-%d'))]"/>
-            </search>
-        </field>
-    </record>
-
-    <record id="mail_activity_action_reminders" model="ir.actions.act_window">
-        <field name="name">Reminders</field>
-        <field name="res_model">mail.activity</field>
-        <field name="view_type">form</field>
-        <field name="search_view_id" ref="mail_activity_view_search_reminder"/>
-        <field name="view_ids"
-                   eval="[(5, 0, 0),
-                          (0, 0, {'view_mode': 'kanban', 'view_id': ref('mail_activity_view_kanban')}),
-                          (0, 0, {'view_mode': 'form', 'view_id': ref('mail_activity_view_form_reminder')})]"/>
-        <field name="view_id" ref="mail.mail_activity_view_kanban"/>
-        <field name="view_mode">kanban,form</field>
-        <field name="domain">[('user_id', '=', uid), ('res_model', '=', False), ('res_id', 'in', [0,None])]</field>
-    </record>
 </odoo>
diff --git a/addons/note/__init__.py b/addons/note/__init__.py
index dc5e6b693d19..3ea0f0cac454 100644
--- a/addons/note/__init__.py
+++ b/addons/note/__init__.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from . import models
+from . import controllers
+from . import models
\ No newline at end of file
diff --git a/addons/note/__manifest__.py b/addons/note/__manifest__.py
index 7a0edd704a91..02cb893ca1d2 100644
--- a/addons/note/__manifest__.py
+++ b/addons/note/__manifest__.py
@@ -15,13 +15,18 @@
     'data': [
         'security/note_security.xml',
         'security/ir.model.access.csv',
+        'data/mail_activity_data.xml',
         'data/note_data.xml',
         'views/note_views.xml',
         'views/note_templates.xml',
+        'views/mail_activity_views.xml',
     ],
     'demo': [
         'data/note_demo.xml',
     ],
+    'qweb': [
+        'static/src/xml/systray.xml',
+    ],
     'test': [
     ],
     'installable': True,
diff --git a/addons/note/controllers/__init__.py b/addons/note/controllers/__init__.py
new file mode 100644
index 000000000000..4d2e8b5ad274
--- /dev/null
+++ b/addons/note/controllers/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import note
\ No newline at end of file
diff --git a/addons/note/controllers/note.py b/addons/note/controllers/note.py
new file mode 100644
index 000000000000..bdcf2e850598
--- /dev/null
+++ b/addons/note/controllers/note.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import http
+from odoo.http import request
+
+
+class NoteController(http.Controller):
+
+    @http.route('/note/new', type='json', auth='user')
+    def note_new_from_systray(self, note, activity_type_id=None, date_deadline=None):
+        """ Route to create note and their activity directly from the systray """
+        note = request.env['note.note'].create({'memo': note})
+        if date_deadline:
+            activity_values = {
+                'note': note.memo,
+                'date_deadline': date_deadline,
+                'res_model_id': request.env.ref("note.model_note_note").id,
+                'res_id': note.id,
+                'note_id': note.id,
+            }
+            if not activity_type_id:
+                activity_type_id = request.env['mail.activity.type'].sudo().search([('category', '=', 'reminder')], limit=1).id
+            if activity_type_id:
+                activity_values['activity_type_id'] = activity_type_id
+            request.env['mail.activity'].create(activity_values)
+        return note.id
diff --git a/addons/note/data/mail_activity_data.xml b/addons/note/data/mail_activity_data.xml
new file mode 100644
index 000000000000..5b2a5e6c9052
--- /dev/null
+++ b/addons/note/data/mail_activity_data.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+    <data noupdate="1">
+        <record id="mail_activity_data_reminder" model="mail.activity.type">
+            <field name="name">Reminder</field>
+            <field name="category">reminder</field>
+            <field name="icon">fa-tasks</field>
+            <field name="days">0</field>
+            <field name="sequence">20</field>
+        </record>
+    </data>
+</odoo>
diff --git a/addons/note/models/__init__.py b/addons/note/models/__init__.py
index 5c651fca9a01..db6de6e3c7ff 100644
--- a/addons/note/models/__init__.py
+++ b/addons/note/models/__init__.py
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
+from . import mail_activity
 from . import note
 from . import res_users
diff --git a/addons/note/models/mail_activity.py b/addons/note/models/mail_activity.py
new file mode 100644
index 000000000000..67f7ea829661
--- /dev/null
+++ b/addons/note/models/mail_activity.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, fields
+
+
+class MailActivityType(models.Model):
+    _inherit = "mail.activity.type"
+
+    category = fields.Selection(selection_add=[('reminder', 'Reminder')])
+
+
+class MailActivity(models.Model):
+    _inherit = "mail.activity"
+
+    note_id = fields.Many2one('note.note', string="Related Note", ondelete='cascade')
diff --git a/addons/note/models/res_users.py b/addons/note/models/res_users.py
index cfeba15922fa..be218c27b28e 100644
--- a/addons/note/models/res_users.py
+++ b/addons/note/models/res_users.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from odoo import api, models
+from odoo import api, models, modules, _
 
 
 class Users(models.Model):
@@ -19,3 +19,28 @@ class Users(models.Model):
                 if stage:
                     stage.sudo().copy(default={'user_id': user.id})
         return user
+
+    @api.model
+    def activity_user_count(self):
+        """ If user have not scheduled any note, it will not appear in activity menu.
+            Making note activity always visible with number of notes on label. If there is no notes,
+            activity menu not visible for note.
+        """
+        activities = super(Users, self).activity_user_count()
+        notes_count = self.env['note.note'].search_count([('user_id', '=', self.env.uid), ('open', '=', True)])
+        if notes_count:
+            note_index = next((index for (index, a) in enumerate(activities) if a["model"] == "note.note"), None)
+            note_label = ("%s (%d)") % (_('Notes'), notes_count)
+            if note_index is not None:
+                activities[note_index]['name'] = note_label
+            else:
+                activities.append({
+                    'name': note_label,
+                    'model': 'note.note',
+                    'icon': modules.module.get_module_icon(self.env['note.note']._original_module),
+                    'total_count': 0,
+                    'today_count': 0,
+                    'overdue_count': 0,
+                    'planned_count': 0
+                })
+        return activities
diff --git a/addons/note/static/src/js/systray.js b/addons/note/static/src/js/systray.js
new file mode 100644
index 000000000000..54a2fe6bdd14
--- /dev/null
+++ b/addons/note/static/src/js/systray.js
@@ -0,0 +1,138 @@
+odoo.define('note.systray', function (require) {
+"use strict";
+
+var core = require('web.core');
+var ActivityMenu = require('mail.systray').ActivityMenu;
+var datepicker = require('web.datepicker');
+
+var _t = core._t;
+
+ActivityMenu.include({
+    events: _.extend({}, ActivityMenu.prototype.events, {
+        'click .o_note_show': '_onAddNoteClick',
+        'click .o_note_save': '_onNoteSaveClick',
+        'click .o_note_set_datetime': '_onNoteDateTimeSetClick',
+        'keydown input.o_note_input': '_onNoteInputKeyDown',
+        'click .o_note': '_onNewNoteClick',
+    }),
+    //--------------------------------------------------
+    // Private
+    //--------------------------------------------------
+    /**
+     * Moving notes at first place
+     * @override
+     */
+    _getActivityData: function () {
+        var self = this;
+        return this._super.apply(this, arguments).then(function() {
+            var reminderIndex = _.findIndex(self.activities, function (val) { return val.model == 'note.note'; });
+            if (reminderIndex > 0) {
+                self.activities.splice(0, 0, self.activities.splice(reminderIndex, 1)[0]);
+            }
+        });
+    },
+    /**
+     * Save the note to database using datepicker date and field as note
+     * @private
+     */
+    _saveNote: function () {
+        var note = this.$('.o_note_input').val().trim();
+        if (! note) {
+            return;
+        }
+        var params = {'note': note};
+        var noteDateTime = this.noteDateTimeWidget.getValue();
+        if (noteDateTime) {
+            params = _.extend(params, {'date_deadline': noteDateTime});
+        }
+        this.$('.o_note_show').removeClass('hidden');
+        this.$('.o_note').addClass('hidden');
+        this._rpc({
+            route: '/note/new',
+            params: params,
+        }).then(this._updateActivityPreview.bind(this));
+    },
+    //-----------------------------------------
+    // Handlers
+    //-----------------------------------------
+    /**
+     * @override
+     */
+    _onActivityFilterClick: function (ev) {
+        var $el = $(ev.currentTarget);
+        if(!$el.hasClass("o_note")) {
+            var data = _.extend({}, $el.data(), $(ev.target).data());
+            if (data.res_model === "note.note" && data.filter === "my") {
+                this.do_action({
+                    type: 'ir.actions.act_window',
+                    name: data.model_name,
+                    res_model:  data.res_model,
+                    views: [[false, 'kanban'], [false, 'form'], [false, 'list']]
+                });
+            } else {
+                this._super.apply(this, arguments);
+            }
+        }
+    },
+    /**
+     * When add new note button clicked, toggling quick note create view inside
+     * Systray activity view
+     *
+     * @private
+     * @param {MouseEvent} ev
+     */
+    _onAddNoteClick: function (ev) {
+        ev.stopPropagation();
+        if (!this.noteDateTimeWidget){
+            this.noteDateTimeWidget = new datepicker.DateWidget(this, {useCurrent: true});
+        }
+        this.noteDateTimeWidget.appendTo(this.$('.o_note_datetime'));
+        this.noteDateTimeWidget.$input.attr('placeholder', _t("Today"));
+        this.$('.o_note_show, .o_note').toggleClass('hidden');
+        this.$('.o_note_input').val('').focus();
+      
+    },
+    /**
+     * When focusing on input for new quick note systerm tray must be open.
+     * Preventing to close
+     *
+     * @private
+     * @param {MouseEvent} ev
+     */
+    _onNewNoteClick: function (ev) {
+        ev.stopPropagation();
+    },
+    /**
+     * Opens datetime picker for note.
+     * Quick FIX due to no option for set custom icon instead of caret in datepicker.
+     *
+     * @private
+     * @param {MouseEvent} ev
+     */
+    _onNoteDateTimeSetClick: function (ev) {
+        ev.preventDefault();
+        ev.stopPropagation();
+        this.noteDateTimeWidget.$input.click();
+    },
+    /**
+     * Saving note (quick create) and updating activity preview
+     *
+     * @private
+     * @param {MouseEvent} ev
+     */
+    _onNoteSaveClick: function (ev) {
+        this._saveNote();
+    },
+    /**
+     * Handling Enter key for quick create note.
+     *
+     * @private
+     * @param {KeyboardEvent} ev
+     */
+    _onNoteInputKeyDown: function (ev) {
+        if (ev.which === $.ui.keyCode.ENTER) {
+            this._saveNote();
+        }
+    },
+});
+});
diff --git a/addons/note/static/src/less/note.less b/addons/note/static/src/less/note.less
index c92c5cd05000..926e7ddb9137 100644
--- a/addons/note/static/src/less/note.less
+++ b/addons/note/static/src/less/note.less
@@ -23,3 +23,41 @@
         }
     }
 }
+
+// Quick create notes from systray
+.o_note.o_mail_channel_preview {
+    background-color: white;
+    .o_channel_info {
+        .o_channel_title {
+            .o_channel_name {
+                .o-flex(1, 1, 100%);
+            }
+        }
+        .o_note_input_box {
+            .o-flex-display();
+            p {
+                .o-flex(1, 1, auto);
+            }
+        }
+        .o_note_save {
+            font-size: 11px;
+            font-weight: bold;
+        }
+    }
+    .o_note_input {
+        border: none;
+    }
+    .o_note_datetime {
+        .o_datepicker {
+            .o_datepicker_input {
+                float: right;
+                text-align: right;
+                border: none;
+                font-size: 11px;
+            }
+            .o_datepicker_button {
+                display: none;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/addons/note/static/src/xml/systray.xml b/addons/note/static/src/xml/systray.xml
new file mode 100644
index 000000000000..4b2052c3b851
--- /dev/null
+++ b/addons/note/static/src/xml/systray.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates>
+    <t t-extend="mail.chat.ActivityMenuPreview">
+        <t t-jquery="t[t-foreach*='activities'][t-as*='activity']" t-operation="after">
+            <div class="o_note_show">
+                <a class="btn btn-block text-center">Add new note</a>
+            </div>
+            <div class="o_note o_mail_channel_preview hidden">
+                <div class="o_mail_channel_image o_mail_channel_app">
+                    <img src="/note/static/description/icon.png"/>
+                </div>
+                <div class="o_channel_info">
+                    <div class="o_channel_title">
+                        <span class="o_channel_name"><strong>Add a note</strong></span>
+                        <div class="o_note_datetime"/>
+                        <span class="ml4">
+                            <a class="o_note_set_datetime text-muted">
+                                <span class="fa fa-clock-o"/>
+                            </a>
+                        </span>
+                    </div>
+                    <div class="o_note_input_box">
+                        <p><input class="o_note_input" type="text" placeholder="Remember..." /></p>
+                        <span class="ml8 mr4">
+                            <a class="o_note_save">SAVE</a>
+                        </span>
+                    </div>
+                </div>
+            </div>
+        </t>
+    </t>
+</templates>
\ No newline at end of file
diff --git a/addons/note/static/tests/systray_tests.js b/addons/note/static/tests/systray_tests.js
new file mode 100644
index 000000000000..2b07bf857574
--- /dev/null
+++ b/addons/note/static/tests/systray_tests.js
@@ -0,0 +1,66 @@
+odoo.define('note.systray_tests', function (require) {
+"use strict";
+
+var ChatManager = require('mail.ChatManager');
+var systray = require('mail.systray');
+var testUtils = require('web.test_utils');
+var createBusService = require('mail.testUtils').createBusService;
+
+QUnit.module('note', {}, function () {
+
+QUnit.module("ActivityMenu", {
+    beforeEach: function () {
+        this.services = [ChatManager, createBusService()];
+        this.data = {
+            'mail.activity.menu': {
+                records: [],
+            },
+        };
+    }
+});
+
+QUnit.test('note activity menu widget: create note from activity menu', function (assert) {
+    assert.expect(8);
+    var self = this;
+    var activityMenu = new systray.ActivityMenu();
+    testUtils.addMockEnvironment(activityMenu, {
+        services: this.services,
+        mockRPC: function (route, args) {
+            if (args.method === 'activity_user_count') {
+                return $.when(self.data['mail.activity.menu']['records']);
+            }
+            if (route === '/note/new') {
+                return $.when();
+            }
+            return this._super(route, args);
+        },
+    });
+    activityMenu.appendTo($('#qunit-fixture'));
+    assert.ok(activityMenu.$el.hasClass('o_mail_navbar_item'), 'should be the instance of widget');
+
+    // toggle quick create for note
+    var step = 1;
+    activityMenu.$('.dropdown-toggle').click();
+    assert.strictEqual(activityMenu.$('.o_note_show').hasClass("hidden"), false, 'ActivityMenu should have Add new note CTA');
+    activityMenu.$('.o_note_show').click();
+    assert.strictEqual(activityMenu.$('.o_note_show').hasClass("hidden"), true, 'ActivityMenu should hide CTA when entering a new note');
+    assert.strictEqual(activityMenu.$('.o_note').hasClass("hidden"), false, 'ActivityMenu should display input for new note');
+
+    // creating quick note without date
+    activityMenu.$("input.o_note_input").val("New Note");
+    activityMenu.$(".o_note_save").click();
+    assert.strictEqual(activityMenu.$('.o_note_show').hasClass("hidden"), false, 'ActivityMenu add note button should be displayed');
+    assert.strictEqual(activityMenu.$('.o_note').hasClass("hidden"), true, 'ActivityMenu add note input should be hidden');
+
+    // creating quick note with date
+    step = 2;
+    activityMenu.$('.o_note_show').click();
+    activityMenu.$('input.o_note_input').val("New Note");
+    activityMenu.$('.o_note_set_datetime').click();
+    activityMenu.$(".o_note_save").click();
+    assert.strictEqual(activityMenu.$('.o_note_show').hasClass("hidden"), false, 'ActivityMenu add note button should be displayed');
+    assert.strictEqual(activityMenu.$('.o_note').hasClass("hidden"), true, 'ActivityMenu add note input should be hidden');
+    activityMenu.destroy();
+});
+});
+});
diff --git a/addons/note/views/mail_activity_views.xml b/addons/note/views/mail_activity_views.xml
new file mode 100644
index 000000000000..bc980423e3fe
--- /dev/null
+++ b/addons/note/views/mail_activity_views.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<odoo>
+
+    <record id="mail_activity_type_view_form" model="ir.ui.view">
+        <field name="name">mail.activity.type.form.inherit.note</field>
+        <field name="model">mail.activity.type</field>
+        <field name="inherit_id" ref="mail.mail_activity_type_view_form"/>
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='category']" position="attributes">
+                <attribute name="invisible">0</attribute>
+            </xpath>
+        </field>
+    </record>
+</odoo>
\ No newline at end of file
diff --git a/addons/note/views/note_templates.xml b/addons/note/views/note_templates.xml
index 3b6c3e1acc4f..c80d00d84e0e 100644
--- a/addons/note/views/note_templates.xml
+++ b/addons/note/views/note_templates.xml
@@ -3,6 +3,13 @@
     <template id="assets_backend" inherit_id="web.assets_backend">
         <xpath expr="link[last()]" position="after">
             <link rel="stylesheet" type="text/less" href="/note/static/src/less/note.less"/>
+             <script type="text/javascript" src="/note/static/src/js/systray.js"></script>
+        </xpath>
+    </template>
+
+    <template id="qunit_suite" name="note_tests" inherit_id="web.qunit_suite">
+        <xpath expr="//t[@t-set='head']" position="inside">
+            <script type="text/javascript" src="/note/static/tests/systray_tests.js"></script>
         </xpath>
     </template>
 </odoo>
diff --git a/addons/test_mail/tests/test_mail_activity.py b/addons/test_mail/tests/test_mail_activity.py
index e340358a5ee9..5a4121f2c6c0 100644
--- a/addons/test_mail/tests/test_mail_activity.py
+++ b/addons/test_mail/tests/test_mail_activity.py
@@ -69,50 +69,6 @@ class TestMailActivity(BaseFunctionalTest):
                     'res_id': test_record.id,
                 })
 
-    def test_reminder_security(self):
-        reminder = self.env['mail.activity'].sudo(self.user_admin).create({
-            'note': 'Test Reminder',
-            'date_deadline': date.today() + relativedelta(days=1),
-        })
-
-        with self.assertRaises(exceptions.AccessError):
-            # try to delete admin record with demo user
-            reminder.sudo(self.user_employee).unlink()
-
-        with self.assertRaises(exceptions.AccessError):
-            # try to update admin record with demo user
-            reminder.sudo(self.user_employee).write({'note': 'Give money to demo user'})
-
-        # but demo should be able to edit and delete its own reminder
-        demo_reminder = self.env['mail.activity'].sudo(self.user_employee).create({
-            'note': 'Test Reminder demo',
-            'date_deadline': date.today() + relativedelta(days=2),
-        })
-        demo_reminder.write({'note': '<p>Holidays</p>'})
-        self.assertEqual(demo_reminder.note, '<p>Holidays</p>')
-
-        # edit of res_id and res_model should be impossible
-        with self.assertRaises(exceptions.AccessError):
-            demo_reminder.write({'res_id': 1})
-        with self.assertRaises(exceptions.AccessError):
-            demo_reminder.write({'res_model_id': 1})
-
-        demo_reminder.unlink()
-
-    def test_reminder_flow(self):
-        with self.sudoAs('ernest'):
-            reminder = self.env['mail.activity'].create({
-                'note': 'Test Reminder',
-                'date_deadline': date.today(),
-            })
-            self.assertEqual(reminder.summary, 'Test Reminder')
-            reminder.write({'note': 'Holidays\nDestination: Pescara'})
-            self.assertEqual(reminder.summary, 'Holidays')
-            reminder.write({'note': ''})
-            self.assertEqual(reminder.summary, 'Reminder')
-            reminder.write({'note': 'Holidays', 'summary': 'Summary'})
-            self.assertEqual(reminder.summary, 'Summary')
-
     def test_activity_mixin(self):
         today = date.today()
         with self.sudoAs('ernest'):
-- 
GitLab