diff --git a/addons/web_linkedin/__init__.py b/addons/web_linkedin/__init__.py new file mode 100644 index 00000000000..92b70f98cf8 --- /dev/null +++ b/addons/web_linkedin/__init__.py @@ -0,0 +1,2 @@ +import res_config +import web_linkedin \ No newline at end of file diff --git a/addons/web_linkedin/__openerp__.py b/addons/web_linkedin/__openerp__.py new file mode 100644 index 00000000000..680bef0c47b --- /dev/null +++ b/addons/web_linkedin/__openerp__.py @@ -0,0 +1,27 @@ +{ + "name" : "LinkedIn Integration", + 'version': '0.1', + 'category': 'Tools', + 'complexity': "easy", + "description": + """ + OpenERP Web LinkedIn module. + This module provides the Integration of the LinkedIn with OpenERP. + """, + 'update_xml': [ + 'res_partner_view.xml', + 'res_config_view.xml', + ], + "depends" : ["base"], + "js": [ + "static/src/js/*.js" + ], + "css": [ + "static/src/css/*.css" + ], + 'qweb': [ + "static/src/xml/*.xml" + ], + 'installable': True, + 'auto_install': False, +} diff --git a/addons/web_linkedin/res_config.py b/addons/web_linkedin/res_config.py new file mode 100644 index 00000000000..e3e70237086 --- /dev/null +++ b/addons/web_linkedin/res_config.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (C) 2004-2012 OpenERP S.A. (). +# +# 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 + +class base_config_settings(osv.osv_memory): + _inherit = 'base.config.settings' + _name = 'base.config.settings' + _columns = { + 'default_linkedin_api_key': fields.char('LinkedIn API key', size=128, required=True, default_model='res.company', + help="""Give API key of linkedin."""), + 'generate_key': fields.text('Go to URL', readonly=True, + help="""If you have not generate linkedin API Key yet than Go to URL to generate and enter it in above text field."""), + } + _defaults = { + 'generate_key': "To find contact persons from LinkedIn "\ + "\n====================================="\ + "\n* Go to this URL : www.linkedin.com/secure/developer "\ + "\n* Add New Application and fill the form,"\ + "\n - JavaScript API Domain is Your domain name (e.g. abc.com),"\ + "\n - You can give multiple domain (e.g. abc.com, xyz.com)"\ + "\n - programming tools is Javascript"\ + '\n* Copy the "API Key" and paste it in the field "LinkedIn API Key" here above".' + } + + def execute(self, cr, uid, ids, context=None): + super(base_config_settings,self).execute(cr, uid, ids, context=context) + company_obj = self.pool.get('res.company') + data = self.browse(cr, uid, ids[0], context=context) + company_id = company_obj._company_default_get(cr, uid, 'res.users', context=context) + company_obj.write(cr, uid, [company_id], {'default_linkedin_api_key': data.default_linkedin_api_key}, context=context) + +base_config_settings() +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/web_linkedin/res_config_view.xml b/addons/web_linkedin/res_config_view.xml new file mode 100644 index 00000000000..2fef772d0b6 --- /dev/null +++ b/addons/web_linkedin/res_config_view.xml @@ -0,0 +1,26 @@ + + + + General Settings + base.config.settings + + form + 20 + + + + + + + + + + + + + + + + + + diff --git a/addons/web_linkedin/res_partner_view.xml b/addons/web_linkedin/res_partner_view.xml new file mode 100644 index 00000000000..6b8725f60fe --- /dev/null +++ b/addons/web_linkedin/res_partner_view.xml @@ -0,0 +1,36 @@ + + + + + res.partner.linkedin.inherit + res.partner + form + + + + + + + + + + + + + + res.company.linkedin.inherit + res.company + form + + + + + + + + + + + + + diff --git a/addons/web_linkedin/static/src/css/linkedin.css b/addons/web_linkedin/static/src/css/linkedin.css new file mode 100644 index 00000000000..0ca3dc90ac9 --- /dev/null +++ b/addons/web_linkedin/static/src/css/linkedin.css @@ -0,0 +1,39 @@ +.ul-ldn-dropdown { + list-style: none outside none; + padding: 1px; + max-height: 500px; + margin: 0px; + background-color: rgb(255, 255, 255); + border: 1px solid rgb(153, 153, 153); +} + +.li-ldn-dropdown { + margin: 0px; + display: block; + cursor: default; + padding: 3px; + border: 1px solid rgb(255, 255, 255); + background-color: transparent; +} +.li-ldn-dropdown td{ + font-size:10px; + font-weight:normal; + padding: 2px 2px 0px; +} + +.li-ldn-dropdown:hover { + margin: 0px; + display: block; + cursor: pointer; + border: 1px solid rgb(10, 36, 106); + background-color: rgb(182, 189, 210) +} + +.search-box { + background: none repeat scroll 0 0%, -moz-linear-gradient(#EFEFEF, #D8D8D8) repeat scroll 0 0 transparent; + background: none repeat scroll 0 0%, -webkit-linear-gradient(#EFEFEF, #D8D8D8) repeat scroll 0 0 transparent; + border: 1px solid #ABABAB; + border-radius: 3px 3px 3px 3px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + max-height: 450px; +} diff --git a/addons/web_linkedin/static/src/img/Linkedin_blue.png b/addons/web_linkedin/static/src/img/Linkedin_blue.png new file mode 100644 index 00000000000..c37d0218f7d Binary files /dev/null and b/addons/web_linkedin/static/src/img/Linkedin_blue.png differ diff --git a/addons/web_linkedin/static/src/img/Linkedin_grey.png b/addons/web_linkedin/static/src/img/Linkedin_grey.png new file mode 100644 index 00000000000..726e012f220 Binary files /dev/null and b/addons/web_linkedin/static/src/img/Linkedin_grey.png differ diff --git a/addons/web_linkedin/static/src/img/icon.png b/addons/web_linkedin/static/src/img/icon.png new file mode 100644 index 00000000000..119f74abdd3 Binary files /dev/null and b/addons/web_linkedin/static/src/img/icon.png differ diff --git a/addons/web_linkedin/static/src/img/linkedin-profile.gif b/addons/web_linkedin/static/src/img/linkedin-profile.gif new file mode 100644 index 00000000000..e347e5e3ff8 Binary files /dev/null and b/addons/web_linkedin/static/src/img/linkedin-profile.gif differ diff --git a/addons/web_linkedin/static/src/img/loading.png b/addons/web_linkedin/static/src/img/loading.png new file mode 100644 index 00000000000..5ab0089fccb Binary files /dev/null and b/addons/web_linkedin/static/src/img/loading.png differ diff --git a/addons/web_linkedin/static/src/img/twitt-follow.png b/addons/web_linkedin/static/src/img/twitt-follow.png new file mode 100644 index 00000000000..684813a1ee4 Binary files /dev/null and b/addons/web_linkedin/static/src/img/twitt-follow.png differ diff --git a/addons/web_linkedin/static/src/js/linkedin.js b/addons/web_linkedin/static/src/js/linkedin.js new file mode 100644 index 00000000000..e48b7fa7a9a --- /dev/null +++ b/addons/web_linkedin/static/src/js/linkedin.js @@ -0,0 +1,667 @@ +/*--------------------------------------------------------- + * OpenERP web_linkedin (module) + *---------------------------------------------------------*/ + +openerp.web_linkedin = function(instance) { + var QWeb = instance.web.qweb; + var _t = instance.web._t; + instance.web.form.widgets.add( + 'Linkedin', 'instance.web_linkedin.Linkedin'); + instance.web_linkedin.Linkedin = instance.web.form.FieldChar.extend({ + template: 'Linkedin', + isAuthorized: false, + render_value: function() { + this._super(); + var self = this; + this.$element.find('#loader').hide(); + if (!this.get("effective_readonly")) { + this._super(); + var context = new instance.web.CompoundContext(this.build_context()); + var build_context = this.build_context(); + this.apikey = build_context.__contexts[0].api_key; + if(this.view.fields['linkedin_id']){ + if(this.view.datarecord['linkedin_id']){ + this.$element.find('#linkedindefault').hide(); + this.$element.find('#linkedinrecord').show(); + }else{ + this.$element.find('#linkedinrecord').hide(); + this.$element.find('#linkedindefault').show(); + } + } + try { + IN.init({ api_key : this.apikey }); + } catch(e) { + if(!this.apikey){ + this.APIWarning = e; + } + if (e.type == "undefined_method") { + this.APIWarning = e; + } + } + var head = document.head || document.getElementsByTagName('head')[0]; + var tag = document.createElement('script'); + tag.type = 'text/javascript'; + tag.src = "http://platform.linkedin.com/in.js"; + if(this.apikey){ + // Registered API key is necessary to integrate with LinkedIn. + tag.innerHTML = 'api_key : '+this.apikey+'\n'; + } + tag.innerHTML = tag.innerHTML + 'authorize : true'; + // On load script Loading text is displayed + /*if(this.$element.find("#imagediv").find('.oe_loading')){ + this.$element.find("#imagediv").find('.oe_loading').remove(); + } + tag.onload=this.$element.find("#imagediv").append('Loading....');*/ + var temp = 0; + $(head).find('script').each( function(i,val) { + if($(val).attr('src')=="http://platform.linkedin.com/in.js"){ + temp = 1; + } + }); + if(temp != 1) { + head.appendChild( tag ); + } + this.notification = new instance.web.Notification(this); + this.notification.appendTo(this.$element); + this.$element.find(".linkedin_icon").click( this.do_load_linkedin ); + this.removeTemplate(); + if(this.view.fields['name'].get_value()!=false){ + /* if value get then display button of profile url */ + if (this.view.fields['profile_id'].get_value() || this.view.datarecord['profile_id']) { + this.setTemplate(this.view.datarecord['profile_id'] , false ); + } + /* if value get then display button of twitter */ + if (this.view.fields['twitter_id'].get_value() || this.view.datarecord['twitter_id']) { + this.setTemplate( false, this.view.datarecord['twitter_id']); + } + } + if (this.view.datarecord['linkedin_id']) { + if (this.view.datarecord['profile_id'] && !this.view.datarecord['twitter_id']) { + if (this.$element.find('#twitterid')) { + this.$element.find('#twitterid').remove(); + } + } + else if (!this.view.datarecord['profile_id'] && this.view.datarecord['twitter_id']) { + if (this.$element.find('#profileid')) { + this.$element.find('#profileid').remove(); + } + } + }else{ + this.removeTemplate(); + } + } else { + this.removeTemplate(); + if(this.view.fields['name'].get_value()!=false){ + var tagtr = document.createElement('tr'); + tagtr.id = "profiletwittor-tr"; + this.$element.append(tagtr); + /* if value get then display button of profile url */ + if (this.view.fields['profile_id'] && this.view.datarecord['profile_id']) { + this.setTemplate( this.view.datarecord['profile_id'] , false ); + } + /* if value get then display button of twitter */ + if (this.view.fields['twitter_id'] && this.view.datarecord['twitter_id']) { + this.setTemplate( false, this.view.datarecord['twitter_id'] ); + } + } + } + }, + APIKeyWarning: function(e) { + e.message= "Linkedin API Key is not registerd/correct.\n Go to Settings, 'General Settings' menu and follow steps to register the LinkedIn API Key."; + instance.web.dialog($(QWeb.render("CrashManager.warning", _t(e))), { + title: _t("Linkedin API Key Warning"), + modal: true, + height: 200, + width: 500, + buttons: [ + { + text: _t("Ok"), + click: function() { $(this).dialog("close"); } + }] + }); + }, + setTemplate: function( URL, AccountName ) { + if(AccountName){ + var AccountName = AccountName.replace(/[^a-zA-Z 0-9]+/g, ''); + Twitt = "https://twitter.com/intent/follow?original_referer=http%3A%2F%2Flocalhost%3A8069%2Fweb%2Fwebclient%2Fhome&screen_name="+AccountName+"&source=followbutton&variant=2.0" + this.$element.find('tr#profiletwittor-tr').append(QWeb.render('TwitterURL',{'URLID': Twitt, 'account': AccountName})) + }else if(URL){ + this.$element.find('tr#profiletwittor-tr').append(QWeb.render('ProfileURL',{'URLID': URL })) + } + }, + removeTemplate: function( flag ) { + if (flag) { + this.$element.find('#searchresults').remove(); + } else { + if (this.$element.find('#profileid')) { + this.$element.find('#profileid').remove(); + } + if (this.$element.find('#twitterid')) { + this.$element.find('#twitterid').remove(); + } + } + }, + /* Load Linkedin Data On search */ + do_load_linkedin: function( e ) { + var self = this; + this.msg_Counter=0; /* used to display notification, when record not found on Linkedin search */ + this.removeTemplate( 1 ); + if(!this.apikey){ + this.APIKeyWarning(this.APIWarning); + e.preventDefault(); + e.stopPropagation(); + e.stopImmediatePropagation(); + return false; + } + if (IN.ENV.auth.oauth_token) { + if (self.$element.find("input").val()) { + self.$element.find('#loader').show(); + $('.linkedin_icon').css('display', 'none'); + /* People Search */ + IN.API.Raw("/people-search:(people:(id,first-name,last-name,picture-url,public-profile-url,formatted-name,location,phone-numbers,im-accounts,main-address,headline))") + .params({ + "first-name": self.$element.find("input").val(), + "count" : 4 + }) + .result( self.do_fetch_detail ); + /* Company Search */ + IN.API.Raw("/company-search:(companies:(id,name,description,industry,logo-url,website-url,locations,twitter-id))") + .params({ + "keywords": self.$element.find("input").val(), + "count" : 4 + }) + .result( self.do_fetch_detail ); + }else{ + this.notification.warn(_t("Linkedin Search"), _t("Please Enter Required Field.")); + } + } + else { + self.do_authorize(); + } + e.preventDefault(); + e.stopPropagation(); + e.stopImmediatePropagation(); + }, + do_authorize: function(resultCallback){ + this.check_authorized(); + if (this.isAuthorized == false){ + IN.User.authorize(resultCallback); + } + }, + check_authorized: function(){ + this.isAuthorized = IN.User.isAuthorized(); + }, + /* Fetch Result from Linkedin and set in searchbox */ + do_fetch_detail: function(result, metadata) { + var self = this; + if (result.people) { + if (result.people._total==0) { + this.msg_Counter++; + } + var count = 0; + for (i in result.people.values) { + var temp = self.validName(result.people.values[i].firstName, result.people.values[i].lastName) + if (temp) { + count++; + } + } + if (count == 4 || count==result.people._total) { + result.people._total = 0; + } + this.resultcontact = result; + }else if (result.companies) { + if (result.companies._total == 0) { + this.msg_Counter++; + } + this.resultcompany = result; + } + this.removeTemplate( 1 ); + if (this.msg_Counter == 2) { + // dialog box + /*new instance.web.dialog($(QWeb.render("SearchWarning")), { + title: _t("Linkedin Search"), + modal: true, + buttons: [ + {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + ] + });*/ + // notification + this.notification.warn(_t("Linkedin Search"), _t("Record Not Found.")); + this.$element.find('#loader').hide(); + if(this.view.fields['linkedin_id']){ + if(this.view.datarecord['linkedin_id']){ + this.$element.find('#linkedindefault').hide(); + this.$element.find('#linkedinrecord').show(); + }else{ + this.$element.find('#linkedinrecord').hide(); + this.$element.find('#linkedindefault').show(); + } + } + } else { + if (this.resultcontact || this.resultcompany) { + this.$element.find('#linkedin-field-name').append(QWeb.render( 'Linkedincontact', {'result' : this.resultcontact, 'resultcompany' : this.resultcompany})) ; + } + } + if(this.$element.find('#searchresults .search-box ul li')){ + this.$element.find('#loader').hide(); + if(this.view.fields['linkedin_id']){ + if(this.view.datarecord['linkedin_id']){ + this.$element.find('#linkedindefault').hide(); + this.$element.find('#linkedinrecord').show(); + }else{ + this.$element.find('#linkedinrecord').hide(); + this.$element.find('#linkedindefault').show(); + } + } + } + this.$element.find('#searchresults .search-box ul li').click( function() { + self.getdata( this ); + }); + $(document).click( function() { + self.removeTemplate( 1 ); + }); + }, + /* Selected record's data fetched */ + getdata: function( e ) { + var self = this; + if (this.resultcontact) { + for (i in this.resultcontact.people.values) { + if (self.resultcontact.people.values[i].id == $(e).attr('id')) { + self.removeTemplate( 1 ); + this.getTwitterAccount( self.resultcontact.people.values[i] ) + } + } + } + if(this.resultcompany){ + for ( i in this.resultcompany.companies.values ) { + if ( self.resultcompany.companies.values[i].id == $(e).attr('id') ) { + self.removeTemplate( 1 ); + self.map_values(self.resultcompany.companies.values[i]); + } + } + } + }, + /* Based on Linkedin Id of record fetch Twitter Account Detail for People */ + getTwitterAccount: function( values, flag, mainfield ){ + var self = this; + IN.API.Profile(values.id).fields('twitter-accounts') + .result(function(acname){ + values.twitterAccounts = acname.values[0].twitterAccounts + if(flag){ + self.map_values(values, flag, mainfield); + }else{ + self.map_values(values); + } + }); + }, + /* Mapping of Linkedin Fields with res.partner Fields + linkedinrecord : contains linkedin record's data + flag : indicates mapping of People search record or for company's contacts/connections (people) + if(flag) mapping for contacts of company + if(!flag) mapping for people search + mainfield : class of child_ids field + */ + map_values: function (linkedinrecord, flag, mainfield){ + var self = this, tempdata = {}, temp_data = 0, id = this.view.datarecord.id; + _(this.view.fields).each(function (field, f) { + if (f=='name') { + if (!flag) { + if (linkedinrecord.formattedName) { + field.set_value(linkedinrecord['formattedName'] || false); + } else if(linkedinrecord.name) { + field.set_value(linkedinrecord['name'] || false); + } + } else { + tempdata[f] = linkedinrecord.firstName+' '+linkedinrecord.lastName; + } + } + else if (f=='property_account_payable') { + if(flag == 1)tempdata[f] = field.get_value() + } + else if (f=='property_account_receivable') { + if(flag == 1)tempdata[f] = field.get_value() + } + else if (f=='type') { + (flag == 1) ? tempdata[f] = field.get_value() : field.get_value(); + } + else if (f=='linkedin_id') { + (flag == 1) ? tempdata[f] = linkedinrecord['id'] : field.set_value(linkedinrecord['id']); + } + else if (f=='profile_id') { + if (linkedinrecord.publicProfileUrl) { + (flag == 1) ? tempdata[f] = linkedinrecord.publicProfileUrl : field.set_value(linkedinrecord.publicProfileUrl); + } else { + field.set_value(false); + tempdata[f] = false; + } + } + else if (f=='twitter_id') { + if (linkedinrecord.twitterAccounts && linkedinrecord.twitterAccounts._total >= 1) { + (flag == 1) ? tempdata[f] = linkedinrecord.twitterAccounts.values[0].providerAccountName : field.set_value(linkedinrecord.twitterAccounts.values[0].providerAccountName); + }else if (linkedinrecord.twitterId) { + (flag == 1) ? tempdata[f] = linkedinrecord.twitterId : field.set_value(linkedinrecord.twitterId); + } else { + (flag == 1) ? tempdata[f] = false : field.set_value(false); + } + } + else if (f=='mobile') { + if (!flag && linkedinrecord.phoneNumbers && linkedinrecord['phoneNumbers']._total>=1 && linkedinrecord['phoneNumbers'].values[0].phoneType == "mobile") { + field.set_value( linkedinrecord['phoneNumbers'].values[0].phoneNumber || false ); + }else if (flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='phone') { + if (!flag && linkedinrecord.phoneNumbers && linkedinrecord['phoneNumbers']._total>=1 && linkedinrecord['phoneNumbers'].values[0].phoneType != "mobile") { + field.set_value(linkedinrecord['phoneNumbers'].values[0].phoneNumber || false); + } else if(flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='email') { + if (!flag && linkedinrecord.imAccounts && linkedinrecord['imAccounts']._total>=1) { + field.set_value(linkedinrecord['imAccounts'].values[0].imAccountName); + } else if(flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='photo') { + if (!flag) { + if (linkedinrecord.pictureUrl && linkedinrecord['pictureUrl']) { + /* Fetch binary data from URL for People */ + self.rpc('/web_linkedin/binary/url2binary',{'url':linkedinrecord['pictureUrl']},function(data){ + field.set_value(data); + }); + } else if (linkedinrecord.logoUrl && linkedinrecord['logoUrl']) { + /* Fetch binary data from URL for Company */ + self.rpc('/web_linkedin/binary/url2binary',{'url':linkedinrecord['logoUrl']},function(data){ + field.set_value(data); + }); + } else { + field.set_value(false); + } + } + else{ + if (linkedinrecord['pictureUrl']) { + temp_data = 1; + /* Fetch binary data from URL for contact of Company */ + self.rpc('/web_linkedin/binary/url2binary',{'url':linkedinrecord['pictureUrl']}).done(function(res){ + tempdata[f] = res; + self.set_o2mdata(tempdata,mainfield) + }); + } else { + tempdata[f] = "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 TkSuQmCC"; + } + } + } + else if (f=='street') { + if (!flag && linkedinrecord.mainAddress && linkedinrecord['mainAddress']) { + field.set_value(linkedinrecord['mainAddress']); + } else if(flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='country_id') { + if (!flag && linkedinrecord.location && linkedinrecord['location']) { + field.field.domain = [['code', '=', linkedinrecord['location'].country['code'].toUpperCase()]]; + (new instance.web.DataSetSearch(self, field.field.relation,field.field.context,field.field.domain)).read_slice(['id','name'],{}).then(function(res){ + field.original_value = [res[0].id, res[0].name]; + field.set_value(res[0].id) + }) + } else if (!flag && linkedinrecord.locations && linkedinrecord.locations._total>0) { + if (linkedinrecord.locations.values[0].address['country-code']) { + field.field.domain = ['code', '=', linkedinrecord.locations.values[0].address['country-code'].toUpperCase()]; + (new instance.web.DataSetSearch(self, field.field.relation,field.field.context,field.field.domain)).read_slice(['id','name'],{}).then(function(res){ + field.original_value = [res[0].id, res[0].name]; + field.set_value(res[0].id) + }) + } else { + field.set_value(false); + } + } else if(flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='city') { + if (!flag && linkedinrecord.location && linkedinrecord['location']) { + field.set_value(linkedinrecord['location'].name.split(' ')[0] || false); + } else if (!flag && linkedinrecord.locations && linkedinrecord.locations._total>0) { + if (linkedinrecord.locations.values[0].address['city']) { + field.set_value(linkedinrecord.locations.values[0].address['city']); + } else { + field.set_value(false); + } + } else if (flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='website') { + if (!flag && linkedinrecord.websiteUrl) { + field.set_value(linkedinrecord['websiteUrl'] || false); + } else if (flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='customer') { + if(flag == 1)tempdata[f] = true; + } + else if (f=='supplier') { + } + else if (f=='active') { + (flag == 1) ? tempdata[f] = true : field.set_value(true); + } + else if (f=='is_company') { + if (!flag && linkedinrecord.formattedName) { + field.set_value(false); + } else { + field.set_value(true); + tempdata[f] = false; + } + } + else if (f=='zip') { + if (!flag && linkedinrecord.locations && linkedinrecord.locations._total>0) { + if (linkedinrecord.locations.values[0].address['postalCode']) { + field.set_value(linkedinrecord.locations.values[0].address['postalCode']); + } else { + field.set_value(false); + } + }else if (flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='parent_id') { + if (!flag && linkedinrecord.formattedName) { + field.set_value(false); + } else if (!flag && linkedinrecord.name) { + field.set_value(false); + } else { + if (linkedinrecord.formattedName) { + tempdata[f] = [id,self.view.fields['name'].get_value()]; + } + } + } + else if (f=='fax') { + if (!flag && linkedinrecord.locations && linkedinrecord.locations._total>0) { + if (linkedinrecord.locations.values[0].contactInfo['fax']) { + field.set_value(linkedinrecord.locations.values[0].contactInfo['fax']); + } else { + field.set_value(false); + } + } else if (flag == 1) { + tempdata[f] = field.get_value(); + } else { + field.set_value(false); + } + } + else if (f=='use_parent_address') { + (flag == 1) ? tempdata[f] = true : field.set_value(false); + } + else if (f=='child_ids') { + /* For Company Set value of child_ids field */ + if (!flag && linkedinrecord.name) { + self.$element.find('#loader').show(); + $('.linkedin_icon').css('display', 'none'); + /* Fetch contact of Company */ + IN.API.Raw("/people-search:(people:(id,first-name,last-name,formatted-name,picture-url,publicProfileUrl,phone-numbers,im-accounts,main-address,location,relation-to-viewer:(related-connections)))") + //"id", "firstName", "lastName", "pictureUrl", "publicProfileUrl", "formatted-name", "headline", "location", "industry", "languages", "phone-numbers", "im-accounts", "main-address" + .params({ + "company-name" : linkedinrecord.name, + "current-company": true, + "count" : 25 + }) + .result( function (getresult){ + if(getresult.people._total==0){ + self.$element.find('#loader').hide(); + if(self.view.fields['linkedin_id']){ + if(self.view.datarecord['linkedin_id']){ + self.$element.find('#linkedindefault').hide(); + self.$element.find('#linkedinrecord').show(); + }else{ + self.$element.find('#linkedinrecord').hide(); + self.$element.find('#linkedindefault').show(); + } + } + } + self.totalids = [],self.updteids = []; + _(field.dataset.ids).each( function(i) { + if (typeof(i)=="number") { + self.totalids.push(i); + var mobile = self.view.fields['mobile'].get_value(); + var phone = self.view.fields['phone'].get_value(); + var email = self.view.fields['email'].get_value(); + var fax = self.view.fields['fax'].get_value(); + var website = self.view.fields['website'].get_value(); + var zip = self.view.fields['zip'].get_value(); + var city = self.view.fields['city'].get_value(); + var country_id = self.view.fields['country_id'].get_value(); + var street = self.view.fields['street'].get_value(); + field.dataset.write(i,{'mobile':mobile,'phone':phone,'email':email,'fax':fax,'website':website,'zip':zip,'city':city,'country_id':country_id,'street':street},{}); + } + }); + field.dataset.ids = self.totalids; + var counter = 0;/* Indicates All searched records are Invalid or valid */ + self.t_count=0; + self.o2m_count = 0; + for (i in getresult.people.values) { + var connectTemp = self.validName(getresult.people.values[i].firstName, getresult.people.values[i].lastName) + if (connectTemp) { + counter++; + } else { + self.t_count++; + self.getTwitterAccount(getresult.people.values[i], 1, field); + } + } + if (getresult.people._count) { + var total_Count = getresult.people._count; + }else if (getresult.people._total) { + var total_Count = getresult.people._total; + } + /* If counter == total no. of people then all searched records are invalid */ + if (counter == total_Count) { + field.dataset.to_create = []; + field.dataset.ids = []; + field.reload_current_view(); + }else if(getresult.people._total == 0 || getresult.people._count == 0){ + field.dataset.ids = self.totalids; + field.reload_current_view(); + } + }); + } + /* For People Set value of child_ids field */ + else if (!flag && linkedinrecord.formattedName) { + field.set_value(false); + field.set({'invisible':true}); + } + /* For Contact of company Set value of child_ids field */ + else { + tempdata[f] = false; + } + } + else { + (flag == 1) ? tempdata[f] = false : field.set_value(false); + } + field._dirty_flag = true; + field.on('changed_value', self, function() { + if (!flag) { + self.view.do_onchange(field); + self.view.on_form_changed(true); + self.view.do_notify_change(); + } + }); + }); + if (!flag) { + this.removeTemplate(); + if (linkedinrecord.publicProfileUrl) { + this.setTemplate( linkedinrecord.publicProfileUrl , false ); + } + if (linkedinrecord.twitterId) { + this.setTemplate( false , linkedinrecord.twitterId ); + } + if (linkedinrecord.twitterAccounts && linkedinrecord.twitterAccounts._total >= 1) { + this.setTemplate( false , linkedinrecord.twitterAccounts.values[0].providerAccountName ); + } + } + if (flag && temp_data == 0) { + self.set_o2mdata(tempdata, mainfield); + } + }, + /* Update existing value of child_ids field */ + set_childids: function( ids ) { + var self = this; + _(ids).each(function(i){ + self.view.fields['child_ids'].dataset.set_ids(self.view.fields['child_ids'].dataset.ids.concat([i])); + self.view.fields['child_ids'].dataset.write(i, {"parent_id":false}, {}); + }); + }, + /* Set/create o2m contacts of child_ids field */ + set_o2mdata: function(data,field){ + var self = this; + self.o2m_count++; + field.dataset.create(data).then( function(r) { + self.totalids.push(r.result); + field.dataset.set_ids(field.dataset.ids.concat([r.result])); + field.dataset.on_change(); + }).then(); + field.dataset.ids = self.totalids; + field.reload_current_view(); + if (self.t_count == self.o2m_count) { + self.$element.find('#loader').hide(); + //$('.linkedin_icon').css('display', 'block'); + if(this.view.fields['linkedin_id']){ + if(this.view.datarecord['linkedin_id']){ + this.$element.find('#linkedindefault').hide(); + this.$element.find('#linkedinrecord').show(); + }else{ + this.$element.find('#linkedinrecord').hide(); + this.$element.find('#linkedindefault').show(); + } + } + } + }, + /* Name of Searched Linkedin Record is valid or Not */ + validName: function(fname, lname){ + if ((fname == "Private" || fname == "private") || (lname == "Private" || lname == "private") || (fname == "" && lname == "")) { + return true; + } else { + return false; + } + } + }); +}; +// vim:et fdc=0 fdl=0: diff --git a/addons/web_linkedin/static/src/xml/linkedin.xml b/addons/web_linkedin/static/src/xml/linkedin.xml new file mode 100644 index 00000000000..9321e54787d --- /dev/null +++ b/addons/web_linkedin/static/src/xml/linkedin.xml @@ -0,0 +1,124 @@ + + + + + + + + + + +
+ + +
+ + + Search on LinkedIn + Search on LinkedIn + + + +
+
+
+ + + + + View profile on LinkedIn + + + + + + + + Follow + + + + +
Record Not Found.
+
+ +
+ +
+
+ + + + + + + +
+ + +
    +
  • + + + + + +
    + + + + + + + +
    + +
    +
  • +
