diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/mail/static/src/components/partner_im_status_icon | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/mail/static/src/components/partner_im_status_icon')
4 files changed, 316 insertions, 0 deletions
diff --git a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js new file mode 100644 index 00000000..e4af9da6 --- /dev/null +++ b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js @@ -0,0 +1,74 @@ +odoo.define('mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js', function (require) { +'use strict'; + +const useShouldUpdateBasedOnProps = require('mail/static/src/component_hooks/use_should_update_based_on_props/use_should_update_based_on_props.js'); +const useStore = require('mail/static/src/component_hooks/use_store/use_store.js'); + +const { Component } = owl; + +class PartnerImStatusIcon extends Component { + + /** + * @override + */ + constructor(...args) { + super(...args); + useShouldUpdateBasedOnProps(); + useStore(props => { + const partner = this.env.models['mail.partner'].get(props.partnerLocalId); + return { + partner, + partnerImStatus: partner && partner.im_status, + partnerRoot: this.env.messaging.partnerRoot, + }; + }); + } + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * @returns {mail.partner} + */ + get partner() { + return this.env.models['mail.partner'].get(this.props.partnerLocalId); + } + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} ev + */ + _onClick(ev) { + if (!this.props.hasOpenChat) { + return; + } + this.partner.openChat(); + } + +} + +Object.assign(PartnerImStatusIcon, { + defaultProps: { + hasBackground: true, + hasOpenChat: false, + }, + props: { + partnerLocalId: String, + hasBackground: Boolean, + /** + * Determines whether a click on `this` should open a chat with + * `this.partner`. + */ + hasOpenChat: Boolean, + }, + template: 'mail.PartnerImStatusIcon', +}); + +return PartnerImStatusIcon; + +}); diff --git a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss new file mode 100644 index 00000000..608c281a --- /dev/null +++ b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss @@ -0,0 +1,59 @@ +// ------------------------------------------------------------------ +// Layout +// ------------------------------------------------------------------ + +.o_PartnerImStatusIcon { + display: flex; + flex-flow: column; + + width: 1.2em; + height: 1.2em; + line-height: 1.3em; +} + +.o_PartnerImStatusIcon_outerBackground { + transform: scale(1.5); +} + +.o-background { + transform: scale(1); + margin-inline-end: map-get($spacers, 1); + margin-top: 2px; +} + +// ------------------------------------------------------------------ +// Style +// ------------------------------------------------------------------ + +.o_PartnerImStatusIcon { + &.o-has-open-chat { + cursor: pointer; + } +} + +.o_PartnerImStatusIcon_innerBackground { + color: white; +} + +.o_PartnerImStatusIcon_icon { + + &.o-away { + color: theme-color('warning'); + } + + &.o-bot { + color: $o-enterprise-primary-color; + } + + &.o-offline { + color: gray('700'); + } + + &.o-online { + color: $o-enterprise-primary-color; + } +} + + + + diff --git a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml new file mode 100644 index 00000000..ca20a547 --- /dev/null +++ b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<templates xml:space="preserve"> + + <t t-name="mail.PartnerImStatusIcon" owl="1"> + <span class="o_PartnerImStatusIcon fa-stack" + t-att-class="{ + 'o-away': partner and partner.im_status === 'away', + 'o-background': !props.hasBackground, + 'o-bot': partner and env.messaging.partnerRoot === partner, + 'o-has-open-chat': props.hasOpenChat, + 'o-offline': partner and partner.im_status === 'offline', + 'o-online': partner and partner.im_status === 'online', + }" + t-on-click="_onClick" + t-att-data-partner-local-id="partner ? partner.localId : undefined" + > + <t t-if="partner" name="rootCondition"> + <t t-if="props.hasBackground"> + <i class="o_PartnerImStatusIcon_outerBackground fa fa-circle fa-stack-1x"/> + <i class="o_PartnerImStatusIcon_innerBackground fa fa-circle fa-stack-1x"/> + </t> + <t t-if="partner.im_status === 'online'"> + <i class="o_PartnerImStatusIcon_icon o-online fa fa-circle fa-stack-1x" title="Online" role="img" aria-label="User is online"/> + </t> + <t t-if="partner.im_status === 'away'"> + <i class="o_PartnerImStatusIcon_icon o-away fa fa-circle fa-stack-1x" title="Idle" role="img" aria-label="User is idle"/> + </t> + <t t-if="partner.im_status === 'offline'"> + <i class="o_PartnerImStatusIcon_icon o-offline fa fa-circle-o fa-stack-1x" title="Offline" role="img" aria-label="User is offline"/> + </t> + <t t-if="partner === env.messaging.partnerRoot"> + <i class="o_PartnerImStatusIcon_icon o-bot fa fa-heart fa-stack-1x" title="Bot" role="img" aria-label="User is a bot"/> + </t> + </t> + </span> + </t> + +</templates> diff --git a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon_tests.js b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon_tests.js new file mode 100644 index 00000000..1a68a5e0 --- /dev/null +++ b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon_tests.js @@ -0,0 +1,145 @@ +odoo.define('mail/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, + afterNextRender, + beforeEach, + createRootComponent, + start, +} = require('mail/static/src/utils/test_utils.js'); + +QUnit.module('mail', {}, 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('initially online', async function (assert) { + assert.expect(3); + + await this.start(); + const partner = this.env.models['mail.partner'].create({ + id: 7, + name: "Demo User", + im_status: 'online', + }); + await this.createPartnerImStatusIcon(partner); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon`).length, + 1, + "should have partner IM status icon" + ); + assert.strictEqual( + document.querySelector(`.o_PartnerImStatusIcon`).dataset.partnerLocalId, + partner.localId, + "partner IM status icon should be linked to partner with ID 7" + ); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon.o-online`).length, + 1, + "partner IM status icon should have online status rendering" + ); +}); + +QUnit.test('initially offline', async function (assert) { + assert.expect(1); + + await this.start(); + const partner = this.env.models['mail.partner'].create({ + id: 7, + name: "Demo User", + im_status: 'offline', + }); + await this.createPartnerImStatusIcon(partner); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon.o-offline`).length, + 1, + "partner IM status icon should have offline status rendering" + ); +}); + +QUnit.test('initially away', async function (assert) { + assert.expect(1); + + await this.start(); + const partner = this.env.models['mail.partner'].create({ + id: 7, + name: "Demo User", + im_status: 'away', + }); + await this.createPartnerImStatusIcon(partner); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon.o-away`).length, + 1, + "partner IM status icon should have away status rendering" + ); +}); + +QUnit.test('change icon on change partner im_status', async function (assert) { + assert.expect(4); + + await this.start(); + const partner = this.env.models['mail.partner'].create({ + id: 7, + name: "Demo User", + im_status: 'online', + }); + await this.createPartnerImStatusIcon(partner); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon.o-online`).length, + 1, + "partner IM status icon should have online status rendering" + ); + + await afterNextRender(() => partner.update({ im_status: 'offline' })); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon.o-offline`).length, + 1, + "partner IM status icon should have offline status rendering" + ); + + await afterNextRender(() => partner.update({ im_status: 'away' })); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon.o-away`).length, + 1, + "partner IM status icon should have away status rendering" + ); + + await afterNextRender(() => partner.update({ im_status: 'online' })); + assert.strictEqual( + document.querySelectorAll(`.o_PartnerImStatusIcon.o-online`).length, + 1, + "partner IM status icon should have online status rendering in the end" + ); +}); + +}); +}); +}); + +}); |
