Browse Source

[ADD] bus_presence_override: Add module.

pull/382/head
Brett Wood 7 years ago
committed by Holger Brunn
parent
commit
f700c54247
  1. 52
      bus_presence_override/README.rst
  2. 5
      bus_presence_override/__init__.py
  3. 24
      bus_presence_override/__manifest__.py
  4. 5
      bus_presence_override/models/__init__.py
  5. 83
      bus_presence_override/models/res_partner.py
  6. BIN
      bus_presence_override/static/description/icon.png
  7. 59
      bus_presence_override/static/src/js/systray.js
  8. 47
      bus_presence_override/static/src/less/systray.less
  9. 35
      bus_presence_override/static/src/xml/systray.xml
  10. 7
      bus_presence_override/status_constants.py
  11. 5
      bus_presence_override/tests/__init__.py
  12. 92
      bus_presence_override/tests/test_res_partner.py
  13. 16
      bus_presence_override/views/assets.xml

52
bus_presence_override/README.rst

@ -0,0 +1,52 @@
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
=====================
Bus Presence Override
=====================
This module adds the ability for users to define their Online, Away, or Offline status
manually instead of the system calculating it.
Away and disconnection timers are still in effect.
Usage
=====
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/205/10.0
Known Issues / Roadmap
======================
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/social/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Brett Wood <bwood@laslabs.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.

5
bus_presence_override/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import models

24
bus_presence_override/__manifest__.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
"name": "Bus Presence Override",
"summary": "Adds user-defined im status (online, away, offline).",
"version": "10.0.1.0.0",
"category": "Social",
"website": "https://github.com/OCA/social",
"author": "LasLabs, Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"mail",
],
"data": [
"views/assets.xml",
],
"qweb": [
"static/src/xml/systray.xml",
],
}

5
bus_presence_override/models/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import res_partner

83
bus_presence_override/models/res_partner.py

@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import api, fields, models
from odoo.addons.bus.models.bus_presence import AWAY_TIMER
from odoo.addons.bus.models.bus_presence import DISCONNECTION_TIMER
from ..status_constants import ONLINE, AWAY, OFFLINE
class ResPartner(models.Model):
_inherit = 'res.partner'
im_status_custom = fields.Selection(
selection=[
(ONLINE, 'Online'),
(AWAY, 'Away'),
(OFFLINE, 'Offline'),
],
string='Status',
default=ONLINE,
)
@api.model
def _get_partners_presence(self):
""" This method gets any relevant partners' im status.
Example:
.. code-block:: python
res = self.env['res.partner']._get_partners_presence()
im_status = res.get(partner.id, OFFLINE)
Returns:
dict: Structured like so: {partner_id: im_status}
"""
self.env.cr.execute(
"""
SELECT
U.partner_id as id,
CASE WHEN age(now() AT TIME ZONE 'UTC', B.last_poll)
> interval %s THEN 'offline'
WHEN age(now() AT TIME ZONE 'UTC', B.last_presence)
> interval %s THEN 'away'
ELSE 'online'
END as status
FROM bus_presence B
JOIN res_users U ON B.user_id = U.id
WHERE U.partner_id IN %s AND U.active = 't'
""",
("%s seconds" % DISCONNECTION_TIMER,
"%s seconds" % AWAY_TIMER, tuple(self.ids))
)
all_status = self.env.cr.dictfetchall()
all_status_dict = dict(
((status['id'], status['status']) for status in all_status)
)
return all_status_dict
@api.multi
def _compute_im_status(self):
presence = self._get_partners_presence()
for record in self:
record.im_status = presence.get(record.id, OFFLINE)
computed = record.im_status
custom = record.im_status_custom
if computed == OFFLINE:
record.im_status_custom = computed
elif custom in (AWAY, OFFLINE):
record.im_status = custom
elif computed == AWAY and custom == ONLINE:
record.im_status_custom = computed

BIN
bus_presence_override/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

59
bus_presence_override/static/src/js/systray.js

