[IMP] mail_activity_team

pull/877/head
Adrià Gil Sorribes 2019-07-17 16:05:01 +02:00 committed by Alba Riera
parent 6d586fa3f3
commit a04207cb8e
10 changed files with 120 additions and 105 deletions

View File

@ -19,8 +19,5 @@
"views/mail_activity_views.xml", "views/mail_activity_views.xml",
"views/res_users_views.xml", "views/res_users_views.xml",
], ],
"qweb": ["static/src/xml/systray.xml"],
'qweb': [
'static/src/xml/systray.xml',
],
} }

View File

@ -2,4 +2,3 @@ from . import mail_activity_team
from . import mail_activity from . import mail_activity
from . import mail_activity_mixin from . import mail_activity_mixin
from . import res_users from . import res_users
from . import mail_activity_mixin

View File

@ -1,13 +1,14 @@
# Copyright 2021 Tecnativa - David Vidal # Copyright 2021 Tecnativa - David Vidal
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models, fields from odoo import api, fields, models
class MailActivityMixin(models.AbstractModel): class MailActivityMixin(models.AbstractModel):
_inherit = "mail.activity.mixin" _inherit = "mail.activity.mixin"
activity_team_user_ids = fields.Many2many( activity_team_user_ids = fields.Many2many(
comodel_name='res.users', string='test field', comodel_name="res.users",
string="test field",
compute="_compute_activity_team_user_ids", compute="_compute_activity_team_user_ids",
search="_search_activity_team_user_ids", search="_search_activity_team_user_ids",
) )
@ -15,12 +16,11 @@ class MailActivityMixin(models.AbstractModel):
@api.depends("activity_ids") @api.depends("activity_ids")
def _compute_activity_team_user_ids(self): def _compute_activity_team_user_ids(self):
for rec in self: for rec in self:
rec.activity_team_user_ids = rec.activity_ids.mapped( rec.activity_team_user_ids = rec.activity_ids.mapped("team_id.member_ids")
"team_id.member_ids")
@api.model @api.model
def _search_activity_team_user_ids(self, operator, operand): def _search_activity_team_user_ids(self, operator, operand):
return [('activity_ids.team_id.member_ids', operator, operand)] return [("activity_ids.team_id.member_ids", operator, operand)]
def activity_schedule( def activity_schedule(
self, act_type_xmlid="", date_deadline=None, summary="", note="", **act_values self, act_type_xmlid="", date_deadline=None, summary="", note="", **act_values

View File

@ -1,6 +1,6 @@
# Copyright 2018 ForgeFlow, S.L. # Copyright 2018 ForgeFlow, S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, fields, api, modules from odoo import api, fields, models, modules
class ResUsers(models.Model): class ResUsers(models.Model):
@ -13,9 +13,9 @@ class ResUsers(models.Model):
) )
@api.model @api.model
def activity_user_count(self, user_id=False): def systray_get_activities(self):
if not self._context.get('team_activities', False): if not self._context.get("team_activities", False):
return super().activity_user_count() return super().systray_get_activities()
query = """SELECT m.id, count(*), act.res_model as model, query = """SELECT m.id, count(*), act.res_model as model,
CASE CASE
WHEN %(today)s::date - WHEN %(today)s::date -
@ -35,35 +35,40 @@ class ResUsers(models.Model):
) )
GROUP BY m.id, states, act.res_model, act.user_id; GROUP BY m.id, states, act.res_model, act.user_id;
""" """
user = user_id if user_id else self.env.uid user = self.env.uid
self.env.cr.execute(query, { self.env.cr.execute(
'today': fields.Date.context_today(self), query, {"today": fields.Date.context_today(self), "user_id": user}
'user_id': user, )
})
activity_data = self.env.cr.dictfetchall() activity_data = self.env.cr.dictfetchall()
model_ids = [a['id'] for a in activity_data] model_ids = [a["id"] for a in activity_data]
model_names = {n[0]: n[1] for n in model_names = {
self.env['ir.model'].browse(model_ids).name_get()} n[0]: n[1] for n in self.env["ir.model"].browse(model_ids).name_get()
}
user_activities = {} user_activities = {}
for activity in activity_data: for activity in activity_data:
if not user_activities.get(activity['model']): if not user_activities.get(activity["model"]):
user_activities[activity['model']] = { user_activities[activity["model"]] = {
'name': model_names[activity['id']], "name": model_names[activity["id"]],
'model': activity['model'], "model": activity["model"],
'icon': modules.module.get_module_icon( "type": "activity",
self.env[activity['model']]._original_module), "icon": modules.module.get_module_icon(
'total_count': 0, 'today_count': 0, 'overdue_count': 0, self.env[activity["model"]]._original_module
'planned_count': 0, ),
"total_count": 0,
"today_count": 0,
"overdue_count": 0,
"planned_count": 0,
} }
user_activities[activity['model']][ user_activities[activity["model"]][
'%s_count' % activity['states']] += activity['count'] "%s_count" % activity["states"]
if activity['states'] in ('today', 'overdue'): ] += activity["count"]
user_activities[activity['model']]['total_count'] += activity[ if activity["states"] in ("today", "overdue"):
'count'] user_activities[activity["model"]]["total_count"] += activity["count"]
if activity['user_id'] == user: if activity["user_id"] == user and activity["states"] in (
user_activities[ "today",
activity['model'] "overdue",
]['total_count'] -= activity['count'] ):
user_activities[activity["model"]]["total_count"] -= activity["count"]
return list(user_activities.values()) return list(user_activities.values())

