From c92422b2ace39a0dde2cb1952da4a26159257377 Mon Sep 17 00:00:00 2001 From: "Atul Patel (OpenERP)" Date: Thu, 9 Aug 2012 15:23:41 +0530 Subject: [PATCH 01/65] [ADD]: Add vote system in openchatter bzr revid: atp@tinyerp.com-20120809095341-xn70i8beof20b07h --- addons/mail/__init__.py | 1 + addons/mail/mail_message.py | 41 +++++++++++++++++++ addons/mail/mail_thread.py | 14 ++++++- addons/mail/mail_vote.py | 36 +++++++++++++++++ addons/mail/security/ir.model.access.csv | 1 + addons/mail/static/src/css/mail.css | 29 ++++++++++++++ addons/mail/static/src/img/vote.gif | Bin 0 -> 892 bytes addons/mail/static/src/js/mail.js | 48 ++++++++++++++++++++++- addons/mail/static/src/xml/mail.xml | 22 ++++++++++- 9 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 addons/mail/mail_vote.py create mode 100644 addons/mail/static/src/img/vote.gif diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py index cbd477f55e6..4cf2caf8804 100644 --- a/addons/mail/__init__.py +++ b/addons/mail/__init__.py @@ -24,6 +24,7 @@ import mail_message import mail_thread import mail_group import mail_subscription +import mail_vote import ir_needaction import res_users import res_partner diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index b96b6e3791e..1b5178e7271 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -230,6 +230,7 @@ class mail_message(osv.Model): select=True, ondelete='set null', help="Parent message, used for displaying as threads with hierarchy"), 'child_ids': fields.one2many('mail.message', 'parent_id', 'Child Messages'), + 'vote_ids': fields.one2many('mail.vote', 'msg_id', 'Votes'), } _defaults = { @@ -237,6 +238,46 @@ class mail_message(osv.Model): 'state': 'received', } + + #--------------------------------------------------- + #Mail Vote system (Like or Unlike comments + #----------------------------------------------------- + + def get_vote_summary(self, cr, uid, ids, context=None): + ''' + Return message ,count vote of message id given by .particular user with True or False. + ''' + for message in self.browse(cr, uid, ids, context): + is_vote_liked = False + vote_count = len(message.vote_ids) + for vote in message.vote_ids: + if vote.user_id.id == uid: + is_vote_liked = True + break + res = { + 'msg_id': message.id, + 'vote_count': vote_count, + 'is_vote_liked': is_vote_liked + } + return res + + def vote_toggle(self, cr, uid, ids, context=None): + ''' + Toggles when Comment is liked or unlike. + Return the number of votes of particular message. + ''' + vote_pool = self.pool.get('mail.vote') + vote_count = 0 + for message in self.browse(cr, uid, ids, context): + voters_id = vote_pool.search(cr, uid, [('msg_id', '=', message.id), ('user_id', '=', uid)], context=context) + if not voters_id: + new_vote_id = vote_pool.create(cr, uid, {'msg_id': message.id, 'user_id': uid}, context=context) + else: + vote_pool.unlink(cr, uid, voters_id, context=context) + if message.vote_ids: + vote_count = len(message.vote_ids) + return vote_count + #------------------------------------------------------ # Email api #------------------------------------------------------ diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index f0dd023bf06..092050ff812 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -64,12 +64,14 @@ class mail_thread(osv.Model): def _get_message_ids(self, cr, uid, ids, name, args, context=None): res = {} + img_vote = "" for id in ids: message_ids = self.message_search(cr, uid, [id], context=context) subscriber_ids = self.message_get_subscribers(cr, uid, [id], context=context) + vote_list = self.message_vote_ids(cr, uid, ids, context=context) res[id] = { 'message_ids': message_ids, - 'message_summary': "9 %d + %d" % (len(message_ids), len(subscriber_ids)), + 'message_summary': "Msg: %d . Fol: %d . %s %d" % (len(message_ids), len(subscriber_ids), img_vote, len(vote_list)), } return res @@ -100,7 +102,15 @@ class mail_thread(osv.Model): #------------------------------------------------------ # Automatic subscription when creating/reading #------------------------------------------------------ - + def message_vote_ids(self, cr, uid, ids, context=None): + message_pool = self.pool.get('mail.message') + vote_list = [] + message_ids = self.message_search(cr, uid, [id], context=context) + for message in message_pool.browse(cr, uid, message_ids, context=context): + if message.vote_ids: + vote_list.append(message.vote_ids) + return vote_list + def create(self, cr, uid, vals, context=None): """Automatically subscribe the creator """ thread_id = super(mail_thread, self).create(cr, uid, vals, context=context) diff --git a/addons/mail/mail_vote.py b/addons/mail/mail_vote.py new file mode 100644 index 00000000000..5d63de80864 --- /dev/null +++ b/addons/mail/mail_vote.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2012-Today OpenERP SA (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see +# +############################################################################## + +from osv import osv, fields +from tools.translate import _ + +class mail_vote(osv.Model): + ''' + Mail vote feature allow users to like and unlike particular message or Document's message comment. + It counts the number of votes per document. + ''' + _name = 'mail.vote' + _description = 'Mail Vote' + _columns = { + 'msg_id': fields.many2one('mail.message', 'Message', required=True), + 'user_id': fields.many2one('res.users', 'User', required=True), + } +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/mail/security/ir.model.access.csv b/addons/mail/security/ir.model.access.csv index 3677d424c14..1941a41a259 100644 --- a/addons/mail/security/ir.model.access.csv +++ b/addons/mail/security/ir.model.access.csv @@ -7,3 +7,4 @@ access_mail_notification_all,mail.notification.all,model_mail_notification,,1,1, access_mail_group,mail.group,model_mail_group,base.group_user,1,1,1,1 access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,0 access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,1 +access_mail_vote,mail.vote,model_mail_vote,base.group_user,1,1,1,1 diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index c0317633aa7..ae934eeb4ff 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -275,6 +275,35 @@ display: none; } +/*--------------------------------------------------------------*/ +/* Mail Vote System (Like or Unlike Comment) +/*--------------------------------------------------------------*/ + +.oe_mail_vote_image{ + height='12px'; + width='16px'; +} + +button.oe_mail_msg_vote_like{ + height:21px; + width: 30px; + padding: 1px; + background: #8A89BA; + margin-top: -4px; +} + +button.oe_mail_msg_vote_like:hover{ + background: #8A89BA; +} + +button.oe_mail_msg_vote_like span { + color: white; +} + +span.oe_mail_vote_string{ + color: #807FB4; +} + /* ------------------------------------------------------------ */ /* mail.compose.message form view & OpenERP hacks /* ------------------------------------------------------------ */ diff --git a/addons/mail/static/src/img/vote.gif b/addons/mail/static/src/img/vote.gif new file mode 100644 index 0000000000000000000000000000000000000000..0e6b874770e1122b3f08f01d26bae9f08b94cfe6 GIT binary patch literal 892 zcmZ?wbhEHb_7cRVe_wN7y z|G^4JiO~=kZXuxflZBCi;Xi{8$YY>9!N3v8@Sju0!k~eniGy7zp};`#5CadBg-XW) zha;V=k}f;~2O1ohWSp~PDnG_IFtaO6lF_`F(#WJ0K8@#t(X&(2OcGCB>Da7xoQcbW V?}tRu!6p_1OTLJPi-`^l)&OE6GJpU8 literal 0 HcmV?d00001 diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index da6816d3441..8b60e96744c 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -559,6 +559,48 @@ openerp.mail = function(session) { return display_done && compose_done; }, + //Mail vote Functionality... + add_vote_event: function(element){ + vote_img = element.find('.oe_mail_msg_vote_like'); + self = this; + if (vote_img) + vote_img.click(function(){ + self.subscribe_vote($(this).attr('data-id')); + }); + return + }, + + find_parent_element: function(name, message_id){ + parent_element = false; + _.each($(name), function(element){ + if ($(element).attr("data-id") == message_id){ + parent_element = element; + } + }); + return parent_element; + }, + + render_vote: function(message_id){ + var self = this; + this.mail_message = new session.web.DataSet(this, 'mail.message'); + this.mail_message.call('get_vote_summary',[[parseInt(message_id)]]).then(function(result){ + if (result){ + parent_element = self.find_parent_element(".oe_mail_msg_vote", message_id); + vote_element = session.web.qweb.render('VoteDisplay', result); + $(parent_element).html(vote_element); + self.add_vote_event($(parent_element)); + } + }); + }, + + subscribe_vote: function(message_id){ + var self = this; + this.mail_message = new session.web.DataSet(this, 'mail.message'); + return this.mail_message.call('vote_toggle', [[parseInt(message_id)]]).then(function(result){ + self.render_vote(message_id); + }); + }, + /** * Override-hack of do_action: automatically reload the chatter. * Normally it should be called only when clicking on 'Post/Send' @@ -697,6 +739,10 @@ openerp.mail = function(session) { display_comments: function (records) { var self = this; + //Render Vote. + _.each(records, function(record){ + self.render_vote(record.id); + }); // sort the records mail.ChatterUtils.records_struct_add_records(this.comments_structure, records, this.params.parent_id); //build attachments download urls and compute time-relative from dates @@ -1119,7 +1165,7 @@ openerp.mail = function(session) { var records = self.comments_structure.tree_struct[root_id]['for_thread_msgs']; var model_name = self.comments_structure.msgs[root_id]['model']; var res_id = self.comments_structure.msgs[root_id]['res_id']; - var render_res = session.web.qweb.render('mail.wall_thread_container', {}); + var render_res = session.web.qweb.render('mail.Wall_thread_container', {}); $('
  • ').html(render_res).appendTo(self.$element.find('ul.oe_mail_wall_threads')); var thread = new mail.Thread(self, { 'res_model': model_name, 'res_id': res_id, 'uid': self.session.uid, 'records': records, diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 86d115f29c8..bd18d78e41d 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -45,7 +45,7 @@ wall_thread_container template for the wall Each discussion thread is contained inside this template --> - + + + + Votes : + +
  • + + + + + + +
  • + +
  • @@ -155,6 +174,7 @@
  • +
  • Reply
  • + - diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index d1fb3f8a395..ab8f2dabd5a 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -554,7 +554,7 @@ class stock_warehouse_orderpoint(osv.osv): 'logic': fields.selection([('max','Order to Max'),('price','Best price (not yet active!)')], 'Reordering Mode', required=True), 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True, ondelete="cascade"), 'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="cascade"), - 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade', domain=[('type','=','product')]), + 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade', domain=[('type','!=','service')]), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), 'product_min_qty': fields.float('Minimum Quantity', required=True, help="When the virtual stock goes below the Min Quantity specified for this field, OpenERP generates "\ diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 6927bf68c25..7584f239f34 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -106,6 +106,7 @@
    +
    @@ -880,12 +881,12 @@ - + - + @@ -970,7 +971,7 @@ stock.picking.out.tree - stock.picking + stock.picking.out @@ -1000,7 +1001,7 @@ - - - - - - -
  • @@ -161,12 +142,10 @@
  • -
  • + +
  • Reply
  • Reply
  • -
  • 1 Attachment @@ -200,4 +179,17 @@ + +
  • + + votes + + +
  • + From 4b896c36af9f94f66e998331c7504d7fdcd41b8c Mon Sep 17 00:00:00 2001 From: Odowan Kenobi Date: Tue, 18 Sep 2012 15:04:36 +0200 Subject: [PATCH 52/65] [REF] allow to intercept the signals sent to workflows (through buttons) in objects. This is done by adding a function named _workflow_signal() in orm that can be inherited in dedicated objects. Courtesy from Olivier Dony bzr revid: qdp-launchpad@openerp.com-20120918130436-ll7potrsya23lc36 --- openerp/osv/orm.py | 6 ++++++ openerp/osv/osv.py | 12 +++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 48689c3c26e..3eafd247f59 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -3792,6 +3792,12 @@ class BaseModel(object): for res_id in ids: getattr(wf_service, trigger)(uid, self._name, res_id, cr) + def _workflow_signal(self, cr, uid, ids, signal, context=None): + """Send given workflow signal""" + wf_service = netsvc.LocalService("workflow") + for res_id in ids: + wf_service.trg_validate(uid, self._name, res_id, signal, cr) + def unlink(self, cr, uid, ids, context=None): """ Delete records with given ids diff --git a/openerp/osv/osv.py b/openerp/osv/osv.py index 877e804314c..94f179c7897 100644 --- a/openerp/osv/osv.py +++ b/openerp/osv/osv.py @@ -184,16 +184,18 @@ class object_proxy(object): cr.close() return res - def exec_workflow_cr(self, cr, uid, obj, method, *args): - wf_service = netsvc.LocalService("workflow") - return wf_service.trg_validate(uid, obj, args[0], method, cr) + def exec_workflow_cr(self, cr, uid, obj, signal, *args): + object = pooler.get_pool(cr.dbname).get(obj) + if not object: + raise except_osv('Object Error', 'Object %s doesn\'t exist' % str(obj)) + return object._workflow_signal(cr, uid, [args[0]], signal) @check - def exec_workflow(self, db, uid, obj, method, *args): + def exec_workflow(self, db, uid, obj, signal, *args): cr = pooler.get_db(db).cursor() try: try: - res = self.exec_workflow_cr(cr, uid, obj, method, *args) + res = self.exec_workflow_cr(cr, uid, obj, signal, *args) cr.commit() except Exception: cr.rollback() From 2c09f43b7efe7d7696d87029b1107ce563c4dfc3 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Tue, 18 Sep 2012 16:31:01 +0200 Subject: [PATCH 53/65] [IMP] Added helper for buttons in dialogs bzr revid: nicolas.vanhoren@openerp.com-20120918143101-wbdyaou23l8wx9zd --- addons/web/static/src/js/chrome.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 3114aaf315f..d5b45a87bf5 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -79,6 +79,9 @@ instance.web.Dialog = instance.web.Widget.extend({ } } if (options) { + if (options.buttons) { + this.params_buttons = true; + } _.extend(this.dialog_options, options); } }, @@ -123,7 +126,13 @@ instance.web.Dialog = instance.web.Widget.extend({ if (! this.dialog_inited) this.init_dialog(); var o = this.get_options(options); + if (! this.no_erase_buttons) { + this.$buttons.appendTo($("body")); + } instance.web.dialog(this.$el, o).dialog('open'); + if (! this.no_erase_buttons) { + this.$buttons.appendTo(this.$el.dialog("widget")); + } if (o.height === 'auto' && o.max_height) { this.$el.css({ 'max-height': o.max_height, 'overflow-y': 'auto' }); } @@ -133,6 +142,10 @@ instance.web.Dialog = instance.web.Widget.extend({ this.renderElement(); var o = this.get_options(options); instance.web.dialog(this.$el, o); + if (! this.params_buttons) { + this.$buttons = $('
    '); + this.$el.dialog("widget").append(this.$buttons); + } var res = this.start(); this.dialog_inited = true; return res; From d9d3aab5151b1651d6eb36057f121ebee4af76f0 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Tue, 18 Sep 2012 16:49:24 +0200 Subject: [PATCH 54/65] [FIX] Problem with popups bzr revid: nicolas.vanhoren@openerp.com-20120918144924-2y72o7tauxspk4la --- addons/web/static/src/js/chrome.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index d5b45a87bf5..9fdfb50307f 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -126,11 +126,11 @@ instance.web.Dialog = instance.web.Widget.extend({ if (! this.dialog_inited) this.init_dialog(); var o = this.get_options(options); - if (! this.no_erase_buttons) { + if (! this.params_buttons) { this.$buttons.appendTo($("body")); } instance.web.dialog(this.$el, o).dialog('open'); - if (! this.no_erase_buttons) { + if (! this.params_buttons) { this.$buttons.appendTo(this.$el.dialog("widget")); } if (o.height === 'auto' && o.max_height) { From 74410c8985a78d87d10341174d95d853415e5e52 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Tue, 18 Sep 2012 16:59:25 +0200 Subject: [PATCH 55/65] [IMP] replaced tipsy in m2o by a dialog bzr revid: nicolas.vanhoren@openerp.com-20120918145925-avk5z92hqesqdqq9 --- addons/web/static/src/js/view_form.js | 45 ++++++++++++++++++--------- addons/web/static/src/xml/base.xml | 10 ++++++ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index d5eaf21c5e2..c188abc853e 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2616,6 +2616,7 @@ instance.web.form.CompletionFieldMixin = { var dataset = new instance.web.DataSet(this, this.field.relation, self.build_context()); var blacklist = this.get_search_blacklist(); + this.last_query = search_val; return this.orderer.add(dataset.name_search( search_val, new instance.web.CompoundDomain(self.build_domain(), [["id", "not in", blacklist]]), @@ -2723,6 +2724,32 @@ instance.web.form.CompletionFieldMixin = { }, }; +instance.web.form.M2ODialog = instance.web.Dialog.extend({ + template: "M2ODialog", + init: function(parent) { + this._super(parent, { + title: _.str.sprintf(_t("Add %s"), parent.string), + width: 312, + }); + }, + start: function() { + var self = this; + this.$buttons.html(QWeb.render("M2ODialog.buttons")); + this.$("input").val(this.getParent().last_query); + this.$buttons.find(".oe_form_m2o_qc_button").click(function(){ + self.getParent()._quick_create(self.$("input").val()); + self.destroy(); + }); + this.$buttons.find(".oe_form_m2o_sc_button").click(function(){ + self.getParent()._search_create_popup("form", undefined, self.getParent()._create_context(self.$("input").val())); + self.destroy(); + }); + this.$buttons.find(".oe_form_m2o_cancel_button").click(function(){ + self.destroy(); + }); + }, +}); + instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instance.web.form.CompletionFieldMixin, instance.web.form.ReinitializeFieldMixin, { template: "FieldMany2One", init: function(field_manager, node) { @@ -2754,25 +2781,13 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc this.render_value(); }, init_error_displayer: function() { - this.$input.tipsy({ - title: function() { - return QWeb.render('Tipsy.alert', { - message: "No element was selected, you should create or select one from the dropdown list." - }); - }, - trigger:'manual', - fade: true, - gravity: 's', - html: true, - opacity: 1, - offset: 4, - }); + // nothing }, hide_error_displayer: function() { - this.$input.tipsy("hide"); + // doesn't work }, show_error_displayer: function() { - this.$input.tipsy("show"); + new instance.web.form.M2ODialog(this).open(); }, render_editable: function() { var self = this; diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index aafac1019fd..4cc2629822d 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1700,4 +1700,14 @@
    + +
    + Name: +
    +
    + + + + + From 2ae49751eb9e97b4ec9820a07258f5d07a527d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 18 Sep 2012 17:05:17 +0200 Subject: [PATCH 56/65] [TEST] mail: added tests for the vote feature. bzr revid: tde@openerp.com-20120918150517-c08jw61c9fpasisc --- addons/mail/tests/test_mail.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py index 1fab5dd1732..57a59e2595f 100644 --- a/addons/mail/tests/test_mail.py +++ b/addons/mail/tests/test_mail.py @@ -647,3 +647,33 @@ class test_mail(TestMailMockups): msg1.refresh() self.assertEqual(5, len(group_pigs.message_ids), 'group should contain 5 messages') self.assertEqual(2, len(msg1.child_ids), 'msg1 should have 2 children now') + + def test_60_vote(self): + """ Test designed for the vote/unvote feature. """ + cr, uid = self.cr, self.uid + group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) + user_admin = self.res_users.browse(cr, uid, uid) + msg1 = group_pigs.message_post(body='My Body', subject='1') + msg1 = self.mail_message.browse(cr, uid, msg1) + + # Create user Bert Tartopoils + user_bert_id = self.res_users.create(cr, uid, {'name': 'Bert', 'login': 'bert'}) + user_bert = self.res_users.browse(cr, uid, user_bert_id) + + # Test: msg1 and msg2 have void vote_user_ids + self.assertFalse(msg1.vote_user_ids, 'newly created message msg1 has not void vote_user_ids') + # Do: Admin vote for msg1 + self.mail_message.vote_toggle(cr, uid, [msg1.id]) + msg1.refresh() + # Test: msg1 has Admin as voter + self.assertEqual(set(msg1.vote_user_ids), set([user_admin]), 'after voting, Admin is not the voter') + # Do: Bert vote for msg1 + self.mail_message.vote_toggle(cr, uid, [msg1.id], [user_bert_id]) + msg1.refresh() + # Test: msg1 has Admin and Bert as voters + self.assertEqual(set(msg1.vote_user_ids), set([user_admin, user_bert]), 'after voting, Admin and Bert are not the voters') + # Do: Admin unvote for msg1 + self.mail_message.vote_toggle(cr, uid, [msg1.id]) + msg1.refresh() + # Test: msg1 has Bert as voter + self.assertEqual(set(msg1.vote_user_ids), set([user_bert]), 'after unvoting for Admin, Bert is not the voter') From 21833581643ac28af36e778f479c0bdbcc461285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 18 Sep 2012 17:05:44 +0200 Subject: [PATCH 57/65] [CLEAN] mail: vote: cleaned before merging. bzr revid: tde@openerp.com-20120918150544-2pgwh1mhi5yyqi22 --- addons/mail/mail_message.py | 19 ++++++++----------- addons/mail/mail_vote.py | 8 ++++---- addons/mail/static/src/img/vote.gif | Bin 892 -> 0 bytes addons/mail/static/src/js/mail.js | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 addons/mail/static/src/img/vote.gif diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 4b7c0c645e3..1d5d85e36e0 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -130,7 +130,8 @@ class mail_message(osv.Model): 'unread': fields.function(_get_unread, fnct_search=_search_unread, type='boolean', string='Unread', help='Functional field to search for unread messages linked to uid'), - 'vote_user_ids': fields.many2many('res.users', 'mail_vote', 'message_id', 'user_id', 'Votes'), + 'vote_user_ids': fields.many2many('res.users', 'mail_vote', 'message_id', 'user_id', string='Votes', + help='Users that voted for this message'), } def _needaction_domain_get(self, cr, uid, context=None): @@ -153,19 +154,16 @@ class mail_message(osv.Model): #------------------------------------------------------ def vote_toggle(self, cr, uid, ids, user_ids=None, context=None): - ''' - Toggles when Comment is liked or unlike. - create vote entries if current user like comment.. - ''' + ''' Toggles voting ''' if not user_ids: user_ids = [uid] for message in self.read(cr, uid, ids, ['vote_user_ids'], context=context): for user_id in user_ids: - has_voted = user_id in message['vote_user_ids'] + has_voted = user_id in message.get('vote_user_ids') if not has_voted: - self.write(cr, uid, ids, {'vote_user_ids': [(4, user_id)]}, context=context) + self.write(cr, uid, message.get('id'), {'vote_user_ids': [(4, user_id)]}, context=context) else: - self.write(cr, uid, ids, {'vote_user_ids': [(3, user_id)]}, context=context) + self.write(cr, uid, message.get('id'), {'vote_user_ids': [(3, user_id)]}, context=context) return True #------------------------------------------------------ @@ -174,11 +172,10 @@ class mail_message(osv.Model): def _message_dict_get(self, cr, uid, msg, context=None): """ Return a dict representation of the message browse record. """ - vote_pool = self.pool.get('mail.vote') has_voted = False vote_ids = self.pool.get('res.users').name_get(cr, uid, [user.id for user in msg.vote_user_ids], context=context) - for user_id in msg.vote_user_ids: - if (user_id.id == uid): + for vote in vote_ids: + if vote[0] == uid: has_voted = True break attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)] diff --git a/addons/mail/mail_vote.py b/addons/mail/mail_vote.py index 3d69734f198..1e439fe0aeb 100644 --- a/addons/mail/mail_vote.py +++ b/addons/mail/mail_vote.py @@ -30,10 +30,10 @@ class mail_vote(osv.Model): _name = 'mail.vote' _description = 'Mail Vote' _columns = { - 'message_id': fields.many2one('mail.message', 'Message', required=True, - select=1), - 'user_id': fields.many2one('res.users', 'User', required=True, - select=1), + 'message_id': fields.many2one('mail.message', 'Message', select=1, + ondelete='cascade', required=True), + 'user_id': fields.many2one('res.users', 'User', select=1, + ondelete='cascade', required=True), } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mail/static/src/img/vote.gif b/addons/mail/static/src/img/vote.gif deleted file mode 100644 index 0e6b874770e1122b3f08f01d26bae9f08b94cfe6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 892 zcmZ?wbhEHb_7cRVe_wN7y z|G^4JiO~=kZXuxflZBCi;Xi{8$YY>9!N3v8@Sju0!k~eniGy7zp};`#5CadBg-XW) zha;V=k}f;~2O1ohWSp~PDnG_IFtaO6lF_`F(#WJ0K8@#t(X&(2OcGCB>Da7xoQcbW V?}tRu!6p_1OTLJPi-`^l)&OE6GJpU8 diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 2f5f95fbb62..57c777441e7 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -529,7 +529,7 @@ openerp.mail = function(session) { record.vote_user_ids.splice(idx, 1); } else { - record.vote_user_ids.push([this.session.uid, 'Current user']); + record.vote_user_ids.push([this.session.uid, 'You']); } record.has_voted = ! record.has_voted; var vote_element = session.web.qweb.render('mail.thread.message.vote', {'record': record}); From 61ebb4042b5d7d0e98a1ac6be8cc63f917fd84de Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 18 Sep 2012 17:11:08 +0200 Subject: [PATCH 58/65] [IMP] kanban: many2many_tags => bzr revid: chm@openerp.com-20120918151108-8fpv61vmlmbjkws7 --- addons/base_calendar/base_calendar_view.xml | 2 +- addons/base_setup/res_partner_view.xml | 2 +- addons/note/note_view.xml | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml index 89066ce74bb..0ea2be4f37f 100644 --- a/addons/base_calendar/base_calendar_view.xml +++ b/addons/base_calendar/base_calendar_view.xml @@ -418,7 +418,7 @@ ir.actions.act_window calendar.event form - tree,form,calendar + calendar,tree,form
    diff --git a/addons/base_setup/res_partner_view.xml b/addons/base_setup/res_partner_view.xml index 5e54c0b8629..ad520799c1f 100644 --- a/addons/base_setup/res_partner_view.xml +++ b/addons/base_setup/res_partner_view.xml @@ -13,10 +13,10 @@ + - diff --git a/addons/note/note_view.xml b/addons/note/note_view.xml index 5617fae4376..e7636aa4b85 100644 --- a/addons/note/note_view.xml +++ b/addons/note/note_view.xml @@ -2,8 +2,6 @@ - - note.stage.form @@ -39,8 +37,6 @@ [('user_id','=',uid)] - - note.note.kanban @@ -85,7 +81,8 @@ -
    + +
    @@ -192,7 +189,11 @@ {'search_default_open_true':True} - + + + + + \ No newline at end of file From 8cb1f558a0f7d0c5eb43b75f153e2b374351999d Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 18 Sep 2012 17:15:01 +0200 Subject: [PATCH 59/65] [IMP] kanban: many2many_tags => other views bzr revid: chm@openerp.com-20120918151501-4kkf7ve1m7wvj3le --- addons/base_setup/res_partner_view.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/base_setup/res_partner_view.xml b/addons/base_setup/res_partner_view.xml index ad520799c1f..57e8d70531d 100644 --- a/addons/base_setup/res_partner_view.xml +++ b/addons/base_setup/res_partner_view.xml @@ -10,9 +10,6 @@ - - - From b08efa691824370130be1f009472ba7f59096127 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 18 Sep 2012 17:17:48 +0200 Subject: [PATCH 60/65] [FIX] Apply inputs maxlength according to field's size bzr revid: fme@openerp.com-20120918151748-gfzmmk61ih5g79yb --- addons/web/static/src/xml/base.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 4cc2629822d..232d4b618d7 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -919,6 +919,7 @@ t-att-tabindex="widget.node.attrs.tabindex" t-att-autofocus="widget.node.attrs.autofocus" t-att-placeholder="widget.node.attrs.placeholder" + t-att-maxlength="widget.field.size" /> @@ -933,6 +934,7 @@ t-att-tabindex="widget.node.attrs.tabindex" t-att-autofocus="widget.node.attrs.autofocus" t-att-placeholder="widget.node.attrs.placeholder" + t-att-maxlength="widget.field.size" />
    @@ -951,6 +953,7 @@ t-att-tabindex="widget.node.attrs.tabindex" t-att-autofocus="widget.node.attrs.autofocus" t-att-placeholder="! widget.get('effective_readonly') ? widget.node.attrs.placeholder : ''" + t-att-maxlength="widget.field.size" > Date: Tue, 18 Sep 2012 17:30:35 +0200 Subject: [PATCH 61/65] [IMP]kanban : div widget many2many_tags => field bzr revid: chm@openerp.com-20120918153035-xutvjflw057s8t18 --- addons/web_kanban/static/src/js/kanban.js | 40 +++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index fe15b22feee..6d68e62899a 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -71,6 +71,9 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ this.fields_keys = _.keys(this.fields_view.fields); this.add_qweb_template(); this.has_been_loaded.resolve(); + + this._super.apply(this, arguments); + return $.when(); }, _is_quick_create_enabled: function() { @@ -85,6 +88,9 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ return false; return this._super(action); }, + /* add_qweb_template + * select the nodes into the xml and send to extract_aggregates the nodes with TagName="field" + */ add_qweb_template: function() { for (var i=0, ii=this.fields_view.arch.children.length; i < ii; i++) { var child = this.fields_view.arch.children[i]; @@ -97,6 +103,9 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ } } }, + /* extract_aggregates + * extract the agggregates from the nodes (TagName="field") + */ extract_aggregates: function(node) { for (var j = 0, jj = this.group_operators.length; j < jj; j++) { if (node.attrs[this.group_operators[j]]) { @@ -121,9 +130,15 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ } switch (node.tag) { case 'field': - node.tag = QWeb.prefix; - node.attrs[QWeb.prefix + '-esc'] = 'record.' + node.attrs['name'] + '.value'; - this.extract_aggregates(node); + if(this.fields_view.fields[ node.attrs['name'] ].type == 'many2many'){ + node.tag = 'div'; + node.attrs['class'] = 'oe_kanban_many2many_tags'; + node.attrs['model'] = this.fields_view.fields[node.attrs['name']].relation; + node.attrs['t-att-data'] = 'record.' + node.attrs['name'] + '.raw_value'; + }else { + node.tag = QWeb.prefix; + node.attrs[QWeb.prefix + '-esc'] = 'record.' + node.attrs['name'] + '.value'; + } break; case 'button': case 'a': @@ -163,17 +178,16 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ } } }, - /* widget for list of tags/categories... - * make :
    + /* widget for list of tags/categories... */ transform_widget_many2many: function(){ var self=this, arg={}; // select all widget - self.$el.find("[widget='many2many_tags']").each(function(){ - var model = $(this).attr("model"), - data = $(this).attr("data"), - list = data.split(","); + self.$el.find(".oe_kanban_many2many_tags").each(function(){ + var model = $(this).attr("model"); + var data = $(this).attr("data"); + var list = data.split(","); //select all id (per model) if(!arg[model]) arg[model]=[]; for(var t=0;t'+result[t][1]+''); } - }, - function(r){ - console.log('Error',r); } ); } @@ -717,6 +728,9 @@ instance.web_kanban.KanbanRecord = instance.web.Widget.extend({ transform_record: function(record) { var self = this, new_record = {}; + + console.log(this, record); + _.each(record, function(value, name) { var r = _.clone(self.view.fields_view.fields[name] || {}); if ((r.type === 'date' || r.type === 'datetime') && value) { From 24ed9b15630e0c772cbcfab98fe456f6f82d024f Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 18 Sep 2012 18:59:02 +0200 Subject: [PATCH 62/65] [IMP]kanban: css bzr revid: chm@openerp.com-20120918165902-c5nh169w4c1ur14v --- addons/web_kanban/static/src/css/kanban.css | 4 ++++ addons/web_kanban/static/src/css/kanban.sass | 3 +++ 2 files changed, 7 insertions(+) diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 48cf725ead3..fec1bc508ec 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -143,6 +143,10 @@ position: relative; top: -8px; } +.openerp .oe_kanban_view .oe_kanban_add, .openerp .oe_kanban_view .oe_kanban_card .oe_dropdown_toggle { + cursor: pointer; + display:inline-block; +} .openerp .oe_kanban_view .oe_kanban_add { float: right; } diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass index 95a63dbd1a2..5ae4c9c4f10 100644 --- a/addons/web_kanban/static/src/css/kanban.sass +++ b/addons/web_kanban/static/src/css/kanban.sass @@ -154,6 +154,9 @@ cursor: pointer position: relative top: -8px + .oe_kanban_card, .oe_dropdown_toggle + cursor: pointer + display:inline-block .oe_kanban_add float: right From 3ad1a9614378f606721d1ee904e130fd1fe5dbb8 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 18 Sep 2012 19:19:47 +0200 Subject: [PATCH 63/65] [IMP]kanban: correctif bzr revid: chm@openerp.com-20120918171947-f2114v0oa0cu8wb7 --- addons/web_kanban/static/src/js/kanban.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index d5389c6fa0b..970a4e81fca 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -396,6 +396,8 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ } else { this.$el.find('.oe_kanban_draghandle').removeClass('oe_kanban_draghandle'); } + + this.transform_widget_many2many(); }, on_record_moved : function(record, old_group, old_index, new_group, new_index) { var self = this; @@ -811,7 +813,7 @@ instance.web_kanban.KanbanRecord = instance.web.Widget.extend({ } }); - if (this.$el.find('.oe_kanban_global_click').length) { + if (this.$el.find('.oe_kanban_global_click,.oe_kanban_global_click_edit').length) { this.$el.on('click', function(ev) { if (!ev.isTrigger && !$(ev.target).data('events')) { var trigger = true; @@ -852,8 +854,15 @@ instance.web_kanban.KanbanRecord = instance.web.Widget.extend({ }); } }, + /* actions when user click on the block with a specific class + * open on normal view : oe_kanban_global_click + * open on form/edit view : oe_kanban_global_click_edit + */ on_card_clicked: function(ev) { - this.view.open_record(this.id); + if(this.$el.find('.oe_kanban_global_click_edit').size()>0) + this.do_action_edit(); + else + this.do_action_open(); }, setup_color_picker: function() { var self = this; From ab8722f1b4d4de2aacc7e42a77ce08cb141ab86e Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 18 Sep 2012 21:38:56 +0200 Subject: [PATCH 64/65] [IMP] kanban: field many2many_tags bzr revid: chm@openerp.com-20120918193856-2lq5q8lnw3dtpqbe --- addons/base_setup/res_partner_view.xml | 2 +- addons/hr_recruitment/hr_recruitment_view.xml | 4 +--- addons/note/note_view.xml | 2 ++ addons/portal_project_issue/portal_project_issue_view.xml | 1 + addons/project_issue/project_issue_view.xml | 4 +--- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/addons/base_setup/res_partner_view.xml b/addons/base_setup/res_partner_view.xml index 57e8d70531d..15b80151831 100644 --- a/addons/base_setup/res_partner_view.xml +++ b/addons/base_setup/res_partner_view.xml @@ -9,7 +9,7 @@ - + diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml index 098a8aec210..08e5f31a2d2 100644 --- a/addons/hr_recruitment/hr_recruitment_view.xml +++ b/addons/hr_recruitment/hr_recruitment_view.xml @@ -314,9 +314,7 @@
    diff --git a/addons/note/note_view.xml b/addons/note/note_view.xml index ca684b42522..b356efc9549 100644 --- a/addons/note/note_view.xml +++ b/addons/note/note_view.xml @@ -82,7 +82,9 @@ + +
    diff --git a/addons/portal_project_issue/portal_project_issue_view.xml b/addons/portal_project_issue/portal_project_issue_view.xml index 5d0b4ce081e..1030dedbdf8 100644 --- a/addons/portal_project_issue/portal_project_issue_view.xml +++ b/addons/portal_project_issue/portal_project_issue_view.xml @@ -27,6 +27,7 @@ +
    Creation: diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index fea22c519a8..be7427fe8f4 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -269,9 +269,7 @@