summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/widgets/discuss
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/widgets/discuss
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/mail/static/src/widgets/discuss')
-rw-r--r--addons/mail/static/src/widgets/discuss/discuss.js397
-rw-r--r--addons/mail/static/src/widgets/discuss/discuss.scss36
-rw-r--r--addons/mail/static/src/widgets/discuss/discuss.xml27
3 files changed, 460 insertions, 0 deletions
diff --git a/addons/mail/static/src/widgets/discuss/discuss.js b/addons/mail/static/src/widgets/discuss/discuss.js
new file mode 100644
index 00000000..86f3ba32
--- /dev/null
+++ b/addons/mail/static/src/widgets/discuss/discuss.js
@@ -0,0 +1,397 @@
+odoo.define('mail/static/src/widgets/discuss/discuss.js', function (require) {
+'use strict';
+
+const components = {
+ Discuss: require('mail/static/src/components/discuss/discuss.js'),
+};
+const InvitePartnerDialog = require('mail/static/src/widgets/discuss_invite_partner_dialog/discuss_invite_partner_dialog.js');
+
+const AbstractAction = require('web.AbstractAction');
+const { action_registry, qweb } = require('web.core');
+
+const { Component } = owl;
+
+const DiscussWidget = AbstractAction.extend({
+ template: 'mail.widgets.Discuss',
+ hasControlPanel: true,
+ loadControlPanel: true,
+ withSearchBar: true,
+ searchMenuTypes: ['filter', 'favorite'],
+ /**
+ * @override {web.AbstractAction}
+ * @param {web.ActionManager} parent
+ * @param {Object} action
+ * @param {Object} [action.context]
+ * @param {string} [action.context.active_id]
+ * @param {Object} [action.params]
+ * @param {string} [action.params.default_active_id]
+ * @param {Object} [options={}]
+ */
+ init(parent, action, options={}) {
+ this._super(...arguments);
+
+ // render buttons in control panel
+ this.$buttons = $(qweb.render('mail.widgets.Discuss.DiscussControlButtons'));
+ this.$buttons.find('button').css({ display: 'inline-block' });
+ this.$buttons.on('click', '.o_invite', ev => this._onClickInvite(ev));
+ this.$buttons.on('click', '.o_widget_Discuss_controlPanelButtonMarkAllRead',
+ ev => this._onClickMarkAllAsRead(ev)
+ );
+ this.$buttons.on('click', '.o_mobile_new_channel', ev => this._onClickMobileNewChannel(ev));
+ this.$buttons.on('click', '.o_mobile_new_message', ev => this._onClickMobileNewMessage(ev));
+ this.$buttons.on('click', '.o_unstar_all', ev => this._onClickUnstarAll(ev));
+ this.$buttons.on('click', '.o_widget_Discuss_controlPanelButtonSelectAll', ev => this._onClickSelectAll(ev));
+ this.$buttons.on('click', '.o_widget_Discuss_controlPanelButtonUnselectAll', ev => this._onClickUnselectAll(ev));
+ this.$buttons.on('click', '.o_widget_Discuss_controlPanelButtonModeration.o-accept', ev => this._onClickModerationAccept(ev));
+ this.$buttons.on('click', '.o_widget_Discuss_controlPanelButtonModeration.o-discard', ev => this._onClickModerationDiscard(ev));
+ this.$buttons.on('click', '.o_widget_Discuss_controlPanelButtonModeration.o-reject', ev => this._onClickModerationReject(ev));
+
+ // control panel attributes
+ this.action = action;
+ this.actionManager = parent;
+ this.searchModelConfig.modelName = 'mail.message';
+ this.discuss = undefined;
+ this.options = options;
+
+ this.component = undefined;
+
+ this._lastPushStateActiveThread = null;
+ },
+ /**
+ * @override
+ */
+ async willStart() {
+ await this._super(...arguments);
+ this.env = Component.env;
+ await this.env.messagingCreatedPromise;
+ const initActiveId = this.options.active_id ||
+ (this.action.context && this.action.context.active_id) ||
+ (this.action.params && this.action.params.default_active_id) ||
+ 'mail.box_inbox';
+ this.discuss = this.env.messaging.discuss;
+ this.discuss.update({ initActiveId });
+ },
+ /**
+ * @override {web.AbstractAction}
+ */
+ destroy() {
+ if (this.component) {
+ this.component.destroy();
+ this.component = undefined;
+ }
+ if (this.$buttons) {
+ this.$buttons.off().remove();
+ }
+ this._super(...arguments);
+ },
+ /**
+ * @override {web.AbstractAction}
+ */
+ on_attach_callback() {
+ this._super(...arguments);
+ if (this.component) {
+ // prevent twice call to on_attach_callback (FIXME)
+ return;
+ }
+ const DiscussComponent = components.Discuss;
+ this.component = new DiscussComponent();
+ this._pushStateActionManagerEventListener = ev => {
+ ev.stopPropagation();
+ if (this._lastPushStateActiveThread === this.discuss.thread) {
+ return;
+ }
+ this._pushStateActionManager();
+ this._lastPushStateActiveThread = this.discuss.thread;
+ };
+ this._showRainbowManEventListener = ev => {
+ ev.stopPropagation();
+ this._showRainbowMan();
+ };
+ this._updateControlPanelEventListener = ev => {
+ ev.stopPropagation();
+ this._updateControlPanel();
+ };
+
+ this.el.addEventListener(
+ 'o-push-state-action-manager',
+ this._pushStateActionManagerEventListener
+ );
+ this.el.addEventListener(
+ 'o-show-rainbow-man',
+ this._showRainbowManEventListener
+ );
+ this.el.addEventListener(
+ 'o-update-control-panel',
+ this._updateControlPanelEventListener
+ );
+ return this.component.mount(this.el);
+ },
+ /**
+ * @override {web.AbstractAction}
+ */
+ on_detach_callback() {
+ this._super(...arguments);
+ if (this.component) {
+ this.component.destroy();
+ }
+ this.component = undefined;
+ this.el.removeEventListener(
+ 'o-push-state-action-manager',
+ this._pushStateActionManagerEventListener
+ );
+ this.el.removeEventListener(
+ 'o-show-rainbow-man',
+ this._showRainbowManEventListener
+ );
+ this.el.removeEventListener(
+ 'o-update-control-panel',
+ this._updateControlPanelEventListener
+ );
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ _pushStateActionManager() {
+ this.actionManager.do_push_state({
+ action: this.action.id,
+ active_id: this.discuss.activeId,
+ });
+ },
+ /**
+ * @private
+ * @returns {boolean}
+ */
+ _shouldHaveInviteButton() {
+ return (
+ this.discuss.thread &&
+ this.discuss.thread.channel_type === 'channel'
+ );
+ },
+ /**
+ * @private
+ */
+ _showRainbowMan() {
+ this.trigger_up('show_effect', {
+ message: this.env._t("Congratulations, your inbox is empty!"),
+ type: 'rainbow_man',
+ });
+ },
+ /**
+ * @private
+ */
+ _updateControlPanel() {
+ // Invite
+ if (this._shouldHaveInviteButton()) {
+ this.$buttons.find('.o_invite').removeClass('o_hidden');
+ } else {
+ this.$buttons.find('.o_invite').addClass('o_hidden');
+ }
+ // Mark All Read
+ if (
+ this.discuss.threadView &&
+ this.discuss.thread &&
+ this.discuss.thread === this.env.messaging.inbox
+ ) {
+ this.$buttons
+ .find('.o_widget_Discuss_controlPanelButtonMarkAllRead')
+ .removeClass('o_hidden')
+ .prop('disabled', this.discuss.threadView.messages.length === 0);
+ } else {
+ this.$buttons
+ .find('.o_widget_Discuss_controlPanelButtonMarkAllRead')
+ .addClass('o_hidden');
+ }
+ // Unstar All
+ if (
+ this.discuss.threadView &&
+ this.discuss.thread &&
+ this.discuss.thread === this.env.messaging.starred
+ ) {
+ this.$buttons
+ .find('.o_unstar_all')
+ .removeClass('o_hidden')
+ .prop('disabled', this.discuss.threadView.messages.length === 0);
+ } else {
+ this.$buttons
+ .find('.o_unstar_all')
+ .addClass('o_hidden');
+ }
+ // Mobile: Add channel
+ if (
+ this.env.messaging.device.isMobile &&
+ this.discuss.activeMobileNavbarTabId === 'channel'
+ ) {
+ this.$buttons
+ .find('.o_mobile_new_channel')
+ .removeClass('o_hidden');
+ } else {
+ this.$buttons
+ .find('.o_mobile_new_channel')
+ .addClass('o_hidden');
+ }
+ // Mobile: Add message
+ if (
+ this.env.messaging.device.isMobile &&
+ this.discuss.activeMobileNavbarTabId === 'chat'
+ ) {
+ this.$buttons
+ .find('.o_mobile_new_message')
+ .removeClass('o_hidden');
+ } else {
+ this.$buttons
+ .find('.o_mobile_new_message')
+ .addClass('o_hidden');
+ }
+ // Select All & Unselect All
+ const $selectAll = this.$buttons.find('.o_widget_Discuss_controlPanelButtonSelectAll');
+ const $unselectAll = this.$buttons.find('.o_widget_Discuss_controlPanelButtonUnselectAll');
+
+ if (
+ this.discuss.threadView &&
+ (
+ this.discuss.threadView.checkedMessages.length > 0 ||
+ this.discuss.threadView.uncheckedMessages.length > 0
+ )
+ ) {
+ $selectAll.removeClass('o_hidden');
+ $selectAll.toggleClass('disabled', this.discuss.threadView.uncheckedMessages.length === 0);
+ $unselectAll.removeClass('o_hidden');
+ $unselectAll.toggleClass('disabled', this.discuss.threadView.checkedMessages.length === 0);
+ } else {
+ $selectAll.addClass('o_hidden');
+ $selectAll.addClass('disabled');
+ $unselectAll.addClass('o_hidden');
+ $unselectAll.addClass('disabled');
+ }
+
+ // Moderation Actions
+ const $moderationButtons = this.$buttons.find('.o_widget_Discuss_controlPanelButtonModeration');
+ if (
+ this.discuss.threadView &&
+ this.discuss.threadView.checkedMessages.length > 0 &&
+ this.discuss.threadView.checkedMessages.filter(
+ message => !message.isModeratedByCurrentPartner
+ ).length === 0
+ ) {
+ $moderationButtons.removeClass('o_hidden');
+ } else {
+ $moderationButtons.addClass('o_hidden');
+ }
+
+ let title;
+ if (this.env.messaging.device.isMobile || !this.discuss.thread) {
+ title = this.env._t("Discuss");
+ } else {
+ const prefix =
+ this.discuss.thread.channel_type === 'channel' &&
+ this.discuss.thread.public !== 'private'
+ ? '#'
+ : '';
+ title = `${prefix}${this.discuss.thread.displayName}`;
+ }
+
+ this.updateControlPanel({
+ cp_content: {
+ $buttons: this.$buttons,
+ },
+ title,
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ _onClickInvite() {
+ new InvitePartnerDialog(this, {
+ activeThreadLocalId: this.discuss.thread.localId,
+ messagingEnv: this.env,
+ }).open();
+ },
+ /**
+ * @private
+ */
+ _onClickMarkAllAsRead() {
+ this.env.models['mail.message'].markAllAsRead(this.domain);
+ },
+ /**
+ * @private
+ */
+ _onClickMobileNewChannel() {
+ this.discuss.update({ isAddingChannel: true });
+ },
+ /**
+ * @private
+ */
+ _onClickMobileNewMessage() {
+ this.discuss.update({ isAddingChat: true });
+ },
+ /**
+ * @private
+ */
+ _onClickModerationAccept() {
+ this.env.models['mail.message'].moderate(
+ this.discuss.threadView.checkedMessages,
+ 'accept'
+ );
+ },
+ /**
+ * @private
+ */
+ _onClickModerationDiscard() {
+ this.discuss.update({ hasModerationDiscardDialog: true });
+ },
+ /**
+ * @private
+ */
+ _onClickModerationReject() {
+ this.discuss.update({ hasModerationRejectDialog: true });
+ },
+ /**
+ * @private
+ */
+ _onClickSelectAll() {
+ this.env.models['mail.message'].checkAll(
+ this.discuss.thread,
+ this.discuss.stringifiedDomain
+ );
+ },
+ /**
+ * @private
+ */
+ _onClickUnselectAll() {
+ this.env.models['mail.message'].uncheckAll(
+ this.discuss.thread,
+ this.discuss.stringifiedDomain
+ );
+ },
+ /**
+ * @private
+ */
+ _onClickUnstarAll() {
+ this.env.models['mail.message'].unstarAll();
+ },
+ /**
+ * @private
+ * @param {Object} searchQuery
+ */
+ _onSearch: function (searchQuery) {
+ this.discuss.update({
+ stringifiedDomain: JSON.stringify(searchQuery.domain),
+ });
+ },
+});
+
+action_registry.add('mail.widgets.discuss', DiscussWidget);
+
+return DiscussWidget;
+
+});
diff --git a/addons/mail/static/src/widgets/discuss/discuss.scss b/addons/mail/static/src/widgets/discuss/discuss.scss
new file mode 100644
index 00000000..2bed9b7c
--- /dev/null
+++ b/addons/mail/static/src/widgets/discuss/discuss.scss
@@ -0,0 +1,36 @@
+// ------------------------------------------------------------------
+// Layout
+// ------------------------------------------------------------------
+
+.o_widget_Discuss {
+ display: flex;
+ flex: 0 0 100%;
+ flex-flow: column;
+ height: 100%;
+}
+
+// ------------------------------------------------------------------
+// Style
+// ------------------------------------------------------------------
+
+.o_widget_Discuss {
+
+ .o_control_panel {
+ border-bottom: 0; // cancel default border, so that we only apply it on top of discuss content
+ }
+
+ .o_Discuss_content {
+ border-top: 1px solid darken($o-control-panel-background-color, 20%);
+ }
+
+ .o_Discuss.o-mobile {
+
+ &:not(.o-adding-item) {
+ border-top: 1px solid darken($o-control-panel-background-color, 20%);
+ }
+
+ &.o-adding-item .o_Discuss_mobileAddItemHeader {
+ border-bottom: 1px solid darken($o-control-panel-background-color, 20%);
+ }
+ }
+}
diff --git a/addons/mail/static/src/widgets/discuss/discuss.xml b/addons/mail/static/src/widgets/discuss/discuss.xml
new file mode 100644
index 00000000..f8e6de37
--- /dev/null
+++ b/addons/mail/static/src/widgets/discuss/discuss.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates xml:space="preserve">
+
+ <!--
+ @param {mail/static/src/widgets/discuss/discuss.js} widget
+ -->
+ <t t-name="mail.widgets.Discuss">
+ <div class="o_widget_Discuss"/>
+ </t>
+
+ <!-- @param {boolean} isMobile -->
+ <t t-name="mail.widgets.Discuss.DiscussControlButtons">
+ <div>
+ <button class="o_widget_Discuss_controlPanelButtonInvite o_invite o_hidden btn btn-primary" type="button" title="Invite people">Invite</button>
+ <button class="o_widget_Discuss_controlPanelButtonMarkAllRead o_hidden btn btn-secondary" type="button" title="Mark all as read">Mark all read</button>
+ <button class="o_widget_Discuss_controlPanelButtonUnstarAll o_unstar_all o_hidden btn btn-secondary" type="button" title="Unstar all messages">Unstar all</button>
+ <button class="o_widget_Discuss_controlPanelButtonMobileNewMessage o_mobile_new_message o_hidden btn btn-secondary" type="button" title="New Message">New Message</button>
+ <button class="o_widget_Discuss_controlPanelButtonMobileNewChannel o_mobile_new_channel o_hidden btn btn-secondary" title="New Channel" type="button">New Channel</button>
+ <button class="o_widget_Discuss_controlPanelButtonSelectAll btn btn-secondary o_hidden" title="Select all messages">Select All</button>
+ <button class="o_widget_Discuss_controlPanelButtonUnselectAll btn btn-secondary o_hidden" title="Unselect all messages">Unselect All</button>
+ <button class="o_widget_Discuss_controlPanelButtonModeration btn btn-secondary o_hidden o-accept" title="Accept selected messages">Accept</button>
+ <button class="o_widget_Discuss_controlPanelButtonModeration btn btn-secondary o_hidden o-reject" title="Reject selected messages">Reject</button>
+ <button class="o_widget_Discuss_controlPanelButtonModeration btn btn-secondary o_hidden o-discard" title="Discard selected messages">Discard</button>
+ </div>
+ </t>
+
+</templates>