').html(render_res).appendTo(self.$element.find('div.oe_mail_wall_threads'));
+ var thread = new mail.Thread(self, {
+ 'res_model': model_name, 'res_id': records[0]['res_id'], 'uid': self.session.uid, 'records': records,
+ 'parent_id': false, 'thread_level': self.params.thread_level}
+ );
+ thread.appendTo(self.$element.find('div.oe_mail_wall_thread:last'));
+ });
+ });
+ },
+
+ /**
+ * Add records to sorted_comments array
+ * @param {Array} records records from mail.message sorted by date desc
+ * @returns {Object} sc sorted_comments: dict
+ * sc.model_list = [record.model names]
+ * sc.models[model_name] = {
+ * 'root_ids': [root record.ids],
+ * 'id_to_root': {record.id: root.id, ..},
+ * 'msgs': {'root_id': [records]}, still sorted by date desc
+ * }, for each model
+ */
+ sort_comments: function (records) {
+ var self = this;
+ var sc = {'model_list': [], 'models': {}}
+ var cur_iter = 0; var max_iter = 10; var modif = true;
+ /* step1: get roots */
+ while ( modif && (cur_iter++) < max_iter) {
+ modif = false;
+ _(records).each(function (record) {
+ if (_.indexOf(sc['model_list'], record.model) == -1) {
+ sc['model_list'].push(record.model);
+ sc['models'][record.model] = {'root_ids': [], 'id_to_root': {}, 'msgs': {}};
+ }
+ if (! self.sorted_comments['models'][record.model]) {
+ self.sorted_comments['models'][record.model] = {'root_ids': []};
+ }
+ var rmod = sc['models'][record.model];
+ if (record.parent_id == false && (_.indexOf(rmod['root_ids'], record.id) == -1)) {
+ rmod['root_ids'].push(record.id);
+ rmod['msgs'][record.id] = [];
+ self.sorted_comments['models'][record.model]['root_ids'].push(record.id);
+ modif = true;
+ }
+ else {
+ if ((_.indexOf(rmod['root_ids'], record.parent_id[0]) != -1) && (! rmod['id_to_root'][record.id])) {
+ rmod['id_to_root'][record.id] = record.parent_id[0];
+ modif = true;
+ }
+ else if ( rmod['id_to_root'][record.parent_id[0]] && (! rmod['id_to_root'][record.id])) {
+ rmod['id_to_root'][record.id] = rmod['id_to_root'][record.parent_id[0]];
+ modif = true;
+ }
+ }
+ });
+ }
+ /* step2: add records */
+ _(records).each(function (record) {
+ var root_id = sc['models'][record.model]['id_to_root'][record.id];
+ if (! root_id) root_id = record.id;
+ sc['models'][record.model]['msgs'][root_id].push(record);
+ });
+ return sc;
+ },
+
+ /**
+ * Create a domain to fetch new comments according to
+ * comment already present in sorted_comments
+ * @param {Object} sorted_comments (see sort_comments)
+ * @returns {Array} fetch_domain (OpenERP domain style)
+ */
+ get_fetch_domain: function (sorted_comments) {
+ var domain = [];
+ _(sorted_comments.models).each(function (sc_model, model_name) { //each model
+ var ids = [];
+ _(sc_model.root_ids).each(function (id) { // each record
+ ids.push(id);
+ });
+ domain.push('|', ['model', '!=', model_name], '!', ['id', 'child_of', ids]);
+ });
+ return domain;
+ },
+
+ /**
+ * Action: Shows more discussions
+ */
+ do_more: function () {
+ var domain = this.get_fetch_domain(this.sorted_comments);
+ return this.fetch_comments(domain);
+ },
+
+ /**
+ * Action: Posts a comment
+ */
+ do_comment: function () {
+ var body_text = this.$element.find('textarea.oe_mail_wall_action_textarea').val();
+ return this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, false, 'comment']).then(this.init_comments());
+ },
+
+ /**
+ * Tools: get avatar mini (TODO: should be moved in some tools ?)
+ */
+ thread_get_mini: function(model, field, id) {
+ return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || '');
+ },
+ });
+};
+
+// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml
new file mode 100644
index 00000000000..1a04d4e44c0
--- /dev/null
+++ b/addons/mail/static/src/xml/mail.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
You have loaded all discussions.
+
+
+
+
+
+
+
+
+
+
+
OpenSocial
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![User img]()
+
+
+
+
+
+
+
+
+
You have loaded all messages in this thread.
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+ via OpenERP System Notification
+
+ on
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/project/__openerp__.py b/addons/project/__openerp__.py
index 96a7dc4f28f..fc196890f78 100644
--- a/addons/project/__openerp__.py
+++ b/addons/project/__openerp__.py
@@ -67,6 +67,9 @@ Dashboard for project members that includes:
'test/project_process.yml',
'test/task_process.yml',
],
+ 'css': [
+ 'static/src/css/project_task.css',
+ ],
'installable': True,
'auto_install': False,
'application': True,
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index 26abe86fe99..9f791f81053 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -344,44 +344,46 @@
oe_kanban_color_green
-
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
-
-
-
-
- ,
-
-
-
-
-
-
- !
-
+
+
![]()
+
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+ !
+
+
+
-