de77aec424470a518d7c8280190c2d2660316a0c
[odoo/odoo.git] / addons / mail / static / src / js / mail_followers.js
1 openerp_mail_followers = function(session, mail) {
2     var _t = session.web._t,
3        _lt = session.web._lt;
4
5     var mail_followers = session.mail_followers = {};
6
7     /** 
8      * ------------------------------------------------------------
9      * mail_followers Widget
10      * ------------------------------------------------------------
11      *
12      * This widget handles the display of a list of records as a vertical
13      * list, with an image on the left. The widget itself is a floatting
14      * right-sided box.
15      * This widget is mainly used to display the followers of records
16      * in OpenChatter.
17      */
18
19     /* Add the widget to registry */
20     session.web.form.widgets.add('mail_followers', 'openerp.mail_followers.Followers');
21
22     mail_followers.Followers = session.web.form.AbstractField.extend({
23         template: 'mail.followers',
24
25         init: function() {
26             this._super.apply(this, arguments);
27             this.image = this.node.attrs.image || 'image_small';
28             this.comment = this.node.attrs.help || false;
29             this.displayed_nb = this.node.attrs.displayed_nb || 10;
30             this.ds_model = new session.web.DataSetSearch(this, this.view.model);
31             this.ds_follow = new session.web.DataSetSearch(this, this.field.relation);
32             this.ds_users = new session.web.DataSetSearch(this, 'res.users');
33
34             this.value = [];
35         },
36
37         start: function() {
38             // use actual_mode property on view to know if the view is in create mode anymore
39             this.view.on("change:actual_mode", this, this.on_check_visibility_mode);
40             this.on_check_visibility_mode();
41             this.reinit();
42             this.bind_events();
43             this._super();
44         },
45
46         on_check_visibility_mode: function () {
47             this.set({"force_invisible": this.view.get("actual_mode") == "create"});
48         },
49
50         set_value: function(_value) {
51             this.value = _value;
52             this._super(_value);
53         },
54
55         reinit: function() {
56             this.message_is_follower == undefined;
57             this.display_buttons();
58         },
59
60         bind_events: function() {
61             var self = this;
62             // event: click on '(Un)Follow' button, that toggles the follow for uid
63             this.$('.oe_follower').on('click', function (event) {
64                 if($(this).hasClass('oe_notfollow'))
65                     self.do_follow();
66                 else
67                     self.do_unfollow();
68             });
69             // event: click on a subtype, that (un)subscribe for this subtype
70             this.$el.on('click', '.oe_subtype_list input', self.do_update_subscription);
71             // event: click on 'invite' button, that opens the invite wizard
72             this.$('.oe_invite').on('click', function (event) {
73                 action = {
74                     type: 'ir.actions.act_window',
75                     res_model: 'mail.wizard.invite',
76                     view_mode: 'form',
77                     view_type: 'form',
78                     views: [[false, 'form']],
79                     target: 'new',
80                     context: {
81                         'default_res_model': self.view.dataset.model,
82                         'default_res_id': self.view.datarecord.id,
83                     },
84                 }
85                 self.do_action(action, {
86                     on_close: function() {
87                         self.read_value();
88                     },
89                 });
90             });
91         },
92
93         read_value: function () {
94             var self = this;
95             return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
96                 self.value = results[0].message_follower_ids;
97                 self.render_value();
98             });
99         },
100
101         render_value: function () {
102             this.reinit();
103             return this.fetch_followers(this.value);
104         },
105
106         fetch_followers: function (value_) {
107             this.value = value_ || {};
108             return this.ds_follow.call('read', [this.value, ['name', 'user_ids']])
109                 .then(this.proxy('display_followers'), this.proxy('fetch_generic'))
110                 .then(this.proxy('display_buttons'))
111                 .then(this.proxy('fetch_subtypes'));
112         },
113
114         /** Read on res.partner failed: fall back on a generic case
115             - fetch current user partner_id (call because no other smart solution currently) FIXME
116             - then display a generic message about followers */
117         fetch_generic: function (error, event) {
118             var self = this;
119             event.preventDefault();
120             return this.ds_users.call('read', [this.session.uid, ['partner_id']]).then(function (results) {
121                 var pid = results['partner_id'][0];
122                 self.message_is_follower = (_.indexOf(self.value, pid) != -1);
123             }).then(self.proxy('display_generic'));
124         },
125         _format_followers: function(count){
126             // TDE note: why redefining _t ?
127             function _t(str) { return str; }
128             var str = '';
129             if(count <= 0){
130                 str = _t('No followers');
131             }else if(count === 1){
132                 str = _t('One follower');
133             }else{
134                 str = ''+count+' '+_t('followers');
135             }
136             return str;
137         },
138         /* Display generic info about follower, for people not having access to res_partner */
139         display_generic: function () {
140             var self = this;
141             var node_user_list = this.$('.oe_follower_list').empty();
142             this.$('.oe_follower_title').html(this._format_followers(this.value.length));
143         },
144
145         /** Display the followers */
146         display_followers: function (records) {
147             var self = this;
148             records = records || [];
149             this.message_is_follower = this.set_is_follower(records);
150             // clean and display title
151             var node_user_list = this.$('.oe_follower_list').empty();
152             this.$('.oe_follower_title').html(this._format_followers(records.length));
153             // truncate number of displayed followers
154             truncated = records.splice(0, this.displayed_nb);
155             _(truncated).each(function (record) {
156                 record.avatar_url = mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record.id);
157                 $(session.web.qweb.render('mail.followers.partner', {'record': record})).appendTo(node_user_list);
158             });
159             // FVA note: be sure it is correctly translated
160             if (truncated.length < records.length) {
161                 $('<div class="oe_partner">And ' + (records.length - truncated.length) + ' more.</div>').appendTo(node_user_list);
162             }
163         },
164
165         /** Computes whether the current user is in the followers */
166         set_is_follower: function (records) {
167             var user_ids = _.pluck(_.pluck(records, 'user_ids'), 0);
168             return _.indexOf(user_ids, this.session.uid) != -1;
169         },
170
171         display_buttons: function () {
172             if (this.message_is_follower) {
173                 this.$('button.oe_follower').removeClass('oe_notfollow').addClass('oe_following');
174             }
175             else {
176                 this.$('button.oe_follower').removeClass('oe_following').addClass('oe_notfollow');
177             }
178
179             if (this.view.is_action_enabled('edit'))
180                 this.$('span.oe_mail_invite_wrapper').hide();
181             else
182                 this.$('span.oe_mail_invite_wrapper').show();
183         },
184
185         /** Fetch subtypes, only if current user is follower */
186         fetch_subtypes: function () {
187             var subtype_list_ul = this.$('.oe_subtype_list').empty();
188             if (! this.message_is_follower) return;
189             var context = new session.web.CompoundContext(this.build_context(), {});
190             this.ds_model.call('message_get_subscription_data', [[this.view.datarecord.id], context]).then(this.proxy('display_subtypes'));
191         },
192
193         /** Display subtypes: {'name': default, followed} */
194         display_subtypes:function (data) {
195             var self = this;
196             var subtype_list_ul = this.$('.oe_subtype_list');
197             subtype_list_ul.empty();
198             var records = data[this.view.datarecord.id || this.view.dataset.ids[0]].message_subtype_data;
199             if (records.length > 1) {
200                 _(records).each(function (record, record_name) {
201                     record.name = record_name;
202                     record.followed = record.followed || undefined;
203                     $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') );
204                 });
205             }
206         },
207
208         do_follow: function () {
209             var context = new session.web.CompoundContext(this.build_context(), {});
210             this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context])
211                 .then(this.proxy('read_value'));
212
213             _.each(this.$('.oe_subtype_list input'), function (record) {
214                 console.log(record);
215                 $(record).attr('checked', 'checked');
216             });
217         },
218         
219         do_unfollow: function () {
220             _(this.$('.oe_msg_subtype_check')).each(function (record) {
221                 $(record).attr('checked',false);
222             });
223             var context = new session.web.CompoundContext(this.build_context(), {});
224             return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context])
225                 .then(this.proxy('read_value'));
226         },
227
228         do_update_subscription: function (event) {
229             var self = this;
230
231             var checklist = new Array();
232             _(this.$('.oe_actions input[type="checkbox"]')).each(function (record) {
233                 if ($(record).is(':checked')) {
234                     checklist.push(parseInt($(record).data('id')));
235                 }
236             });
237
238             if (!checklist.length) {
239                 this.do_unfollow();
240             } else {
241                 var context = new session.web.CompoundContext(this.build_context(), {});
242                 return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], checklist, context])
243                     .then(this.proxy('read_value'));
244             }
245         },
246     });
247 };