summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/components/discuss_sidebar_item
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/discuss_sidebar_item
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/mail/static/src/components/discuss_sidebar_item')
-rw-r--r--addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.js220
-rw-r--r--addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.scss109
-rw-r--r--addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.xml63
3 files changed, 392 insertions, 0 deletions
diff --git a/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.js b/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.js
new file mode 100644
index 00000000..0226035c
--- /dev/null
+++ b/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.js
@@ -0,0 +1,220 @@
+odoo.define('mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.js', function (require) {
+'use strict';
+
+const components = {
+ EditableText: require('mail/static/src/components/editable_text/editable_text.js'),
+ ThreadIcon: require('mail/static/src/components/thread_icon/thread_icon.js'),
+};
+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 { isEventHandled } = require('mail/static/src/utils/utils.js');
+
+const Dialog = require('web.Dialog');
+
+const { Component } = owl;
+
+class DiscussSidebarItem extends Component {
+
+ /**
+ * @override
+ */
+ constructor(...args) {
+ super(...args);
+ useShouldUpdateBasedOnProps();
+ useStore(props => {
+ const discuss = this.env.messaging.discuss;
+ const thread = this.env.models['mail.thread'].get(props.threadLocalId);
+ const correspondent = thread ? thread.correspondent : undefined;
+ return {
+ correspondentName: correspondent && correspondent.name,
+ discussIsRenamingThread: discuss && discuss.renamingThreads.includes(thread),
+ isDiscussThread: discuss && discuss.thread === thread,
+ starred: this.env.messaging.starred,
+ thread,
+ threadChannelType: thread && thread.channel_type,
+ threadCounter: thread && thread.counter,
+ threadDisplayName: thread && thread.displayName,
+ threadGroupBasedSubscription: thread && thread.group_based_subscription,
+ threadLocalMessageUnreadCounter: thread && thread.localMessageUnreadCounter,
+ threadMassMailing: thread && thread.mass_mailing,
+ threadMessageNeedactionCounter: thread && thread.message_needaction_counter,
+ threadModel: thread && thread.model,
+ };
+ });
+ }
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * Get the counter of this discuss item, which is based on the thread type.
+ *
+ * @returns {integer}
+ */
+ get counter() {
+ if (this.thread.model === 'mail.box') {
+ return this.thread.counter;
+ } else if (this.thread.channel_type === 'channel') {
+ return this.thread.message_needaction_counter;
+ } else if (this.thread.channel_type === 'chat') {
+ return this.thread.localMessageUnreadCounter;
+ }
+ return 0;
+ }
+
+ /**
+ * @returns {mail.discuss}
+ */
+ get discuss() {
+ return this.env.messaging && this.env.messaging.discuss;
+ }
+
+ /**
+ * @returns {boolean}
+ */
+ hasUnpin() {
+ return this.thread.channel_type === 'chat';
+ }
+
+ /**
+ * @returns {mail.thread}
+ */
+ get thread() {
+ return this.env.models['mail.thread'].get(this.props.threadLocalId);
+ }
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @returns {Promise}
+ */
+ _askAdminConfirmation() {
+ return new Promise(resolve => {
+ Dialog.confirm(this,
+ this.env._t("You are the administrator of this channel. Are you sure you want to leave?"),
+ {
+ buttons: [
+ {
+ text: this.env._t("Leave"),
+ classes: 'btn-primary',
+ close: true,
+ click: resolve
+ },
+ {
+ text: this.env._t("Discard"),
+ close: true
+ }
+ ]
+ }
+ );
+ });
+ }
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onCancelRenaming(ev) {
+ this.discuss.cancelThreadRenaming(this.thread);
+ }
+
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClick(ev) {
+ if (isEventHandled(ev, 'EditableText.click')) {
+ return;
+ }
+ this.thread.open();
+ }
+
+ /**
+ * Stop propagation to prevent selecting this item.
+ *
+ * @private
+ * @param {CustomEvent} ev
+ */
+ _onClickedEditableText(ev) {
+ ev.stopPropagation();
+ }
+
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ async _onClickLeave(ev) {
+ ev.stopPropagation();
+ if (this.thread.creator === this.env.messaging.currentUser) {
+ await this._askAdminConfirmation();
+ }
+ this.thread.unsubscribe();
+ }
+
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickRename(ev) {
+ ev.stopPropagation();
+ this.discuss.setThreadRenaming(this.thread);
+ }
+
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickSettings(ev) {
+ ev.stopPropagation();
+ return this.env.bus.trigger('do-action', {
+ action: {
+ type: 'ir.actions.act_window',
+ res_model: this.thread.model,
+ res_id: this.thread.id,
+ views: [[false, 'form']],
+ target: 'current'
+ },
+ });
+ }
+
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickUnpin(ev) {
+ ev.stopPropagation();
+ this.thread.unsubscribe();
+ }
+
+ /**
+ * @private
+ * @param {CustomEvent} ev
+ * @param {Object} ev.detail
+ * @param {string} ev.detail.newName
+ */
+ _onValidateEditableText(ev) {
+ ev.stopPropagation();
+ this.discuss.renameThread(this.thread, ev.detail.newName);
+ }
+
+}
+
+Object.assign(DiscussSidebarItem, {
+ components,
+ props: {
+ threadLocalId: String,
+ },
+ template: 'mail.DiscussSidebarItem',
+});
+
+return DiscussSidebarItem;
+
+});
diff --git a/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.scss b/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.scss
new file mode 100644
index 00000000..aebc4b9a
--- /dev/null
+++ b/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.scss
@@ -0,0 +1,109 @@
+// ------------------------------------------------------------------
+// Layout
+// ------------------------------------------------------------------
+
+.o_DiscussSidebarItem {
+ display: flex;
+ align-items: center;
+ padding: map-get($spacers, 1) 0;
+
+ &:hover .o_DiscussSidebarItem_commands {
+ display: flex;
+ }
+}
+
+.o_DiscussSidebarItem_activeIndicator {
+ width: $o-mail-discuss-sidebar-active-indicator-width;
+ align-self: stretch;
+ flex: 0 0 auto;
+}
+
+.o_DiscussSidebarItem_command {
+ margin-left: 3px;
+ margin-right: 3px;
+
+ &:first-child {
+ margin-left: 0px;
+ }
+
+ &:last-child {
+ margin-right: 0px;
+ }
+}
+
+.o_DiscussSidebarItem_commands {
+ display: none;
+}
+
+.o_DiscussSidebarItem_item {
+ margin-left: 3px;
+ margin-right: 3px;
+
+ &:first-child {
+ margin-left: 0px;
+ margin-right: $o-mail-discuss-sidebar-active-indicator-margin-right;
+ }
+
+ &:last-child {
+ margin-right: $o-mail-discuss-sidebar-scrollbar-width;
+ }
+}
+
+.o_DiscussSidebarItem_name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ &.o-editable {
+ margin-left: $o-mail-discuss-sidebar-active-indicator-width + $o-mail-discuss-sidebar-active-indicator-margin-right;
+ margin-right: $o-mail-discuss-sidebar-scrollbar-width;
+ }
+}
+
+.o_DiscussSidebarItem_nameInput {
+ width: 100%;
+}
+
+// ------------------------------------------------------------------
+// Style
+// ------------------------------------------------------------------
+
+.o_DiscussSidebarItem {
+ cursor: pointer;
+
+ &:hover {
+ background-color: darken(gray('900'), 5%);
+ }
+
+ &.o-starred-box {
+ .o_DiscussSidebarItem_counter {
+ border-color: gray('600');
+ background-color: gray('600');
+ }
+ }
+}
+
+.o_DiscussSidebarItem_activeIndicator.o-item-active {
+ background-color: $o-brand-primary;
+}
+
+.o_DiscussSidebarItem_command:not(:hover) {
+ color: gray('600');
+}
+
+.o_DiscussSidebarItem_counter {
+ background-color: $o-brand-primary;
+}
+
+.o_DiscussSidebarItem_name {
+
+ &.o-item-unread {
+ font-weight: bold;
+ }
+}
+
+.o_DiscussSidebarItem_nameInput {
+ outline: none;
+ border: none;
+ border-radius: 2px;
+}
diff --git a/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.xml b/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.xml
new file mode 100644
index 00000000..74aace21
--- /dev/null
+++ b/addons/mail/static/src/components/discuss_sidebar_item/discuss_sidebar_item.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates xml:space="preserve">
+
+ <t t-name="mail.DiscussSidebarItem" owl="1">
+ <div class="o_DiscussSidebarItem"
+ t-att-class="{
+ 'o-active': thread and discuss.thread === thread,
+ 'o-starred-box': thread and thread === env.messaging.starred,
+ 'o-unread': thread and thread.localMessageUnreadCounter > 0,
+ }" t-on-click="_onClick" t-att-data-thread-local-id="thread ? thread.localId : undefined" t-att-data-thread-name="thread ? thread.displayName : undefined"
+ >
+ <t t-if="thread">
+ <div class=" o_DiscussSidebarItem_activeIndicator o_DiscussSidebarItem_item" t-att-class="{ 'o-item-active': discuss.thread === thread }"/>
+ <ThreadIcon class="o_DiscussSidebarItem_item" threadLocalId="thread.localId"/>
+ <t t-if="thread.channel_type === 'chat' and discuss.renamingThreads.includes(thread)">
+ <div class="o_DiscussSidebarItem_item o_DiscussSidebarItem_name o-editable">
+ <EditableText
+ class="o_DiscussSidebarItem_nameInput"
+ placeholder="thread.correspondent ? thread.correspondent.name : thread.name"
+ value="thread.displayName"
+ t-on-o-cancel="_onCancelRenaming"
+ t-on-o-clicked="_onClickedEditableText"
+ t-on-o-validate="_onValidateEditableText"
+ />
+ </div>
+ </t>
+ <t t-else="">
+ <div class="o_DiscussSidebarItem_item o_DiscussSidebarItem_name" t-att-class="{ 'o-item-unread': thread.localMessageUnreadCounter > 0 }">
+ <t t-esc="thread.displayName"/>
+ </div>
+ <t t-if="thread.mass_mailing">
+ <i class="fa fa-envelope-o" title="Messages are sent by email" role="img"/>
+ </t>
+ </t>
+ <div class="o-autogrow o_DiscussSidebarItem_item"/>
+ <t t-if="thread.model !== 'mail.box'">
+ <div class="o_DiscussSidebarItem_commands o_DiscussSidebarItem_item">
+ <t t-if="thread.channel_type === 'channel'">
+ <div class="fa fa-cog o_DiscussSidebarItem_command o_DiscussSidebarItem_commandSettings" t-on-click="_onClickSettings" title="Channel settings" role="img"/>
+ <t t-if="!thread.message_needaction_counter and !thread.group_based_subscription">
+ <div class="o_DiscussSidebarItem_command o_DiscussSidebarItem_commandLeave fa fa-times" t-on-click="_onClickLeave" title="Leave this channel" role="img"/>
+ </t>
+ </t>
+ <t t-if="thread.channel_type === 'chat'">
+ <div class="o_DiscussSidebarItem_command o_DiscussSidebarItem_commandRename fa fa-cog" t-on-click="_onClickRename" title="Rename conversation" role="img"/>
+ </t>
+ <t t-if="hasUnpin()">
+ <t t-if="!thread.localMessageUnreadCounter">
+ <div class="fa fa-times o_DiscussSidebarItem_command o_DiscussSidebarItem_commandUnpin" t-on-click="_onClickUnpin" title="Unpin conversation" role="img"/>
+ </t>
+ </t>
+ </div>
+ </t>
+ <t t-if="counter > 0">
+ <div class="o_DiscussSidebarItem_counter o_DiscussSidebarItem_item badge badge-pill">
+ <t t-esc="counter"/>
+ </div>
+ </t>
+ </t>
+ </div>
+ </t>
+
+</templates>