[IMP] im_livechat, mail: Discuss UI in mobile
- Extract mobile specific code for the client action to a specific file - Massive clean of less rules - Unify channels preview of the systray dropdown and the mobile UI of Discuss - Ensure to only load the last message of each channel in mobile, as this is not used in desktop (unless the user opens the systray menu) - Make livechat available in Discuss mobile UI
This commit is contained in:
@@ -7,9 +7,20 @@
|
||||
<t t-set="disable_add_channel" t-value="true"/>
|
||||
<t t-call="mail.chat.SidebarTitle">
|
||||
<t t-set="channel_title">Livechat</t>
|
||||
<t t-set="channel_icon">fa-comments</t>
|
||||
</t>
|
||||
<t t-call="mail.chat.SidebarItems"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Mobile templates -->
|
||||
<t t-extend="mail.client_action_mobile">
|
||||
<t t-jquery=".o_mail_mobile_tabs" t-operation="append">
|
||||
<div class="o_mail_mobile_tab" data-type="livechat">
|
||||
<span class="fa fa-comments"/>
|
||||
<span class="o_tab_title">Livechat</span>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</template>
|
||||
|
||||
@@ -355,9 +355,11 @@ class Channel(models.Model):
|
||||
.filtered(lambda p: p.id != self.env.user.partner_id.id)
|
||||
.read(['id', 'name', 'im_status']))
|
||||
|
||||
last_message = channel.channel_fetch_preview()
|
||||
if last_message:
|
||||
info['last_message'] = last_message[0].get('last_message')
|
||||
# add last message preview (only used in mobile)
|
||||
if self._context.get('isMobile', False):
|
||||
last_message = channel.channel_fetch_preview()
|
||||
if last_message:
|
||||
info['last_message'] = last_message[0].get('last_message')
|
||||
|
||||
# add user session state, if available and if user is logged
|
||||
if partner_channels.ids:
|
||||
@@ -577,9 +579,9 @@ class Channel(models.Model):
|
||||
'email_send': False,
|
||||
'channel_partner_ids': [(4, self.env.user.partner_id.id)]
|
||||
})
|
||||
channel_info = new_channel.channel_info('creation')[0]
|
||||
notification = _('<div class="o_mail_notification">created <a href="#" class="o_channel_redirect" data-oe-id="%s">#%s</a></div>') % (new_channel.id, new_channel.name,)
|
||||
new_channel.message_post(body=notification, message_type="notification", subtype="mail.mt_comment")
|
||||
channel_info = new_channel.channel_info('creation')[0]
|
||||
self.env['bus.bus'].sendone((self._cr.dbname, 'res.partner', self.env.user.partner_id.id), channel_info)
|
||||
return channel_info
|
||||
|
||||
|
||||
@@ -82,8 +82,11 @@ function add_message (data, options) {
|
||||
_.each(msg.channel_ids, function (channel_id) {
|
||||
var channel = chat_manager.get_channel(channel_id);
|
||||
if (channel) {
|
||||
// For mobile tabs view, we show recent message for channel.
|
||||
channel.last_message = msg;
|
||||
// update the channel's last message (displayed in the channel
|
||||
// preview, in mobile)
|
||||
if (!channel.last_message || msg.id > channel.last_message.id) {
|
||||
channel.last_message = msg;
|
||||
}
|
||||
add_to_cache(msg, []);
|
||||
if (options.domain && options.domain !== []) {
|
||||
add_to_cache(msg, options.domain);
|
||||
@@ -97,7 +100,7 @@ function add_message (data, options) {
|
||||
update_channel_unread_counter(channel, channel.unread_counter+1);
|
||||
}
|
||||
if (channel.is_chat && options.show_notification) {
|
||||
if (!client_action_open && config.device.size_class !== config.device.SIZES.XS) {
|
||||
if (!client_action_open && !config.isMobile) {
|
||||
// automatically open chat window
|
||||
chat_manager.bus.trigger('open_chat', channel, { passively: true });
|
||||
}
|
||||
@@ -260,6 +263,9 @@ function add_channel (data, options) {
|
||||
} else {
|
||||
channel = chat_manager.make_channel(data, options);
|
||||
channels.push(channel);
|
||||
if (data.last_message) {
|
||||
channel.last_message = add_message(data.last_message);
|
||||
}
|
||||
// In case of a static channel (Inbox, Starred), the name is translated thanks to _lt
|
||||
// (lazy translate). In this case, channel.name is an object, not a string.
|
||||
channels = _.sortBy(channels, function (channel) { return _.isString(channel.name) ? channel.name.toLowerCase() : '' });
|
||||
@@ -290,7 +296,6 @@ function make_channel (data, options) {
|
||||
group_based_subscription: data.group_based_subscription,
|
||||
needaction_counter: data.message_needaction_counter || 0,
|
||||
unread_counter: 0,
|
||||
last_message: data.last_message,
|
||||
last_seen_message_id: data.seen_message_id,
|
||||
cache: {'[]': {
|
||||
all_history_loaded: false,
|
||||
@@ -641,7 +646,8 @@ var ChatManager = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
|
||||
start: function () {
|
||||
this.is_ready = session.is_bound.then(function(){
|
||||
return session.rpc('/mail/client_action');
|
||||
var context = _.extend({isMobile: config.isMobile}, session.user_context);
|
||||
return session.rpc('/mail/client_action', {context: context});
|
||||
}).then(this._onMailClientAction.bind(this));
|
||||
|
||||
add_channel({
|
||||
@@ -1026,11 +1032,12 @@ var ChatManager = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
create_channel: function (name, type) {
|
||||
var method = type === "dm" ? "channel_get" : "channel_create";
|
||||
var args = type === "dm" ? [[name]] : [name, type];
|
||||
|
||||
var context = _.extend({isMobile: config.isMobile}, session.user_context);
|
||||
return this._rpc({
|
||||
model: 'mail.channel',
|
||||
method: method,
|
||||
args: args,
|
||||
kwargs: {context: context},
|
||||
})
|
||||
.then(add_channel);
|
||||
},
|
||||
@@ -1150,9 +1157,10 @@ var ChatManager = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
|
||||
get_channels_preview: function (channels) {
|
||||
var channels_preview = _.map(channels, function (channel) {
|
||||
var info;
|
||||
if (channel.channel_ids && _.contains(channel.channel_ids,"channel_inbox")) {
|
||||
// map inbox(mail_message) data with existing channel/chat template
|
||||
var info = _.pick(channel, 'id', 'body', 'avatar_src', 'res_id', 'model', 'module_icon', 'subject','date', 'record_name', 'status', 'displayed_author', 'email_from', 'unread_counter');
|
||||
info = _.pick(channel, 'id', 'body', 'avatar_src', 'res_id', 'model', 'module_icon', 'subject','date', 'record_name', 'status', 'displayed_author', 'email_from', 'unread_counter');
|
||||
info.last_message = {
|
||||
body: info.body,
|
||||
date: info.date,
|
||||
@@ -1164,8 +1172,8 @@ var ChatManager = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
info.id = 'channel_inbox';
|
||||
return info;
|
||||
}
|
||||
var info = _.pick(channel, 'id', 'is_chat', 'name', 'status', 'unread_counter');
|
||||
info.last_message = _.last(channel.cache['[]'].messages);
|
||||
info = _.pick(channel, 'id', 'is_chat', 'name', 'status', 'unread_counter');
|
||||
info.last_message = channel.last_message || _.last(channel.cache['[]'].messages);
|
||||
if (!info.is_chat) {
|
||||
info.image_src = '/web/image/mail.channel/'+channel.id+'/image_small';
|
||||
} else if (channel.direct_partner_id) {
|
||||
@@ -1197,9 +1205,22 @@ var ChatManager = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
channel_preview.last_message = add_message(channel.last_message);
|
||||
}
|
||||
});
|
||||
return _.filter(channels_preview, function (channel) {
|
||||
return channel.last_message; // remove empty channels
|
||||
// sort channels: 1. unread, 2. chat, 3. date of last msg
|
||||
channels_preview.sort(function (c1, c2) {
|
||||
return Math.min(1, c2.unread_counter) - Math.min(1, c1.unread_counter) ||
|
||||
c2.is_chat - c1.is_chat ||
|
||||
!!c2.last_message - !!c1.last_message ||
|
||||
(c2.last_message && c2.last_message.date.diff(c1.last_message.date));
|
||||
});
|
||||
|
||||
// generate last message preview (inline message body and compute date to display)
|
||||
_.each(channels_preview, function (channel) {
|
||||
if (channel.last_message) {
|
||||
channel.last_message_preview = chat_manager.get_message_body_preview(channel.last_message.body);
|
||||
channel.last_message_date = channel.last_message.date.fromNow();
|
||||
}
|
||||
});
|
||||
return channels_preview;
|
||||
});
|
||||
},
|
||||
get_message_body_preview: function (message_body) {
|
||||
|
||||
@@ -77,13 +77,6 @@ return Widget.extend({
|
||||
this.unread_msgs = counter;
|
||||
this.render_header();
|
||||
},
|
||||
|
||||
/**
|
||||
* When user status (online/offline/away) changed, this method update
|
||||
* user status with last seen and render header again.
|
||||
*
|
||||
* @param {string} status
|
||||
*/
|
||||
update_status: function (status) {
|
||||
this.status = status;
|
||||
this.render_header();
|
||||
@@ -92,8 +85,8 @@ return Widget.extend({
|
||||
this.$header.html(QWeb.render('mail.ChatWindowHeaderContent', {
|
||||
status: this.status,
|
||||
title: this.title,
|
||||
isMobile: this.isMobile,
|
||||
unread_counter: this.unread_msgs,
|
||||
widget: this,
|
||||
}));
|
||||
},
|
||||
fold: function () {
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
odoo.define('mail.chat_client_action_mobile', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ChatAction = require('mail.chat_client_action');
|
||||
var chat_manager = require('mail.chat_manager');
|
||||
|
||||
var config = require('web.config');
|
||||
var core = require('web.core');
|
||||
var session = require('web.session');
|
||||
|
||||
var QWeb = core.qweb;
|
||||
|
||||
if (!config.isMobile) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChatAction.include({
|
||||
template: 'mail.client_action_mobile',
|
||||
need_control_panel: false, // in mobile, we use a custom control panel
|
||||
events: _.extend(ChatAction.prototype.events, {
|
||||
'click .o_mail_mobile_tab': '_onMobileTabClicked',
|
||||
'click .o_channel_inbox_item': '_onMobileInboxButtonClicked',
|
||||
'click .o_mail_channel_preview': '_onMobileChannelClicked',
|
||||
}),
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.currentState = this.defaultChannelID;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$mainContent = this.$('.o_mail_chat_content');
|
||||
return this._super.apply(this, arguments)
|
||||
.then(this._updateControlPanel.bind(this));
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
on_attach_callback: function () {
|
||||
if (this.channel && this._isInInboxTab()) {
|
||||
this.thread.scroll_to({offset: this.channels_scrolltop[this.channel.id]});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
on_detach_callback: function () {
|
||||
if (this._isInInboxTab()) {
|
||||
this.channels_scrolltop[this.channel.id] = this.thread.get_scrolltop();
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns {Boolean} true iff we currently are in the Inbox tab
|
||||
*/
|
||||
_isInInboxTab: function () {
|
||||
return _.contains(['channel_inbox', 'channel_starred'], this.currentState);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_renderButtons: function () {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
_.each(['dm', 'public', 'private'], function (type) {
|
||||
var selector = '.o_mail_chat_button_' + type;
|
||||
self.$buttons.on('click', selector, self._onAddChannel.bind(self));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Overrides to only store the channel state if we are in the Inbox tab, as
|
||||
* this is the only tab in which we actually have a displayed channel
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_restoreChannelState: function () {
|
||||
if (this._isInInboxTab()) {
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Overrides to toggle the visibility of the tabs when a message is selected
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_selectMessage: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.$('.o_mail_mobile_tabs').addClass('o_hidden');
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_setChannel: function (channel) {
|
||||
if (channel.type !== 'static') {
|
||||
chat_manager.detach_channel(channel);
|
||||
} else {
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Overrides to only store the channel state if we are in the Inbox tab, as
|
||||
* this is the only tab in which we actually have a displayed channel
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_storeChannelState: function () {
|
||||
if (this.channel && this._isInInboxTab()) {
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_toggleSearchView: function () {
|
||||
this.searchviewDisplayed = !this.searchviewDisplayed;
|
||||
this.searchview.$el.toggleClass('o_hidden', !this.searchviewDisplayed);
|
||||
this.$buttons.toggleClass('o_hidden', this.searchviewDisplayed);
|
||||
},
|
||||
/**
|
||||
* Overrides to toggle the visibility of the tabs when a message is unselected
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_unselectMessage: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.$('.o_mail_mobile_tabs').removeClass('o_hidden');
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_updateChannels: function () {
|
||||
return this._updateContent(this.currentState);
|
||||
},
|
||||
/**
|
||||
* Redraws the content of the client action according to its current state.
|
||||
*
|
||||
* @private
|
||||
* @param {string} type the channel's type to display (e.g. 'channel_inbox',
|
||||
* 'channel_starred', 'dm'...).
|
||||
*/
|
||||
_updateContent: function (type) {
|
||||
var self = this;
|
||||
var inInbox = type === 'channel_inbox' || type === 'channel_starred';
|
||||
if (!inInbox && this._isInInboxTab()) {
|
||||
// we're leaving the inbox, so store the thread scrolltop
|
||||
this._storeChannelState();
|
||||
}
|
||||
var previouslyInInbox = this._isInInboxTab();
|
||||
this.currentState = type;
|
||||
|
||||
// fetch content to display
|
||||
var def;
|
||||
if (inInbox) {
|
||||
def = this._fetchAndRenderThread();
|
||||
} else {
|
||||
var channels = _.where(chat_manager.get_channels(), {type: type});
|
||||
def = chat_manager.get_channels_preview(channels);
|
||||
}
|
||||
return $.when(def).then(function (channelsPreview) {
|
||||
// update content
|
||||
if (inInbox) {
|
||||
if (!previouslyInInbox) {
|
||||
self.$('.o_mail_chat_tab_pane').remove();
|
||||
self.$mainContent.append(self.thread.$el);
|
||||
self.$mainContent.append(self.extended_composer.$el);
|
||||
}
|
||||
self._restoreChannelState();
|
||||
} else {
|
||||
self.thread.$el.detach();
|
||||
self.extended_composer.$el.detach();
|
||||
var $content = $(QWeb.render("mail.chat.MobileTabPane", {
|
||||
channels: channelsPreview,
|
||||
get_message_body_preview: chat_manager.get_message_body_preview,
|
||||
moment: moment,
|
||||
partner_id: session.partner_id,
|
||||
type: type,
|
||||
widget: self,
|
||||
}));
|
||||
self._prepareAddChannelInput($content.find('.o_mail_add_channel input'), type);
|
||||
self.$mainContent.html($content);
|
||||
}
|
||||
|
||||
// update control panel
|
||||
self.$buttons.find('button').addClass('o_hidden');
|
||||
self.$buttons.find('.o_mail_chat_button_' + type).removeClass('o_hidden');
|
||||
self.$buttons.find('.o_mail_chat_button_mark_read').toggleClass('o_hidden', type !== 'channel_inbox');
|
||||
self.$buttons.find('.o_mail_chat_button_unstar_all').toggleClass('o_hidden', type !== 'channel_starred');
|
||||
self.$('.o_enable_searchview').toggleClass('o_hidden', !inInbox);
|
||||
if (!inInbox && self.searchviewDisplayed) {
|
||||
self._toggleSearchView(); // close the searchview when leaving Inbox
|
||||
}
|
||||
|
||||
// update Inbox page buttons
|
||||
if (inInbox) {
|
||||
self.$('.o_mail_chat_mobile_inbox_buttons').removeClass('o_hidden');
|
||||
self.$('.o_channel_inbox_item').removeClass('btn-primary').addClass('btn-default');
|
||||
self.$('.o_channel_inbox_item[data-type=' + type + ']').removeClass('btn-default').addClass('btn-primary');
|
||||
} else {
|
||||
self.$('.o_mail_chat_mobile_inbox_buttons').addClass('o_hidden');
|
||||
}
|
||||
|
||||
// update bottom buttons
|
||||
self.$('.o_mail_mobile_tab').removeClass('active');
|
||||
// channel_inbox and channel_starred share the same tab
|
||||
type = type === 'channel_starred' ? 'channel_inbox' : type;
|
||||
self.$('.o_mail_mobile_tab[data-type=' + type + ']').addClass('active');
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_updateControlPanel: function () {
|
||||
this.$buttons.appendTo(this.$('.o_mail_chat_mobile_control_panel'));
|
||||
this.searchview.$el.appendTo(this.$('.o_mail_chat_mobile_control_panel'));
|
||||
var $enable_searchview = $('<button/>', {type: 'button'})
|
||||
.addClass('o_enable_searchview btn fa fa-search')
|
||||
.on('click', this._toggleSearchView.bind(this));
|
||||
$enable_searchview.insertAfter(this.searchview.$el);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onAddChannel: function () {
|
||||
this.$('.o_mail_add_channel').show().find('input').focus();
|
||||
},
|
||||
/**
|
||||
* Switches to the clicked channel in the Inbox page (Inbox or Starred).
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent}
|
||||
*/
|
||||
_onMobileInboxButtonClicked: function (event) {
|
||||
this._setChannel(chat_manager.get_channel($(event.currentTarget).data('type')));
|
||||
this._updateContent(this.channel.id);
|
||||
},
|
||||
/**
|
||||
* Switches to another tab.
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent}
|
||||
*/
|
||||
_onMobileTabClicked: function (event) {
|
||||
var type = $(event.currentTarget).data('type');
|
||||
if (type === 'channel_inbox') {
|
||||
this._setChannel(chat_manager.get_channel('channel_inbox'));
|
||||
}
|
||||
this._updateContent(type);
|
||||
},
|
||||
/**
|
||||
* Opens a channel in a chat windown (full screen in mobile).
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent}
|
||||
*/
|
||||
_onMobileChannelClicked: function (event) {
|
||||
var channelId = $(event.currentTarget).data("channel_id");
|
||||
chat_manager.detach_channel(chat_manager.get_channel(channelId));
|
||||
},
|
||||
});
|
||||
|
||||
});
|
||||
@@ -5,8 +5,8 @@ var chat_mixin = require('mail.chat_mixin');
|
||||
var DocumentViewer = require('mail.DocumentViewer');
|
||||
var utils = require('mail.utils');
|
||||
|
||||
var core = require('web.core');
|
||||
var config = require('web.config');
|
||||
var core = require('web.core');
|
||||
var data = require('web.data');
|
||||
var dom = require('web.dom');
|
||||
var session = require('web.session');
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
odoo.define('mail.systray', function (require) {
|
||||
"use strict";
|
||||
|
||||
var config = require('web.config');
|
||||
var core = require('web.core');
|
||||
var framework = require('web.framework');
|
||||
var session = require('web.session');
|
||||
var SystrayMenu = require('web.SystrayMenu');
|
||||
var Widget = require('web.Widget');
|
||||
var config = require('web.config');
|
||||
|
||||
var chat_manager = require('mail.chat_manager');
|
||||
|
||||
@@ -28,9 +28,9 @@ var MessagingMenu = Widget.extend({
|
||||
"click .o_new_message": "on_click_new_message",
|
||||
"click .o_mail_channel_preview": "_onClickChannel",
|
||||
},
|
||||
init: function (parent) {
|
||||
this.isMobile = config.isMobile;
|
||||
this._super(parent);
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.isMobile = config.isMobile; // used by the template
|
||||
},
|
||||
start: function () {
|
||||
this.$filter_buttons = this.$('.o_filter_button');
|
||||
@@ -88,23 +88,6 @@ var MessagingMenu = Widget.extend({
|
||||
});
|
||||
},
|
||||
_render_channels_preview: function (channels_preview) {
|
||||
// Sort channels: 1. channels with unread messages, 2. chat, 3. by date of last msg
|
||||
channels_preview.sort(function (c1, c2) {
|
||||
return Math.min(1, c2.unread_counter) - Math.min(1, c1.unread_counter) ||
|
||||
c2.is_chat - c1.is_chat ||
|
||||
c2.last_message.date.diff(c1.last_message.date);
|
||||
});
|
||||
|
||||
// Generate last message preview (inline message body and compute date to display)
|
||||
_.each(channels_preview, function (channel) {
|
||||
channel.last_message_preview = chat_manager.get_message_body_preview(channel.last_message.body);
|
||||
if (channel.last_message.date.isSame(new Date(), 'd')) { // today
|
||||
channel.last_message_date = channel.last_message.date.format('LT');
|
||||
} else {
|
||||
channel.last_message_date = channel.last_message.date.format('lll');
|
||||
}
|
||||
});
|
||||
|
||||
this.$channels_preview.html(QWeb.render('mail.chat.ChannelsPreview', {
|
||||
channels: channels_preview,
|
||||
}));
|
||||
@@ -116,9 +99,9 @@ var MessagingMenu = Widget.extend({
|
||||
},
|
||||
on_click_filter_button: function (event) {
|
||||
event.stopPropagation();
|
||||
this.$filter_buttons.removeClass('o_selected');
|
||||
this.$filter_buttons.removeClass('active');
|
||||
var $target = $(event.currentTarget);
|
||||
$target.addClass('o_selected');
|
||||
$target.addClass('active');
|
||||
this.filter = $target.data('filter');
|
||||
this.update_channels_preview();
|
||||
},
|
||||
@@ -130,14 +113,14 @@ var MessagingMenu = Widget.extend({
|
||||
|
||||
/**
|
||||
* When a channel is clicked on, we want to open chat/channel window
|
||||
* If channel is inbox then redirect to that record view
|
||||
* If record not linked redirect to Inbox
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onClickChannel: function (event) {
|
||||
var self = this;
|
||||
var channelID = $(event.currentTarget).data('channel_id');
|
||||
if (channelID == 'channel_inbox') {
|
||||
if (channelID === 'channel_inbox') {
|
||||
var resID = $(event.currentTarget).data('res_id');
|
||||
var resModel = $(event.currentTarget).data('res_model');
|
||||
if (resModel && resID) {
|
||||
@@ -148,8 +131,11 @@ var MessagingMenu = Widget.extend({
|
||||
res_id: resID
|
||||
});
|
||||
} else {
|
||||
// if no model linked redirect to inbox
|
||||
framework.redirect('mail/view?message_id=channel_inbox');
|
||||
this.do_action('mail.mail_channel_action_client_chat', {clear_breadcrumbs: true})
|
||||
.then(function () {
|
||||
self.trigger_up('hide_app_switcher');
|
||||
core.bus.trigger('change_menu_section', chat_manager.get_discuss_menu_id());
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var channel = chat_manager.get_channel(channelID);
|
||||
|
||||
@@ -272,6 +272,7 @@ function render_hidden_sessions_dropdown () {
|
||||
sessions: display_state.hidden_sessions,
|
||||
open: display_state.windows_dropdown_is_open,
|
||||
unread_counter: display_state.hidden_unread_counter,
|
||||
widget: {isMobile: config.isMobile},
|
||||
}));
|
||||
return $dropdown;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@o-chat-window-width: 325px;
|
||||
@o-mail-chatter-gap: 10px; // has to be defined here as this file is both in
|
||||
// backend and other assets (livechat)
|
||||
@o-chat-header-height: 44px;
|
||||
@o-chat-header-height: 46px;
|
||||
|
||||
.o_chat_window {
|
||||
.o-flex-display();
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
height: @o-chat-header-height;
|
||||
padding-top: 10px;
|
||||
padding-top: 12px;
|
||||
border-radius: 0px;
|
||||
.o_chat_title {
|
||||
font-size: 16px;
|
||||
@@ -58,7 +58,6 @@
|
||||
|
||||
.o_chat_title {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
.o-flex(1, 1, auto);
|
||||
.o-text-overflow();
|
||||
}
|
||||
@@ -78,115 +77,22 @@
|
||||
.o_mail_thread {
|
||||
.o-flex(1, 1, auto);
|
||||
overflow: auto;
|
||||
border: 1px solid @odoo-color-silver-dark; // cannot use gray-lighter-dark as this file is also frontend
|
||||
border-width: 0 1px;
|
||||
font-weight: 400;
|
||||
|
||||
.o_thread_date_separator {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 25px;
|
||||
border-bottom: 1px dashed #cccccc;
|
||||
margin: 0px 0px 15px 0px;
|
||||
.o_thread_date {
|
||||
background-color: @o-chat-window-bg;
|
||||
}
|
||||
}
|
||||
.o_thread_message {
|
||||
padding: 4px 5px;
|
||||
.o_thread_message_sidebar {
|
||||
margin-right: 10px;
|
||||
|
||||
.o_thread_message_avatar {
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ebebeb;
|
||||
max-width: 40px;
|
||||
}
|
||||
}
|
||||
padding: 4px 5px 0px 10px;
|
||||
|
||||
.o_mail_info {
|
||||
|
||||
.o_thread_author, strong a.o_mail_mailto, strong a.o_mail_mailto:hover {
|
||||
font-weight: 500;
|
||||
color: #111;
|
||||
font-size: 11px;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
font-size: 13px;
|
||||
}
|
||||
margin-top: 5px;
|
||||
}
|
||||
.o_mail_timestamp {
|
||||
font-size: 11px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.o_thread_message_star {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.o_document_link {
|
||||
display: block;
|
||||
max-width: 90%;
|
||||
font-size: 12px;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
font-size: 14px;
|
||||
}
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
padding-bottom: 0px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.o_thread_message_content {
|
||||
font-size: 12px;
|
||||
padding-right: 10px;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
font-size: 14px;
|
||||
}
|
||||
color: #333;
|
||||
p {
|
||||
margin: 0px 0px 8px;
|
||||
}
|
||||
ul.o_mail_thread_message_tracking {
|
||||
padding-left: 20px;
|
||||
}
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_chat_composer {
|
||||
.o-flex(0, 0, auto);
|
||||
border-left: 1px solid #ebebeb;
|
||||
border-right: 1px solid #ebebeb;
|
||||
|
||||
.o_composer_buttons > button {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.o_composer_button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.o_composer_mobile_button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o_composer_mobile_button {
|
||||
display: inline-block;
|
||||
background-color: @odoo-brand-optional;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
> input {
|
||||
padding: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
.o_composer_input > textarea {
|
||||
border-color: transparent;
|
||||
}
|
||||
.o_chat_composer input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,277 +8,6 @@
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
height: auto;
|
||||
|
||||
.o_mail_chat_inbox_starred_button {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 40px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 10px;
|
||||
text-align: center;
|
||||
background: #ffffff;
|
||||
|
||||
.o_channel_inbox_item {
|
||||
width: 50%;
|
||||
border: 1px solid @odoo-brand-optional;
|
||||
|
||||
&:first-child {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_content {
|
||||
padding-top: 80px;
|
||||
padding-bottom: 55px;
|
||||
|
||||
.o_mail_no_content {
|
||||
padding-top: 30px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin: auto 0px;
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_mobile_tabs {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.o_mail_chat_tab_pane {
|
||||
display: none;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 55px;
|
||||
overflow-x: scroll;
|
||||
display: block;
|
||||
background: #ffffff;
|
||||
|
||||
.o_mail_mobile_add_channel {
|
||||
width: auto;
|
||||
padding: 5px 0px; // larger padding-left than titles
|
||||
position: relative;
|
||||
margin: 10px;
|
||||
display: none;
|
||||
border: 1px solid #afafaf;
|
||||
border-radius: 4px;
|
||||
|
||||
> input {
|
||||
width: 100%;
|
||||
padding: 5px 8px;
|
||||
padding-left: 20px;
|
||||
border: none;
|
||||
}
|
||||
> span {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_tab_pane_item {
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
overflow: hidden;
|
||||
max-height: 100px;
|
||||
position: relative;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.item_avatar_status {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 10px;
|
||||
width: 55px;
|
||||
vertical-align: top;
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
max-width: 55px;
|
||||
}
|
||||
|
||||
.o_mail_user_status {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
right: -8px;
|
||||
font-size: 13px;
|
||||
color: #cc0000;
|
||||
border-radius: 30px;
|
||||
background: #fff;
|
||||
padding: 2px;
|
||||
|
||||
&.o_user_online {
|
||||
color: #21b799;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat_user_detail {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
vertical-align: middle;
|
||||
padding-top: 5px;
|
||||
padding-left: 65px;
|
||||
|
||||
h2 {
|
||||
font-size: 17px;
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
color: #414141;
|
||||
|
||||
small {
|
||||
float: right;
|
||||
}
|
||||
|
||||
&.unread {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline-block;
|
||||
color: #b3b3b3;
|
||||
max-height: 27px;
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
line-height: 15px;
|
||||
|
||||
&.unread{
|
||||
font-weight: 700;
|
||||
color: #8f8f8f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_mobile_control_panel {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_mobile_control_panel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background: #ffffff;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
min-height: 44px;
|
||||
box-shadow: 0px 0px 20px #afafaf;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
height: auto;
|
||||
z-index: 1;
|
||||
|
||||
.o_mail_channel_title {
|
||||
padding: 5px 10px 5px 0px;
|
||||
color: #8f8f8f;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.o_searchview {
|
||||
color: #414141;
|
||||
background: none;
|
||||
border-color: transparent;
|
||||
padding: 5px 5px 0px 5px;
|
||||
|
||||
.o_searchview_input {
|
||||
width: 250px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_enable_searchview, .o_enable_searchview:focus,
|
||||
.o_enable_searchview:hover, .o_enable_searchview:active {
|
||||
color: #414141;
|
||||
background: none;
|
||||
border-color: transparent;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
|
||||
&::before {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
.o_searchview_more {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_mobile_tabs {
|
||||
display: none;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 20px #afafaf;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
|
||||
.o_mail_chat_mobile_tab {
|
||||
display: inline-block;
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
padding: 8px 4px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
|
||||
&:first-child:nth-last-child(4),
|
||||
&:first-child:nth-last-child(4) ~ .o_mail_chat_mobile_tab {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&:first-child:nth-last-child(5),
|
||||
&:first-child:nth-last-child(5) ~ .o_mail_chat_mobile_tab {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: 1px solid #d7d7d7;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
&.fa {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.o_tab_title{
|
||||
font-size: 8px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
span {
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_tab_pane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.o_mail_annoying_notification_bar {
|
||||
height: 40px;
|
||||
background-color: #DFA941;
|
||||
@@ -315,12 +44,6 @@
|
||||
overflow: auto;
|
||||
padding: @odoo-horizontal-padding 0;
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
width: 100%;
|
||||
float: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: @screen-lg-min) {
|
||||
width: @mail-chat-sidebar-width + 50px;
|
||||
}
|
||||
@@ -398,12 +121,6 @@
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
margin-left: 0;
|
||||
display: block;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
@media (min-width: @screen-lg-min) {
|
||||
margin-left: @mail-chat-sidebar-width + 50px;
|
||||
}
|
||||
@@ -538,9 +255,221 @@
|
||||
font-size: 1em;
|
||||
position: relative;
|
||||
&.o_user_online {
|
||||
color: @brand-success;
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
&.o_user_idle {
|
||||
color: @brand-warning;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Mobile
|
||||
// ------------------------------------------------------------------
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o_mail_chat {
|
||||
.o-flex-display();
|
||||
.o-flex-flow(column, nowrap);
|
||||
background: white;
|
||||
|
||||
.o_mail_chat_mobile_control_panel {
|
||||
.o-flex(0, 0, auto);
|
||||
padding: 5px;
|
||||
min-height: 44px;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
box-shadow: 0px 0px 10px #afafaf;
|
||||
z-index: 1; // so that box shaddow is above thread's images
|
||||
.o_searchview {
|
||||
border: none;
|
||||
padding: 5px 5px 0px 5px;
|
||||
.o_searchview_input {
|
||||
font-size: 15px;
|
||||
}
|
||||
.o_searchview_more {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.o_enable_searchview, .o_enable_searchview:focus,
|
||||
.o_enable_searchview:hover, .o_enable_searchview:active {
|
||||
.o-position-absolute(@right: 5px, @top: 5px);
|
||||
color: gray;
|
||||
background: none;
|
||||
font-size: 15px;
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_mobile_inbox_buttons {
|
||||
.o-flex(0, 0, auto);
|
||||
padding: 15px 15px 10px 15px;
|
||||
.o_channel_inbox_item {
|
||||
width: 50%;
|
||||
border: 1px solid @odoo-brand-optional;
|
||||
&:first-child {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_content {
|
||||
.o-flex(1, 0, 0);
|
||||
margin-left: 0;
|
||||
background-color: transparent;
|
||||
.o_mail_no_content {
|
||||
.o-position-absolute(@top: 30%);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.o_mail_chat_tab_pane {
|
||||
overflow-x: scroll;
|
||||
.o_mail_add_channel {
|
||||
display: none;
|
||||
position: relative;
|
||||
padding: 5px 0px;
|
||||
margin: 10px;
|
||||
border: 1px solid #afafaf;
|
||||
border-radius: 4px;
|
||||
> span {
|
||||
.o-position-absolute(@top: 10px, @left: 10px);
|
||||
}
|
||||
> input {
|
||||
border: none;
|
||||
padding: 5px 8px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_mail_mobile_tabs {
|
||||
.o-flex(0, 0, auto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Channel preview: shared between client action (mobile) and systray
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
.o_mail_channel_preview {
|
||||
.o-flex-display();
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
.o_mail_channel_image {
|
||||
.o-flex(0, 0, auto);
|
||||
position: relative;
|
||||
text-align: center;
|
||||
> img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.o_mail_user_status {
|
||||
.o-position-absolute(@bottom: 0px, @right: 0px);
|
||||
}
|
||||
}
|
||||
.o_channel_info {
|
||||
.o-flex(1, 1, 100%);
|
||||
overflow: hidden;
|
||||
.o_channel_title {
|
||||
.o-flex-display();
|
||||
.o_channel_name {
|
||||
.o-flex(0, 1, auto);
|
||||
.o-text-overflow();
|
||||
}
|
||||
.o_channel_counter {
|
||||
.o-flex(1, 1, auto);
|
||||
}
|
||||
.o_channel_name, .o_channel_counter {
|
||||
color: @odoo-main-text-color;
|
||||
}
|
||||
.o_last_message_date {
|
||||
.o-flex(0, 0, auto);
|
||||
color: @odoo-main-color-muted;
|
||||
}
|
||||
}
|
||||
.o_last_message_preview {
|
||||
width: 100%;
|
||||
max-height: 20px;
|
||||
color: @odoo-main-color-muted;
|
||||
.o-text-overflow();
|
||||
}
|
||||
}
|
||||
&.o_channel_unread {
|
||||
background-color: #f5f5f5;
|
||||
.o_channel_info {
|
||||
.o_channel_title {
|
||||
.o_channel_name, .o_channel_counter {
|
||||
font-weight: 700;
|
||||
}
|
||||
.o_last_message_date {
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o_mail_channel_preview {
|
||||
height: 85px;
|
||||
padding: 15px;
|
||||
.o_channel_info {
|
||||
margin-left: 15px;
|
||||
padding-top: 5px;
|
||||
.o_channel_title {
|
||||
.o_channel_name, .o_channel_counter {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.o_last_message_date {
|
||||
padding-top: 2px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.o_channel_unread {
|
||||
.o_channel_info .o_last_message_preview {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_mail_channel_image {
|
||||
width: 55px;
|
||||
> img {
|
||||
max-height: 55px;
|
||||
}
|
||||
}
|
||||
.o_mail_mobile_tabs {
|
||||
.o-flex-display();
|
||||
.o-flex-flow(row, nowrap);
|
||||
border-top: 1px solid #ebebeb;
|
||||
box-shadow: 0px 0px 10px #afafaf;
|
||||
z-index: 1; // so that box shaddow is above thread's images
|
||||
.o_mail_mobile_tab {
|
||||
.o-flex(1, 1, 0);
|
||||
padding: 8px 4px;
|
||||
text-align: center;
|
||||
&:not(:last-child) {
|
||||
border-right: 1px solid #d7d7d7;
|
||||
}
|
||||
> span {
|
||||
display: block;
|
||||
&.fa {
|
||||
font-size: 16px;
|
||||
}
|
||||
&.o_tab_title{
|
||||
font-size: 8px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
&.active > span {
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,11 @@
|
||||
.o_composer_button_full_composer {
|
||||
.o-position-absolute(0, 0);
|
||||
}
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o_composer_button_send {
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Both inline and not-inline design. Mini-composer disabled.
|
||||
|
||||
@@ -26,53 +26,35 @@
|
||||
}
|
||||
|
||||
.o_chat_composer {
|
||||
background: #fff;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
position: relative;
|
||||
.o_composer {
|
||||
.o_composer_input {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
width: 70%;
|
||||
textarea {
|
||||
display: block;
|
||||
width: 80%;
|
||||
> textarea {
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
}
|
||||
@media (max-width: @screen-xs-max) {
|
||||
width: 70%;
|
||||
> textarea {
|
||||
padding: 15px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_chatter_composer_tools {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
|
||||
.o-position-absolute(@right: 0px, @top: 0px);
|
||||
button {
|
||||
padding: 10px;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
padding: 13px;
|
||||
}
|
||||
&.btn-icon{
|
||||
&.btn-icon {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_composer_tabs_toggle_button {
|
||||
display: none;
|
||||
}
|
||||
.o_composer_attachments_list {
|
||||
margin: 0px;
|
||||
}
|
||||
.o_composer_attachments_list, .o_composer_buttons {
|
||||
.o_composer_button_emoji, .o_composer_button_add_attachment {
|
||||
&:hover, &:focus {
|
||||
background-color: #FFFFFF !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,11 @@
|
||||
.o-flex-flow(column, nowrap);
|
||||
}
|
||||
.o_notification_counter {
|
||||
.o-position-absolute(@top: 20%, @right: 1px);
|
||||
background: @odoo-brand-optional;
|
||||
color: white;
|
||||
padding: 0em 0.5em;
|
||||
padding: 0em 0.3em;
|
||||
font-size: 0.7em;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
position: absolute;
|
||||
margin: 0px;
|
||||
}
|
||||
.o_mail_navbar_dropdown {
|
||||
width: 350px;
|
||||
@@ -46,19 +43,16 @@
|
||||
.o-flex(0, 0, auto);
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid lightgray;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
padding: 5px;
|
||||
}
|
||||
.o_filter_button, .o_new_message {
|
||||
.btn-link;
|
||||
padding: 5px;
|
||||
}
|
||||
.o_filter_button {
|
||||
color: @odoo-main-color-muted;
|
||||
&:hover, &.o_selected {
|
||||
&:hover, &.active {
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
&.o_selected {
|
||||
&.active {
|
||||
cursor: default;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -71,71 +65,28 @@
|
||||
min-height: 50px;
|
||||
overflow-y: auto;
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.o_mail_channel_preview {
|
||||
.o-flex-display();
|
||||
height: 50px;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
padding: 10px;
|
||||
height: 85px;
|
||||
}
|
||||
&~.o_mail_channel_preview {
|
||||
border-top: 1px solid lightgray;
|
||||
}
|
||||
&.o_channel_unread {
|
||||
background-color: lighten(lightgray, 10%);
|
||||
}
|
||||
&:hover {
|
||||
background-color: lighten(lightgray, 5%);
|
||||
}
|
||||
|
||||
.o_channel_image {
|
||||
.o-flex(0, 0, 36px);
|
||||
max-height: 36px;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o-flex(0, 0, 50px);
|
||||
border-radius: 3px;
|
||||
margin-right: 10px;
|
||||
max-height: 50px;
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.o_mail_channel_preview {
|
||||
height: 50px;
|
||||
padding: 5px;
|
||||
.o_mail_channel_image {
|
||||
width: 40px;
|
||||
> img {
|
||||
max-height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_channel_info {
|
||||
.o-flex(1, 1, 100%);
|
||||
margin-left: 5px;
|
||||
overflow: hidden;
|
||||
|
||||
.o_channel_title {
|
||||
.o-flex-display();
|
||||
.o_channel_name {
|
||||
.o-flex(1, 1, auto);
|
||||
.o-text-overflow();
|
||||
color: @odoo-main-text-color;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
font-size: 1.4em;
|
||||
color: #000;
|
||||
font-weight: 300;
|
||||
.o_channel_info {
|
||||
margin-left: 10px;
|
||||
.o_channel_title {
|
||||
.o_channel_name, .o_channel_counter {
|
||||
color: #666666;
|
||||
}
|
||||
.o_last_message_date {
|
||||
padding-top: 2px;
|
||||
font-size: x-small;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.o_last_message_date {
|
||||
.o-flex(0, 0, auto);
|
||||
padding-top: 3px;
|
||||
font-size: xx-small;
|
||||
color: @odoo-main-color-muted;
|
||||
}
|
||||
}
|
||||
.o_last_message_preview {
|
||||
width: 100%;
|
||||
max-height: 20px;
|
||||
color: @odoo-main-color-muted;
|
||||
.o-text-overflow();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,78 +102,6 @@
|
||||
opacity: 0.5;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
&.o_mail_navbar_mobile {
|
||||
position: relative;
|
||||
|
||||
.o_mail_navbar_mobile_header {
|
||||
padding: 5px 5px 5px 0px;
|
||||
min-height: 44px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.o_mail_navbar_dropdown_channels {
|
||||
padding-bottom: 55px;
|
||||
}
|
||||
|
||||
.o_mail_navbar_mobile_tabs {
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 20px #afafaf;
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
|
||||
.o_mail_navbar_mobile_tab {
|
||||
display: inline-block;
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
padding: 8px 4px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
font-size: 1.2em;
|
||||
color: #666666;
|
||||
|
||||
&:first-child:nth-last-child(3),
|
||||
&:first-child:nth-last-child(3) ~ .o_mail_navbar_mobile_tab {
|
||||
width: 33.33%;
|
||||
}
|
||||
|
||||
&:first-child:nth-last-child(4),
|
||||
&:first-child:nth-last-child(4) ~ .o_mail_navbar_mobile_tab {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&:first-child:nth-last-child(5),
|
||||
&:first-child:nth-last-child(5) ~ .o_mail_navbar_mobile_tab {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: 1px solid #d7d7d7;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
&.fa {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.o_tab_title{
|
||||
font-size: 11px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
&.o_selected {
|
||||
span {
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +109,35 @@
|
||||
display: none; // hide 'new message' button if chat windows are disabled
|
||||
}
|
||||
|
||||
// Fix for enterprise nav bar
|
||||
.o_main_navbar .o_menu_systray .o_notification_counter {
|
||||
top: 5px;
|
||||
// Mobile rules
|
||||
// Goal: mock the design of Discuss in mobile
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.o_mail_navbar_item {
|
||||
.o_notification_counter {
|
||||
top: 10%;
|
||||
}
|
||||
.o_mail_navbar_dropdown {
|
||||
position: relative;
|
||||
.o_mail_navbar_dropdown_top {
|
||||
padding: 5px;
|
||||
}
|
||||
.o_mail_navbar_mobile_header {
|
||||
padding: 5px;
|
||||
height: 44px;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
}
|
||||
.o_mail_navbar_dropdown_channels {
|
||||
max-height: none;
|
||||
padding-bottom: 52px; // leave space for tabs
|
||||
}
|
||||
.o_mail_mobile_tabs {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
background-color: white;
|
||||
color: @odoo-main-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
.o_thread_date_separator {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 30px;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
border-bottom: 1px solid @odoo-color-silver-darker; // cannot use gray-lighter-darker as this file is also frontend
|
||||
text-align: center;
|
||||
|
||||
@@ -69,14 +73,12 @@
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.o_thread_icons {
|
||||
.o_thread_icon {
|
||||
cursor: pointer;
|
||||
> .o_thread_icon {
|
||||
opacity: 0;
|
||||
&.fa-star {
|
||||
opacity: @mail-thread-icon-opacity;
|
||||
color: gold;
|
||||
}
|
||||
opacity: 0;
|
||||
&.fa-star {
|
||||
opacity: @mail-thread-icon-opacity;
|
||||
color: gold;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +86,7 @@
|
||||
.o_thread_message_side_date {
|
||||
opacity: @mail-thread-side-date-opacity;
|
||||
}
|
||||
.o_thread_icons > * {
|
||||
.o_thread_icon {
|
||||
opacity: @mail-thread-icon-opacity;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
@@ -96,69 +98,6 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.o_message_attachments {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
|
||||
.o_attachment {
|
||||
width: initial;
|
||||
height: initial;
|
||||
|
||||
.o_image {
|
||||
position: initial;
|
||||
top: initial;
|
||||
left: initial;
|
||||
bottom: initial;
|
||||
right: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.o_message_attachment {
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
margin: 5px 5px 5px 5px;
|
||||
position: relative;
|
||||
background-color: #cccccc;
|
||||
|
||||
.download_icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
span {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
position: absolute;
|
||||
top: 37%;
|
||||
left: 37%;
|
||||
padding: 5px;
|
||||
border-radius: 30px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
a.o_image {
|
||||
width: 80px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 60px;
|
||||
width: 80px;
|
||||
opacity: 0.5;
|
||||
|
||||
&.o_image_view {
|
||||
cursor: pointer;
|
||||
background-color: #000;
|
||||
object-fit: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_thread_message_core {
|
||||
.o-flex(1, 1, auto);
|
||||
min-width: 0;
|
||||
@@ -270,9 +209,7 @@
|
||||
}
|
||||
|
||||
.o_web_client.o_touch_device {
|
||||
.o_thread_icons {
|
||||
> .o_thread_icon {
|
||||
opacity: @mail-thread-icon-opacity;
|
||||
}
|
||||
.o_mail_thread .o_thread_icon {
|
||||
opacity: @mail-thread-icon-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</t>
|
||||
|
||||
<t t-name="mail.ChatWindowHeaderContent">
|
||||
<span t-if="isMobile">
|
||||
<span t-if="widget.isMobile">
|
||||
<a href="#" class="o_chat_window_close fa fa-1x fa-arrow-left mr4"/>
|
||||
</span>
|
||||
<span class="o_chat_title">
|
||||
@@ -49,7 +49,7 @@
|
||||
<t t-esc="title"/>
|
||||
<span t-if="unread_counter"> (<t t-esc="unread_counter"/>)</span>
|
||||
</span>
|
||||
<span t-if="!isMobile" class="o_chat_window_buttons">
|
||||
<span t-if="!widget.isMobile" class="o_chat_window_buttons">
|
||||
<a href="#" class="o_chat_window_close fa fa-close"/>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="o_mail_chat">
|
||||
<div class="o_mail_chat_sidebar"/>
|
||||
<div class="o_mail_chat_content">
|
||||
<t t-if="widget.notification_bar && !widget.isMobile">
|
||||
<t t-if="widget.notification_bar">
|
||||
<div class="o_mail_annoying_notification_bar">
|
||||
<span class="o_mail_request_permission">Odoo needs your permission to <a href="#"> enable desktop notifications</a>.</span>
|
||||
<span class="fa fa-close"></span>
|
||||
@@ -17,13 +17,13 @@
|
||||
</t>
|
||||
<t t-name="mail.chat.Sidebar">
|
||||
<div class="o_mail_chat_sidebar">
|
||||
<div t-attf-class="o_mail_chat_title_main o_mail_chat_channel_item #{(active_channel_id == 'channel_inbox') ? 'o_active': ''}"
|
||||
<div t-attf-class="o_mail_chat_title_main o_mail_chat_channel_item #{(active_channel_id === 'channel_inbox') ? 'o_active': ''}"
|
||||
data-channel-id="channel_inbox">
|
||||
<span class="o_channel_name"><i class="fa fa-inbox mr8"/>Inbox</span>
|
||||
<t t-set="counter" t-value="needaction_counter"/>
|
||||
<t t-call="mail.chat.SidebarNeedaction"/>
|
||||
</div>
|
||||
<div t-attf-class="o_mail_chat_title_main o_mail_chat_title_starred o_mail_chat_channel_item #{(active_channel_id == 'channel_starred') ? 'o_active': ''}"
|
||||
<div t-attf-class="o_mail_chat_title_main o_mail_chat_title_starred o_mail_chat_channel_item #{(active_channel_id === 'channel_starred') ? 'o_active': ''}"
|
||||
data-channel-id="channel_starred">
|
||||
<span class="o_channel_name"><i class="fa fa-star-o mr8"/>Starred</span>
|
||||
<t t-set="counter" t-value="starred_counter"/>
|
||||
@@ -129,13 +129,13 @@
|
||||
|
||||
<!-- Buttons of the Control Panel -->
|
||||
<t t-name="mail.chat.ControlButtons">
|
||||
<div class="o_mail_chat_buttons">
|
||||
<button type="button" class="btn btn-primary btn-sm o_mail_chat_button_invite" title="Invite people">Invite</button>
|
||||
<div>
|
||||
<button type="button" class="btn btn-primary btn-sm o_mail_chat_button_invite hidden-xs" title="Invite people">Invite</button>
|
||||
<button type="button" class="btn btn-default btn-sm o_mail_chat_button_mark_read" title="Mark all as read">Mark all read</button>
|
||||
<button type="button" class="btn btn-default btn-sm o_mail_chat_button_unstar_all" title="Unstar all messages">Unstar all</button>
|
||||
<button type="button" class="btn btn-default btn-sm o_mail_chat_button_unsubscribe" title="Unsubscribe from channel">Unsubscribe</button>
|
||||
<button type="button" class="btn btn-default btn-sm o_mail_chat_button_dm o_hidden visible-xs" title="New Message">New Message</button>
|
||||
<button t-if="!disable_add_channel" type="button" class="btn btn-default btn-sm o_mail_chat_button_public o_mail_chat_button_private o_hidden visible-xs" title="New Channel">New Channel</button>
|
||||
<button type="button" class="btn btn-default btn-sm o_mail_chat_button_unsubscribe hidden-xs" title="Unsubscribe from channel">Unsubscribe</button>
|
||||
<button type="button" class="btn btn-default btn-sm o_mail_chat_button_dm visible-xs" title="New Message">New Message</button>
|
||||
<button t-if="!disable_add_channel" type="button" class="btn btn-default btn-sm o_mail_chat_button_public o_mail_chat_button_private visible-xs" title="New Channel">New Channel</button>
|
||||
<button t-if="debug" type="button" class="btn btn-default btn-sm o_mail_chat_button_settings" title="Open channel settings">Settings</button>
|
||||
</div>
|
||||
</t>
|
||||
@@ -145,86 +145,84 @@
|
||||
<input type="text" class="o_input o_mail_chat_partner_invite_input" id="mail_search_partners"/>
|
||||
</div>
|
||||
|
||||
<t t-name="mail.chat.MobileInboxStarredButtons">
|
||||
<div class="o_mail_chat_inbox_starred_button">
|
||||
<button type="button" class="btn btn-primary btn-sm visible-xs-inline o_channel_inbox_item" title="Inbox" data-type="channel_inbox">Inbox</button><button type="button" class="btn btn-default btn-sm visible-xs-inline o_channel_inbox_item" title="Starred" data-type="channel_starred">Starred</button>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.chat.MobileControlPanel">
|
||||
<div class="o_mail_chat_mobile_control_panel"/>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.chat.MobileTabs">
|
||||
<div class="o_mail_chat_mobile_tabs">
|
||||
<div class="o_mail_chat_mobile_tab" data-channel-id="channel_inbox" data-type="channel_inbox">
|
||||
<span class="fa fa-envelope"/>
|
||||
<span class="o_tab_title">Inbox</span>
|
||||
<!-- Mobile templates -->
|
||||
<t t-name="mail.client_action_mobile">
|
||||
<div class="o_mail_chat">
|
||||
<div class="o_mail_chat_mobile_control_panel"/>
|
||||
<div class="o_mail_chat_mobile_inbox_buttons">
|
||||
<button type="button" class="btn btn-primary btn-sm visible-xs-inline o_channel_inbox_item" title="Inbox" data-type="channel_inbox">
|
||||
Inbox
|
||||
</button><button type="button" class="btn btn-default btn-sm visible-xs-inline o_channel_inbox_item" title="Starred" data-type="channel_starred">
|
||||
Starred
|
||||
</button>
|
||||
</div>
|
||||
<div class="o_mail_chat_mobile_tab" data-type="dm">
|
||||
<span class="fa fa-comments"/>
|
||||
<span class="o_tab_title">Chat</span>
|
||||
</div>
|
||||
<div class="o_mail_chat_mobile_tab" data-type="public">
|
||||
<span class="fa fa-users"/>
|
||||
<span class="o_tab_title">Channels</span>
|
||||
</div>
|
||||
<div class="o_mail_chat_mobile_tab" data-type="private">
|
||||
<span class="fa fa-lock"/>
|
||||
<span class="o_tab_title">Private&nbsp;Channels</span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.chat.MobileTabPanes">
|
||||
<t t-foreach="channels" t-as="item">
|
||||
<div class="o_mail_chat_tab_pane" t-att-data-type="item.type">
|
||||
<div t-if="!disable_add_channel" class="o_mail_add_channel o_mail_mobile_add_channel" t-att-data-type="type">
|
||||
<span t-if="type == 'private' || type == 'public'">#</span>
|
||||
<t t-set="input_placeholder" t-if="type == 'private' || 'public'">Add a channel</t>
|
||||
<t t-set="input_placeholder" t-if="type == 'dm'">Open chat</t>
|
||||
<input type="text" t-attf-placeholder="#{input_placeholder}"/>
|
||||
<div class="o_mail_chat_content"/>
|
||||
<div class="o_mail_mobile_tabs">
|
||||
<div class="o_mail_mobile_tab" data-type="channel_inbox">
|
||||
<span class="fa fa-inbox"/>
|
||||
<span class="o_tab_title">Inbox</span>
|
||||
</div>
|
||||
<div class="o_mail_mobile_tab" data-type="dm">
|
||||
<span class="fa fa-user"/>
|
||||
<span class="o_tab_title">Chat</span>
|
||||
</div>
|
||||
<div class="o_mail_mobile_tab" data-type="public">
|
||||
<span class="fa fa-users"/>
|
||||
<span class="o_tab_title">Channels</span>
|
||||
</div>
|
||||
<div class="o_mail_mobile_tab" data-type="private">
|
||||
<span class="fa fa-eye-slash"/>
|
||||
<span class="o_tab_title">Private Channels</span>
|
||||
</div>
|
||||
<t t-foreach="item.channels" t-as="channel">
|
||||
<t t-call="mail.chat.MobileTabPaneItems">
|
||||
<t t-set="type" t-value="item.type"/>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.chat.MobileTabPaneItems">
|
||||
<div class="o_mail_tab_pane_item" t-att-data-channel-id="channel.id">
|
||||
<div class="item_avatar_status">
|
||||
<img t-if="type == 'dm'" t-att-src="'/web/image/res.partner/'+ channel.direct_partner_id+'/image_small'"/>
|
||||
<img t-if="type != 'dm'" t-att-src="'/web/image/mail.channel/'+ channel.id+'/image_small'"/>
|
||||
<i t-if="channel.status == 'online'" class="o_mail_user_status o_user_online fa fa-circle" title="Online"/>
|
||||
<i t-if="channel.status == 'away'" class="o_mail_user_status o_user_idle fa fa-circle" title="Idle"/>
|
||||
<i t-if="channel.status == 'offline'" class="o_mail_user_status fa fa-circle" title="Offline"/>
|
||||
</div>
|
||||
<t t-set="is_author" t-value="channel.last_message && channel.last_message.author_id[0] == partner_id"/>
|
||||
<t t-set="is_unread" t-value="channel.last_message && channel.last_seen_message_id < channel.last_message.id && !is_author"/>
|
||||
<div class="chat_user_detail">
|
||||
<h2 t-attf-class="#{is_unread ? 'unread' : ''}"><t t-esc="channel.name"/><small class="o_message_timestamp" t-attf-title="#{channel.last_message ? channel.last_message.date : ''}"><t t-if="channel.last_message" t-esc="moment(channel.last_message.date).fromNow()"/></small></h2>
|
||||
<p t-attf-class="#{is_unread ? 'unread' : ''}">
|
||||
<t t-if="channel.last_message">
|
||||
<span t-if="is_author" class="fa fa-mail-reply"/>
|
||||
<t t-if="channel.last_message" t-raw="get_message_body_preview(channel.last_message.body)"/>
|
||||
<t t-if="channel.last_message.body == ''">
|
||||
<t t-if="channel.last_message.attachment_ids.length != 0">
|
||||
<t t-esc="channel.last_message.attachment_ids.length"/> attachment(s)
|
||||
</t>
|
||||
<t t-if="channel.last_message.tracking_value_ids and channel.last_message.tracking_value_ids.length > 0">
|
||||
<t t-if="channel.last_message.subtype_description">
|
||||
<strong><t t-esc="channel.last_message.record_name"/></strong>
|
||||
: <t t-esc="channel.last_message.subtype_description"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.chat.MobileTabPane">
|
||||
<div class="o_mail_chat_tab_pane" t-att-data-type="type">
|
||||
<div t-if="!disable_add_channel" class="o_mail_add_channel" t-att-data-type="type">
|
||||
<span t-if="type == 'private' || type == 'public'">#</span>
|
||||
<t t-set="input_placeholder" t-if="type == 'private' || type == 'public'">Add a channel</t>
|
||||
<t t-set="input_placeholder" t-if="type == 'dm'">Open chat</t>
|
||||
<input type="text" t-attf-placeholder="#{input_placeholder}"/>
|
||||
</div>
|
||||
<t t-foreach="channels" t-as="channel">
|
||||
<t t-call="mail.chat.ChannelPreview"/>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- The ChannelPreview template is used by the client action in mobile, and by the systray menu -->
|
||||
<t t-name="mail.chat.ChannelPreview">
|
||||
<div t-attf-class="o_mail_channel_preview #{channel.unread_counter ? 'o_channel_unread' : ''}"
|
||||
t-att-data-channel_id="channel.id" t-att-data-res_id="channel.res_id" t-att-data-res_model="channel.model">
|
||||
<div class="o_mail_channel_image">
|
||||
<img class="o_mail_channel_image" t-att-src="channel.image_src"/>
|
||||
<i t-if="channel.status === 'online'" class="o_mail_user_status o_user_online fa fa-circle" title="Online"/>
|
||||
<i t-if="channel.status === 'away'" class="o_mail_user_status o_user_idle fa fa-circle" title="Idle"/>
|
||||
</div>
|
||||
<div class="o_channel_info">
|
||||
<div class="o_channel_title">
|
||||
<span class="o_channel_name">
|
||||
<t t-esc="channel.name"/>
|
||||
</span>
|
||||
<span class="o_channel_counter">
|
||||
<t t-if="channel.unread_counter">&nbsp;(<t t-esc="channel.unread_counter"/>)</t>
|
||||
</span>
|
||||
<span class="o_last_message_date"> <t t-esc="channel.last_message_date"/> </span>
|
||||
</div>
|
||||
<div t-if="channel.last_message" class="o_last_message_preview">
|
||||
<t t-if="channel.last_message.is_author">
|
||||
<span class="fa fa-mail-reply"/> You:
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-esc="channel.last_message.displayed_author"/>:
|
||||
</t>
|
||||
<t t-raw="channel.last_message_preview"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
<div class="o_chatter_composer_tools">
|
||||
<button tabindex="4" class="btn btn-sm btn-icon fa fa-smile-o o_composer_button_emoji" type="button" data-toggle="popover"/>
|
||||
<button tabindex="5" class="btn btn-sm btn-icon fa fa-paperclip o_composer_button_add_attachment" type="button"/>
|
||||
<button t-if="widget.options.isMobile" tabindex="3" class="btn btn-sm btn-icon fa fa-paper-plane-o o_composer_button_send o_composer_mobile_button" type="button"/>
|
||||
<button t-if="widget.options.isMobile" tabindex="3" class="btn btn-sm btn-icon fa fa-paper-plane-o o_composer_button_send" type="button"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_composer_attachments_list"/>
|
||||
</div>
|
||||
<div class="o_composer_send">
|
||||
<button tabindex="3" class="btn btn-sm btn-primary o_composer_button_send" type="button"><t t-esc="widget.options.send_text"/></button>
|
||||
<button tabindex="3" class="btn btn-sm btn-primary o_composer_button_send hidden-xs" type="button"><t t-esc="widget.options.send_text"/></button>
|
||||
</div>
|
||||
<span class="hide">
|
||||
<t t-call="HiddenInputFile">
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
</t>
|
||||
|
||||
<t t-extend="mail.ChatWindowHeaderContent">
|
||||
<t t-jquery=".o_chat_window_close" t-operation="before">
|
||||
<a t-if="!isMobile" href="#" class="o_chat_window_expand fa fa-expand" title="
|
||||
Open in Discuss"/>
|
||||
<t t-jquery=".o_chat_window_buttons" t-operation="prepend">
|
||||
<a href="#" class="o_chat_window_expand fa fa-expand" title="Open in Discuss"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" title="Conversations" href="#">
|
||||
<i class="fa fa-comments"/> <span class="o_notification_counter badge"/>
|
||||
</a>
|
||||
<ul t-att-class="'o_mail_navbar_dropdown dropdown-menu ' + (widget.isMobile ? 'o_mail_navbar_mobile' : '')" role="menu">
|
||||
<ul class="o_mail_navbar_dropdown dropdown-menu" role="menu">
|
||||
<li t-if="widget.isMobile">
|
||||
<div class="o_mail_navbar_mobile_header">
|
||||
<button type="button" class="btn btn-default btn-sm o_new_message"> New message </button>
|
||||
@@ -14,7 +14,7 @@
|
||||
</li>
|
||||
<li t-if="!widget.isMobile" class="o_mail_navbar_dropdown_top">
|
||||
<div>
|
||||
<button type="button" class="btn btn-sm o_filter_button o_selected"> All </button>
|
||||
<button type="button" class="btn btn-sm o_filter_button active"> All </button>
|
||||
<button type="button" class="btn btn-sm o_filter_button" data-filter='chat'> Chat </button>
|
||||
<button type="button" class="btn btn-sm o_filter_button" data-filter='channels'> Channels </button>
|
||||
</div>
|
||||
@@ -22,16 +22,16 @@
|
||||
</li>
|
||||
<li class="o_mail_navbar_dropdown_channels"/>
|
||||
<li t-if="widget.isMobile">
|
||||
<div class="o_mail_navbar_mobile_tabs">
|
||||
<div class="o_mail_navbar_mobile_tab o_filter_button o_selected">
|
||||
<div class="o_mail_mobile_tabs">
|
||||
<div class="o_mail_mobile_tab o_filter_button active">
|
||||
<span class="fa fa-envelope"/>
|
||||
<span class="o_tab_title">All</span>
|
||||
</div>
|
||||
<div class="o_mail_navbar_mobile_tab o_filter_button" data-filter='chat'>
|
||||
<span class="fa fa-comments"/>
|
||||
<div class="o_mail_mobile_tab o_filter_button" data-filter='chat'>
|
||||
<span class="fa fa-user"/>
|
||||
<span class="o_tab_title">Chat</span>
|
||||
</div>
|
||||
<div class="o_mail_navbar_mobile_tab o_filter_button" data-filter='channels'>
|
||||
<div class="o_mail_mobile_tab o_filter_button" data-filter='channels'>
|
||||
<span class="fa fa-users"/>
|
||||
<span class="o_tab_title">Channels</span>
|
||||
</div>
|
||||
@@ -48,26 +48,7 @@
|
||||
</li>
|
||||
</t>
|
||||
<t t-foreach="channels" t-as="channel">
|
||||
<div t-attf-class="o_mail_channel_preview #{channel.unread_counter ? 'o_channel_unread' : ''}"
|
||||
t-att-data-channel_id="channel.id" t-att-data-res_id="channel.res_id" t-att-data-res_model="channel.model">
|
||||
<img class="o_channel_image" t-att-src="channel.image_src"/>
|
||||
<div class="o_channel_info">
|
||||
<div class="o_channel_title">
|
||||
<span class="o_channel_name">
|
||||
<t t-if="channel.status" t-call="mail.chat.UserStatus">
|
||||
<t t-set="status" t-value="channel.status"/>
|
||||
</t>
|
||||
<t t-esc="channel.name"/>
|
||||
<t t-if="channel.unread_counter">(<t t-esc="channel.unread_counter"/>)</t>
|
||||
</span>
|
||||
<span class="o_last_message_date"> <t t-esc="channel.last_message_date"/> </span>
|
||||
</div>
|
||||
<div class="o_last_message_preview">
|
||||
<t t-esc="channel.last_message.displayed_author"/>:
|
||||
<t t-raw="channel.last_message_preview"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<t t-call="mail.chat.ChannelPreview"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
@@ -79,7 +60,9 @@
|
||||
</t>
|
||||
<t t-foreach="activities" t-as="activity">
|
||||
<div class="o_mail_channel_preview" t-att-data-res_model="activity.model" t-att-data-model_name="activity.name" data-filter='my'>
|
||||
<img class="o_channel_image" t-att-src="activity.icon"/>
|
||||
<div class="o_mail_channel_image">
|
||||
<img t-att-src="activity.icon"/>
|
||||
</div>
|
||||
<div class="o_channel_info">
|
||||
<div class="o_channel_title">
|
||||
<span class="o_channel_name">
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
<t t-esc="message.date.format('hh:mm')"/>
|
||||
</span>
|
||||
<i t-if="!message.display_author and options.display_stars and message.message_type != 'notification'"
|
||||
t-att-class="'fa o_thread_message_star ' + (message.is_starred ? 'fa-star' : 'fa-star-o')"
|
||||
t-att-class="'fa o_thread_message_star o_thread_icon ' + (message.is_starred ? 'fa-star' : 'fa-star-o')"
|
||||
t-att-data-message-id="message.id" title="Mark as Todo"/>
|
||||
</div>
|
||||
<div t-att-class="'o_thread_message_core' + (message.is_note ? ' o_mail_note' : '')">
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
odoo.define('mail.client_action_test', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ActionManager = require('web.ActionManager');
|
||||
var core = require('web.core');
|
||||
var testUtils = require('web.test_utils');
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
@@ -10,59 +8,64 @@ var ChatAction = require("mail.chat_client_action");
|
||||
|
||||
QUnit.module('mail', {}, function () {
|
||||
|
||||
QUnit.module('ChatAction', {
|
||||
QUnit.module('Discuss client action', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
"mail.message": {
|
||||
fields: {
|
||||
id: {type: 'integer', string: 'ID'}
|
||||
}
|
||||
}
|
||||
'mail.message': {
|
||||
fields: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
this.createChatAction = function (params) {
|
||||
var parent = new Widget();
|
||||
testUtils.addMockEnvironment(parent, {
|
||||
data: this.data,
|
||||
archs: {
|
||||
'mail.message,false,search': '<search/>',
|
||||
},
|
||||
config: {
|
||||
isMobile: true
|
||||
},
|
||||
});
|
||||
var chatAction = new ChatAction(parent, params);
|
||||
chatAction.set_cp_bus(new Widget());
|
||||
chatAction.appendTo($('#qunit-fixture'));
|
||||
|
||||
return chatAction;
|
||||
};
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Mobile Test case
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
QUnit.test('mobile basic rendering', function (assert) {
|
||||
QUnit.skip('mobile basic rendering', function (assert) {
|
||||
// Unfortunately, this test is skipped for now because there is no way to
|
||||
// execute the whole test suite in mobile (it only works test by test), so
|
||||
// as the client action include for mobile is rejected when we are not in
|
||||
// mobile, it isn't possible to test it
|
||||
// Moreover, RPCs done by the chat_manager (e.g. message_fetch) should be
|
||||
// properly mocked.
|
||||
assert.expect(11);
|
||||
|
||||
function createParent (params) {
|
||||
var actionManager = new ActionManager();
|
||||
testUtils.addMockEnvironment(actionManager, params);
|
||||
return actionManager;
|
||||
}
|
||||
|
||||
var action = {
|
||||
id: 1,
|
||||
context: {'active_channel_id': 'channel_inbox', 'active_ids': ['channel_inbox']},
|
||||
params: {'default_active_id': 'channel_inbox'}
|
||||
};
|
||||
|
||||
var parent = createParent({
|
||||
data: {},
|
||||
});
|
||||
|
||||
var parent = new Widget();
|
||||
testUtils.addMockEnvironment(parent, {
|
||||
data: this.data,
|
||||
config: {
|
||||
isMobile: true
|
||||
},
|
||||
archs: {
|
||||
'mail.message,false,search': '<search/>',
|
||||
}
|
||||
},
|
||||
config: {
|
||||
isMobile: true,
|
||||
},
|
||||
});
|
||||
|
||||
var chatAction = new ChatAction(parent, action, {});
|
||||
chatAction.set_cp_bus(new Widget());
|
||||
var params = {
|
||||
id: 1,
|
||||
context: {},
|
||||
params: {},
|
||||
};
|
||||
var chatAction = this.createChatAction(params);
|
||||
|
||||
chatAction.appendTo($('#qunit-fixture'));
|
||||
|
||||
// test for basic view rendering for mobile
|
||||
// test basic rendering in mobile
|
||||
assert.equal(chatAction.$(".o_mail_chat_mobile_control_panel").length, 1, "Mobile control panel created");
|
||||
assert.equal(chatAction.$(".o_mail_chat_mobile_tab").length, 4, "Four mobile tabs created");
|
||||
assert.equal(chatAction.$(".o_mail_mobile_tab").length, 4, "Four mobile tabs created");
|
||||
assert.equal(chatAction.$('.o_mail_chat_content').length, 1, "One default chat content pane created");
|
||||
assert.equal(chatAction.$(".o_mail_chat_tab_pane").length, 3, "Three mobile tab panes created");
|
||||
|
||||
@@ -71,12 +74,12 @@ QUnit.test('mobile basic rendering', function (assert) {
|
||||
assert.ok(chatAction.$(".o_channel_inbox_item:nth(0)").hasClass("btn-primary"), "Showing 'Inbox'");
|
||||
|
||||
// Starred
|
||||
chatAction.mailMobileInboxButtons.find(".o_channel_inbox_item[data-type='channel_starred']").click();
|
||||
chatAction.$(".o_channel_inbox_item[data-type='channel_starred']").click();
|
||||
assert.ok(chatAction.$(".o_channel_inbox_item:nth(1)").hasClass("btn-primary"), "Clicked on 'Starred'");
|
||||
|
||||
assert.ok(chatAction.$(".o_mail_chat_content").is(":visible"), "Default main content pane visible");
|
||||
|
||||
chatAction.$(".o_mail_chat_mobile_tab[data-type='dm']").click();
|
||||
chatAction.$(".o_mail_mobile_tab[data-type='dm']").click();
|
||||
assert.equal(chatAction.activeMobileTab, "dm", "After click on 'Conversation', is now active tab");
|
||||
|
||||
assert.ok(!chatAction.$(".o_mail_chat_content").is(":visible"), "none", "'Main' content pane is invisible");
|
||||
@@ -86,4 +89,4 @@ QUnit.test('mobile basic rendering', function (assert) {
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<script type="text/javascript" src="/mail/static/src/js/many2many_tags_email.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/mail/static/src/js/client_action.js"></script>
|
||||
<script type="text/javascript" src="/mail/static/src/js/client_action_mobile.js"></script>
|
||||
<script type="text/javascript" src="/mail/static/src/js/chat_window.js"></script>
|
||||
<script type="text/javascript" src="/mail/static/src/js/extended_chat_window.js"></script>
|
||||
<script type="text/javascript" src="/mail/static/src/js/document_viewer.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user