summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/components/partner_im_status_icon
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/mail/static/src/components/partner_im_status_icon
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/mail/static/src/components/partner_im_status_icon')
-rw-r--r--addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js74
-rw-r--r--addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss59
-rw-r--r--addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml38
-rw-r--r--addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon_tests.js145
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"
+ );
+});
+
+});
+});
+});
+
+});