[REF] mail: update to the new module system

This commit is contained in:
Géry Debongnie
2015-03-18 09:01:50 +01:00
parent 97f4ba3e3d
commit 0ceeff515c
7 changed files with 2582 additions and 2531 deletions
+65 -55
View File
@@ -1,58 +1,68 @@
openerp_announcement = function(instance) {
instance.web.WebClient.include({
show_application: function() {
return $.when(this._super.apply(this, arguments)).then(this.proxy('show_annoucement_bar'));
},
_ab_location: function(dbuuid) {
return _.str.sprintf('https://services.openerp.com/openerp-enterprise/ab/css/%s.css', dbuuid);
},
show_annoucement_bar: function() {
if (this.session.get_cookie('ab') === 'c') {
odoo.define(['web.core', 'web.Model', 'web.session', 'web.WebClient'], function (require) {
"use strict";
var core = require('web.core');
var Model = require('web.Model');
var session = require('web.session');
var WebClient = require('web.WebClient');
var QWeb = core.qweb;
WebClient.include({
show_application: function() {
return $.when(this._super.apply(this, arguments)).then(this.proxy('show_announcement_bar'));
},
_ab_location: function(dbuuid) {
return _.str.sprintf('https://services.openerp.com/openerp-enterprise/ab/css/%s.css', dbuuid);
},
show_announcement_bar: function() {
if (session.get_cookie('ab') === 'c') {
return;
}
var self = this;
var config_parameter = new Model('ir.config_parameter');
$(QWeb.render('WebClient.announcement_bar')).prependTo($('body'));
var $bar = $('#announcement_bar_table');
return config_parameter.call('get_param', ['database.uuid', false]).then(function(dbuuid) {
if (!dbuuid) {
return;
}
var self = this;
var config_parameter = new instance.web.Model('ir.config_parameter');
$(openerp.qweb.render('WebClient.announcement_bar')).prependTo($('body'));
var $bar = $('#announcement_bar_table');
return config_parameter.call('get_param', ['database.uuid', false]).then(function(dbuuid) {
if (!dbuuid) {
return;
}
var $link = $bar.find('.url a');
$link.attr('href', _.str.sprintf('%s/%s', $link.attr('href'), dbuuid));
var $css = $('<link />').attr({
rel : 'stylesheet',
type: 'text/css',
media: 'screen',
href: self._ab_location(dbuuid)
});
$css.on('load', function() {
var close = function() {
var ttl = 7*24*60*60;
self.session.set_cookie('ab', 'c', ttl);
$bar.slideUp();
setTimeout(function () {
$('.openerp_webclient_container').css('height', 'calc(100% - 34px)');
}, 400);
};
/*
We need a timeout of at least 350ms because the announcement bar appears
with an animation of 350ms and the computed height might be wrong if we don't wait
*/
setTimeout(function(){
var height = $('#announcement_bar_table').outerHeight()
+ $('#oe_main_menu_navbar').outerHeight();
$('.openerp_webclient_container').css('height', 'calc(100% - ' + height + 'px)');
$bar.find('.close').on('click', close);
self.trigger('ab_loaded', $bar);
}, 400)
});
$('head').append($css);
}).fail(function(result, ev){
ev.preventDefault();
var $link = $bar.find('.url a');
$link.attr('href', _.str.sprintf('%s/%s', $link.attr('href'), dbuuid));
var $css = $('<link />').attr({
rel : 'stylesheet',
type: 'text/css',
media: 'screen',
href: self._ab_location(dbuuid)
});
}
});
};
$css.on('load', function() {
var close = function() {
var ttl = 7*24*60*60;
session.set_cookie('ab', 'c', ttl);
$bar.slideUp();
setTimeout(function () {
$('.openerp_webclient_container').css('height', 'calc(100% - 34px)');
}, 400);
};
/*
We need a timeout of at least 350ms because the announcement bar appears
with an animation of 350ms and the computed height might be wrong if we don't wait
*/
setTimeout(function(){
var height = $('#announcement_bar_table').outerHeight()
+ $('#oe_main_menu_navbar').outerHeight();
$('.openerp_webclient_container').css('height', 'calc(100% - ' + height + 'px)');
$bar.find('.close').on('click', close);
self.trigger('ab_loaded', $bar);
}, 400);
});
$('head').append($css);
}).fail(function(result, ev){
ev.preventDefault();
});
}
});
});
File diff suppressed because it is too large Load Diff
+371 -363
View File
@@ -1,380 +1,388 @@
openerp_mail_followers = function(session, mail) {
var _t = session.web._t,
_lt = session.web._lt;
odoo.define('mail.mail_followers', ['mail.utils', 'web.core', 'web.data', 'web.Dialog', 'web.form_common', 'web.session', 'web.web_client'], function (require) {
"use strict";
var mail_followers = session.mail_followers = {};
var mail_utils = require('mail.utils');
var core = require('web.core');
var data = require('web.data');
var Dialog = require('web.Dialog');
var form_common = require('web.form_common');
var session = require('web.session');
var web_client = require('web.web_client');
/**
* ------------------------------------------------------------
* mail_followers Widget
* ------------------------------------------------------------
*
* This widget handles the display of a list of records as a vertical
* list, with an image on the left. The widget itself is a floatting
* right-sided box.
* This widget is mainly used to display the followers of records
* in OpenChatter.
*/
var _t = core._t;
var qweb = core.qweb;
/* Add the widget to registry */
session.web.form.widgets.add('mail_followers', 'openerp.mail_followers.Followers');
/**
* ------------------------------------------------------------
* mail_followers Widget
* ------------------------------------------------------------
*
* This widget handles the display of a list of records as a vertical
* list, with an image on the left. The widget itself is a floatting
* right-sided box.
* This widget is mainly used to display the followers of records
* in OpenChatter.
*/
mail_followers.Followers = session.web.form.AbstractField.extend({
template: 'mail.followers',
init: function() {
this._super.apply(this, arguments);
this.image = this.node.attrs.image || 'image_small';
this.comment = this.node.attrs.help || false;
this.displayed_limit = this.node.attrs.displayed_nb || 10;
this.displayed_nb = this.displayed_limit;
this.ds_model = new session.web.DataSetSearch(this, this.view.model);
this.ds_users = new session.web.DataSetSearch(this, 'res.users');
var Followers = form_common.AbstractField.extend({
template: 'mail.followers',
this.value = [];
this.followers = [];
this.view_is_editable = this.__parentedParent.is_action_enabled('edit');
},
init: function() {
this._super.apply(this, arguments);
this.image = this.node.attrs.image || 'image_small';
this.comment = this.node.attrs.help || false;
this.displayed_limit = this.node.attrs.displayed_nb || 10;
this.displayed_nb = this.displayed_limit;
this.ds_model = new data.DataSetSearch(this, this.view.model);
this.ds_users = new data.DataSetSearch(this, 'res.users');
start: function() {
// use actual_mode property on view to know if the view is in create mode anymore
this.view.on("change:actual_mode", this, this.on_check_visibility_mode);
this.on_check_visibility_mode();
this.reinit();
this.bind_events();
this._super();
},
on_check_visibility_mode: function () {
this.set({"force_invisible": this.view.get("actual_mode") == "create"});
},
set_value: function(_value) {
this.value = _value;
this._super(_value);
},
reinit: function() {
this.message_is_follower == undefined;
this.display_buttons();
},
bind_events: function() {
var self = this;
// event: click on '(Un)Follow' button, that toggles the follow for uid
this.$('.oe_follower').on('click', function (event) {
if($(this).hasClass('oe_notfollow'))
self.do_follow();
else
self.do_unfollow();
});
// event: click on a subtype, that (un)subscribe for this subtype
this.$el.on('click', '.oe_subtype_list input', function(event) {
self.do_update_subscription(event);
var $list = self.$('.oe_subtype_list');
if(!$list.hasClass('open')) {
$list.addClass('open');
}
if(self.$('.oe_subtype_list ul')[0].children.length < 1) {
$list.removeClass('open');
}
event.stopPropagation();
});
// event: click on 'invite' button, that opens the invite wizard
this.$('.oe_invite').on('click', self.on_invite_follower);
// event: click on 'edit_subtype(pencil)' button to edit subscription
this.$el.on('click', '.oe_edit_subtype', self.on_edit_subtype);
this.$el.on('click', '.oe_remove_follower', self.on_remove_follower);
this.$el.on('click', '.oe_show_more', self.on_show_more_followers);
this.$el.on('click', 'a[data-partner]', self.on_follower_clicked);
},
on_edit_subtype: function(event) {
var self = this;
var $currentTarget = $(event.currentTarget);
var user_pid = $currentTarget.data('id');
$('div.oe_edit_actions').remove();
self.$dialog = new session.web.Dialog(this, {
size: 'small',
title: _t('Edit Subscription of ') + $currentTarget.siblings('a').text(),
buttons: [
{ text: _t("Apply"), click: function() {
self.do_update_subscription(event, user_pid);
this.parents('.modal').modal('hide');
}},
{ text: _t("Cancel"), click: function() { this.parents('.modal').modal('hide'); }}
],
}, "<div class='oe_edit_actions'>").open();
return self.fetch_subtypes(user_pid);
},
on_invite_follower: function (event) {
var self = this;
var action = {
type: 'ir.actions.act_window',
res_model: 'mail.wizard.invite',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
name: _t('Invite Follower'),
target: 'new',
context: {
'default_res_model': this.view.dataset.model,
'default_res_id': this.view.datarecord.id,
},
}
this.do_action(action, {
on_close: function() {
self.read_value();
},
});
},
on_show_more_followers: function (event) {
this.displayed_nb += this.displayed_limit;
this.display_followers(false);
},
on_remove_follower: function (event) {
var partner_id = $(event.target).data('id');
var name = $(event.target).parent().find("a").html();
if (confirm(_.str.sprintf(_t("Warning! \n %s won't be notified of any email or discussion on this document. Do you really want to remove him from the followers ?"), name))) {
var context = new session.web.CompoundContext(this.build_context(), {});
return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id], [partner_id], context])
.then(this.proxy('read_value'));
}
},
on_follower_clicked: function (event) {
event.preventDefault();
var partner_id = $(event.target).data('partner');
var state = {
'model': 'res.partner',
'id': partner_id,
'title': this.record_name
};
session.webclient.action_manager.do_push_state(state);
var action = {
type:'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: 'res.partner',
views: [[false, 'form']],
res_id: partner_id,
}
this.do_action(action);
},
read_value: function () {
var self = this;
this.displayed_nb = this.displayed_limit;
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
self.value = results[0].message_follower_ids;
self.render_value();
});
},
render_value: function () {
this.reinit();
return this.fetch_followers(this.value);
},
fetch_followers: function (value_) {
this.value = value_ || [];
return this.ds_model.call('read_followers_data', [this.value])
.then(this.proxy('display_followers'), this.proxy('fetch_generic'))
.then(this.proxy('display_buttons'))
.then(this.proxy('fetch_subtypes'));
},
/** Read on res.partner failed: fall back on a generic case
- fetch current user partner_id (call because no other smart solution currently) FIXME
- then display a generic message about followers */
fetch_generic: function (error, event) {
var self = this;
event.preventDefault();
return this.ds_users.call('read', [[this.session.uid], ['partner_id']]).then(function (results) {
var pid = results[0]['partner_id'][0];
self.message_is_follower = (_.indexOf(self.value, pid) != -1);
}).then(self.proxy('display_generic'));
},
_format_followers: function(count){
var str = '';
if(count <= 0){
str = _t('No followers');
}else if(count === 1){
str = _t('One follower');
}else{
str = ''+count+' '+_t('followers');
}
return str;
},
/* Display generic info about follower, for people not having access to res_partner */
display_generic: function () {
var self = this;
var node_user_list = this.$('.oe_follower_list').empty();
this.$('.oe_follower_title').html(this._format_followers(this.value.length));
},
/** Display the followers */
display_followers: function (records) {
var self = this;
this.message_is_follower = false;
this.followers = records || this.followers;
// clean and display title
var node_user_list = this.$('.oe_follower_list').empty();
this.$('.oe_follower_title').html(this._format_followers(this.followers.length));
self.message_is_follower = _.indexOf(this.followers.map(function (rec) { return rec[2]['is_uid']}), true) != -1;
// truncate number of displayed followers
var truncated = this.followers.slice(0, this.displayed_nb);
_(truncated).each(function (record) {
partner = {
'id': record[0],
'name': record[1],
'is_uid': record[2]['is_uid'],
'is_editable': record[2]['is_editable'],
'avatar_url': mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record[0]),
}
$(session.web.qweb.render('mail.followers.partner', {'record': partner, 'widget': self})).appendTo(node_user_list);
// On mouse-enter it will show the edit_subtype pencil.
if (partner.is_editable) {
self.$('.oe_follower_list').on('mouseenter mouseleave', function(e) {
self.$('.oe_edit_subtype').toggleClass('oe_hidden', e.type == 'mouseleave');
self.$('.oe_follower_list').find('.oe_partner').toggleClass('oe_partner_name', e.type == 'mouseenter');
});
}
});
// FVA note: be sure it is correctly translated
if (truncated.length < this.followers.length) {
$(session.web.qweb.render('mail.followers.show_more', {'number': (this.followers.length - truncated.length)} )).appendTo(node_user_list);
}
},
display_buttons: function () {
if (this.message_is_follower) {
this.$('button.oe_follower').removeClass('oe_notfollow').addClass('oe_following');
}
else {
this.$('button.oe_follower').removeClass('oe_following').addClass('oe_notfollow');
}
if (this.view.is_action_enabled('edit'))
this.$('span.oe_mail_invite_wrapper').hide();
else
this.$('span.oe_mail_invite_wrapper').show();
},
/** Fetch subtypes, only if current user is follower */
fetch_subtypes: function (user_pid) {
var self = this;
var dialog = false;
if (user_pid) {
dialog = true;
} else {
var subtype_list_ul = this.$('.oe_subtype_list ul').empty();
if (! this.message_is_follower) {
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true);
return;
}
else {
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false);
}
}
var id = this.view.datarecord.id;
this.ds_model.call('message_get_subscription_data', [[id], user_pid, new session.web.CompoundContext(this.build_context(), {})])
.then(function (data) {self.display_subtypes(data, id, dialog);});
},
/** Display subtypes: {'name': default, followed} */
display_subtypes:function (data, id, dialog) {
var self = this;
if (dialog) {
var $list = self.$dialog.$el;
}
else {
var $list = this.$('.oe_subtype_list ul');
}
var records = data[id].message_subtype_data;
this.records_length = $.map(records, function(value, index) { return index; }).length;
if (this.records_length > 1) { self.display_followers(); }
var old_model = '';
_(records).each(function (record, record_name) {
if (old_model != record.parent_model){
if (old_model != ''){
var index = $($list).find('.oe_subtype').length;
$($($list).find('.oe_subtype')[index-1]).addClass('subtype-border');
}
old_model = record.parent_model;
}
record.name = record_name;
record.followed = record.followed || undefined;
$(session.web.qweb.render('mail.followers.subtype', {'record': record, 'dialog': dialog})).appendTo($list);
});
},
do_follow: function () {
var context = new session.web.CompoundContext(this.build_context(), {});
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false);
this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context])
.then(this.proxy('read_value'));
_.each(this.$('.oe_subtype_list input'), function (record) {
$(record).attr('checked', 'checked');
});
},
this.value = [];
this.followers = [];
do_unfollow: function (user_pid) {
var self = this;
if (confirm(_t("Warning! \nYou won't be notified of any email or discussion on this document. Do you really want to unfollow this document ?"))) {
_(this.$('.oe_msg_subtype_check')).each(function (record) {
$(record).attr('checked',false);
this.view_is_editable = this.__parentedParent.is_action_enabled('edit');
},
start: function() {
// use actual_mode property on view to know if the view is in create mode anymore
this.view.on("change:actual_mode", this, this.on_check_visibility_mode);
this.on_check_visibility_mode();
this.reinit();
this.bind_events();
this._super();
},
on_check_visibility_mode: function () {
this.set({"force_invisible": this.view.get("actual_mode") == "create"});
},
set_value: function(_value) {
this.value = _value;
this._super(_value);
},
reinit: function() {
this.message_is_follower = false;
this.display_buttons();
},
bind_events: function() {
var self = this;
// event: click on '(Un)Follow' button, that toggles the follow for uid
this.$('.oe_follower').on('click', function (event) {
if($(this).hasClass('oe_notfollow'))
self.do_follow();
else
self.do_unfollow();
});
// event: click on a subtype, that (un)subscribe for this subtype
this.$el.on('click', '.oe_subtype_list input', function(event) {
self.do_update_subscription(event);
var $list = self.$('.oe_subtype_list');
if(!$list.hasClass('open')) {
$list.addClass('open');
}
if(self.$('.oe_subtype_list ul')[0].children.length < 1) {
$list.removeClass('open');
}
event.stopPropagation();
});
// event: click on 'invite' button, that opens the invite wizard
this.$('.oe_invite').on('click', self.on_invite_follower);
// event: click on 'edit_subtype(pencil)' button to edit subscription
this.$el.on('click', '.oe_edit_subtype', self.on_edit_subtype);
this.$el.on('click', '.oe_remove_follower', self.on_remove_follower);
this.$el.on('click', '.oe_show_more', self.on_show_more_followers);
this.$el.on('click', 'a[data-partner]', self.on_follower_clicked);
},
on_edit_subtype: function(event) {
var self = this;
var $currentTarget = $(event.currentTarget);
var user_pid = $currentTarget.data('id');
$('div.oe_edit_actions').remove();
self.$dialog = new Dialog(this, {
size: 'small',
title: _t('Edit Subscription of ') + $currentTarget.siblings('a').text(),
buttons: [
{ text: _t("Apply"), click: function() {
self.do_update_subscription(event, user_pid);
this.parents('.modal').modal('hide');
}},
{ text: _t("Cancel"), click: function() { this.parents('.modal').modal('hide'); }}
],
}, "<div class='oe_edit_actions'>").open();
return self.fetch_subtypes(user_pid);
},
on_invite_follower: function (event) {
var self = this;
var action = {
type: 'ir.actions.act_window',
res_model: 'mail.wizard.invite',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
name: _t('Invite Follower'),
target: 'new',
context: {
'default_res_model': this.view.dataset.model,
'default_res_id': this.view.datarecord.id,
},
};
this.do_action(action, {
on_close: function() {
self.read_value();
},
});
},
on_show_more_followers: function (event) {
this.displayed_nb += this.displayed_limit;
this.display_followers(false);
},
on_remove_follower: function (event) {
var partner_id = $(event.target).data('id');
var name = $(event.target).parent().find("a").html();
if (confirm(_.str.sprintf(_t("Warning! \n %s won't be notified of any email or discussion on this document. Do you really want to remove him from the followers ?"), name))) {
var context = new data.CompoundContext(this.build_context(), {});
return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id], [partner_id], context])
.then(this.proxy('read_value'));
}
},
on_follower_clicked: function (event) {
event.preventDefault();
var partner_id = $(event.target).data('partner');
var state = {
'model': 'res.partner',
'id': partner_id,
'title': this.record_name
};
web_client.action_manager.do_push_state(state);
var action = {
type:'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: 'res.partner',
views: [[false, 'form']],
res_id: partner_id,
};
this.do_action(action);
},
read_value: function () {
var self = this;
this.displayed_nb = this.displayed_limit;
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
self.value = results[0].message_follower_ids;
self.render_value();
});
},
render_value: function () {
this.reinit();
return this.fetch_followers(this.value);
},
fetch_followers: function (value_) {
this.value = value_ || [];
return this.ds_model.call('read_followers_data', [this.value])
.then(this.proxy('display_followers'), this.proxy('fetch_generic'))
.then(this.proxy('display_buttons'))
.then(this.proxy('fetch_subtypes'));
},
/** Read on res.partner failed: fall back on a generic case
- fetch current user partner_id (call because no other smart solution currently) FIXME
- then display a generic message about followers */
fetch_generic: function (error, event) {
var self = this;
event.preventDefault();
return this.ds_users.call('read', [[session.uid], ['partner_id']]).then(function (results) {
var pid = results[0]['partner_id'][0];
self.message_is_follower = (_.indexOf(self.value, pid) != -1);
}).then(self.proxy('display_generic'));
},
_format_followers: function(count){
var str = '';
if(count <= 0){
str = _t('No followers');
}else if(count === 1){
str = _t('One follower');
}else{
str = ''+count+' '+_t('followers');
}
return str;
},
/* Display generic info about follower, for people not having access to res_partner */
display_generic: function () {
this.$('.oe_follower_list').empty();
this.$('.oe_follower_title').html(this._format_followers(this.value.length));
},
/** Display the followers */
display_followers: function (records) {
var self = this;
this.message_is_follower = false;
this.followers = records || this.followers;
// clean and display title
var node_user_list = this.$('.oe_follower_list').empty();
this.$('.oe_follower_title').html(this._format_followers(this.followers.length));
self.message_is_follower = _.indexOf(this.followers.map(function (rec) { return rec[2]['is_uid'];}), true) != -1;
// truncate number of displayed followers
var truncated = this.followers.slice(0, this.displayed_nb);
_(truncated).each(function (record) {
var partner = {
'id': record[0],
'name': record[1],
'is_uid': record[2]['is_uid'],
'is_editable': record[2]['is_editable'],
'avatar_url': mail_utils.get_image(session, 'res.partner', 'image_small', record[0]),
};
$(qweb.render('mail.followers.partner', {'record': partner, 'widget': self})).appendTo(node_user_list);
// On mouse-enter it will show the edit_subtype pencil.
if (partner.is_editable) {
self.$('.oe_follower_list').on('mouseenter mouseleave', function(e) {
self.$('.oe_edit_subtype').toggleClass('oe_hidden', e.type == 'mouseleave');
self.$('.oe_follower_list').find('.oe_partner').toggleClass('oe_partner_name', e.type == 'mouseenter');
});
var action_unsubscribe = 'message_unsubscribe_users';
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true);
var follower_ids = [this.session.uid];
if (user_pid) {
action_unsubscribe = 'message_unsubscribe';
follower_ids = [user_pid];
}
var context = new session.web.CompoundContext(this.build_context(), {});
return this.ds_model.call(action_unsubscribe, [[this.view.datarecord.id], follower_ids, context])
.then(this.proxy('read_value'));
}
return false;
},
});
// FVA note: be sure it is correctly translated
if (truncated.length < this.followers.length) {
$(qweb.render('mail.followers.show_more', {'number': (this.followers.length - truncated.length)} )).appendTo(node_user_list);
}
},
do_update_subscription: function (event, user_pid) {
var self = this;
display_buttons: function () {
if (this.message_is_follower) {
this.$('button.oe_follower').removeClass('oe_notfollow').addClass('oe_following');
}
else {
this.$('button.oe_follower').removeClass('oe_following').addClass('oe_notfollow');
}
var action_subscribe = 'message_subscribe_users';
var follower_ids = [this.session.uid];
var oe_action = this.$('.oe_actions input[type="checkbox"]');
if (user_pid) {
action_subscribe = 'message_subscribe';
follower_ids = [user_pid];
oe_action = $('.oe_edit_actions input[type="checkbox"]');
if (this.view.is_action_enabled('edit'))
this.$('span.oe_mail_invite_wrapper').hide();
else
this.$('span.oe_mail_invite_wrapper').show();
},
/** Fetch subtypes, only if current user is follower */
fetch_subtypes: function (user_pid) {
var self = this;
var dialog = false;
if (user_pid) {
dialog = true;
} else {
this.$('.oe_subtype_list ul').empty();
if (! this.message_is_follower) {
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true);
return;
}
var checklist = new Array();
_(oe_action).each(function (record) {
if ($(record).is(':checked')) {
checklist.push(parseInt($(record).data('id')));
else {
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false);
}
}
var id = this.view.datarecord.id;
this.ds_model.call('message_get_subscription_data', [[id], user_pid, new data.CompoundContext(this.build_context(), {})])
.then(function (data) {self.display_subtypes(data, id, dialog);});
},
/** Display subtypes: {'name': default, followed} */
display_subtypes:function (data, id, dialog) {
var self = this;
var $list;
if (dialog) {
$list = self.$dialog.$el;
}
else {
$list = this.$('.oe_subtype_list ul');
}
var records = data[id].message_subtype_data;
this.records_length = $.map(records, function(value, index) { return index; }).length;
if (this.records_length > 1) { self.display_followers(); }
var old_model = '';
_(records).each(function (record, record_name) {
if (old_model != record.parent_model){
if (old_model !== ''){
var index = $($list).find('.oe_subtype').length;
$($($list).find('.oe_subtype')[index-1]).addClass('subtype-border');
}
old_model = record.parent_model;
}
record.name = record_name;
record.followed = record.followed || undefined;
$(qweb.render('mail.followers.subtype', {'record': record, 'dialog': dialog})).appendTo($list);
});
},
do_follow: function () {
var context = new data.CompoundContext(this.build_context(), {});
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false);
this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [session.uid], undefined, context])
.then(this.proxy('read_value'));
_.each(this.$('.oe_subtype_list input'), function (record) {
$(record).attr('checked', 'checked');
});
},
do_unfollow: function (user_pid) {
if (confirm(_t("Warning! \nYou won't be notified of any email or discussion on this document. Do you really want to unfollow this document ?"))) {
_(this.$('.oe_msg_subtype_check')).each(function (record) {
$(record).attr('checked',false);
});
var action_unsubscribe = 'message_unsubscribe_users';
this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true);
var follower_ids = [session.uid];
if (user_pid) {
action_unsubscribe = 'message_unsubscribe';
follower_ids = [user_pid];
}
var context = new data.CompoundContext(this.build_context(), {});
return this.ds_model.call(action_unsubscribe, [[this.view.datarecord.id], follower_ids, context])
.then(this.proxy('read_value'));
}
return false;
},
if (!checklist.length) {
if (!this.do_unfollow(user_pid)) {
$(event.target).attr("checked", "checked");
} else {
self.$('.oe_subtype_list ul').empty();
}
} else {
var context = new session.web.CompoundContext(this.build_context(), {});
return this.ds_model.call(action_subscribe, [[this.view.datarecord.id], follower_ids, checklist, context])
.then(this.proxy('read_value'));
do_update_subscription: function (event, user_pid) {
var self = this;
var action_subscribe = 'message_subscribe_users';
var follower_ids = [session.uid];
var oe_action = this.$('.oe_actions input[type="checkbox"]');
if (user_pid) {
action_subscribe = 'message_subscribe';
follower_ids = [user_pid];
oe_action = $('.oe_edit_actions input[type="checkbox"]');
}
var checklist = [];
_(oe_action).each(function (record) {
if ($(record).is(':checked')) {
checklist.push(parseInt($(record).data('id')));
}
},
});
};
});
if (!checklist.length) {
if (!this.do_unfollow(user_pid)) {
$(event.target).attr("checked", "checked");
} else {
self.$('.oe_subtype_list ul').empty();
}
} else {
var context = new data.CompoundContext(this.build_context(), {});
return this.ds_model.call(action_subscribe, [[this.view.datarecord.id], follower_ids, checklist, context])
.then(this.proxy('read_value'));
}
},
});
/* Add the widget to registry */
core.form_widget_registry.add('mail_followers', Followers);
});
+120
View File
@@ -0,0 +1,120 @@
odoo.define('mail.utils', function () {
"use strict";
/**
* ------------------------------------------------------------
* ChatterUtils
* ------------------------------------------------------------
*
* This class holds a few tools method for Chatter.
* Some regular expressions not used anymore, kept because I want to
* - (^|\s)@((\w|@|\.)*): @login@log.log
* - (^|\s)\[(\w+).(\w+),(\d)\|*((\w|[@ .,])*)\]: [ir.attachment,3|My Label],
* for internal links
*/
/** parse text to find email: Tagada <address@mail.fr> -> [Tagada, address@mail.fr] or False */
function parse_email(text) {
var result = text.match(/(.*)<(.*@.*)>/);
if (result) {
return [_.str.trim(result[1]), _.str.trim(result[2])];
}
result = text.match(/(.*@.*)/);
if (result) {
return [_.str.trim(result[1]), _.str.trim(result[1])];
}
return [text, false];
}
/* Get an image in /web/binary/image?... */
function get_image(session, model, field, id, resize) {
var r = resize ? encodeURIComponent(resize) : '';
id = id || '';
return session.url('/web/binary/image', {model: model, field: field, id: id, resize: r});
}
/* Get the url of an attachment {'id': id} */
function get_attachment_url(session, message_id, attachment_id) {
return session.url('/mail/download_attachment', {
'model': 'mail.message',
'id': message_id,
'method': 'download_attachment',
'attachment_id': attachment_id
});
}
/**
* Replaces some expressions
* - :name - shortcut to an image
*/
function do_replace_expressions(string) {
var icon_list = ['al', 'pinky'];
/* special shortcut: :name, try to find an icon if in list */
var regex_login = new RegExp(/(^|\s):((\w)*)/g);
var regex_res = regex_login.exec(string);
while (regex_res !== null) {
var icon_name = regex_res[2];
if (_.include(icon_list, icon_name))
string = string.replace(regex_res[0], regex_res[1] + '<img src="/mail/static/src/img/_' + icon_name + '.png" width="22px" height="22px" alt="' + icon_name + '"/>');
regex_res = regex_login.exec(string);
}
return string;
}
/**
* Replaces textarea text into html text (add <p>, <a>)
* TDE note : should be done server-side, in Python -> use mail.compose.message ?
*/
function get_text2html(text) {
return text
.replace(/((?:https?|ftp):\/\/[\S]+)/g,'<a href="$1">$1</a> ')
.replace(/[\n\r]/g,'<br/>');
}
/* Returns the complete domain with "&"
* TDE note: please add some comments to explain how/why
*/
function expand_domain(domain) {
var nb_and = -1;
var k;
// TDE note: smarted code maybe ?
for (k = domain.length-1; k >= 0 ; k-- ) {
if (typeof domain[k] != 'object' ) {
nb_and -= 2;
continue;
}
nb_and += 1;
}
for (k = 0; k < nb_and ; k++) {
domain.unshift('&');
}
return domain;
}
// inserts zero width space between each letter of a string so that
// the word will correctly wrap in html boxes smaller than the text
function breakword(str){
var out = '';
if (!str) {
return str;
}
for(var i = 0, len = str.length; i < len; i++){
out += _.str.escapeHTML(str[i]) + '&#8203;';
}
return out;
}
return {
parse_email: parse_email,
get_image: get_image,
get_attachment_url: get_attachment_url,
do_replace_expressions: do_replace_expressions,
get_text2html: get_text2html,
expand_domain: expand_domain,
breakword: breakword,
};
});
@@ -1,12 +1,19 @@
openerp_FieldMany2ManyTagsEmail = function(instance) {
var _t = instance.web._t;
odoo.define('mail.many2manytags', ['web.core', 'web.form_common', 'web.form_relational', 'web.Model'], function (require) {
"use strict";
var core = require('web.core');
var form_common = require('web.form_common');
var form_relational = require('web.form_relational');
var Model = require('web.Model');
var _t = core._t;
/**
* Extend of FieldMany2ManyTags widget method.
* When the user add a partner and the partner don't have an email, open a popup to purpose to add an email.
* The user can choose to add an email or cancel and close the popup.
*/
instance.web.form.FieldMany2ManyTagsEmail = instance.web.form.FieldMany2ManyTags.extend({
var FieldMany2ManyTagsEmail = form_relational.FieldMany2ManyTags.extend({
start: function() {
this.values = [];
@@ -41,7 +48,7 @@ instance.web.form.FieldMany2ManyTagsEmail = instance.web.form.FieldMany2ManyTags
_check_email_popup: function (ids) {
var self = this;
new instance.web.Model('res.partner').call("search", [[
new Model('res.partner').call("search", [[
["id", "in", ids],
["email", "=", false],
["notify_email", "=", 'always'] ]],
@@ -54,7 +61,7 @@ instance.web.form.FieldMany2ManyTagsEmail = instance.web.form.FieldMany2ManyTags
// unvalid partner
_.each(record_ids, function (id) {
var pop = new instance.web.form.FormOpenPopup(self);
var pop = new form_common.FormOpenPopup(self);
pop.show_element(
'res.partner',
id,
@@ -81,6 +88,6 @@ instance.web.form.FieldMany2ManyTagsEmail = instance.web.form.FieldMany2ManyTags
/**
* Registry of form fields
*/
instance.web.form.widgets.add('many2many_tags_email', 'instance.web.form.FieldMany2ManyTagsEmail');
core.form_widget_registry.add('many2many_tags_email', FieldMany2ManyTagsEmail);
};
});
+73 -68
View File
@@ -1,78 +1,83 @@
openerp.mail.suggestions = function(session, mail) {
var _t = session.web._t;
var QWeb = session.web.qweb;
odoo.define(['mail.mail', 'web.core', 'web.data', 'web.session', 'web.Widget'], function (require) {
var suggestions = session.suggestions = {};
var removed_suggested_group = session.suggestions.removed_suggested_group = [];
var mail = require('mail.mail');
var core = require('web.core');
var data = require('web.data');
var real_session = require('web.session');
var Widget = require('web.Widget');
suggestions.Groups = session.web.Widget.extend({
events: {
'click .oe_suggestion_remove.oe_suggestion_group': 'stop_group_suggestion',
'click .oe_suggestion_remove_item.oe_suggestion_group': 'remove_group_suggestion',
'click .oe_suggestion_join': 'join_group',
},
var QWeb = core.qweb;
init: function () {
this._super.apply(this, arguments);
this.mail_group = new session.web.DataSetSearch(this, 'mail.group');
this.res_users = new session.web.DataSetSearch(this, 'res.users');
this.groups = [];
},
var removed_suggested_group = [];
start: function () {
this._super.apply(this, arguments);
return this.fetch_suggested_groups();
},
var Groups = Widget.extend({
events: {
'click .oe_suggestion_remove.oe_suggestion_group': 'stop_group_suggestion',
'click .oe_suggestion_remove_item.oe_suggestion_group': 'remove_group_suggestion',
'click .oe_suggestion_join': 'join_group',
},
fetch_suggested_groups: function () {
var self = this;
var group = self.mail_group.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_group}).then(function (res) {
_(res).each(function (result) {
result['image']=self.session.url('/web/binary/image', {model: 'mail.group', field: 'image_small', id: result.id});
});
self.groups = res;
init: function () {
this._super.apply(this, arguments);
this.mail_group = new data.DataSetSearch(this, 'mail.group');
this.res_users = new data.DataSetSearch(this, 'res.users');
this.groups = [];
},
start: function () {
this._super.apply(this, arguments);
return this.fetch_suggested_groups();
},
fetch_suggested_groups: function () {
var self = this;
var group = self.mail_group.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_group}).then(function (res) {
_(res).each(function (result) {
result.image = real_session.url('/web/binary/image', {model: 'mail.group', field: 'image_small', id: result.id});
});
return $.when(group).then(this.proxy('display_suggested_groups'));
},
self.groups = res;
});
return $.when(group).then(this.proxy('display_suggested_groups'));
},
display_suggested_groups: function () {
var suggested_groups = this.$('.oe_sidebar_suggestion.oe_suggestion_group');
if (suggested_groups) {
suggested_groups.empty();
}
if (this.groups.length === 0) {
return this.$el.empty();
}
return this.$el.empty().html(QWeb.render('mail.suggestions.groups', {'widget': this}));
},
join_group: function (event) {
var self = this;
var group_id = parseInt($(event.currentTarget).attr('id'), 10);
return this.mail_group.call('message_subscribe_users', [[group_id], [this.session.uid]]).then(function(res) {
self.fetch_suggested_groups();
});
},
remove_group_suggestion: function (event) {
removed_suggested_group.push($(event.currentTarget).attr('id'));
return this.fetch_suggested_groups();
},
stop_group_suggestion: function (event) {
var self = this;
return this.res_users.call('stop_showing_groups_suggestions', [this.session.uid]).then(function(res) {
self.$(".oe_sidebar_suggestion.oe_suggestion_group").hide();
});
display_suggested_groups: function () {
var suggested_groups = this.$('.oe_sidebar_suggestion.oe_suggestion_group');
if (suggested_groups) {
suggested_groups.empty();
}
});
if (this.groups.length === 0) {
return this.$el.empty();
}
return this.$el.empty().html(QWeb.render('mail.suggestions.groups', {'widget': this}));
},
session.mail.WallSidebar.include({
start: function () {
this._super.apply(this, arguments);
var sug_groups = new suggestions.Groups(this);
return sug_groups.appendTo(this.$('.oe_suggestions_groups'));
},
});
join_group: function (event) {
var self = this;
var group_id = parseInt($(event.currentTarget).attr('id'), 10);
return this.mail_group.call('message_subscribe_users', [[group_id], [this.session.uid]]).then(function(res) {
self.fetch_suggested_groups();
});
},
};
remove_group_suggestion: function (event) {
removed_suggested_group.push($(event.currentTarget).attr('id'));
return this.fetch_suggested_groups();
},
stop_group_suggestion: function (event) {
var self = this;
return this.res_users.call('stop_showing_groups_suggestions', [this.session.uid]).then(function(res) {
self.$(".oe_sidebar_suggestion.oe_suggestion_group").hide();
});
}
});
mail.WallSidebar.include({
start: function () {
this._super.apply(this, arguments);
var sug_groups = new Groups(this);
return sug_groups.appendTo(this.$('.oe_suggestions_groups'));
},
});
});
+1
View File
@@ -7,6 +7,7 @@
<link rel="stylesheet" href="/mail/static/src/css/mail_group.css"/>
<link rel="stylesheet" href="/mail/static/src/css/announcement.css"/>
<script type="text/javascript" src="/mail/static/src/js/mail.js"></script>
<script type="text/javascript" src="/mail/static/src/js/mail_utils.js"></script>
<script type="text/javascript" src="/mail/static/src/js/mail_followers.js"></script>
<script type="text/javascript" src="/mail/static/src/js/many2many_tags_email.js"></script>
<script type="text/javascript" src="/mail/static/src/js/announcement.js"></script>