View File

@ -1,99 +1,108 @@
odoo.define('mail_activity_team.systray', function (require) { odoo.define("mail_activity_team.systray.ActivityMenu", function(require) {
"use strict"; "use strict";
var systray = require('mail.systray'); var ActivityMenu = require("mail.systray.ActivityMenu");
var session = require("web.session"); var session = require("web.session");
systray.ActivityMenu.include({ ActivityMenu.include({
events: _.extend({}, systray.ActivityMenu.prototype.events, { events: _.extend({}, ActivityMenu.prototype.events, {
'click .o_filter_button': 'on_click_filter_button', "click .o_filter_button": "_onClickFilterButton",
}), }),
start: function () { start: function() {
this._super.apply(this, arguments); this._super.apply(this, arguments);
this.$filter_buttons = this.$('.o_filter_button'); this.$filter_buttons = this.$(".o_filter_button");
this.$my_activities = this.$filter_buttons.first(); this.$my_activities = this.$filter_buttons.first();
this.filter = 'my'; this.filter = "my";
session.user_context = _.extend({}, session.user_context, { session.user_context = _.extend({}, session.user_context, {
'team_activities': false team_activities: false,
}); });
}, },
_updateCounter: function (data) { _updateCounter: function(data) {
this._super.apply(this, arguments); this._super.apply(this, data);
this.$('.o_new_notification_counter').text(this.activityCounter); this.$(".o_notification_counter").text(this.activityCounter);
}, },
on_click_filter_button: function (event) { _onClickFilterButton: function(event) {
var self = this; var self = this;
event.stopPropagation(); event.stopPropagation();
self.$filter_buttons.removeClass('active'); self.$filter_buttons.removeClass("active");
var $target = $(event.currentTarget); var $target = $(event.currentTarget);
$target.addClass('active'); $target.addClass("active");
self.filter = $target.data('filter'); self.filter = $target.data("filter");
session.user_context = _.extend({}, session.user_context, { session.user_context = _.extend({}, session.user_context, {
'team_activities': self.filter === 'team' team_activities: self.filter === "team",
}); });
self._updateActivityPreview(); self._updateActivityPreview();
}, },
_onActivityFilterClick: function (event) { _onActivityFilterClick: function(event) {
if (this.filter === 'my') { if (this.filter === "my") {
this._super.apply(this, arguments); this._super.apply(this, arguments);
} }
if (this.filter === 'team') { if (this.filter === "team") {
var data = _.extend( var data = _.extend(
{}, {},
$(event.currentTarget).data(), $(event.currentTarget).data(),
$(event.target).data() $(event.target).data()
); );
var context = {}; var context = {};
if (data.filter === 'my') { if (data.filter === "my") {
context.search_default_activities_overdue = 1; context.search_default_activities_overdue = 1;
context.search_default_activities_today = 1; context.search_default_activities_today = 1;
} else { } else {
context['search_default_activities_' + data.filter] = 1; context["search_default_activities_" + data.filter] = 1;
} }
this.do_action({ this.do_action({
type: 'ir.actions.act_window', type: "ir.actions.act_window",
name: data.model_name, name: data.model_name,
res_model: data.res_model, res_model: data.res_model,
views: [[false, 'kanban'], [false, 'form']], views: [
[false, "kanban"],
[false, "form"],
],
search_view_id: [false], search_view_id: [false],
domain: [ domain: [["activity_team_user_ids", "in", session.uid]],
['activity_team_user_ids', 'in', session.uid] context: context,
],
context:context,
}); });
} }
}, },
_getActivityData: function(){ _open_boards_activities_domain: function() {
if (this.filter === "team") {
return {additional_context: {search_default_my_team_activities: 1}};
}
return this._super.apply(this, arguments);
},
_getActivityData: function() {
var self = this; var self = this;
return self._super.apply(self, arguments).then(function (data) { return self._super.apply(self, arguments).then(function() {
session.user_context = _.extend({}, session.user_context, { session.user_context = _.extend({}, session.user_context, {
'team_activities': !session.user_context['team_activities'], team_activities: !session.user_context.team_activities,
}); });
self._rpc({ self._rpc({
model: 'res.users', model: "res.users",
method: 'activity_user_count', method: "systray_get_activities",
args: [],
kwargs: { kwargs: {
context: session.user_context, context: session.user_context,
}, },
}).then(function (data) { }).then(function(data) {
self.activityCounter += _.reduce(data, function( self.activityCounter += _.reduce(
total_count, p_data data,
){ return total_count + p_data.total_count; }, 0); function(total_count, p_data) {
self.$('.o_new_notification_counter').text(self.activityCounter); return total_count + p_data.total_count || 0;
self.$el.toggleClass('o_no_notification', !self.activityCounter); },
0
);
self.$(".o_notification_counter").text(self.activityCounter);
self.$el.toggleClass("o_no_notification", !self.activityCounter);
session.user_context = _.extend({}, session.user_context, { session.user_context = _.extend({}, session.user_context, {
'team_activities': !session.user_context['team_activities'], team_activities: !session.user_context.team_activities,
}); });
}); });
}); });
} },
}); });
}); });

