[FIX] hr_holidays: show plane icon according to user status

task-2377882

closes odoo/odoo#64614

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Xavier Dubuc
2021-01-22 10:20:31 +00:00
parent 6169ae7e87
commit 12004c5665
9 changed files with 269 additions and 29 deletions
+2
View File
@@ -14,6 +14,8 @@ class ResPartner(models.Model):
if partner.id in absent_now:
if partner.im_status == 'online':
partner.im_status = 'leave_online'
elif partner.im_status == 'away':
partner.im_status = 'leave_away'
else:
partner.im_status = 'leave_offline'
+2
View File
@@ -46,6 +46,8 @@ class User(models.Model):
if user.id in on_leave_user_ids:
if user.im_status == 'online':
user.im_status = 'leave_online'
elif user.im_status == 'away':
user.im_status = 'leave_away'
else:
user.im_status = 'leave_offline'
@@ -1,12 +0,0 @@
// -----------------------------------------------------------------------------
// Style
// -----------------------------------------------------------------------------
.o_PartnerImStatusIcon_icon {
&.o-leave-online {
color: $o-enterprise-primary-color;
}
&.o-leave-offline {
color: theme-color('warning');
}
}
@@ -3,10 +3,13 @@
<t t-inherit="mail.PartnerImStatusIcon" t-inherit-mode="extension">
<xpath expr="//*[@name='rootCondition']" position="inside">
<t t-if="partner.im_status === 'leave_online'">
<i class="o_PartnerImStatusIcon_icon o-leave-online fa fa-plane fa-stack-1x" title="Online" role="img" aria-label="User is online"/>
<i class="o_PartnerImStatusIcon_icon o-online fa fa-plane fa-stack-1x" title="Online" role="img" aria-label="User is online"/>
</t>
<t t-if="partner.im_status === 'leave_away'">
<i class="o_PartnerImStatusIcon_icon o-away fa fa-plane fa-stack-1x" title="Away" role="img" aria-label="User is away"/>
</t>
<t t-if="partner.im_status === 'leave_offline'">
<i class="o_PartnerImStatusIcon_icon o-leave-offline fa fa-plane fa-stack-1x" title="Out of office" role="img" aria-label="User is out of office"/>
<i class="o_PartnerImStatusIcon_icon o-offline fa fa-plane fa-stack-1x" title="Out of office" role="img" aria-label="User is out of office"/>
</t>
</xpath>
</t>
@@ -0,0 +1,111 @@
odoo.define('hr_holidays/static/src/components/partner_im_status_icon/partner_im_status_icon_tests.js', function (require) {
'use strict';
const components = {
PartnerImStatusIcon: require('mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js'),
};
const {
afterEach,
beforeEach,
createRootComponent,
start,
} = require('mail/static/src/utils/test_utils.js');
QUnit.module('hr_holidays', {}, function () {
QUnit.module('components', {}, function () {
QUnit.module('partner_im_status_icon', {}, function () {
QUnit.module('partner_im_status_icon_tests.js', {
beforeEach() {
beforeEach(this);
this.createPartnerImStatusIcon = async partner => {
await createRootComponent(this, components.PartnerImStatusIcon, {
props: { partnerLocalId: partner.localId },
target: this.widget.el
});
};
this.start = async params => {
const { env, widget } = await start(Object.assign({}, params, {
data: this.data,
}));
this.env = env;
this.widget = widget;
};
},
afterEach() {
afterEach(this);
},
});
QUnit.test('on leave & online', async function (assert) {
assert.expect(2);
await this.start();
const partner = this.env.models['mail.partner'].create({
id: 7,
name: "Demo User",
im_status: 'leave_online',
});
await this.createPartnerImStatusIcon(partner);
assert.hasClass(
document.querySelector('.o_PartnerImStatusIcon_icon'),
'o-online',
"partner IM status icon should have online status rendering"
);
assert.hasClass(
document.querySelector('.o_PartnerImStatusIcon_icon'),
'fa-plane',
"partner IM status icon should have leave status rendering"
);
});
QUnit.test('on leave & away', async function (assert) {
assert.expect(2);
await this.start();
const partner = this.env.models['mail.partner'].create({
id: 7,
name: "Demo User",
im_status: 'leave_away',
});
await this.createPartnerImStatusIcon(partner);
assert.hasClass(
document.querySelector('.o_PartnerImStatusIcon_icon'),
'o-away',
"partner IM status icon should have away status rendering"
);
assert.hasClass(
document.querySelector('.o_PartnerImStatusIcon_icon'),
'fa-plane',
"partner IM status icon should have leave status rendering"
);
});
QUnit.test('on leave & offline', async function (assert) {
assert.expect(2);
await this.start();
const partner = this.env.models['mail.partner'].create({
id: 7,
name: "Demo User",
im_status: 'leave_offline',
});
await this.createPartnerImStatusIcon(partner);
assert.hasClass(
document.querySelector('.o_PartnerImStatusIcon_icon'),
'o-offline',
"partner IM status icon should have offline status rendering"
);
assert.hasClass(
document.querySelector('.o_PartnerImStatusIcon_icon'),
'fa-plane',
"partner IM status icon should have leave status rendering"
);
});
});
});
});
});
@@ -1,11 +0,0 @@
// ------------------------------------------------------------------
// Style
// ------------------------------------------------------------------
.o_ThreadIcon_leaveOnline {
color: $o-enterprise-primary-color;
}
.o_ThreadIcon_leaveOffline {
color: theme-color('warning');
}
@@ -3,10 +3,13 @@
<t t-inherit="mail.ThreadIcon" t-inherit-mode="extension">
<xpath expr="//*[@name='noImStatusCondition']" position="before">
<t t-elif="thread.correspondent.im_status === 'leave_online'">
<div class="o_ThreadIcon_leaveOnline fa fa-plane" title="Online"/>
<div class="o_ThreadIcon_online fa fa-plane" title="Online"/>
</t>
<t t-elif="thread.correspondent.im_status === 'leave_away'">
<div class="o_ThreadIcon_away fa fa-plane" title="Away"/>
</t>
<t t-elif="thread.correspondent.im_status === 'leave_offline'">
<div class="o_ThreadIcon_leaveOffline fa fa-plane" title="Out of office"/>
<div class="o_ThreadIcon_offline fa fa-plane" title="Out of office"/>
</t>
</xpath>
</t>
@@ -0,0 +1,142 @@
odoo.define('hr_holidays/static/src/components/thread_icon/thread_icon_tests.js', function (require) {
'use strict';
const components = {
ThreadIcon: require('mail/static/src/components/thread_icon/thread_icon.js'),
};
const {
afterEach,
beforeEach,
createRootComponent,
start,
} = require('mail/static/src/utils/test_utils.js');
QUnit.module('mail', {}, function () {
QUnit.module('components', {}, function () {
QUnit.module('thread_icon', {}, function () {
QUnit.module('thread_icon_tests.js', {
beforeEach() {
beforeEach(this);
this.createThreadIcon = async thread => {
await createRootComponent(this, components.ThreadIcon, {
props: { threadLocalId: thread.localId },
target: this.widget.el
});
};
this.start = async params => {
const { env, widget } = await start(Object.assign({}, params, {
data: this.data,
}));
this.env = env;
this.widget = widget;
};
},
afterEach() {
afterEach(this);
},
});
QUnit.test('thread icon of a chat when correspondent is on leave & online', async function (assert) {
assert.expect(2);
this.data['res.partner'].records.push({
id: 7,
im_status: 'leave_online',
name: 'Demo',
});
this.data['mail.channel'].records.push({
channel_type: 'chat',
id: 20,
members: [this.data.currentPartnerId, 7],
});
await this.start();
const thread = this.env.models['mail.thread'].findFromIdentifyingData({
id: 20,
model: 'mail.channel',
});
await this.createThreadIcon(thread);
assert.containsOnce(
document.body,
'.o_ThreadIcon_online',
"thread icon should have online status rendering"
);
assert.hasClass(
document.querySelector('.o_ThreadIcon_online'),
'fa-plane',
"thread icon should have leave status rendering"
);
});
QUnit.test('thread icon of a chat when correspondent is on leave & away', async function (assert) {
assert.expect(2);
this.data['res.partner'].records.push({
id: 7,
im_status: 'leave_away',
name: 'Demo',
});
this.data['mail.channel'].records.push({
channel_type: 'chat',
id: 20,
members: [this.data.currentPartnerId, 7],
});
await this.start();
const thread = this.env.models['mail.thread'].findFromIdentifyingData({
id: 20,
model: 'mail.channel',
});
await this.createThreadIcon(thread);
assert.containsOnce(
document.body,
'.o_ThreadIcon_away',
"thread icon should have away status rendering"
);
assert.hasClass(
document.querySelector('.o_ThreadIcon_away'),
'fa-plane',
"thread icon should have leave status rendering"
);
});
QUnit.test('thread icon of a chat when correspondent is on leave & offline', async function (assert) {
assert.expect(2);
this.data['res.partner'].records.push({
id: 7,
im_status: 'leave_offline',
name: 'Demo',
});
this.data['mail.channel'].records.push({
channel_type: 'chat',
id: 20,
members: [this.data.currentPartnerId, 7],
});
await this.start();
const thread = this.env.models['mail.thread'].findFromIdentifyingData({
id: 20,
model: 'mail.channel',
});
await this.createThreadIcon(thread);
assert.containsOnce(
document.body,
'.o_ThreadIcon_offline',
"thread icon should have offline status rendering"
);
assert.hasClass(
document.querySelector('.o_ThreadIcon_offline'),
'fa-plane',
"thread icon should have leave status rendering"
);
});
});
});
});
});
@@ -11,8 +11,6 @@
<xpath expr="link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/hr_holidays/static/src/scss/time_off.scss"/>
<link rel="stylesheet" type="text/scss" href="/hr_holidays/static/src/bugfix/bugfix.scss"/>
<link rel="stylesheet" type="text/scss" href="/hr_holidays/static/src/components/partner_im_status_icon/partner_im_status_icon.scss"/>
<link rel="stylesheet" type="text/scss" href="/hr_holidays/static/src/components/thread_icon/thread_icon.scss"/>
<link rel="stylesheet" type="text/scss" href="/hr_holidays/static/src/components/thread_view/thread_view.scss"/>
</xpath>
</template>
@@ -25,6 +23,8 @@
<template id="qunit_suite" name="hr_holidays_qunit_suite" inherit_id="web.qunit_suite_tests">
<xpath expr="." position="inside">
<script type="text/javascript" src="/hr_holidays/static/src/bugfix/bugfix_tests.js"></script>
<script type="text/javascript" src="/hr_holidays/static/src/components/partner_im_status_icon/partner_im_status_icon_tests.js"/>
<script type="text/javascript" src="/hr_holidays/static/src/components/thread_icon/thread_icon_tests.js"/>
<script type="text/javascript" src="/hr_holidays/static/src/components/thread_view/thread_view_tests.js"/>
<script type="text/javascript" src="/hr_holidays/static/tests/test_leave_stats_widget.js"></script>
</xpath>