[IMP] LinkedIn module
bzr revid: nicolas.vanhoren@openerp.com-20120808133325-xagh0bnxoggq1ruh
This commit is contained in:
commit
f74e90799c
|
@ -0,0 +1,2 @@
|
|||
|
||||
import web_linkedin
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"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': [
|
||||
'web_linkedin_view.xml',
|
||||
],
|
||||
"depends" : ["base"],
|
||||
"js": [
|
||||
"static/src/js/*.js"
|
||||
],
|
||||
"css": [
|
||||
"static/src/css/*.css"
|
||||
],
|
||||
'qweb': [
|
||||
"static/src/xml/*.xml"
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
|
||||
.openerp .oe_linkedin_img {
|
||||
float: right;
|
||||
width: 1.5em;
|
||||
margin-top: -1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.openerp .oe_linkedin_input {
|
||||
margin-right:1.5em;
|
||||
}
|
||||
|
||||
.openerp .oe_linkedin_entity {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.openerp .oe_linkedin_entity .oe_linkedin_thumb {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.openerp .oe_linkedin_entity .oe_linkedin_thumb span {
|
||||
height: 70px;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.openerp .oe_linkedin_entity img {
|
||||
max-width: 70px;
|
||||
max-height: 70px;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 453 B |
|
@ -0,0 +1,288 @@
|
|||
/*---------------------------------------------------------
|
||||
* OpenERP web_linkedin (module)
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.web_linkedin = function(instance) {
|
||||
var QWeb = instance.web.qweb;
|
||||
var _t = instance.web._t;
|
||||
|
||||
instance.web_linkedin.LinkedinTester = instance.web.Class.extend({
|
||||
init: function() {
|
||||
this.linkedin_added = false;
|
||||
this.linkedin_def = $.Deferred();
|
||||
this.auth_def = $.Deferred();
|
||||
},
|
||||
test_linkedin: function() {
|
||||
var self = this;
|
||||
return this.test_api_key().pipe(function() {
|
||||
if (self.linkedin_added)
|
||||
return self.linkedin_def.promise();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = "http://platform.linkedin.com/in.js";
|
||||
tag.innerHTML = 'api_key : ' + self.api_key + '\nauthorize : true';
|
||||
document.getElementsByTagName('head')[0].appendChild(tag);
|
||||
self.linkedin_added = true;
|
||||
$(tag).load(function() {
|
||||
IN.Event.on(IN, "auth", function() {
|
||||
self.auth_def.resolve();
|
||||
});
|
||||
self.linkedin_def.resolve();
|
||||
});
|
||||
return self.linkedin_def.promise();
|
||||
});
|
||||
},
|
||||
test_api_key: function() {
|
||||
var self = this;
|
||||
if (this.api_key) {
|
||||
return $.when();
|
||||
}
|
||||
return new instance.web.Model("ir.config_parameter").call("set_param", ["web.linkedin.apikey", ""]).pipe(function() {
|
||||
return new instance.web.Model("ir.config_parameter").call("get_param", ["web.linkedin.apikey"]).pipe(function(a) {
|
||||
if (!!a) {
|
||||
self.api_key = a;
|
||||
return true;
|
||||
} else {
|
||||
return $.Deferred().reject();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
test_authentication: function() {
|
||||
return this.auth_def.promise();
|
||||
},
|
||||
});
|
||||
|
||||
instance.web_linkedin.tester = new instance.web_linkedin.LinkedinTester();
|
||||
|
||||
instance.web_linkedin.Linkedin = instance.web.form.FieldChar.extend({
|
||||
init: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.display_dm = new instance.web.DropMisordered(true);
|
||||
},
|
||||
initialize_content: function() {
|
||||
var $ht = $(QWeb.render("FieldChar.linkedin"));
|
||||
var $in = this.$("input");
|
||||
$in.replaceWith($ht);
|
||||
this.$(".oe_linkedin_input").append($in);
|
||||
this.$(".oe_linkedin_img").click(_.bind(this.search_linkedin, this));
|
||||
this._super();
|
||||
|
||||
},
|
||||
search_linkedin: function() {
|
||||
var self = this;
|
||||
this.display_dm.add(instance.web_linkedin.tester.test_linkedin()).then(function() {
|
||||
var pop = new instance.web_linkedin.LinkedinPopup(self, self.get("value"));
|
||||
pop.open();
|
||||
pop.on("selected", this, function(entity) {
|
||||
self.selected_entity(entity);
|
||||
});
|
||||
}, _.bind(this.linkedin_disabled, this));
|
||||
},
|
||||
linkedin_disabled: function() {
|
||||
if (instance.connection.uid !== 1) {
|
||||
instance.web.dialog($(QWeb.render("LinkedIn.DisabledWarning")), {
|
||||
title: _t("LinkedIn is not enabled"),
|
||||
buttons: [
|
||||
{text: _t("Ok"), click: function() { $(this).dialog("close"); }}
|
||||
]
|
||||
});
|
||||
} else {
|
||||
new instance.web_linkedin.KeyWizard(this).open();
|
||||
}
|
||||
},
|
||||
selected_entity: function(entity) {
|
||||
var self = this;
|
||||
this.create_on_change(entity).then(function(to_change) {
|
||||
self.view.on_processed_onchange({value:to_change});
|
||||
});
|
||||
},
|
||||
create_on_change: function(entity) {
|
||||
var self = this;
|
||||
var to_change = {};
|
||||
var defs = [];
|
||||
if (entity.__type === "company") {
|
||||
to_change.is_company = true;
|
||||
to_change.name = entity.name;
|
||||
to_change.photo = false;
|
||||
if (entity.logoUrl) {
|
||||
defs.push(self.rpc('/web_linkedin/binary/url2binary',
|
||||
{'url': entity.logoUrl}).pipe(function(data){
|
||||
to_change.photo = data;
|
||||
}));
|
||||
}
|
||||
to_change.website = entity.websiteUrl;
|
||||
to_change.phone = false;
|
||||
_.each(entity.locations.values || [], function(el) {
|
||||
to_change.phone = el.contactInfo.phone1;
|
||||
});
|
||||
var children_def = $.Deferred();
|
||||
IN.API.PeopleSearch().fields(commonPeopleFields).params({
|
||||
"company-name" : entity.name,
|
||||
"current-company": true,
|
||||
"count": 25,
|
||||
}).result(function(result) {
|
||||
children_def.resolve(result);
|
||||
});
|
||||
defs.push(children_def.pipe(function(result) {
|
||||
var defs = _.map(result.people.values || [], function(el) {
|
||||
el.__type = "people";
|
||||
return self.create_on_change(el);
|
||||
});
|
||||
return $.when.apply($, defs).pipe(function() {
|
||||
var p_to_change = _.toArray(arguments);
|
||||
to_change.child_ids = p_to_change;
|
||||
});
|
||||
}));
|
||||
/* TODO
|
||||
to_change.linkedinUrl = _.str.sprintf("http://www.linkedin.com/company/%d", entity.id);
|
||||
*/
|
||||
} else { // people
|
||||
to_change.is_company = false;
|
||||
to_change.name = entity.formattedName;
|
||||
to_change.photo = false;
|
||||
if (entity.pictureUrl) {
|
||||
defs.push(self.rpc('/web_linkedin/binary/url2binary',
|
||||
{'url': entity.pictureUrl}).pipe(function(data){
|
||||
to_change.photo = data;
|
||||
}));
|
||||
}
|
||||
to_change.mobile = false;
|
||||
to_change.phone = false;
|
||||
_.each(entity.phoneNumbers.values || [], function(el) {
|
||||
if (el.phoneType === "mobile") {
|
||||
to_change.mobile = el.phoneNumber;
|
||||
} else {
|
||||
to_change.phone = el.phoneNumber;
|
||||
}
|
||||
});
|
||||
to_change.function = entity.headline;
|
||||
/* TODO
|
||||
to_change.linkedinUrl = entity.publicProfileUrl;
|
||||
*/
|
||||
}
|
||||
return $.when.apply($, defs).pipe(function() {
|
||||
return to_change;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.form.widgets.add('linkedin', 'instance.web_linkedin.Linkedin');
|
||||
|
||||
var commonPeopleFields = ["id", "picture-url", "public-profile-url",
|
||||
"formatted-name", "location", "phone-numbers", "im-accounts",
|
||||
"main-address", "headline"];
|
||||
|
||||
instance.web_linkedin.LinkedinPopup = instance.web.Dialog.extend({
|
||||
template: "Linkedin.popup",
|
||||
init: function(parent, text) {
|
||||
this._super(parent, {title:_t("LinkedIn search")});
|
||||
this.text = text;
|
||||
this.limit = 15;
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
var self = this;
|
||||
this.on("authentified", this, this.authentified);
|
||||
instance.web_linkedin.tester.test_authentication().then(function() {
|
||||
self.trigger("authentified");
|
||||
});
|
||||
},
|
||||
authentified: function() {
|
||||
var self = this;
|
||||
cdef = $.Deferred();
|
||||
pdef = $.Deferred();
|
||||
IN.API.Raw(_.str.sprintf(
|
||||
"company-search:(companies:" +
|
||||
"(id,name,logo-url,description,industry,website-url,locations))?keywords=%s&count=%d",
|
||||
encodeURI(this.text), this.limit)).result(function (result) {
|
||||
cdef.resolve(result);
|
||||
});
|
||||
IN.API.PeopleSearch().fields(commonPeopleFields).
|
||||
params({"keywords": this.text, "count": this.limit}).result(function(result) {
|
||||
pdef.resolve(result);
|
||||
});
|
||||
return $.when(cdef, pdef).then(function(companies, people) {
|
||||
var lst = companies.companies.values || [];
|
||||
var plst = people.people.values || [];
|
||||
lst = _.initial(lst, _.min([self.limit / 2, plst.length]));
|
||||
_.map(lst, function(el) {
|
||||
el.__type = "company";
|
||||
return el;
|
||||
});
|
||||
plst = _.first(plst, self.limit - lst.length)
|
||||
_.map(plst, function(el) {
|
||||
el.__type = "people";
|
||||
return el;
|
||||
});
|
||||
lst = plst.concat(lst);
|
||||
console.log("Linkedin search found:", lst.length, lst);
|
||||
self.result = lst;
|
||||
self.display_result();
|
||||
});
|
||||
},
|
||||
display_result: function() {
|
||||
var self = this;
|
||||
var i = 0;
|
||||
var $row;
|
||||
_.each(self.result, function(el) {
|
||||
var pc = new instance.web_linkedin.EntityWidget(self, el);
|
||||
if (i % 5 === 0) {
|
||||
$row = $("<div style='display: table-row;width:100%'/>");
|
||||
$row.appendTo(self.$(">div"));
|
||||
}
|
||||
pc.appendTo($row);
|
||||
pc.$element.css("display", "table-cell");
|
||||
pc.$element.css("width", "20%");
|
||||
pc.on("selected", self, function(data) {
|
||||
self.trigger("selected", data);
|
||||
self.destroy();
|
||||
});
|
||||
i++;
|
||||
});
|
||||
if (self.result.length === 0) {
|
||||
self.$(">div").text(_t("No results found"));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
instance.web_linkedin.EntityWidget = instance.web.Widget.extend({
|
||||
template: "Linkedin.EntityWidget",
|
||||
init: function(parent, data) {
|
||||
this._super(parent);
|
||||
this.data = data;
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.$element.click(function() {
|
||||
self.trigger("selected", self.data);
|
||||
});
|
||||
if (this.data.__type === "company") {
|
||||
this.$("h3").text(this.data.name);
|
||||
self.$("img").attr("src", this.data.logoUrl);
|
||||
} else { // people
|
||||
this.$("h3").text(this.data.formattedName);
|
||||
self.$("img").attr("src", this.data.pictureUrl);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
instance.web_linkedin.KeyWizard = instance.web.Dialog.extend({
|
||||
template: "LinkedIn.KeyWizard",
|
||||
init: function(parent, text) {
|
||||
this._super(parent, {title:_t("LinkedIn API Key")});
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
var self = this;
|
||||
this.$("button").click(function() {
|
||||
var value = self.$("input").val();
|
||||
return new instance.web.Model("ir.config_parameter").call("set_param", ["web.linkedin.apikey", value]).pipe(function() {
|
||||
self.destroy();
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
// vim:et fdc=0 fdl=0:
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- vim:fdl=1:
|
||||
-->
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="FieldChar.linkedin">
|
||||
<img class="oe_linkedin_img" t-att-src='_s + "/web_linkedin/static/src/img/Linkedin_blue.png"'/>
|
||||
<div class="oe_linkedin_input"/>
|
||||
</t>
|
||||
<t t-name="Linkedin.popup">
|
||||
<div>
|
||||
<script type="in/Login">
|
||||
</script>
|
||||
<div style='display: table;width:100%'/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Linkedin.EntityWidget">
|
||||
<div class="oe_linkedin_entity">
|
||||
<span class="oe_linkedin_thumb">
|
||||
<span>
|
||||
<img t-att-src='_s + "/web_linkedin/static/src/img/ghost_profile_60x60_v1.png"'/>
|
||||
</span>
|
||||
</span>
|
||||
<h3/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="LinkedIn.DisabledWarning">
|
||||
<div>
|
||||
LinkedIn access was not enabled on this server.
|
||||
Please ask your administrator to activate it.
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="LinkedIn.KeyWizard">
|
||||
<div>
|
||||
<p>
|
||||
To use the LinkedIn module with this database, an API Key is required. Please follow this procedure:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Go to this URL:
|
||||
<a href="https://www.linkedin.com/secure/developer" target="_blank">https://www.linkedin.com/secure/developer</a>.
|
||||
</li>
|
||||
<li>Log into LinkedIn.</li>
|
||||
<li>Add a new application and fill the form:
|
||||
<ul>
|
||||
<li>JavaScript API Domain is Your domain name (e.g. https://yourcompany.my.openerp.com)</li>
|
||||
<li>You can give multiple domain (e.g. yourcompany.my.openerp.com)</li>
|
||||
<li>The programming tool is Javascript</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Copy the API key here:
|
||||
<input type="text"/>
|
||||
<button>Apply</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
|
@ -0,0 +1,33 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import web.common.http
|
||||
import base64
|
||||
import urllib2
|
||||
|
||||
class Binary(web.common.http.Controller):
|
||||
_cp_path = "/web_linkedin/binary"
|
||||
|
||||
@web.common.http.jsonrequest
|
||||
def url2binary(self, req,url):
|
||||
bfile = urllib2.urlopen(url)
|
||||
return base64.b64encode(bfile.read())
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_linkedin_partner_form" model="ir.ui.view">
|
||||
<field name="name">res.partner.linkedin.inherit</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="replace">
|
||||
<field name="name" default_focus="1" nolabel="1" widget="linkedin" />
|
||||
</field>
|
||||
<!--<field name="title" position="before">
|
||||
<field name="linkedin_id" invisible="1"/>
|
||||
<field name="profile_id" invisible="1"/>
|
||||
<field name="twitter_id" invisible="1"/>
|
||||
</field>-->
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
Loading…
Reference in New Issue