@ -0,0 +1,59 @@
/* Copyright 2017 LasLabs Inc.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
odoo.define('bus_presence_override.systray', function (require) {
"use strict";
var DataModel = require('web.DataModel');
var session = require('web.session');
var SystrayMenu = require('web.SystrayMenu');
var Widget = require('web.Widget');
var Systray = Widget.extend({
template:'systray',
events: {
'click .o_user_presence_status': 'on_click_user_presence_status',
},
init: function() {
this._super.apply(this, arguments);
this.Partners = new DataModel('res.partner');
this.status_icons = {
'online': 'fa fa-circle o_user_online',
'away': 'fa fa-circle o_user_idle',
'offline': 'fa fa-circle-o',
}
},
start: function () {
this._update_im_status_custom(status='online');
return this._super()
},
on_click_user_presence_status: function (event) {
var status = $(event.target).attr('name');
this._update_im_status_custom(status);
},
_get_im_status: function () {
var self = this;
this.Partners.query(['im_status'])
.filter([['id', '=', session.partner_id]])
.first()
.then(function (result) {
self._update_systray_status_icon(result['im_status']);
});
},
_update_systray_status_icon: function (status) {
$('#userStatus i').removeClass()
.addClass('o_mail_user_status ' + this.status_icons[status]);
},
_update_im_status_custom: function (status) {
var self = this;
this.Partners.call('write', [[session.partner_id], {'im_status_custom': status}])
.then(function () {
self._update_systray_status_icon(status);
});
},
});
SystrayMenu.Items.push(Systray);
});

47
bus_presence_override/static/src/less/systray.less

@ -0,0 +1,47 @@
/* Copyright 2017 LasLabs Inc.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
#userStatus {
&:hover i {
color: #d3d3d3 !important;
}
i {
padding-top: 2px;
}
}
.o_user_presence_dropdown {
min-width: 85px;
.o_user_presence_status {
margin-top: 2px;
padding: 4px 8px;
width: 100%;
display: block;
font-size: 13px;
}
&:hover {
cursor: pointer;
}
}
@media (max-width: @screen-xs-max) {
.o_user_presence_status {
color: #9d9d9d;
&:hover {
color: #ffffff;
}
}
}
@media (min-width: @screen-sm-min) {
.o_user_presence_status:hover {
background-color: #e0e0e0;
}
}

35
bus_presence_override/static/src/xml/systray.xml

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 LasLabs Inc.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<templates>
<t t-name="systray">
<li class="o_mail_navbar_item">
<a id="userStatus" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" title="Status" href="#">
<i class="o_mail_user_status" />
</a>
<ul class="dropdown-menu o_user_presence_dropdown" role="menu">
<li>
<span name="online" class="o_user_presence_status">
<i t-attf-class="o_mail_user_status o_user_online fa fa-circle" />
Online
</span>
</li>
<li>
<span name="away" class="o_user_presence_status">
<i class="o_mail_user_status o_user_idle fa fa-circle" />
Away
</span>
</li>
<li>
<span name="offline" class="o_user_presence_status">
<i class="o_mail_user_status fa fa-circle-o" />
Offline
</span>
</li>
</ul>
</li>
</t>
</templates>

7
bus_presence_override/status_constants.py

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
ONLINE = 'online'
AWAY = 'away'
OFFLINE = 'offline'

5
bus_presence_override/tests/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import test_res_partner

92
bus_presence_override/tests/test_res_partner.py

@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from mock import patch
from odoo.tests.common import TransactionCase
from ..status_constants import ONLINE, AWAY, OFFLINE
GET_PRESENCE = 'odoo.addons.bus_presence_override.models.res_partner.' \
'ResPartner._get_partners_presence'
class TestResPartner(TransactionCase):
def setUp(self):
super(TestResPartner, self).setUp()
self.admin = self.env.ref(
'base.partner_root',
)
@patch(GET_PRESENCE)
def test_compute_im_status_online(self, get_presence):
""" im_status_custom and im_status should both be online """
get_presence.return_value = {self.admin.id: ONLINE}
self.admin.im_status_custom = ONLINE
self.assertEquals(
ONLINE,
self.admin.im_status,
)
self.assertEquals(
ONLINE,
self.admin.im_status_custom,
)
@patch(GET_PRESENCE)
def test_compute_im_status_custom_away_override(self, get_presence):
""" im_status_custom away should override im_status """
get_presence.return_value = {self.admin.id: ONLINE}
self.admin.im_status_custom = AWAY
self.assertEquals(
AWAY,
self.admin.im_status,
)
self.assertEquals(
AWAY,
self.admin.im_status_custom,
)
@patch(GET_PRESENCE)
def test_compute_im_status_custom_offline_override(self, get_presence):
""" im_status_custom offline should override im_status """
get_presence.return_value = {self.admin.id: ONLINE}
self.admin.im_status_custom = OFFLINE
self.assertEquals(
OFFLINE,
self.admin.im_status,
)
self.assertEquals(
OFFLINE,
self.admin.im_status_custom,
)
@patch(GET_PRESENCE)
def test_compute_im_status_away_override(self, get_presence):
""" im_status away should override im_status_custom """
get_presence.return_value = {self.admin.id: AWAY}
self.admin.im_status_custom = ONLINE
self.assertEquals(
AWAY,
self.admin.im_status,
)
self.assertEquals(
AWAY,
self.admin.im_status_custom,
)
@patch(GET_PRESENCE)
def test_compute_im_status_offline_override(self, get_presence):
""" im_status offline should override im_status_custom """
get_presence.return_value = {self.admin.id: OFFLINE}
self.admin.im_status_custom = ONLINE
self.assertEquals(
OFFLINE,
self.admin.im_status,
)
self.assertEquals(
OFFLINE,
self.admin.im_status_custom,
)

16
bus_presence_override/views/assets.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 LasLabs Inc.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<odoo>
<template id="assets_backend" name="Bus Presence Override Assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/bus_presence_override/static/src/less/systray.less"/>
<script type="text/javascript"
src="/bus_presence_override/static/src/js/systray.js"
/>
</xpath>
</template>
</odoo>
Loading…
Cancel
Save