View File

@ -1,7 +0,0 @@
.o_new_notification_counter {
.o-position-absolute(@top: 20%, @right: 1px);
background: @odoo-brand-optional;
color: white;
padding: 0em 0.3em;
font-size: 0.7em;
}

View File

@ -1,11 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<templates> <templates>
<t t-extend="mail.systray.ActivityMenu"> <t t-extend="mail.systray.ActivityMenu">
<t t-jquery=".o_mail_systray_dropdown_items" t-operation="before"> <t t-jquery=".o_mail_systray_dropdown_items" t-operation="before">
<div> <div>
<button type="button" class="btn btn-link o_filter_button active" data-filter='my' role="tab"> My Activities </button> <button
<button type="button" class="btn btn-link o_filter_button" data-filter='team' role="tab"> Team Activities </button> type="button"
class="btn btn-link o_filter_button active"
data-filter='my'
role="tab"
> My Activities </button>
<button
type="button"
class="btn btn-link o_filter_button"
data-filter='team'
role="tab"
> Team Activities </button>
</div> </div>
</t> </t>
</t> </t>

View File

@ -191,9 +191,10 @@ class TestMailActivityTeam(TransactionCase):
self.assertEqual(activity.team_id, self.team2) self.assertEqual(activity.team_id, self.team2)
def test_activity_count(self): def test_activity_count(self):
res = self.env['res.users'].with_context( res = (
{'team_activities': True} self.env["res.users"]
).activity_user_count( .sudo(self.employee.id)
user_id=self.employee.id .with_context({"team_activities": True})
.systray_get_activities()
) )
self.assertEqual(res[0]['total_count'], 0) self.assertEqual(res[0]["total_count"], 0)

View File

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<template id="assets_backend" name="mail assets" <template id="assets_backend" name="mail assets" inherit_id="web.assets_backend">
inherit_id="web.assets_backend">
<xpath expr="." position="inside"> <xpath expr="." position="inside">
<script type="text/javascript" src="/mail_activity_team/static/src/js/systray.js"/> <script
<link rel="stylesheet" href="/mail_activity_team/static/src/less/systray.less" type="text/less"/> type="text/javascript"
src="/mail_activity_team/static/src/js/systray.js"
/>
</xpath> </xpath>
</template> </template>
</odoo> </odoo>

View File

@ -4,7 +4,7 @@
<record id="mail_activity_view_form_popup" model="ir.ui.view"> <record id="mail_activity_view_form_popup" model="ir.ui.view">
<field name="name">mail.activity.view.form.popup</field> <field name="name">mail.activity.view.form.popup</field>
<field name="model">mail.activity</field> <field name="model">mail.activity</field>
<field name="inherit_id" ref="mail.mail_activity_view_form_popup"/> <field name="inherit_id" ref="mail.mail_activity_view_form_popup" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="user_id" position="after"> <field name="user_id" position="after">
<field name="team_id" options="{'no_create': True, 'no_open': True}" /> <field name="team_id" options="{'no_create': True, 'no_open': True}" />