+ + +
+
+
\ No newline at end of file diff --git a/addons/web_linkedin/web_linkedin.py b/addons/web_linkedin/web_linkedin.py new file mode 100644 index 00000000000..77327b92bde --- /dev/null +++ b/addons/web_linkedin/web_linkedin.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# 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 . +# +############################################################################## +import base64 +import urllib2 +import xmlrpclib +import zlib + +from web import common +openerpweb = common.http + +from osv import fields, osv + +class company(osv.osv): + _inherit = 'res.company' + _columns = { + 'default_linkedin_api_key': fields.char('LinkedIn API key', size=128), + } + +company() + +class res_partner(osv.osv): + _inherit = 'res.partner' + + _columns = { + 'linkedin_id': fields.char('Linkedin Id', size=64), + 'twitter_id': fields.char('Twitter', size=128), + 'profile_id': fields.char('Profile URL', size=240), + } + + def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): + company_obj = self.pool.get('res.company') + res = super(res_partner, self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu) + company_id = company_obj._company_default_get(cr, user, 'res.users', context=context) + linkedin_api_key = company_obj.browse(cr, user, company_id, context=context).default_linkedin_api_key + fields = res['fields'] + if fields.get('name'): + ctx = fields.get('name').get('context') + if ctx is None: + ctx = {} + ctx.update({'api_key': linkedin_api_key}) + fields.get('name')['context'] = ctx + return res + +res_partner() + +class Binary(openerpweb.Controller): + _cp_path = "/web_linkedin/binary" + + @openerpweb.jsonrequest + def url2binary(self, req,url): + bfile = urllib2.urlopen(url) + return base64.b64encode(bfile.read()) + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: